From 6b6d22afa8b60d7b8a724544c0e277a8c1839c35 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Thu, 17 Mar 2022 12:13:51 -0300 Subject: [PATCH] Added report conversion using pandoc --- README.md | 9 ++++ debian/control | 1 + docs/samples/generic_plot.kibot.yaml | 13 +++++ kibot/misc.py | 1 + kibot/out_report.py | 51 ++++++++++++++++++- tests/test_plot/test_misc.py | 12 +++++ tests/yaml_samples/report_simple_1.kibot.yaml | 15 ++---- tests/yaml_samples/report_simple_2.kibot.yaml | 50 ++++++++++++++++++ 8 files changed, 139 insertions(+), 13 deletions(-) create mode 100644 tests/yaml_samples/report_simple_2.kibot.yaml diff --git a/README.md b/README.md index 15347b8b..2ed30b0f 100644 --- a/README.md +++ b/README.md @@ -1872,6 +1872,15 @@ Next time you need this list just use an alias, like this: - `name`: [string=''] Used to identify this particular output definition. - `options`: [dict] Options for the `report` output. * Valid keys: + - `convert_from`: [string='markdown'] Original format for the report conversion. Current templates are `markdown`. See `do_convert`. + - `convert_to`: [string='pdf'] Target format for the report conversion. See `do_convert`. + - `converted_output`: [string='%f-%i%I%v.%x'] Converted output file name (%i='report', %x=`convert_to`). Affected by global options. + - `do_convert`: [boolean=false] Run `Pandoc` to convert the report. Note that Pandoc must be installed. + The conversion is done assuming the report is in `convert_from` format. + The output file will be in `convert_to` format. + The available formats depends on the `Pandoc` installation. + In CI/CD environments: the `kicad_auto_test` docker image contains it. + In Debian/Ubuntu environments: install `pandoc`, `texlive-latex-base` and `texlive-latex-recommended`. - `output`: [string='%f-%i%I%v.%x'] Output file name (%i='report', %x='txt'). Affected by global options. - `template`: [string='full'] Name for one of the internal templates (full, simple) or a custom template file. - `output_id`: [string=''] Text to use for the %I expansion content. To differentiate variations of this output. diff --git a/debian/control b/debian/control index a813ac00..a660abff 100644 --- a/debian/control +++ b/debian/control @@ -12,6 +12,7 @@ Architecture: all Multi-Arch: foreign Depends: ${misc:Depends}, ${python3:Depends}, python3-distutils, python3-yaml, kicad (>= 5.1.6), python3-wxgtk4.0 Recommends: kibom.inti-cmnb (>= 1.8.0), interactivehtmlbom.inti-cmnb, pcbdraw, imagemagick, librsvg2-bin, python3-xlsxwriter, rar, poppler-utils +Suggests: pandoc, texlive-latex-base, texlive-latex-recommended Description: KiCad Bot KiBot is a program which helps you to automate the generation of KiCad output documents easily, repeatable, and most of all, scriptably. diff --git a/docs/samples/generic_plot.kibot.yaml b/docs/samples/generic_plot.kibot.yaml index 311b4090..3b0dc75f 100644 --- a/docs/samples/generic_plot.kibot.yaml +++ b/docs/samples/generic_plot.kibot.yaml @@ -1306,6 +1306,19 @@ outputs: type: 'report' dir: 'Example/report_dir' options: + # [string='markdown'] Original format for the report conversion. Current templates are `markdown`. See `do_convert` + convert_from: 'markdown' + # [string='pdf'] Target format for the report conversion. See `do_convert` + convert_to: 'pdf' + # [string='%f-%i%I%v.%x'] Converted output file name (%i='report', %x=`convert_to`). Affected by global options + converted_output: '%f-%i%I%v.%x' + # [boolean=false] Run `Pandoc` to convert the report. Note that Pandoc must be installed. + # The conversion is done assuming the report is in `convert_from` format. + # The output file will be in `convert_to` format. + # The available formats depends on the `Pandoc` installation. + # In CI/CD environments: the `kicad_auto_test` docker image contains it. + # In Debian/Ubuntu environments: install `pandoc`, `texlive-latex-base` and `texlive-latex-recommended` + do_convert: false # [string='%f-%i%I%v.%x'] Output file name (%i='report', %x='txt'). Affected by global options output: '%f-%i%I%v.%x' # [string='full'] Name for one of the internal templates (full, simple) or a custom template file diff --git a/kibot/misc.py b/kibot/misc.py index 23879b22..6710c77f 100644 --- a/kibot/misc.py +++ b/kibot/misc.py @@ -85,6 +85,7 @@ PCBDRAW = 'pcbdraw' URL_PCBDRAW = 'https://github.com/INTI-CMNB/pcbdraw' EXAMPLE_CFG = 'example_template.kibot.yaml' AUTO_SCALE = 0 +PANDOC = 'pandoc' KICAD_VERSION_5_99 = 5099000 KICAD_VERSION_6_0_0 = 6000000 KICAD_VERSION_6_0_2 = 6000002 diff --git a/kibot/out_report.py b/kibot/out_report.py index 8502a205..fd057f99 100644 --- a/kibot/out_report.py +++ b/kibot/out_report.py @@ -6,9 +6,11 @@ import os import re import pcbnew +from subprocess import check_output, STDOUT, CalledProcessError from .gs import GS -from .misc import UI_SMD, UI_VIRTUAL, MOD_THROUGH_HOLE, MOD_SMD, MOD_EXCLUDE_FROM_POS_FILES +from .misc import (UI_SMD, UI_VIRTUAL, MOD_THROUGH_HOLE, MOD_SMD, MOD_EXCLUDE_FROM_POS_FILES, PANDOC, MISSING_TOOL, + FAILED_EXECUTE) from .registrable import RegOutput from .out_base import BaseOptions from .error import KiPlotConfigurationError @@ -18,6 +20,8 @@ from . import log logger = log.get_logger() INF = float('inf') +PANDOC_INSTALL = ("In CI/CD environments: the `kicad_auto_test` docker image contains it.\n" + "In Debian/Ubuntu environments: install `pandoc`, `texlive-latex-base` and `texlive-latex-recommended`") def do_round(v, dig): @@ -115,12 +119,24 @@ class ReportOptions(BaseOptions): """ Output file name (%i='report', %x='txt') """ self.template = 'full' """ Name for one of the internal templates (full, simple) or a custom template file """ + self.convert_from = 'markdown' + """ Original format for the report conversion. Current templates are `markdown`. See `do_convert` """ + self.convert_to = 'pdf' + """ Target format for the report conversion. See `do_convert` """ + self.do_convert = False + """ Run `Pandoc` to convert the report. Note that Pandoc must be installed. + The conversion is done assuming the report is in `convert_from` format. + The output file will be in `convert_to` format. + The available formats depends on the `Pandoc` installation """ + self.converted_output = GS.def_global_output + """ Converted output file name (%i='report', %x=`convert_to`) """ super().__init__() self._expand_id = 'report' self._expand_ext = 'txt' self._mm_digits = 2 self._mils_digits = 0 self._in_digits = 2 + self._help_do_convert += ".\n"+PANDOC_INSTALL def config(self, parent): super().config(parent) @@ -574,8 +590,38 @@ class ReportOptions(BaseOptions): with open(output_file, "wt") as f: f.write(text) + def expand_converted_output(self, out_dir): + aux = self._expand_ext + self._expand_ext = str(self.convert_to) + res = self._parent.expand_filename(out_dir, self.converted_output) + self._expand_ext = aux + return res + def get_targets(self, out_dir): - return [self._parent.expand_filename(out_dir, self.output)] + files = [self._parent.expand_filename(out_dir, self.output)] + if self.do_convert: + files.append(self.expand_converted_output(out_dir)) + return files + + def convert(self, fname): + if not self.do_convert: + return + out = self.expand_converted_output(GS.out_dir) + logger.debug('Converting the report to: {}'.format(out)) + resources = '--resource-path='+GS.out_dir + cmd = [PANDOC, '--from', self.convert_from, '--to', self.convert_to, resources, fname, '-o', out] + logger.debug('Executing {}'.format(cmd)) + try: + check_output(cmd, stderr=STDOUT) + except FileNotFoundError: + logger.error("Unable to convert the report, `{}` must be installed.".format(PANDOC)) + logger.error(PANDOC_INSTALL) + exit(MISSING_TOOL) + except CalledProcessError as e: + logger.error('{} error: {}'.format(PANDOC, e.returncode)) + if e.output: + logger.debug('Output from command: '+e.output.decode()) + exit(FAILED_EXECUTE) def run(self, fname): self.pcb_material = GS.global_pcb_material @@ -624,6 +670,7 @@ class ReportOptions(BaseOptions): self.schematic_pdfs = len(self._schematic_pdfs) > 0 self.schematic_svgs = len(self._schematic_svgs) > 0 self.do_template(self.template, fname) + self.convert(fname) @output_class diff --git a/tests/test_plot/test_misc.py b/tests/test_plot/test_misc.py index 9c11c353..8e51ac29 100644 --- a/tests/test_plot/test_misc.py +++ b/tests/test_plot/test_misc.py @@ -1005,6 +1005,18 @@ def test_report_simple_1(test_dir): ctx.clean_up(keep_project=True) +def test_report_simple_2(test_dir): + prj = 'light_control' + ctx = context.TestContext(test_dir, 'test_report_simple_2', prj, 'report_simple_2', POS_DIR) + ctx.run() + ctx.expect_out_file(prj+'-report.txt') + ctx.expect_out_file(prj+'-report_simple.txt') + ctx.compare_txt(prj+'-report.txt') + ctx.compare_txt(prj+'-report_simple.txt') + ctx.expect_out_file(prj+'-report.pdf') + ctx.clean_up(keep_project=True) + + def test_board_view_1(test_dir): prj = 'glasgow' ctx = context.TestContext(test_dir, 'test_board_view_1', prj, 'boardview', POS_DIR) diff --git a/tests/yaml_samples/report_simple_1.kibot.yaml b/tests/yaml_samples/report_simple_1.kibot.yaml index 8139f514..39233fe4 100644 --- a/tests/yaml_samples/report_simple_1.kibot.yaml +++ b/tests/yaml_samples/report_simple_1.kibot.yaml @@ -9,10 +9,6 @@ global: copper_thickness: "35" outputs: - - name: 'report_full' - comment: "Full design report" - type: report - - name: 'report_simple' comment: "Simple design report" type: report @@ -20,6 +16,10 @@ outputs: options: template: simple + - name: 'report_full' + comment: "Full design report" + type: report + - name: 'print_front' comment: "Top copper and silkscreen" type: svg_pcb_print @@ -40,13 +40,6 @@ outputs: - layer: B.Cu - layer: B.SilkS - - name: 'print_sch' - comment: "Schematic" - type: pdf_sch_print - dir: . - options: - output: Schematic.pdf - - name: 'print_sch_svg' comment: "Schematic" type: svg_sch_print diff --git a/tests/yaml_samples/report_simple_2.kibot.yaml b/tests/yaml_samples/report_simple_2.kibot.yaml new file mode 100644 index 00000000..b0bb2231 --- /dev/null +++ b/tests/yaml_samples/report_simple_2.kibot.yaml @@ -0,0 +1,50 @@ +# Example KiBot config file +kibot: + version: 1 + +global: + solder_mask_color_top: blue + solder_mask_color_bottom: red + pcb_finish: ENIG + copper_thickness: "35" + +outputs: + - name: 'report_simple' + comment: "Simple design report" + type: report + output_id: _simple + options: + template: simple + + - name: 'print_front' + comment: "Top copper and silkscreen" + type: svg_pcb_print + dir: Layers + options: + title: 'Fake title for front copper and silk' + layers: + - layer: F.Cu + - layer: F.SilkS + + - name: 'print_bottom' + comment: "Bottom copper and silkscreen" + type: svg_pcb_print + dir: Layers + options: + title: 'Fake title for bottom copper and silk' + layers: + - layer: B.Cu + - layer: B.SilkS + + - name: 'print_sch_svg' + comment: "Schematic" + type: svg_sch_print + dir: . + options: + output: Schematic.svg + + - name: 'report_full' + comment: "Full design report" + type: report + options: + do_convert: true