diff --git a/CHANGELOG.md b/CHANGELOG.md index 73e58525..77a5e12e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -55,6 +55,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Datasheet downloader. (#119) - Position files now can include virtual components. (#106) - Support for variants on KiCost output. (#106) +- `--cli-order` option to generate outputs in arbitrary order. (#106) ### Changed - Internal BoM: now components with different Tolerance, Voltage, Current diff --git a/README.md b/README.md index 51291dae..e12ff33c 100644 --- a/README.md +++ b/README.md @@ -562,6 +562,10 @@ Each output contain the following data: - `type` selects which type of output will be generated. Examples are *gerbers*, *drill files* and *pick & place files* - `dir` is the directory where this output will be stored. +- `extends` used to use another output's `options` as base. +- `run_by_default` indicates this output will be created when no specific outputs are requested. +- `disable_run_by_default` can be used to disable the `run_by_default` status of other output. +- `output_id` text to use for the %I expansion content. - `options` contains one or more options to configure this output. - `layers` a list of layers used for this output. Not all outputs needs this subsection. @@ -590,13 +594,22 @@ The available values for *type* are: - `position` of the components for the pick & place machine - Documentation - `pdf_sch_print` schematic in PDF format + - `svg_sch_print` schematic in SVG format - `pdf_pcb_print`PDF file containing one or more layer and the page frame - Bill of Materials + - `bom` The internal BoM generator. - `kibom` BoM in HTML or CSV format generated by [KiBoM](https://github.com/INTI-CMNB/KiBoM) - `ibom` Interactive HTML BoM generated by [InteractiveHtmlBom](https://github.com/INTI-CMNB/InteractiveHtmlBom) - `kicost` BoM in XLSX format with costs generated by [KiCost](https://github.com/INTI-CMNB/KiCost) - 3D model: - `step` *Standard for the Exchange of Product Data* for the PCB + - `render_3d` PCB render, from the KiCad's 3D Viewer (broken in KiCad 6.0.0) +- Others: + - `boardview` creates a file useful to repair the board, but without disclosing the full layout. + - `compress` creates an archive containing generated data. + - `download_datasheets` downloads the datasheets for all the components. + - `pcbdraw` nice images of the PCB in customized colors. + - `sch_variant` the schematic after applying all filters and variants, including crossed components. Here is an example of a configuration file to generate the gerbers for the top and bottom layers: @@ -640,6 +653,9 @@ outputs: Most options are the same you'll find in the KiCad dialogs. +Outputs are generated in the order they are declared in the YAML file. +To create them in an arbitrary order use the `--cli-order` command line option and they will be created in the order specified in the command line. + #### Specifying the layers @@ -1364,8 +1380,7 @@ Next time you need this list just use an alias, like this: - `distributors`: [string|list(string)] Include this distributors list. Default is all the available. - `dnf_filter`: [string|list(string)='_none'] Name of the filter to mark components as not fitted. A short-cut to use for simple cases where a variant is an overkill. - Internal variants and filters are currently ignored. - Exception: a KiCost variant that uses `variant` as variant field. + Don't use the `kicost_variant` when using internal variants/filters. - `fields`: [string|list(string)] List of fields to be added to the global data section. - `group_fields`: [string|list(string)] List of fields that can be different for a group. Parts with differences in these fields are grouped together, but displayed individually. @@ -1383,8 +1398,7 @@ Next time you need this list just use an alias, like this: - `field`: [string=''] Name of the field to rename. - `name`: [string=''] New name. - `variant`: [string=''] Board variant to apply. - Internal variants and filters are currently ignored. - Exception: a KiCost variant that uses `variant` as variant field. + Don't use the `kicost_variant` when using internal variants/filters. - `output_id`: [string=''] Text to use for the %I expansion content. To differentiate variations of this output. - `run_by_default`: [boolean=true] When enabled this output will be created when no specific outputs are requested. @@ -2265,7 +2279,7 @@ KiBot: KiCad automation tool for documents generation Usage: kibot [-b BOARD] [-e SCHEMA] [-c CONFIG] [-d OUT_DIR] [-s PRE] - [-q | -v...] [-i] [-m MKFILE] [-g DEF]... [TARGET...] + [-q | -v...] [-i] [-C] [-m MKFILE] [-g DEF]... [TARGET...] kibot [-v...] [-b BOARD] [-e SCHEMA] [-c PLOT_CONFIG] --list kibot [-v...] [-b BOARD] [-d OUT_DIR] [-p | -P] --example kibot [-v...] --help-filters @@ -2283,6 +2297,7 @@ Options: -h, --help Show this help message and exit -b BOARD, --board-file BOARD The PCB .kicad-pcb board file -c CONFIG, --plot-config CONFIG The plotting config file to use + -C, --cli-order Generate outputs using the indicated order -d OUT_DIR, --out-dir OUT_DIR The output directory [default: .] -e SCHEMA, --schematic SCHEMA The schematic file (.sch) -g DEF, --global-redef DEF Overwrite a global value (VAR=VAL) diff --git a/docs/README.in b/docs/README.in index f888d0a8..8550136b 100644 --- a/docs/README.in +++ b/docs/README.in @@ -381,6 +381,10 @@ Each output contain the following data: - `type` selects which type of output will be generated. Examples are *gerbers*, *drill files* and *pick & place files* - `dir` is the directory where this output will be stored. +- `extends` used to use another output's `options` as base. +- `run_by_default` indicates this output will be created when no specific outputs are requested. +- `disable_run_by_default` can be used to disable the `run_by_default` status of other output. +- `output_id` text to use for the %I expansion content. - `options` contains one or more options to configure this output. - `layers` a list of layers used for this output. Not all outputs needs this subsection. @@ -409,13 +413,22 @@ The available values for *type* are: - `position` of the components for the pick & place machine - Documentation - `pdf_sch_print` schematic in PDF format + - `svg_sch_print` schematic in SVG format - `pdf_pcb_print`PDF file containing one or more layer and the page frame - Bill of Materials + - `bom` The internal BoM generator. - `kibom` BoM in HTML or CSV format generated by [KiBoM](https://github.com/INTI-CMNB/KiBoM) - `ibom` Interactive HTML BoM generated by [InteractiveHtmlBom](https://github.com/INTI-CMNB/InteractiveHtmlBom) - `kicost` BoM in XLSX format with costs generated by [KiCost](https://github.com/INTI-CMNB/KiCost) - 3D model: - `step` *Standard for the Exchange of Product Data* for the PCB + - `render_3d` PCB render, from the KiCad's 3D Viewer (broken in KiCad 6.0.0) +- Others: + - `boardview` creates a file useful to repair the board, but without disclosing the full layout. + - `compress` creates an archive containing generated data. + - `download_datasheets` downloads the datasheets for all the components. + - `pcbdraw` nice images of the PCB in customized colors. + - `sch_variant` the schematic after applying all filters and variants, including crossed components. Here is an example of a configuration file to generate the gerbers for the top and bottom layers: @@ -459,6 +472,9 @@ outputs: Most options are the same you'll find in the KiCad dialogs. +Outputs are generated in the order they are declared in the YAML file. +To create them in an arbitrary order use the `--cli-order` command line option and they will be created in the order specified in the command line. + #### Specifying the layers diff --git a/docs/samples/generic_plot.kibot.yaml b/docs/samples/generic_plot.kibot.yaml index 797de934..f9786115 100644 --- a/docs/samples/generic_plot.kibot.yaml +++ b/docs/samples/generic_plot.kibot.yaml @@ -814,8 +814,7 @@ outputs: distributors: # [string|list(string)='_none'] Name of the filter to mark components as not fitted. # A short-cut to use for simple cases where a variant is an overkill. - # Internal variants and filters are currently ignored. - # Exception: a KiCost variant that uses `variant` as variant field + # Don't use the `kicost_variant` when using internal variants/filters dnf_filter: '_none' # [string|list(string)] List of fields to be added to the global data section fields: @@ -847,8 +846,7 @@ outputs: # [string=''] New name name: 'manf#' # [string=''] Board variant to apply. - # Internal variants and filters are currently ignored. - # Exception: a KiCost variant that uses `variant` as variant field + # Don't use the `kicost_variant` when using internal variants/filters variant: '' # PcbDraw - Beautiful 2D PCB render: diff --git a/kibot/__main__.py b/kibot/__main__.py index ffe5147c..4260f96c 100644 --- a/kibot/__main__.py +++ b/kibot/__main__.py @@ -9,7 +9,7 @@ Usage: kibot [-b BOARD] [-e SCHEMA] [-c CONFIG] [-d OUT_DIR] [-s PRE] - [-q | -v...] [-i] [-m MKFILE] [-g DEF]... [TARGET...] + [-q | -v...] [-i] [-C] [-m MKFILE] [-g DEF]... [TARGET...] kibot [-v...] [-b BOARD] [-e SCHEMA] [-c PLOT_CONFIG] --list kibot [-v...] [-b BOARD] [-d OUT_DIR] [-p | -P] --example kibot [-v...] --help-filters @@ -27,6 +27,7 @@ Options: -h, --help Show this help message and exit -b BOARD, --board-file BOARD The PCB .kicad-pcb board file -c CONFIG, --plot-config CONFIG The plotting config file to use + -C, --cli-order Generate outputs using the indicated order -d OUT_DIR, --out-dir OUT_DIR The output directory [default: .] -e SCHEMA, --schematic SCHEMA The schematic file (.sch) -g DEF, --global-redef DEF Overwrite a global value (VAR=VAL) @@ -372,7 +373,7 @@ def main(): generate_makefile(args.makefile, plot_config, outputs) else: # Do all the job (pre-flight + outputs) - generate_outputs(outputs, args.target, args.invert_sel, args.skip_pre) + generate_outputs(outputs, args.target, args.invert_sel, args.skip_pre, args.cli_order) # Print total warnings logger.log_totals() diff --git a/kibot/kiplot.py b/kibot/kiplot.py index 2a1ac0ea..35dceb10 100644 --- a/kibot/kiplot.py +++ b/kibot/kiplot.py @@ -21,6 +21,7 @@ from importlib.util import (spec_from_file_location, module_from_spec) from collections import OrderedDict from .gs import GS +from .registrable import RegOutput from .misc import (PLOT_ERROR, MISSING_TOOL, CMD_EESCHEMA_DO, URL_EESCHEMA_DO, CORRUPTED_PCB, EXIT_BAD_ARGS, CORRUPTED_SCH, EXIT_BAD_CONFIG, WRONG_INSTALL, UI_SMD, UI_VIRTUAL, MOD_SMD, MOD_THROUGH_HOLE, MOD_VIRTUAL, W_PCBNOSCH, W_NONEEDSKIP, W_WRONGCHAR, name2make, W_TIMEOUT, @@ -356,7 +357,7 @@ def run_output(out): config_error("In section '"+out.name+"' ("+out.type+"): "+str(e)) -def generate_outputs(outputs, target, invert, skip_pre): +def generate_outputs(outputs, target, invert, skip_pre, cli_order): logger.debug("Starting outputs for board {}".format(GS.pcb_file)) GS.outputs = outputs preflight_checks(skip_pre) @@ -366,16 +367,31 @@ def generate_outputs(outputs, target, invert, skip_pre): # Skip all targets logger.debug('Skipping all outputs') return + # Check we got a valid list of outputs + for name in target: + out = RegOutput.get_output(name) + if out is None: + logger.error('Unknown output `{}`'.format(name)) + exit(EXIT_BAD_ARGS) # Generate outputs - for out in outputs: - if (((n == 0 or ((out.name not in target) and invert)) and out.run_by_default) or - ((out.name in target) and not invert)): - # Exclude + if cli_order and not invert: + # Use the CLI order + for name in target: + out = RegOutput.get_output(name) config_output(out) logger.info('- '+str(out)) run_output(out) - else: - logger.debug('Skipping `%s` output', str(out)) + else: + # Use the declaration order + for out in outputs: + if (((n == 0 or ((out.name not in target) and invert)) and out.run_by_default) or + ((out.name in target) and not invert)): + # Exclude + config_output(out) + logger.info('- '+str(out)) + run_output(out) + else: + logger.debug('Skipping `%s` output', str(out)) def adapt_file_name(name): diff --git a/tests/test_plot/test_misc.py b/tests/test_plot/test_misc.py index 54546977..a9247d55 100644 --- a/tests/test_plot/test_misc.py +++ b/tests/test_plot/test_misc.py @@ -107,9 +107,9 @@ def test_skip_pre_and_outputs_5(test_dir): ctx.clean_up() -def test_unknown_out(test_dir): +def test_unknown_out_type(test_dir): prj = 'simple_2layer' - ctx = context.TestContext(test_dir, 'UnknownOut', prj, 'unknown_out', POS_DIR) + ctx = context.TestContext(test_dir, 'test_unknown_out_type', prj, 'unknown_out', POS_DIR) ctx.run(EXIT_BAD_CONFIG) ctx.dont_expect_out_file(ctx.get_pos_both_csv_filename()) @@ -118,6 +118,22 @@ def test_unknown_out(test_dir): ctx.clean_up() +def test_unknown_out_name_1(test_dir): + prj = 'simple_2layer' + ctx = context.TestContext(test_dir, 'test_unknown_out_name_1', prj, 'pre_and_position', POS_DIR) + ctx.run(EXIT_BAD_ARGS, extra=['-s', 'all', '-C', 'pp']) + assert ctx.search_err("Unknown output .?pp") + ctx.clean_up() + + +def test_unknown_out_name_2(test_dir): + prj = 'simple_2layer' + ctx = context.TestContext(test_dir, 'test_unknown_out_name_1', prj, 'pre_and_position', POS_DIR) + ctx.run(EXIT_BAD_ARGS, extra=['-s', 'all', 'pp']) + assert ctx.search_err("Unknown output .?pp") + ctx.clean_up() + + def test_select_output(test_dir): prj = '3Rs' ctx = context.TestContext(test_dir, 'DoASCIISkipCSV', prj, 'pre_and_position', POS_DIR) @@ -908,3 +924,19 @@ def test_download_datasheets_1(test_dir): ctx.expect_out_file('DS_test/C0805C102J4GAC7800-1nF__test.pdf') ctx.expect_out_file('DS_test/CR0805-JW-102ELF-3k3__test.pdf') ctx.clean_up() + + +def test_cli_order(test_dir): + prj = 'simple_2layer' + ctx = context.TestContext(test_dir, 'test_cli_order', prj, 'pre_and_position', POS_DIR) + ctx.run(extra=['-s', 'all', '-C', 'pos_ascii', 'position']) + + csv = ctx.get_pos_both_csv_filename() + pos = ctx.get_pos_both_filename() + ctx.expect_out_file(csv) + ctx.expect_out_file(pos) + pos_txt = ctx.search_out('pos_ascii') + csv_txt = ctx.search_out('position') + assert pos_txt.start() < csv_txt.start() + + ctx.clean_up()