From 4ae54f3deda66b9004fcf31f87a49aed0dcc05a8 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Tue, 30 Jun 2020 20:09:14 -0300 Subject: [PATCH] Added --example/-x option to generate a configuration example. The example contains all the available preflights and outputs. If the user specifies a PCB the names of the layers are from the provided PCB --- CHANGELOG.md | 1 + README.md | 19 +- docs/Makefile | 5 +- docs/README.in | 15 + docs/samples/generic_plot.kiplot.yaml | 1033 +++++++++++++++++++------ kiplot/__main__.py | 20 +- kiplot/config_reader.py | 77 +- kiplot/kiplot.py | 52 +- kiplot/misc.py | 2 + kiplot/out_any_layer.py | 2 + kiplot/out_pdf_pcb_print.py | 2 + kiplot/pre_base.py | 4 + kiplot/pre_filters.py | 4 + kiplot/pre_ignore_unconnected.py | 4 + 14 files changed, 993 insertions(+), 247 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f73fedc7..dce518df 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - -e/--schematic option to specify any schematic (not just derived from the PCB name. +- -x/--example option to generate a complete configuration example. - Help for the supported outputs (--help-list-outputs, --help-outputs and --help-output) - Help for the supported preflights (--help-preflights) diff --git a/README.md b/README.md index abd4c30d..03c71eda 100644 --- a/README.md +++ b/README.md @@ -427,6 +427,21 @@ Most options are the same you'll find in the KiCad dialogs. ## Using KiPlot +If you need a template for the configuration file try: + +``` +kiplot --example +``` + +This will generate a file named `example.kiplot.yaml` containing all the available options and comments about them. +You can use it to create your own configuration file. + +If you want to use the layers of a particular PCB in the example use: + +``` +kiplot -b PCB_FILE --example +``` + If the current directory contains only one PCB file and only one configuration file (named *.kiplot.yaml) you can just call `kiplot`. No arguments needed. The tool will figure out which files to use. @@ -495,6 +510,7 @@ Usage: kiplot [-b BOARD] [-e SCHEMA] [-c CONFIG] [-d OUT_DIR] [-s PRE] [-q | -v...] [-i] [TARGET...] kiplot [-c PLOT_CONFIG] --list + kiplot [-b BOARD] --example kiplot --help-list-outputs kiplot --help-output=HELP_OUTPUT kiplot --help-outputs @@ -520,7 +536,8 @@ Options: -q, --quiet Remove information logs -s PRE, --skip-pre PRE Skip preflights, comma separated or `all` -v, --verbose Show debugging information - --version, -V Show program's version number and exit + -V, --version Show program's version number and exit + -x, --example Create an example configuration file. ``` diff --git a/docs/Makefile b/docs/Makefile index 9cf7cc03..5d076e3c 100644 --- a/docs/Makefile +++ b/docs/Makefile @@ -1,7 +1,10 @@ #!/usr/bin/make -all: ../README.md +all: ../README.md samples/generic_plot.kiplot.yaml ../README.md: README.in replace_tags.pl ../kiplot/out_*.py ../kiplot/pre_*.py ../kiplot/__main__.py cat README.in | perl replace_tags.pl > ../README.md +samples/generic_plot.kiplot.yaml: ../kiplot/out_*.py ../kiplot/pre_*.py ../kiplot/config_reader.py + ../src/kiplot --example + mv example.kiplot.yaml $@ diff --git a/docs/README.in b/docs/README.in index 9f6ed8f8..5c316b22 100644 --- a/docs/README.in +++ b/docs/README.in @@ -196,6 +196,21 @@ Most options are the same you'll find in the KiCad dialogs. ## Using KiPlot +If you need a template for the configuration file try: + +``` +kiplot --example +``` + +This will generate a file named `example.kiplot.yaml` containing all the available options and comments about them. +You can use it to create your own configuration file. + +If you want to use the layers of a particular PCB in the example use: + +``` +kiplot -b PCB_FILE --example +``` + If the current directory contains only one PCB file and only one configuration file (named *.kiplot.yaml) you can just call `kiplot`. No arguments needed. The tool will figure out which files to use. diff --git a/docs/samples/generic_plot.kiplot.yaml b/docs/samples/generic_plot.kiplot.yaml index 6b1d0000..bfea5f33 100644 --- a/docs/samples/generic_plot.kiplot.yaml +++ b/docs/samples/generic_plot.kiplot.yaml @@ -1,252 +1,829 @@ -# Example KiPlot config file kiplot: version: 1 preflight: - run_drc: true - run_erc: true - update_xml: true - check_zone_fills: true - ignore_unconnected: false - filters: - - filter: 'Ignore C3 pad 2 too close to anything' - number: 4 - regex: 'Pad 2 of C3' - - filter: 'Ignore unconnected pad 2 of C4' - number: 2 - regex: 'Pad 2 of C4' + # [boolean=false] Runs the DRC (Distance Rules Check). To ensure we have a valid PCB + run_drc: true + # [boolean=false] Runs the ERC (Electrical Rules Check). To ensure the schematic is electrically correct + run_erc: true + # [boolean=false] Update the XML version of the BoM (Bill of Materials). To ensure our generated BoM is up to date + update_xml: true + # [boolean=false] Zones are filled before doing any operation involving PCB layers + check_zone_fills: true + # [boolean=false] Option for `run_drc`. Ignores the unconnected nets. Useful if you didn't finish the routing + ignore_unconnected: false + # A list of entries to filter out ERC/DRC messages. Keys: `filter`, `number` and `regex` + filters: + - filter: 'Filter description' + number: 10 + regex: 'Regular expression to match' outputs: - - - name: 'gerbers' - comment: "Gerbers for the board house" - type: gerber - dir: gerberdir + # DXF (Drawing Exchange Format): + # This output is what you get from the File/Plot menu in pcbnew. + - name: 'dxf_example' + comment: 'Exports the PCB to 2D mechanical EDA tools (like AutoCAD).' + type: 'dxf' + dir: 'Example/dxf_dir' options: - # generic layer options - exclude_edge_layer: false + # [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale) + drill_marks: 'full' + # [boolean=true] do not include the PCB edge layer + exclude_edge_layer: true + # [boolean=false] do not plot the component pads in the silk screen exclude_pads_from_silkscreen: false - use_aux_axis_as_origin: false - plot_sheet_reference: false - plot_footprint_refs: true - plot_footprint_values: true + # [boolean=false] include references and values even when they are marked as invisible force_plot_invisible_refs_vals: false - tent_vias: true - - # gerber options - line_width: 0.15 - subtract_mask_from_silk: true - use_protel_extensions: false - gerber_precision: 4.5 - create_gerber_job_file: true - use_gerber_x2_attributes: true - use_gerber_net_attributes: false - - layers: - - layer: F.Cu - suffix: F_Cu - - layer: F.SilkS - suffix: F_SilkS - # - layer: Inner.1 - # suffix: Inner_1 - - - name: excellon_drill - comment: "Excellon drill files" - type: excellon - dir: gerberdir - options: - metric_units: true - pth_and_npth_single_file: true - use_aux_axis_as_origin: false - minimal_header: false - mirror_y_axis: false - report: 'drill_report.rpt' - map: 'pdf' - - - name: gerber drills - comment: "Gerber drill files" - type: gerb_drill - dir: gerberdir - options: - use_aux_axis_as_origin: false - - - name: postscript - comment: "Postscript files" - type: ps - dir: gerberdir - options: - exclude_edge_layer: false - exclude_pads_from_silkscreen: false - plot_sheet_reference: false + # [boolean=true] include the footprint references plot_footprint_refs: true + # [boolean=true] include the footprint values plot_footprint_values: true - force_plot_invisible_refs_vals: false - tent_vias: true - - # PS options - line_width: 0.15 - drill_marks: full - scaling: 2 - sketch_plot: false - scale_adjust_x: 1.0 - scale_adjust_y: 1.0 - width_adjust: 0 - mirror_plot: false - negative_plot: false - a4_output: true - layers: - - layer: F.Cu - suffix: F_Cu - - layer: F.Fab - suffix: F_Fab - # - layer: Inner.1 - # suffix: Inner_1 - # - - name: DXF - comment: "DXF files" - type: dxf - dir: gerberdir - options: - exclude_edge_layer: false - exclude_pads_from_silkscreen: false - use_aux_axis_as_origin: false + # [boolean=false] currently without effect plot_sheet_reference: false - plot_footprint_refs: true - plot_footprint_values: true - force_plot_invisible_refs_vals: false - tent_vias: true - - # DXF options - drill_marks: full - use_aux_axis_as_origin: false + # [boolean=true] plot using the contour, instead of the center line polygon_mode: true - layers: - - layer: F.Cu - suffix: F_Cu - - layer: F.Fab - suffix: F_Fab - - - name: SVG - comment: "SVG files" - type: svg - dir: gerberdir - options: - exclude_edge_layer: false - exclude_pads_from_silkscreen: false - plot_sheet_reference: false - plot_footprint_refs: true - plot_footprint_values: true - force_plot_invisible_refs_vals: false - tent_vias: true - - # SVG options - line_width: 0.25 - drill_marks: full - mirror_plot: true - negative_plot: true - layers: - - layer: F.Cu - suffix: F_Cu - - layer: F.Fab - suffix: F_Fab - - - name: HPGL - comment: "HPGL files" - type: hpgl - dir: gerberdir - options: - exclude_edge_layer: false - exclude_pads_from_silkscreen: false - plot_sheet_reference: false - plot_footprint_refs: true - plot_footprint_values: true - force_plot_invisible_refs_vals: false - tent_vias: true - - # HPGL options - drill_marks: full - mirror_plot: true + # [boolean=false] don't fill objects, just draw the outline sketch_plot: false - scaling: 0 # auto - pen_width: 0.5 - layers: - - layer: F.Cu - suffix: F_Cu - - layer: B.SilkS - suffix: B_Silks - - - name: PDF - comment: "PDF files" - type: pdf - dir: gerberdir - options: - exclude_edge_layer: false - exclude_pads_from_silkscreen: false - plot_sheet_reference: false - plot_footprint_refs: true - plot_footprint_values: true - force_plot_invisible_refs_vals: false + # [boolean=true] cover the vias tent_vias: true - - # PDF options - drill_marks: small - mirror_plot: false - negative_plot: false - line_width: 0.01 + # [boolean=false] use the auxiliar axis as origin for coordinates + use_aux_axis_as_origin: false layers: - - layer: F.Cu - suffix: F_Cu - - layer: B.SilkS - suffix: B_Silks + - layer: 'F.Cu' + suffix: 'F_Cu' + description: 'Front copper' + - layer: 'B.Cu' + suffix: 'B_Cu' + description: 'Bottom copper' + - layer: 'F.Adhes' + suffix: 'F_Adhes' + description: 'Front adhesive (glue)' + - layer: 'B.Adhes' + suffix: 'B_Adhes' + description: 'Bottom adhesive (glue)' + - layer: 'F.Paste' + suffix: 'F_Paste' + description: 'Front solder paste' + - layer: 'B.Paste' + suffix: 'B_Paste' + description: 'Bottom solder paste' + - layer: 'F.SilkS' + suffix: 'F_SilkS' + description: 'Front silkscreen (artwork)' + - layer: 'B.SilkS' + suffix: 'B_SilkS' + description: 'Bottom silkscreen (artwork)' + - layer: 'F.Mask' + suffix: 'F_Mask' + description: 'Front soldermask (negative)' + - layer: 'B.Mask' + suffix: 'B_Mask' + description: 'Bottom soldermask (negative)' + - layer: 'Dwgs.User' + suffix: 'Dwgs_User' + description: 'User drawings' + - layer: 'Cmts.User' + suffix: 'Cmts_User' + description: 'User comments' + - layer: 'Eco1.User' + suffix: 'Eco1_User' + description: 'For user usage 1' + - layer: 'Eco2.User' + suffix: 'Eco2_User' + description: 'For user usage 2' + - layer: 'Edge.Cuts' + suffix: 'Edge_Cuts' + description: 'Board shape' + - layer: 'Margin' + suffix: 'Margin' + description: 'Margin relative to edge cut' + - layer: 'F.CrtYd' + suffix: 'F_CrtYd' + description: 'Front courtyard area' + - layer: 'B.CrtYd' + suffix: 'B_CrtYd' + description: 'Bottom courtyard area' + - layer: 'F.Fab' + suffix: 'F_Fab' + description: 'Front documentation' + - layer: 'B.Fab' + suffix: 'B_Fab' + description: 'Bottom documentation' - - name: 'position' - type: position - dir: positiondir - options: - format: CSV # CSV or ASCII format - units: millimeters # millimeters or inches - separate_files_for_front_and_back: true - only_smd: true - - - name: 'print_sch' - comment: "Print schematic (PDF)" - type: pdf_sch_print - dir: . - options: - output: Schematic.pdf - - - name: 'print_front' - comment: "Print F.Cu+Dwgs.User" - type: pdf_pcb_print - dir: . - options: - output_name: PCB_Top.pdf - layers: - - layer: F.Cu - - layer: Dwgs.User - - - name: Step - comment: "Generate 3D model (STEP)" - type: step - dir: 3D + # Excellon drill format: + # You can create a map file for documentation purposes. + # This output is what you get from the 'File/Fabrication output/Drill Files' menu in pcbnew. + - name: 'excellon_example' + comment: 'This is the main format for the drilling machine.' + type: 'excellon' + dir: 'Example/excellon_dir' options: + # [string=None] format for a graphical drill map. The valid formats are hpgl, ps, gerber, dxf, svg and pdf. + # Not generated unless a format is specified + map: None + # [boolean=true] use metric units instead of inches metric_units: true - origin: grid # "grid" or "drill" o "X,Y" - no_virtual: false # exclude 3D models for components with 'virtual' attribute - #min_distance: 0.01 # Minimum distance between points to treat them as separate ones (default 0.01 mm) + # [boolean=false] use a minimal header in the file + minimal_header: false + # [boolean=false] invert the Y axis + mirror_y_axis: false + # [boolean=true] generate one file for both, plated holes and non-plated holes, instead of two separated files + pth_and_npth_single_file: true + # [string=None] name of the drill report. Not generated unless a name is specified + report: None + # [boolean=false] use the auxiliar axis as origin for coordinates + use_aux_axis_as_origin: false - - name: 'interactive_bom' - comment: "Interactive Bill of Materials (HTML)" - type: ibom - dir: BoM + # Gerber drill format: + # You can create a map file for documentation purposes. + # This output is what you get from the 'File/Fabrication output/Drill Files' menu in pcbnew. + - name: 'gerb_drill_example' + comment: 'This is the information for the drilling machine in gerber format.' + type: 'gerb_drill' + dir: 'Example/gerb_drill_dir' options: - blacklist: 'DNF*' - name_format: '%f_%r_iBoM' + # [string=None] format for a graphical drill map. The valid formats are hpgl, ps, gerber, dxf, svg and pdf. + # Not generated unless a format is specified + map: None + # [string=None] name of the drill report. Not generated unless a name is specified + report: None + # [boolean=false] use the auxiliar axis as origin for coordinates + use_aux_axis_as_origin: false - - name: 'bom_html' - comment: "Bill of Materials in HTML format" - type: kibom - dir: BoM + # Gerber format: + # This output is what you get from the File/Plot menu in pcbnew. + - name: 'gerber_example' + comment: 'This is the main fabrication format for the PCB.' + type: 'gerber' + dir: 'Example/gerber_dir' options: - format: HTML # HTML or CSV + # [boolean=true] creates a file with information about all the generated gerbers. + # You can use it in gerbview to load all gerbers at once + create_gerber_job_file: true + # [boolean=true] do not include the PCB edge layer + exclude_edge_layer: true + # [boolean=false] do not plot the component pads in the silk screen + exclude_pads_from_silkscreen: false + # [boolean=false] include references and values even when they are marked as invisible + force_plot_invisible_refs_vals: false + # [number=4.6] this the gerber coordinate format, can be 4.5 or 4.6 + gerber_precision: 4.6 + # [number=0.1] line_width for objects without width [mm] + line_width: 0.1 + # [boolean=true] include the footprint references + plot_footprint_refs: true + # [boolean=true] include the footprint values + plot_footprint_values: true + # [boolean=false] currently without effect + plot_sheet_reference: false + # [boolean=false] substract the solder mask from the silk screen + subtract_mask_from_silk: false + # [boolean=true] cover the vias + tent_vias: true + # [boolean=false] use the auxiliar axis as origin for coordinates + use_aux_axis_as_origin: false + # [boolean=true] include netlist metadata + use_gerber_net_attributes: true + # [boolean=true] use the extended X2 format + use_gerber_x2_attributes: true + # [boolean=false] use legacy Protel file extensions + use_protel_extensions: false + layers: + - layer: 'F.Cu' + suffix: 'F_Cu' + description: 'Front copper' + - layer: 'B.Cu' + suffix: 'B_Cu' + description: 'Bottom copper' + - layer: 'F.Adhes' + suffix: 'F_Adhes' + description: 'Front adhesive (glue)' + - layer: 'B.Adhes' + suffix: 'B_Adhes' + description: 'Bottom adhesive (glue)' + - layer: 'F.Paste' + suffix: 'F_Paste' + description: 'Front solder paste' + - layer: 'B.Paste' + suffix: 'B_Paste' + description: 'Bottom solder paste' + - layer: 'F.SilkS' + suffix: 'F_SilkS' + description: 'Front silkscreen (artwork)' + - layer: 'B.SilkS' + suffix: 'B_SilkS' + description: 'Bottom silkscreen (artwork)' + - layer: 'F.Mask' + suffix: 'F_Mask' + description: 'Front soldermask (negative)' + - layer: 'B.Mask' + suffix: 'B_Mask' + description: 'Bottom soldermask (negative)' + - layer: 'Dwgs.User' + suffix: 'Dwgs_User' + description: 'User drawings' + - layer: 'Cmts.User' + suffix: 'Cmts_User' + description: 'User comments' + - layer: 'Eco1.User' + suffix: 'Eco1_User' + description: 'For user usage 1' + - layer: 'Eco2.User' + suffix: 'Eco2_User' + description: 'For user usage 2' + - layer: 'Edge.Cuts' + suffix: 'Edge_Cuts' + description: 'Board shape' + - layer: 'Margin' + suffix: 'Margin' + description: 'Margin relative to edge cut' + - layer: 'F.CrtYd' + suffix: 'F_CrtYd' + description: 'Front courtyard area' + - layer: 'B.CrtYd' + suffix: 'B_CrtYd' + description: 'Bottom courtyard area' + - layer: 'F.Fab' + suffix: 'F_Fab' + description: 'Front documentation' + - layer: 'B.Fab' + suffix: 'B_Fab' + description: 'Bottom documentation' + + # HPGL (Hewlett & Packard Graphics Language): + # This output is what you get from the File/Plot menu in pcbnew. + - name: 'hpgl_example' + comment: 'Exports the PCB for plotters and laser printers.' + type: 'hpgl' + dir: 'Example/hpgl_dir' + options: + # [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale) + drill_marks: 'full' + # [boolean=true] do not include the PCB edge layer + exclude_edge_layer: true + # [boolean=false] do not plot the component pads in the silk screen + exclude_pads_from_silkscreen: false + # [boolean=false] include references and values even when they are marked as invisible + force_plot_invisible_refs_vals: false + # [boolean=false] plot mirrored + mirror_plot: false + # [number=0.5] pen diameter in MILS, useful to fill areas. However, it is in mm in HPGL files + pen_width: 0.5 + # [boolean=true] include the footprint references + plot_footprint_refs: true + # [boolean=true] include the footprint values + plot_footprint_values: true + # [boolean=false] currently without effect + plot_sheet_reference: false + # [number=0] scale factor (0 means autoscaling) + scaling: 0 + # [boolean=false] don't fill objects, just draw the outline + sketch_plot: false + # [boolean=true] cover the vias + tent_vias: true + layers: + - layer: 'F.Cu' + suffix: 'F_Cu' + description: 'Front copper' + - layer: 'B.Cu' + suffix: 'B_Cu' + description: 'Bottom copper' + - layer: 'F.Adhes' + suffix: 'F_Adhes' + description: 'Front adhesive (glue)' + - layer: 'B.Adhes' + suffix: 'B_Adhes' + description: 'Bottom adhesive (glue)' + - layer: 'F.Paste' + suffix: 'F_Paste' + description: 'Front solder paste' + - layer: 'B.Paste' + suffix: 'B_Paste' + description: 'Bottom solder paste' + - layer: 'F.SilkS' + suffix: 'F_SilkS' + description: 'Front silkscreen (artwork)' + - layer: 'B.SilkS' + suffix: 'B_SilkS' + description: 'Bottom silkscreen (artwork)' + - layer: 'F.Mask' + suffix: 'F_Mask' + description: 'Front soldermask (negative)' + - layer: 'B.Mask' + suffix: 'B_Mask' + description: 'Bottom soldermask (negative)' + - layer: 'Dwgs.User' + suffix: 'Dwgs_User' + description: 'User drawings' + - layer: 'Cmts.User' + suffix: 'Cmts_User' + description: 'User comments' + - layer: 'Eco1.User' + suffix: 'Eco1_User' + description: 'For user usage 1' + - layer: 'Eco2.User' + suffix: 'Eco2_User' + description: 'For user usage 2' + - layer: 'Edge.Cuts' + suffix: 'Edge_Cuts' + description: 'Board shape' + - layer: 'Margin' + suffix: 'Margin' + description: 'Margin relative to edge cut' + - layer: 'F.CrtYd' + suffix: 'F_CrtYd' + description: 'Front courtyard area' + - layer: 'B.CrtYd' + suffix: 'B_CrtYd' + description: 'Bottom courtyard area' + - layer: 'F.Fab' + suffix: 'F_Fab' + description: 'Front documentation' + - layer: 'B.Fab' + suffix: 'B_Fab' + description: 'Bottom documentation' + + # IBoM (Interactive HTML BoM): + # For more information: https://github.com/INTI-CMNB/InteractiveHtmlBom + # This output is what you get from the InteractiveHtmlBom plug-in (pcbnew). + - name: 'ibom_example' + comment: 'Generates an interactive web page useful to identify the position of the components in the PCB.' + type: 'ibom' + dir: 'Example/ibom_dir' + options: + # [string=''] List of comma separated blacklisted components or prefixes with *. E.g. 'X1,MH*' + blacklist: '' + # [boolean=false] Blacklist components with empty value + blacklist_empty_val: false + # [number=0] Board rotation in degrees (-180 to 180). Will be rounded to multiple of 5 + board_rotation: 0 + # [string='left-right'] Default BOM view {bom-only,left-right,top-bottom} + bom_view: 'left-right' + # [string='Sourced,Placed'] Comma separated list of checkbox columns + checkboxes: 'Sourced,Placed' + # [boolean=false] Default to dark mode + dark_mode: false + # [string=''] Name of the extra field that indicates do not populate status. Components with this field not empty will be + # blacklisted + dnp_field: '' + # [string=''] Comma separated list of extra fields to pull from netlist or xml file + extra_fields: '' + # [boolean=false] Hide footprint pads by default + hide_pads: false + # [boolean=false] Hide silkscreen by default + hide_silkscreen: false + # [boolean=false] Highlight pin1 by default + highlight_pin1: false + # [boolean=false] Include netlist information in output. + include_nets: false + # [boolean=false] Include track/zone information in output. F.Cu and B.Cu layers only + include_tracks: false + # [string='FB'] Default layer view {F,FB,B} + layer_view: 'FB' + # [string='ibom'] Output file name format supports substitutions: + # %f : original pcb file name without extension. + # %p : pcb/project title from pcb metadata. + # %c : company from pcb metadata. + # %r : revision from pcb metadata. + # %d : pcb date from metadata if available, file modification date otherwise. + # %D : bom generation date. + # %T : bom generation time. Extension .html will be added automatically + name_format: 'ibom' + # [string=''] Path to netlist or xml file + netlist_file: '' + # [boolean=false] Do not blacklist virtual components + no_blacklist_virtual: false + # [boolean=false] Do not redraw pcb on drag by default + no_redraw_on_drag: false + # [boolean=false] Normalize extra field name case. E.g. 'MPN' and 'mpn' will be considered the same field + normalize_field_case: false + # [boolean=false] Show fabrication layer by default + show_fabrication: false + # [string='C,R,L,D,U,Y,X,F,SW,A,~,HS,CNN,J,P,NT,MH'] Default sort order for components. Must contain '~' once + sort_order: 'C,R,L,D,U,Y,X,F,SW,A,~,HS,CNN,J,P,NT,MH' + # [string=''] Name of the extra field that stores board variant for component + variant_field: '' + # [string=''] List of board variants to exclude from the BOM + variants_blacklist: '' + # [string=''] List of board variants to include in the BOM + variants_whitelist: '' + + # KiBoM (KiCad Bill of Materials): + # For more information: https://github.com/INTI-CMNB/KiBoM + # This output is what you get from the 'Tools/Generate Bill of Materials' menu in eeschema. + - name: 'kibom_example' + comment: 'Used to generate the BoM in HTML or CSV format using the KiBoM plug-in.' + type: 'kibom' + dir: 'Example/kibom_dir' + options: + # [string='HTML'] can be `HTML` or `CSV` + format: 'HTML' + + # PDF (Portable Document Format): + # Note that this output isn't the best for documating your project. + # This output is what you get from the File/Plot menu in pcbnew. + - name: 'pdf_example' + comment: 'Exports the PCB to the most common exhange format. Suitable for printing.' + type: 'pdf' + dir: 'Example/pdf_dir' + options: + # [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale) + drill_marks: 'full' + # [boolean=true] do not include the PCB edge layer + exclude_edge_layer: true + # [boolean=false] do not plot the component pads in the silk screen + exclude_pads_from_silkscreen: false + # [boolean=false] include references and values even when they are marked as invisible + force_plot_invisible_refs_vals: false + # [number=0.1] for objects without width [mm] + line_width: 0.1 + # [boolean=false] plot mirrored + mirror_plot: false + # [boolean=false] invert black and white + negative_plot: false + # [boolean=true] include the footprint references + plot_footprint_refs: true + # [boolean=true] include the footprint values + plot_footprint_values: true + # [boolean=false] currently without effect + plot_sheet_reference: false + # [boolean=true] cover the vias + tent_vias: true + layers: + - layer: 'F.Cu' + suffix: 'F_Cu' + description: 'Front copper' + - layer: 'B.Cu' + suffix: 'B_Cu' + description: 'Bottom copper' + - layer: 'F.Adhes' + suffix: 'F_Adhes' + description: 'Front adhesive (glue)' + - layer: 'B.Adhes' + suffix: 'B_Adhes' + description: 'Bottom adhesive (glue)' + - layer: 'F.Paste' + suffix: 'F_Paste' + description: 'Front solder paste' + - layer: 'B.Paste' + suffix: 'B_Paste' + description: 'Bottom solder paste' + - layer: 'F.SilkS' + suffix: 'F_SilkS' + description: 'Front silkscreen (artwork)' + - layer: 'B.SilkS' + suffix: 'B_SilkS' + description: 'Bottom silkscreen (artwork)' + - layer: 'F.Mask' + suffix: 'F_Mask' + description: 'Front soldermask (negative)' + - layer: 'B.Mask' + suffix: 'B_Mask' + description: 'Bottom soldermask (negative)' + - layer: 'Dwgs.User' + suffix: 'Dwgs_User' + description: 'User drawings' + - layer: 'Cmts.User' + suffix: 'Cmts_User' + description: 'User comments' + - layer: 'Eco1.User' + suffix: 'Eco1_User' + description: 'For user usage 1' + - layer: 'Eco2.User' + suffix: 'Eco2_User' + description: 'For user usage 2' + - layer: 'Edge.Cuts' + suffix: 'Edge_Cuts' + description: 'Board shape' + - layer: 'Margin' + suffix: 'Margin' + description: 'Margin relative to edge cut' + - layer: 'F.CrtYd' + suffix: 'F_CrtYd' + description: 'Front courtyard area' + - layer: 'B.CrtYd' + suffix: 'B_CrtYd' + description: 'Bottom courtyard area' + - layer: 'F.Fab' + suffix: 'F_Fab' + description: 'Front documentation' + - layer: 'B.Fab' + suffix: 'B_Fab' + description: 'Bottom documentation' + + # PDF PCB Print (Portable Document Format): + # This is the main format to document your PCB. + # This output is what you get from the 'File/Print' menu in pcbnew. + - name: 'pdf_pcb_print_example' + comment: 'Exports the PCB to the most common exhange format. Suitable for printing.' + type: 'pdf_pcb_print' + dir: 'Example/pdf_pcb_print_dir' + options: + # [string=''] filename for the output PDF (the name of the PCB if empty) + output_name: '' + layers: + - layer: 'F.Cu' + suffix: 'F_Cu' + description: 'Front copper' + - layer: 'B.Cu' + suffix: 'B_Cu' + description: 'Bottom copper' + - layer: 'F.Adhes' + suffix: 'F_Adhes' + description: 'Front adhesive (glue)' + - layer: 'B.Adhes' + suffix: 'B_Adhes' + description: 'Bottom adhesive (glue)' + - layer: 'F.Paste' + suffix: 'F_Paste' + description: 'Front solder paste' + - layer: 'B.Paste' + suffix: 'B_Paste' + description: 'Bottom solder paste' + - layer: 'F.SilkS' + suffix: 'F_SilkS' + description: 'Front silkscreen (artwork)' + - layer: 'B.SilkS' + suffix: 'B_SilkS' + description: 'Bottom silkscreen (artwork)' + - layer: 'F.Mask' + suffix: 'F_Mask' + description: 'Front soldermask (negative)' + - layer: 'B.Mask' + suffix: 'B_Mask' + description: 'Bottom soldermask (negative)' + - layer: 'Dwgs.User' + suffix: 'Dwgs_User' + description: 'User drawings' + - layer: 'Cmts.User' + suffix: 'Cmts_User' + description: 'User comments' + - layer: 'Eco1.User' + suffix: 'Eco1_User' + description: 'For user usage 1' + - layer: 'Eco2.User' + suffix: 'Eco2_User' + description: 'For user usage 2' + - layer: 'Edge.Cuts' + suffix: 'Edge_Cuts' + description: 'Board shape' + - layer: 'Margin' + suffix: 'Margin' + description: 'Margin relative to edge cut' + - layer: 'F.CrtYd' + suffix: 'F_CrtYd' + description: 'Front courtyard area' + - layer: 'B.CrtYd' + suffix: 'B_CrtYd' + description: 'Bottom courtyard area' + - layer: 'F.Fab' + suffix: 'F_Fab' + description: 'Front documentation' + - layer: 'B.Fab' + suffix: 'B_Fab' + description: 'Bottom documentation' + + # PDF Schematic Print (Portable Document Format): + # This is the main format to document your schematic. + # This output is what you get from the 'File/Print' menu in eeschema. + - name: 'pdf_sch_print_example' + comment: 'Exports the PCB to the most common exhange format. Suitable for printing.' + type: 'pdf_sch_print' + dir: 'Example/pdf_sch_print_dir' + options: + # [string=''] filename for the output PDF (the name of the schematic if empty) + output: '' + + # Pick & place: + # This output is what you get from the 'File/Fabrication output/Footprint poistion (.pos) file' menu in pcbnew. + - name: 'position_example' + comment: 'Generates the file with position information for the PCB components, used by the pick and place machine.' + type: 'position' + dir: 'Example/position_dir' + options: + # [string='ASCII'] can be ASCII or CSV + format: 'ASCII' + # [boolean=true] only include the surface mount components + only_smd: true + # [boolean=true] generate two separated files, one for the top and another for the bottom + separate_files_for_front_and_back: true + # [string='millimeters'] can be millimeters or inches + units: 'millimeters' + + # PS (Postscript): + # This output is what you get from the File/Plot menu in pcbnew. + - name: 'ps_example' + comment: 'Exports the PCB to a format suitable for printing.' + type: 'ps' + dir: 'Example/ps_dir' + options: + # [boolean=true] force A4 paper size + a4_output: true + # [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale) + drill_marks: 'full' + # [boolean=true] do not include the PCB edge layer + exclude_edge_layer: true + # [boolean=false] do not plot the component pads in the silk screen + exclude_pads_from_silkscreen: false + # [boolean=false] include references and values even when they are marked as invisible + force_plot_invisible_refs_vals: false + # [number=0.15] for objects without width [mm] + line_width: 0.15 + # [boolean=false] plot mirrored + mirror_plot: false + # [boolean=false] invert black and white + negative_plot: false + # [boolean=true] include the footprint references + plot_footprint_refs: true + # [boolean=true] include the footprint values + plot_footprint_values: true + # [boolean=false] currently without effect + plot_sheet_reference: false + # [number=1.0] fine grain adjust for the X scale (floating point multiplier) + scale_adjust_x: 1.0 + # [number=1.0] fine grain adjust for the Y scale (floating point multiplier) + scale_adjust_y: 1.0 + # [number=1] scale factor (0 means autoscaling) + scaling: 1 + # [boolean=false] don't fill objects, just draw the outline + sketch_plot: false + # [boolean=true] cover the vias + tent_vias: true + # [number=0] this width factor is intended to compensate PS printers/plotters that do not strictly obey line width settings. + # Only used to plot pads and tracks + width_adjust: 0 + layers: + - layer: 'F.Cu' + suffix: 'F_Cu' + description: 'Front copper' + - layer: 'B.Cu' + suffix: 'B_Cu' + description: 'Bottom copper' + - layer: 'F.Adhes' + suffix: 'F_Adhes' + description: 'Front adhesive (glue)' + - layer: 'B.Adhes' + suffix: 'B_Adhes' + description: 'Bottom adhesive (glue)' + - layer: 'F.Paste' + suffix: 'F_Paste' + description: 'Front solder paste' + - layer: 'B.Paste' + suffix: 'B_Paste' + description: 'Bottom solder paste' + - layer: 'F.SilkS' + suffix: 'F_SilkS' + description: 'Front silkscreen (artwork)' + - layer: 'B.SilkS' + suffix: 'B_SilkS' + description: 'Bottom silkscreen (artwork)' + - layer: 'F.Mask' + suffix: 'F_Mask' + description: 'Front soldermask (negative)' + - layer: 'B.Mask' + suffix: 'B_Mask' + description: 'Bottom soldermask (negative)' + - layer: 'Dwgs.User' + suffix: 'Dwgs_User' + description: 'User drawings' + - layer: 'Cmts.User' + suffix: 'Cmts_User' + description: 'User comments' + - layer: 'Eco1.User' + suffix: 'Eco1_User' + description: 'For user usage 1' + - layer: 'Eco2.User' + suffix: 'Eco2_User' + description: 'For user usage 2' + - layer: 'Edge.Cuts' + suffix: 'Edge_Cuts' + description: 'Board shape' + - layer: 'Margin' + suffix: 'Margin' + description: 'Margin relative to edge cut' + - layer: 'F.CrtYd' + suffix: 'F_CrtYd' + description: 'Front courtyard area' + - layer: 'B.CrtYd' + suffix: 'B_CrtYd' + description: 'Bottom courtyard area' + - layer: 'F.Fab' + suffix: 'F_Fab' + description: 'Front documentation' + - layer: 'B.Fab' + suffix: 'B_Fab' + description: 'Bottom documentation' + + # STEP (ISO 10303-21 Clear Text Encoding of the Exchange Structure): + # This is the most common 3D format for exchange purposes. + # This output is what you get from the 'File/Export/STEP' menu in pcbnew. + - name: 'step_example' + comment: 'Exports the PCB as a 3D model.' + type: 'step' + dir: 'Example/step_dir' + options: + # [boolean=true] use metric units instead of inches. + metric_units: true + # [number=-1] the minimum distance between points to treat them as separate ones (-1 is KiCad default: 0.01 mm) + min_distance: -1 + # [boolean=false] used to exclude 3D models for components with 'virtual' attribute + no_virtual: false + # [string='grid'] determines the coordinates origin. Using grid the coordinates are the same as you have in the design sheet. + # The drill option uses the auxiliar reference defined by the user. + # You can define any other origin using the format 'X,Y', i.e. '3.2,-10' + origin: 'grid' + # [string=''] name for the generated STEP file (the name of the PCB if empty) + output: '' + + # SVG (Scalable Vector Graphics): + # Unlike bitmaps SVG drawings can be scaled without losing resolution. + # This output is what you get from the File/Plot menu in pcbnew. + - name: 'svg_example' + comment: 'Exports the PCB to a format suitable for 2D graphics software.' + type: 'svg' + dir: 'Example/svg_dir' + options: + # [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale) + drill_marks: 'full' + # [boolean=true] do not include the PCB edge layer + exclude_edge_layer: true + # [boolean=false] do not plot the component pads in the silk screen + exclude_pads_from_silkscreen: false + # [boolean=false] include references and values even when they are marked as invisible + force_plot_invisible_refs_vals: false + # [number=0.25] for objects without width [mm] + line_width: 0.25 + # [boolean=false] plot mirrored + mirror_plot: false + # [boolean=false] invert black and white + negative_plot: false + # [boolean=true] include the footprint references + plot_footprint_refs: true + # [boolean=true] include the footprint values + plot_footprint_values: true + # [boolean=false] currently without effect + plot_sheet_reference: false + # [boolean=true] cover the vias + tent_vias: true + layers: + - layer: 'F.Cu' + suffix: 'F_Cu' + description: 'Front copper' + - layer: 'B.Cu' + suffix: 'B_Cu' + description: 'Bottom copper' + - layer: 'F.Adhes' + suffix: 'F_Adhes' + description: 'Front adhesive (glue)' + - layer: 'B.Adhes' + suffix: 'B_Adhes' + description: 'Bottom adhesive (glue)' + - layer: 'F.Paste' + suffix: 'F_Paste' + description: 'Front solder paste' + - layer: 'B.Paste' + suffix: 'B_Paste' + description: 'Bottom solder paste' + - layer: 'F.SilkS' + suffix: 'F_SilkS' + description: 'Front silkscreen (artwork)' + - layer: 'B.SilkS' + suffix: 'B_SilkS' + description: 'Bottom silkscreen (artwork)' + - layer: 'F.Mask' + suffix: 'F_Mask' + description: 'Front soldermask (negative)' + - layer: 'B.Mask' + suffix: 'B_Mask' + description: 'Bottom soldermask (negative)' + - layer: 'Dwgs.User' + suffix: 'Dwgs_User' + description: 'User drawings' + - layer: 'Cmts.User' + suffix: 'Cmts_User' + description: 'User comments' + - layer: 'Eco1.User' + suffix: 'Eco1_User' + description: 'For user usage 1' + - layer: 'Eco2.User' + suffix: 'Eco2_User' + description: 'For user usage 2' + - layer: 'Edge.Cuts' + suffix: 'Edge_Cuts' + description: 'Board shape' + - layer: 'Margin' + suffix: 'Margin' + description: 'Margin relative to edge cut' + - layer: 'F.CrtYd' + suffix: 'F_CrtYd' + description: 'Front courtyard area' + - layer: 'B.CrtYd' + suffix: 'B_CrtYd' + description: 'Bottom courtyard area' + - layer: 'F.Fab' + suffix: 'F_Fab' + description: 'Front documentation' + - layer: 'B.Fab' + suffix: 'B_Fab' + description: 'Bottom documentation' diff --git a/kiplot/__main__.py b/kiplot/__main__.py index 33e0ac62..9965ab8f 100644 --- a/kiplot/__main__.py +++ b/kiplot/__main__.py @@ -5,6 +5,7 @@ Usage: kiplot [-b BOARD] [-e SCHEMA] [-c CONFIG] [-d OUT_DIR] [-s PRE] [-q | -v...] [-i] [TARGET...] kiplot [-c PLOT_CONFIG] --list + kiplot [-b BOARD] --example kiplot --help-list-outputs kiplot --help-output=HELP_OUTPUT kiplot --help-outputs @@ -30,7 +31,8 @@ Options: -q, --quiet Remove information logs -s PRE, --skip-pre PRE Skip preflights, comma separated or `all` -v, --verbose Show debugging information - --version, -V Show program's version number and exit + -V, --version Show program's version number and exit + -x, --example Create an example configuration file. """ __author__ = 'John Beard, Salvador E. Tropea' @@ -52,7 +54,7 @@ log.set_domain('kiplot') from .gs import (GS) from .kiplot import (generate_outputs) from .pre_base import (BasePreFlight) -from .config_reader import (CfgYamlReader, print_outputs_help, print_output_help, print_preflights_help) +from .config_reader import (CfgYamlReader, print_outputs_help, print_output_help, print_preflights_help, create_example) from .misc import (NO_PCB_FILE, NO_SCH_FILE, EXIT_BAD_ARGS) from .docopt import docopt from .__version__ import __version__ @@ -122,6 +124,12 @@ def solve_config(a_plot_config): return plot_config +def check_board_file(board_file): + if board_file and not os.path.isfile(board_file): + logger.error("Board file not found: "+board_file) + sys.exit(NO_PCB_FILE) + + def solve_board_file(schematic, a_board_file): board_file = a_board_file if not board_file and schematic: @@ -137,9 +145,7 @@ def solve_board_file(schematic, a_board_file): board_file = board_files[0] logger.warning('More than one PCB file found in current directory.\n' ' Using '+board_file+' if you want to use another use -b option.') - if board_file and not os.path.isfile(board_file): - logger.error("Board file not found: "+board_file) - sys.exit(NO_PCB_FILE) + check_board_file(board_file) return board_file @@ -164,6 +170,10 @@ def main(): if args.help_preflights: print_preflights_help() sys.exit(0) + if args.example: + check_board_file(args.board_file) + create_example(args.board_file) + sys.exit(0) # Determine the YAML file plot_config = solve_config(args.plot_config) diff --git a/kiplot/config_reader.py b/kiplot/config_reader.py index 731e74f8..0c77ba46 100644 --- a/kiplot/config_reader.py +++ b/kiplot/config_reader.py @@ -2,12 +2,13 @@ Class to read KiPlot config files """ -import sys +import os +from sys import (exit, maxsize) from collections import OrderedDict from .error import (KiPlotConfigurationError) -from .kiplot import (Layer) -from .misc import (NO_YAML_MODULE, EXIT_BAD_CONFIG, EXIT_BAD_ARGS) +from .kiplot import (Layer, load_board) +from .misc import (NO_YAML_MODULE, EXIT_BAD_CONFIG, EXIT_BAD_ARGS, EXAMPLE_CFG, WONT_OVERWRITE) from mcpy import activate # noqa: F401 # Output classes from .out_base import BaseOutput @@ -43,12 +44,12 @@ try: except ImportError: # pragma: no cover log.init(False, False) logger.error('No yaml module for Python, install python3-yaml') - sys.exit(NO_YAML_MODULE) + exit(NO_YAML_MODULE) def config_error(msg): logger.error(msg) - sys.exit(EXIT_BAD_CONFIG) + exit(EXIT_BAD_CONFIG) class CfgYamlReader(object): @@ -228,14 +229,14 @@ def trim(docstring): # and split into a list of lines: lines = docstring.expandtabs().splitlines() # Determine minimum indentation (first line doesn't count): - indent = sys.maxsize + indent = maxsize for line in lines[1:]: stripped = line.lstrip() if stripped: indent = min(indent, len(line) - len(stripped)) # Remove indentation (first line is special): trimmed = [lines[0].strip()] - if indent < sys.maxsize: + if indent < maxsize: for line in lines[1:]: trimmed.append(line[indent:].rstrip()) # Strip off trailing and leading blank lines: @@ -287,7 +288,7 @@ def print_outputs_help(details=False): def print_output_help(name): if not BaseOutput.is_registered(name): logger.error('Unknown output type `{}`, try --help-list-outputs'.format(name)) - sys.exit(EXIT_BAD_ARGS) + exit(EXIT_BAD_ARGS) print_one_out_help(True, name, BaseOutput.get_class_for(name)) @@ -300,3 +301,63 @@ def print_preflights_help(): if help is None: help = 'Undocumented' print('- {}: {}.'.format(n, help.rstrip())) + + +def create_example(pcb_file): + if os.path.isfile(EXAMPLE_CFG): + logger.error(EXAMPLE_CFG+" already exists, won't overwrite") + exit(WONT_OVERWRITE) + with open(EXAMPLE_CFG, 'w') as f: + logger.info('Creating {} example configuration'.format(EXAMPLE_CFG)) + f.write('kiplot:\n version: 1\n') + # Preflights + f.write('\npreflight:\n') + pres = BasePreFlight.get_registered() + for n, o in pres.items(): + if o.__doc__: + f.write(' #'+o.__doc__.rstrip()+'\n') + f.write(' {}: {}\n'.format(n, o.get_example())) + # Outputs + outs = BaseOutput.get_registered() + f.write('\noutputs:\n') + # List of layers + if pcb_file: + # We have a PCB to take as reference + load_board(pcb_file) + layers = Layer.get_pcb_layers() + else: + # Use the default list of layers + layers = Layer.get_default_layers() + for n, o in OrderedDict(sorted(outs.items())).items(): + lines = trim(o.__doc__) + if len(lines) == 0: + lines = ['Undocumented', 'No description'] + f.write(' # '+lines[0].rstrip()+':\n') + for ln in range(2, len(lines)): + f.write(' # '+lines[ln].rstrip()+'\n') + f.write(" - name: '{}_example'\n".format(n)) + f.write(" comment: '{}'\n".format(lines[1])) + f.write(" type: '{}'\n".format(n)) + f.write(" dir: 'Example/{}_dir'\n".format(n)) + f.write(" options:\n") + obj = o('', n, '') + for k, v in BaseOutput.get_attrs_gen(obj): + help = getattr(obj, '_help_'+k) + if help: + help_lines = help.split('\n') + for hl in help_lines: + f.write(' # '+hl.strip()+'\n') + val = getattr(obj, k) + if isinstance(val, str): + val = "'{}'".format(val) + elif isinstance(val, bool): + val = str(val).lower() + f.write(' {}: {}\n'.format(k, val)) + if '_layers' in obj.__dict__: + f.write(' layers:\n') + for layer in layers: + f.write(" - layer: '{}'\n".format(layer.name)) + f.write(" suffix: '{}'\n".format(layer.suffix)) + if layer.desc: + f.write(" description: '{}'\n".format(layer.desc)) + f.write('\n') diff --git a/kiplot/kiplot.py b/kiplot/kiplot.py index de252760..6e56fca8 100644 --- a/kiplot/kiplot.py +++ b/kiplot/kiplot.py @@ -53,6 +53,29 @@ class Layer(object): 'F.Fab': pcbnew.F_Fab, 'B.Fab': pcbnew.B_Fab, } + # Default names + DEFAULT_LAYER_DESC = { + 'F.Cu': 'Front copper', + 'B.Cu': 'Bottom copper', + 'F.Adhes': 'Front adhesive (glue)', + 'B.Adhes': 'Bottom adhesive (glue)', + 'F.Paste': 'Front solder paste', + 'B.Paste': 'Bottom solder paste', + 'F.SilkS': 'Front silkscreen (artwork)', + 'B.SilkS': 'Bottom silkscreen (artwork)', + 'F.Mask': 'Front soldermask (negative)', + 'B.Mask': 'Bottom soldermask (negative)', + 'Dwgs.User': 'User drawings', + 'Cmts.User': 'User comments', + 'Eco1.User': 'For user usage 1', + 'Eco2.User': 'For user usage 2', + 'Edge.Cuts': 'Board shape', + 'Margin': 'Margin relative to edge cut', + 'F.CrtYd': 'Front courtyard area', + 'B.CrtYd': 'Bottom courtyard area', + 'F.Fab': 'Front documentation', + 'B.Fab': 'Bottom documentation', + } # Names from the board file pcb_layers = {} @@ -61,13 +84,24 @@ class Layer(object): self.is_inner = False self.name = name self.suffix = suffix + if desc is None and name in Layer.DEFAULT_LAYER_DESC: + desc = Layer.DEFAULT_LAYER_DESC[name] self.desc = desc @staticmethod def set_pcb_layers(board): - for id in range(pcbnew.PCBNEW_LAYER_ID_START, pcbnew.PCB_LAYER_ID_COUNT): + for id in board.GetEnabledLayers().Seq(): Layer.pcb_layers[board.GetLayerName(id)] = id + @staticmethod + def get_pcb_layers(): + layers = [] + for n, id in Layer.pcb_layers.items(): + s = n.replace('.', '_') + d = Layer.DEFAULT_LAYER_DESC.get(n) + layers.append(Layer(n, s, d)) + return layers + def get_layer_id_from_name(self, layer_cnt): """ Get the pcbnew layer from the string provided in the config """ # Priority @@ -94,6 +128,14 @@ class Layer(object): raise PlotError("Inner layer `{}` is not valid for this board".format(self)) return self.id + @staticmethod + def get_default_layers(): + layers = [] + for n, d in Layer.DEFAULT_LAYER_DESC.items(): + s = n.replace('.', '_') + layers.append(Layer(n, s, d)) + return layers + def __str__(self): return "{} ({} '{}' {})".format(self.name, self.id, self.desc, self.suffix) @@ -130,10 +172,12 @@ def check_eeschema_do(): exit(NO_SCH_FILE) -def load_board(): - GS.check_pcb() +def load_board(pcb_file=None): + if not pcb_file: + GS.check_pcb() + pcb_file = GS.pcb_file try: - board = pcbnew.LoadBoard(GS.pcb_file) + board = pcbnew.LoadBoard(pcb_file) if BasePreFlight.get_option('check_zone_fills'): pcbnew.ZONE_FILLER(board).Fill(board.Zones()) # Now we know the names of the layers for this board diff --git a/kiplot/misc.py b/kiplot/misc.py index b8e19fd3..ed1c3ef1 100644 --- a/kiplot/misc.py +++ b/kiplot/misc.py @@ -20,6 +20,7 @@ NO_YAML_MODULE = 15 NO_PCBNEW_MODULE = 16 CORRUPTED_PCB = 17 KICAD2STEP_ERR = 18 +WONT_OVERWRITE = 19 CMD_EESCHEMA_DO = 'eeschema_do' URL_EESCHEMA_DO = 'https://github.com/INTI-CMNB/kicad-automation-scripts' @@ -32,3 +33,4 @@ URL_KIBOM = 'https://github.com/INTI-CMNB/KiBoM' CMD_IBOM = 'generate_interactive_bom.py' URL_IBOM = 'https://github.com/INTI-CMNB/InteractiveHtmlBom' KICAD2STEP = 'kicad2step' +EXAMPLE_CFG = 'example.kiplot.yaml' diff --git a/kiplot/out_any_layer.py b/kiplot/out_any_layer.py index 96be0ae7..29b971f5 100644 --- a/kiplot/out_any_layer.py +++ b/kiplot/out_any_layer.py @@ -13,6 +13,8 @@ AUTO_SCALE = 0 class AnyLayer(BaseOutput): def __init__(self, name, type, description): super(AnyLayer, self).__init__(name, type, description) + # We need layers, so we define it + self._layers = None # Options with document: self.exclude_edge_layer = True diff --git a/kiplot/out_pdf_pcb_print.py b/kiplot/out_pdf_pcb_print.py index 97d3ccae..2c409721 100644 --- a/kiplot/out_pdf_pcb_print.py +++ b/kiplot/out_pdf_pcb_print.py @@ -19,6 +19,8 @@ class PDF_Pcb_Print(BaseOutput): # noqa: F821 This output is what you get from the 'File/Print' menu in pcbnew. """ def __init__(self, name, type, description): super(PDF_Pcb_Print, self).__init__(name, type, description) + # We need layers, so we define it + self._layers = None # Options with document: self.output_name = '' diff --git a/kiplot/pre_base.py b/kiplot/pre_base.py index 60173c32..2730ef59 100644 --- a/kiplot/pre_base.py +++ b/kiplot/pre_base.py @@ -84,6 +84,10 @@ class BasePreFlight(object): """ True for preflights that needs the PCB """ return self._pcb_related + def get_example(): + """ Returns a YAML value for the example config """ + return 'true' + def run(self, brd_file): # pragma: no cover logger.error("The run method for the preflight class name `{}` isn't implemented".format(self._name)) diff --git a/kiplot/pre_filters.py b/kiplot/pre_filters.py index 71afbbec..117e4d2f 100644 --- a/kiplot/pre_filters.py +++ b/kiplot/pre_filters.py @@ -9,6 +9,10 @@ class Filters(BasePreFlight): # noqa: F821 def __init__(self, name, value): super().__init__(name, value) + def get_example(): + """ Returns a YAML value for the example config """ + return "\n - filter: 'Filter description'\n number: 10\n regex: 'Regular expression to match'" + def run(self): pass diff --git a/kiplot/pre_ignore_unconnected.py b/kiplot/pre_ignore_unconnected.py index 2e1c6505..9d783565 100644 --- a/kiplot/pre_ignore_unconnected.py +++ b/kiplot/pre_ignore_unconnected.py @@ -11,6 +11,10 @@ class Ignore_Unconnected(BasePreFlight): # noqa: F821 raise KiPlotConfigurationError('must be boolean') self._enabled = value + def get_example(): + """ Returns a YAML value for the example config """ + return 'false' + def run(self, brd_file): pass