diff --git a/CHANGELOG.md b/CHANGELOG.md index a643901e..806fa055 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] ### Added - Support for full KiBoM configuration from the YAML +- Added default output file name pattern. Can be applied to all outputs. - Unified output name: - `pdf_pcb_print.output` can be used instead of `pdf_pcb_print.output_name` - `gerber.gerber_job_file` option to control the gerber job file name. diff --git a/README.md b/README.md index 915e58c1..de9eeffd 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,7 @@ # KiPlot -![Python application](https://github.com/INTI-CMNB/kiplot/workflows/Python%20application/badge.svg) [![Coverage Status](https://coveralls.io/repos/github/INTI-CMNB/kiplot/badge.svg?branch=master)](https://coveralls.io/github/INTI-CMNB/kiplot?branch=master) +![Python application](https://github.com/INTI-CMNB/kiplot/workflows/Python%20application/badge.svg) +[![Coverage Status](https://coveralls.io/repos/github/INTI-CMNB/kiplot/badge.svg?branch=master)](https://coveralls.io/github/INTI-CMNB/kiplot?branch=master) KiPlot is a program which helps you to generate the fabrication and documentation files for your KiCad projects easily, repeatable, and @@ -78,7 +79,7 @@ preflight: ignore_unconnected: false ``` -### Filtering DRC/ERC errors +#### Filtering DRC/ERC errors Sometimes KiCad reports DRC or ERC errors that you can't get rid off. This could be just because you are part of a team including lazzy people that doesn't want to take the extra effort to solve @@ -129,6 +130,38 @@ A complete Python regular expressions explanation is out the scope of this manua **Important note**: this will create a file named *kiplot_errors.filter* in the output directory. + +### Default global options + +The section `global` contains default global options that affects all the outputs. +Currently only one option is supported. + +#### Default `output` option + +This option controls the default file name pattern used by all the outputs. This makes all the file names coherent. +You can always choose the file name for a particular output. + +The pattern uses the following expansions: + +- **%f** original pcb/sch file name without extension. +- **%p** pcb/sch title from pcb metadata. +- **%c** company from pcb/sch metadata. +- **%r** revision from pcb/sch metadata. +- **%d** pcb/sch date from metadata if available, file modification date otherwise. +- **%D** date the script was started. +- **%T** time the script was started. +- **%i** a contextual ID, depends on the output type. +- **%x** a suitable extension for the output type. + +They are compatible with the ones used by IBoM. +The default value for `global.output` is `%f-%i.%x`. +If you want to include the revision you could add the following definition: + +``` +global: + output: '%f_rev_%r-%i.%x' +``` + ### The *outputs* section In this section you put all the things that you want to generate. This section contains one or more **outputs**. Each output contain the following data: @@ -215,7 +248,7 @@ outputs: Most options are the same you'll find in the KiCad dialogs. -### Specifying the layers +#### Specifying the layers You have various ways to specify the layers. If you need to specify just one layer you can just use its name: @@ -290,7 +323,7 @@ Next time you need this list just use an alias, like this: layers: *copper_and_cmts ``` -### Supported outputs: +#### Supported outputs: * DXF (Drawing Exchange Format) * Type: `dxf` @@ -313,7 +346,7 @@ Next time you need this list just use an alias, like this: - `exclude_pads_from_silkscreen`: [boolean=false] do not plot the component pads in the silk screen. - `force_plot_invisible_refs_vals`: [boolean=false] include references and values even when they are marked as invisible. - `metric_units`: [boolean=false] use mm instead of inches. - - `output`: [string=''] output file name, the default KiCad name if empty. + - `output`: [string='%f-%i.%x'] output file name, the default KiCad name if empty. Affected by global options. - `plot_footprint_refs`: [boolean=true] include the footprint references. - `plot_footprint_values`: [boolean=true] include the footprint values. - `plot_sheet_reference`: [boolean=false] currently without effect. @@ -336,12 +369,12 @@ Next time you need this list just use an alias, like this: - `map`: [dict|string] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map. Not generated unless a format is specified. * Valid keys: - - `output`: [string='%f-%i.%x'] name for the map file, KiCad defaults if empty (%i='PTH_drill_map'). + - `output`: [string='%f-%i.%x'] name for the map file, KiCad defaults if empty (%i='PTH_drill_map'). Affected by global options. - `type`: [string='pdf'] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map. - `metric_units`: [boolean=true] use metric units instead of inches. - `minimal_header`: [boolean=false] use a minimal header in the file. - `mirror_y_axis`: [boolean=false] invert the Y axis. - - `output`: [string='%f-%i.%x'] name for the drill file, KiCad defaults if empty (%i='PTH_drill'). + - `output`: [string='%f-%i.%x'] name for the drill file, KiCad defaults if empty (%i='PTH_drill'). Affected by global options. - `pth_and_npth_single_file`: [boolean=true] generate one file for both, plated holes and non-plated holes, instead of two separated files. - `report`: [dict|string] name of the drill report. Not generated unless a name is specified. * Valid keys: @@ -363,9 +396,9 @@ Next time you need this list just use an alias, like this: - `map`: [dict|string] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map. Not generated unless a format is specified. * Valid keys: - - `output`: [string='%f-%i.%x'] name for the map file, KiCad defaults if empty (%i='PTH_drill_map'). + - `output`: [string='%f-%i.%x'] name for the map file, KiCad defaults if empty (%i='PTH_drill_map'). Affected by global options. - `type`: [string='pdf'] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map. - - `output`: [string='%f-%i.%x'] name for the drill file, KiCad defaults if empty (%i='PTH_drill'). + - `output`: [string='%f-%i.%x'] name for the drill file, KiCad defaults if empty (%i='PTH_drill'). Affected by global options. - `report`: [dict|string] name of the drill report. Not generated unless a name is specified. * Valid keys: - `filename`: [string=''] name of the drill report. Not generated unless a name is specified. @@ -396,7 +429,7 @@ Next time you need this list just use an alias, like this: - `gerber_job_file`: [string='%f-%i.%x'] name for the gerber job file (%i='job', %x='gbrjob'). - `gerber_precision`: [number=4.6] this the gerber coordinate format, can be 4.5 or 4.6. - `line_width`: [number=0.1] [0.02,2] line_width for objects without width [mm]. - - `output`: [string=''] output file name, the default KiCad name if empty. + - `output`: [string='%f-%i.%x'] output file name, the default KiCad name if empty. Affected by global options. - `plot_footprint_refs`: [boolean=true] include the footprint references. - `plot_footprint_values`: [boolean=true] include the footprint values. - `plot_sheet_reference`: [boolean=false] currently without effect. @@ -428,7 +461,7 @@ Next time you need this list just use an alias, like this: - `exclude_pads_from_silkscreen`: [boolean=false] do not plot the component pads in the silk screen. - `force_plot_invisible_refs_vals`: [boolean=false] include references and values even when they are marked as invisible. - `mirror_plot`: [boolean=false] plot mirrored. - - `output`: [string=''] output file name, the default KiCad name if empty. + - `output`: [string='%f-%i.%x'] output file name, the default KiCad name if empty. Affected by global options. - `pen_number`: [number=1] [1,16] pen number. - `pen_speed`: [number=20] [1,99] pen speed. - `pen_width`: [number=15] [0,100] pen diameter in MILS, useful to fill areas. However, it is in mm in HPGL files. @@ -479,7 +512,7 @@ Next time you need this list just use an alias, like this: - `no_blacklist_virtual`: [boolean=false] Do not blacklist virtual components. - `no_redraw_on_drag`: [boolean=false] Do not redraw pcb on drag by default. - `normalize_field_case`: [boolean=false] Normalize extra field name case. E.g. 'MPN' and 'mpn' will be considered the same field. - - `output`: [string='%f-%i.%x'] Filename for the output, use '' to use the IBoM filename (%i=ibom, %x=html). + - `output`: [string='%f-%i.%x'] Filename for the output, use '' to use the IBoM filename (%i=ibom, %x=html). Affected by global options. - `show_fabrication`: [boolean=false] Show fabrication layer by default. - `sort_order`: [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. - `variant_field`: [string=''] Name of the extra field that stores board variant for component. @@ -568,7 +601,7 @@ Next time you need this list just use an alias, like this: - `use_alt`: [boolean=false] Print grouped references in the alternate compressed style eg: R1-R7,R18. - `format`: [string='HTML'] [HTML,CSV,XML,XLSX] format for the BoM. - `number`: [number=1] Number of boards to build (components multiplier). - - `output`: [string='%f-%i.%x'] filename for the output (%i=bom). + - `output`: [string='%f-%i.%x'] filename for the output (%i=bom). Affected by global options. - `separator`: [string=','] CSV Separator. - `variant`: [string=''] Board variant(s), used to determine which components are output to the BoM. To specify multiple variants, @@ -593,7 +626,7 @@ Next time you need this list just use an alias, like this: - `libs`: [list(string)] list of libraries. - `mirror`: [boolean=false] mirror the board. - `no_drillholes`: [boolean=false] do not make holes transparent. - - `output`: [string='%f-%i.%x'] name for the generated file. + - `output`: [string='%f-%i.%x'] name for the generated file. Affected by global options. - `placeholder`: [boolean=false] show placeholder for missing components. - `remap`: [dict|None] replacements for PCB references using components (lib:component). - `show_components`: [string|list(string)] [none,all] list of components to draw, can be also a string for none or all. @@ -641,12 +674,12 @@ Next time you need this list just use an alias, like this: - `line_width`: [number=0.1] [0.02,2] for objects without width [mm]. - `mirror_plot`: [boolean=false] plot mirrored. - `negative_plot`: [boolean=false] invert black and white. - - `output`: [string=''] output file name, the default KiCad name if empty. + - `output`: [string='%f-%i.%x'] output file name, the default KiCad name if empty. Affected by global options. - `plot_footprint_refs`: [boolean=true] include the footprint references. - `plot_footprint_values`: [boolean=true] include the footprint values. - `plot_sheet_reference`: [boolean=false] currently without effect. - `tent_vias`: [boolean=true] cover the vias. - - `output`: [string=''] output file name, the default KiCad name if empty. + - `output`: [string='%f-%i.%x'] output file name, the default KiCad name if empty. Affected by global options. - `plot_footprint_refs`: [boolean=true] include the footprint references. - `plot_footprint_values`: [boolean=true] include the footprint values. - `plot_sheet_reference`: [boolean=false] currently without effect. @@ -669,7 +702,7 @@ 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 `pdf_pcb_print` output. * Valid keys: - - `output`: [string='%f-%i.%x'] filename for the output PDF (%i=layers, %x=pdf). + - `output`: [string='%f-%i.%x'] filename for the output PDF (%i=layers, %x=pdf). Affected by global options. - *output_name*: Alias for output. * PDF Schematic Print (Portable Document Format) @@ -683,7 +716,7 @@ 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 `pdf_sch_print` output. * Valid keys: - - `output`: [string='%f-%i.%x'] filename for the output PDF (%i=schematic %x=pdf). + - `output`: [string='%f-%i.%x'] filename for the output PDF (%i=schematic %x=pdf). Affected by global options. * Pick & place * Type: `position` @@ -697,7 +730,7 @@ Next time you need this list just use an alias, like this: * Valid keys: - `format`: [string='ASCII'] [ASCII,CSV] format for the position file. - `only_smd`: [boolean=true] only include the surface mount components. - - `output`: [string='%f-%i.%x'] output file name (%i='top_pos'|'bottom_pos'|'both_pos', %x='pos'|'csv'). + - `output`: [string='%f-%i.%x'] output file name (%i='top_pos'|'bottom_pos'|'both_pos', %x='pos'|'csv'). Affected by global options. - `separate_files_for_front_and_back`: [boolean=true] generate two separated files, one for the top and another for the bottom. - `units`: [string='millimeters'] [millimeters,inches] units used for the positions. @@ -725,7 +758,7 @@ Next time you need this list just use an alias, like this: - `line_width`: [number=0.15] [0.02,2] for objects without width [mm]. - `mirror_plot`: [boolean=false] plot mirrored. - `negative_plot`: [boolean=false] invert black and white. - - `output`: [string=''] output file name, the default KiCad name if empty. + - `output`: [string='%f-%i.%x'] output file name, the default KiCad name if empty. Affected by global options. - `plot_footprint_refs`: [boolean=true] include the footprint references. - `plot_footprint_values`: [boolean=true] include the footprint values. - `plot_sheet_reference`: [boolean=false] currently without effect. @@ -754,7 +787,7 @@ Next time you need this list just use an alias, like this: - `origin`: [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'. - - `output`: [string='%f-%i.%x'] name for the generated STEP file (%i='3D' %x='step'). + - `output`: [string='%f-%i.%x'] name for the generated STEP file (%i='3D' %x='step'). Affected by global options. * SVG (Scalable Vector Graphics) * Type: `svg` @@ -780,7 +813,7 @@ Next time you need this list just use an alias, like this: - `line_width`: [number=0.25] [0.02,2] for objects without width [mm]. - `mirror_plot`: [boolean=false] plot mirrored. - `negative_plot`: [boolean=false] invert black and white. - - `output`: [string=''] output file name, the default KiCad name if empty. + - `output`: [string='%f-%i.%x'] output file name, the default KiCad name if empty. Affected by global options. - `plot_footprint_refs`: [boolean=true] include the footprint references. - `plot_footprint_values`: [boolean=true] include the footprint values. - `plot_sheet_reference`: [boolean=false] currently without effect. diff --git a/docs/README.in b/docs/README.in index 561b485b..f8166e8a 100644 --- a/docs/README.in +++ b/docs/README.in @@ -1,6 +1,7 @@ # KiPlot -![Python application](https://github.com/INTI-CMNB/kiplot/workflows/Python%20application/badge.svg) [![Coverage Status](https://coveralls.io/repos/github/INTI-CMNB/kiplot/badge.svg?branch=master)](https://coveralls.io/github/INTI-CMNB/kiplot?branch=master) +![Python application](https://github.com/INTI-CMNB/kiplot/workflows/Python%20application/badge.svg) +[![Coverage Status](https://coveralls.io/repos/github/INTI-CMNB/kiplot/badge.svg?branch=master)](https://coveralls.io/github/INTI-CMNB/kiplot?branch=master) KiPlot is a program which helps you to generate the fabrication and documentation files for your KiCad projects easily, repeatable, and @@ -63,7 +64,7 @@ preflight: ignore_unconnected: false ``` -### Filtering DRC/ERC errors +#### Filtering DRC/ERC errors Sometimes KiCad reports DRC or ERC errors that you can't get rid off. This could be just because you are part of a team including lazzy people that doesn't want to take the extra effort to solve @@ -114,6 +115,38 @@ A complete Python regular expressions explanation is out the scope of this manua **Important note**: this will create a file named *kiplot_errors.filter* in the output directory. + +### Default global options + +The section `global` contains default global options that affects all the outputs. +Currently only one option is supported. + +#### Default `output` option + +This option controls the default file name pattern used by all the outputs. This makes all the file names coherent. +You can always choose the file name for a particular output. + +The pattern uses the following expansions: + +- **%f** original pcb/sch file name without extension. +- **%p** pcb/sch title from pcb metadata. +- **%c** company from pcb/sch metadata. +- **%r** revision from pcb/sch metadata. +- **%d** pcb/sch date from metadata if available, file modification date otherwise. +- **%D** date the script was started. +- **%T** time the script was started. +- **%i** a contextual ID, depends on the output type. +- **%x** a suitable extension for the output type. + +They are compatible with the ones used by IBoM. +The default value for `global.output` is `%f-%i.%x`. +If you want to include the revision you could add the following definition: + +``` +global: + output: '%f_rev_%r-%i.%x' +``` + ### The *outputs* section In this section you put all the things that you want to generate. This section contains one or more **outputs**. Each output contain the following data: @@ -200,7 +233,7 @@ outputs: Most options are the same you'll find in the KiCad dialogs. -### Specifying the layers +#### Specifying the layers You have various ways to specify the layers. If you need to specify just one layer you can just use its name: @@ -275,7 +308,7 @@ Next time you need this list just use an alias, like this: layers: *copper_and_cmts ``` -### @outputs@ +#### @outputs@ ## Using KiPlot diff --git a/docs/samples/generic_plot.kiplot.yaml b/docs/samples/generic_plot.kiplot.yaml index e1379a81..89c716e2 100644 --- a/docs/samples/generic_plot.kiplot.yaml +++ b/docs/samples/generic_plot.kiplot.yaml @@ -36,8 +36,8 @@ outputs: force_plot_invisible_refs_vals: false # [boolean=false] use mm instead of inches metric_units: false - # [string=''] output file name, the default KiCad name if empty - output: '' + # [string='%f-%i.%x'] output file name, the default KiCad name if empty . Affected by global options + output: '%f-%i.%x' # [boolean=true] include the footprint references plot_footprint_refs: true # [boolean=true] include the footprint values @@ -65,7 +65,7 @@ outputs: # [dict|string] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map. # Not generated unless a format is specified map: - # [string='%f-%i.%x'] name for the map file, KiCad defaults if empty (%i='PTH_drill_map') + # [string='%f-%i.%x'] name for the map file, KiCad defaults if empty (%i='PTH_drill_map') . Affected by global options output: '%f-%i.%x' # [string='pdf'] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map type: 'pdf' @@ -75,7 +75,7 @@ outputs: minimal_header: false # [boolean=false] invert the Y axis mirror_y_axis: false - # [string='%f-%i.%x'] name for the drill file, KiCad defaults if empty (%i='PTH_drill') + # [string='%f-%i.%x'] name for the drill file, KiCad defaults if empty (%i='PTH_drill') . Affected by global options output: '%f-%i.%x' # [boolean=true] generate one file for both, plated holes and non-plated holes, instead of two separated files pth_and_npth_single_file: true @@ -98,11 +98,11 @@ outputs: # [dict|string] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map. # Not generated unless a format is specified map: - # [string='%f-%i.%x'] name for the map file, KiCad defaults if empty (%i='PTH_drill_map') + # [string='%f-%i.%x'] name for the map file, KiCad defaults if empty (%i='PTH_drill_map') . Affected by global options output: '%f-%i.%x' # [string='pdf'] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map type: 'pdf' - # [string='%f-%i.%x'] name for the drill file, KiCad defaults if empty (%i='PTH_drill') + # [string='%f-%i.%x'] name for the drill file, KiCad defaults if empty (%i='PTH_drill') . Affected by global options output: '%f-%i.%x' # [dict|string] name of the drill report. Not generated unless a name is specified report: @@ -134,8 +134,8 @@ outputs: gerber_precision: 4.6 # [number=0.1] [0.02,2] line_width for objects without width [mm] line_width: 0.1 - # [string=''] output file name, the default KiCad name if empty - output: '' + # [string='%f-%i.%x'] output file name, the default KiCad name if empty . Affected by global options + output: '%f-%i.%x' # [boolean=true] include the footprint references plot_footprint_refs: true # [boolean=true] include the footprint values @@ -173,8 +173,8 @@ outputs: force_plot_invisible_refs_vals: false # [boolean=false] plot mirrored mirror_plot: false - # [string=''] output file name, the default KiCad name if empty - output: '' + # [string='%f-%i.%x'] output file name, the default KiCad name if empty . Affected by global options + output: '%f-%i.%x' # [number=1] [1,16] pen number pen_number: 1 # [number=20] [1,99] pen speed @@ -251,7 +251,7 @@ outputs: 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 - # [string='%f-%i.%x'] Filename for the output, use '' to use the IBoM filename (%i=ibom, %x=html) + # [string='%f-%i.%x'] Filename for the output, use '' to use the IBoM filename (%i=ibom, %x=html) . Affected by global options output: '%f-%i.%x' # [boolean=false] Show fabrication layer by default show_fabrication: false @@ -366,7 +366,7 @@ outputs: format: 'HTML' # [number=1] Number of boards to build (components multiplier) number: 1 - # [string='%f-%i.%x'] filename for the output (%i=bom) + # [string='%f-%i.%x'] filename for the output (%i=bom). Affected by global options output: '%f-%i.%x' # [string=','] CSV Separator separator: ',' @@ -398,7 +398,7 @@ outputs: mirror: false # [boolean=false] do not make holes transparent no_drillholes: false - # [string='%f-%i.%x'] name for the generated file + # [string='%f-%i.%x'] name for the generated file . Affected by global options output: '%f-%i.%x' # [boolean=false] show placeholder for missing components placeholder: false @@ -456,8 +456,8 @@ outputs: mirror_plot: false # [boolean=false] invert black and white negative_plot: false - # [string=''] output file name, the default KiCad name if empty - output: '' + # [string='%f-%i.%x'] output file name, the default KiCad name if empty . Affected by global options + output: '%f-%i.%x' # [boolean=true] include the footprint references plot_footprint_refs: true # [boolean=true] include the footprint values @@ -476,7 +476,7 @@ outputs: type: 'pdf_pcb_print' dir: 'Example/pdf_pcb_print_dir' options: - # [string='%f-%i.%x'] filename for the output PDF (%i=layers, %x=pdf) + # [string='%f-%i.%x'] filename for the output PDF (%i=layers, %x=pdf). Affected by global options output: '%f-%i.%x' # `output_name` is an alias for `output` layers: all @@ -489,7 +489,7 @@ outputs: type: 'pdf_sch_print' dir: 'Example/pdf_sch_print_dir' options: - # [string='%f-%i.%x'] filename for the output PDF (%i=schematic %x=pdf) + # [string='%f-%i.%x'] filename for the output PDF (%i=schematic %x=pdf) . Affected by global options output: '%f-%i.%x' # Pick & place: @@ -503,7 +503,7 @@ outputs: format: 'ASCII' # [boolean=true] only include the surface mount components only_smd: true - # [string='%f-%i.%x'] output file name (%i='top_pos'|'bottom_pos'|'both_pos', %x='pos'|'csv') + # [string='%f-%i.%x'] output file name (%i='top_pos'|'bottom_pos'|'both_pos', %x='pos'|'csv') . Affected by global options output: '%f-%i.%x' # [boolean=true] generate two separated files, one for the top and another for the bottom separate_files_for_front_and_back: true @@ -533,8 +533,8 @@ outputs: mirror_plot: false # [boolean=false] invert black and white negative_plot: false - # [string=''] output file name, the default KiCad name if empty - output: '' + # [string='%f-%i.%x'] output file name, the default KiCad name if empty . Affected by global options + output: '%f-%i.%x' # [boolean=true] include the footprint references plot_footprint_refs: true # [boolean=true] include the footprint values @@ -574,7 +574,7 @@ outputs: # 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='%f-%i.%x'] name for the generated STEP file (%i='3D' %x='step') + # [string='%f-%i.%x'] name for the generated STEP file (%i='3D' %x='step') . Affected by global options output: '%f-%i.%x' # SVG (Scalable Vector Graphics): @@ -599,8 +599,8 @@ outputs: mirror_plot: false # [boolean=false] invert black and white negative_plot: false - # [string=''] output file name, the default KiCad name if empty - output: '' + # [string='%f-%i.%x'] output file name, the default KiCad name if empty . Affected by global options + output: '%f-%i.%x' # [boolean=true] include the footprint references plot_footprint_refs: true # [boolean=true] include the footprint values diff --git a/kiplot/config_reader.py b/kiplot/config_reader.py index 14c3afd7..55ae28b8 100644 --- a/kiplot/config_reader.py +++ b/kiplot/config_reader.py @@ -9,7 +9,7 @@ from collections import OrderedDict from .error import (KiPlotConfigurationError, config_error) from .kiplot import (load_board) from .misc import (NO_YAML_MODULE, EXIT_BAD_ARGS, EXAMPLE_CFG, WONT_OVERWRITE) - +from .gs import GS from .reg_out import RegOutput from .pre_base import BasePreFlight @@ -82,6 +82,20 @@ class CfgYamlReader(object): config_error("In preflight '"+k+"': "+str(e)) BasePreFlight.add_preflight(o_pre) + def _parse_global(self, gb): + """ Get global options """ + logger.debug("Parsing global options: {}".format(gb)) + if not isinstance(gb, dict): + config_error("Incorrect `global` section") + + for k, v in gb.items(): + if k == 'output': + if not isinstance(v, str): + config_error("Global `output` must be a string") + GS.global_output = v + else: + logger.warning("Unknown global option `{}`".format(k)) + def read(self, fstream): """ Read a file object into a config object @@ -102,6 +116,8 @@ class CfgYamlReader(object): version = self._check_version(v) elif k == 'preflight': self._parse_preflight(v) + elif k == 'global': + self._parse_global(v) elif k == 'outputs': if isinstance(v, list): for o in v: diff --git a/kiplot/gs.py b/kiplot/gs.py index 05585c13..145eb3e4 100644 --- a/kiplot/gs.py +++ b/kiplot/gs.py @@ -41,6 +41,9 @@ class GS(object): pcb_date = None pcb_rev = None pcb_comp = None + # Global defaults + global_output = None + def_global_output = '%f-%i.%x' @staticmethod def set_sch(name): diff --git a/kiplot/macros.py b/kiplot/macros.py index 5bd0e23d..18738c7f 100644 --- a/kiplot/macros.py +++ b/kiplot/macros.py @@ -1,3 +1,4 @@ +from .gs import GS # noqa: F401 from ast import (Assign, Name, Attribute, Expr, Num, Str, NameConstant, Load, Store, UnaryOp, USub, ClassDef, Call, ImportFrom, alias) @@ -40,6 +41,7 @@ def document(sentences, to_source, **kw): doc_id = '_help_'+name # Create the type hint for numbers, strings and booleans type_hint = '' + post_hint = '' if isinstance(value, Num): type_hint = '[number={}]'.format(value.n) elif isinstance(value, UnaryOp) and isinstance(value.operand, Num) and isinstance(value.op, USub): @@ -49,12 +51,24 @@ def document(sentences, to_source, **kw): type_hint = "[string='{}']".format(value.s) elif isinstance(value, NameConstant) and isinstance(value.value, bool): type_hint = '[boolean={}]'.format(str(value.value).lower()) + elif isinstance(value, Attribute): + # Used for the default options. I.e. GS.def_global_option + val = eval(to_source(value)) + if isinstance(val, bool): + # Not used yet + type_hint = '[boolean={}]'.format(str(val).lower()) # pragma: no cover + elif isinstance(val, (int, float)): + # Not used yet + type_hint = '[number={}]'.format(val) # pragma: no cover + elif isinstance(val, str): + type_hint = "[string='{}']".format(val) + post_hint += '. Affected by global options' # Transform the string into an assign for _help_ID if is_attr: target = Attribute(value=Name(id='self', ctx=Load()), attr=doc_id, ctx=Store()) else: # pragma: no cover target = Name(id=doc_id, ctx=Store()) - sentences[n] = Assign(targets=[target], value=Str(s=type_hint+s.value.s)) + sentences[n] = Assign(targets=[target], value=Str(s=type_hint+s.value.s.rstrip()+post_hint)) prev = s # Return the modified AST return sentences diff --git a/kiplot/optionable.py b/kiplot/optionable.py index 360ccf8f..9c1d201a 100644 --- a/kiplot/optionable.py +++ b/kiplot/optionable.py @@ -20,8 +20,10 @@ class Optionable(object): _num_range_re = compile(r"\[number=.*\] \[(-?\d+),(-?\d+)\]") def __init__(self): - super().__init__() self._unkown_is_error = False + super().__init__() + if GS.global_output is not None and getattr(self, 'output', None): + setattr(self, 'output', GS.global_output) @staticmethod def _check_str(key, val, doc): diff --git a/kiplot/out_any_drill.py b/kiplot/out_any_drill.py index 6d3905c0..5e7431bf 100644 --- a/kiplot/out_any_drill.py +++ b/kiplot/out_any_drill.py @@ -2,6 +2,7 @@ import os from pcbnew import (PLOT_FORMAT_HPGL, PLOT_FORMAT_POST, PLOT_FORMAT_GERBER, PLOT_FORMAT_DXF, PLOT_FORMAT_SVG, PLOT_FORMAT_PDF, wxPoint) from .optionable import (Optionable, BaseOptions) +from .gs import GS from kiplot.macros import macros, document # noqa: F401 from . import log @@ -9,15 +10,13 @@ logger = log.get_logger(__name__) class DrillMap(Optionable): - _out_def = '%f-%i.%x' - def __init__(self): - super().__init__() with document: - self.output = '%f-%i.%x' # self._out_def not supported by the macro + self.output = GS.def_global_output """ name for the map file, KiCad defaults if empty (%i='PTH_drill_map') """ self.type = 'pdf' """ [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map """ # pragma: no cover + super().__init__() self._unkown_is_error = True @@ -33,7 +32,6 @@ class DrillReport(Optionable): class AnyDrill(BaseOptions): def __init__(self): - super().__init__() # Options with document: self.use_aux_axis_as_origin = False @@ -41,10 +39,11 @@ class AnyDrill(BaseOptions): self.map = DrillMap """ [dict|string] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map. Not generated unless a format is specified """ - self.output = '%f-%i.%x' + self.output = GS.def_global_output """ name for the drill file, KiCad defaults if empty (%i='PTH_drill') """ self.report = DrillReport """ [dict|string] name of the drill report. Not generated unless a name is specified """ # pragma: no cover + super().__init__() # Mappings to KiCad values self._map_map = { 'hpgl': PLOT_FORMAT_HPGL, @@ -61,7 +60,7 @@ class AnyDrill(BaseOptions): # Solve the map for both cases if isinstance(self.map, str): self.map_ext = self._map_ext[self.map] - self.map_output = DrillMap._out_def + self.map_output = GS.global_output if GS.global_output is not None else GS.def_global_output self.map = self._map_map[self.map] elif isinstance(self.map, DrillMap): self.map_ext = self._map_ext[self.map.type] diff --git a/kiplot/out_any_layer.py b/kiplot/out_any_layer.py index b00a6ef9..b050c680 100644 --- a/kiplot/out_any_layer.py +++ b/kiplot/out_any_layer.py @@ -4,6 +4,7 @@ from .out_base import (BaseOutput) from .error import (PlotError, KiPlotConfigurationError) from .optionable import BaseOptions from .layer import Layer +from .gs import GS from kiplot.macros import macros, document # noqa: F401 from . import log @@ -13,7 +14,6 @@ logger = log.get_logger(__name__) class AnyLayerOptions(BaseOptions): """ Base class for: DXF, Gerber, HPGL, PDF, PS and SVG """ def __init__(self): - super().__init__() with document: self.exclude_edge_layer = True """ do not include the PCB edge layer """ @@ -27,10 +27,11 @@ class AnyLayerOptions(BaseOptions): """ include the footprint values """ self.force_plot_invisible_refs_vals = False """ include references and values even when they are marked as invisible """ - self.output = '' + self.output = GS.def_global_output """ output file name, the default KiCad name if empty """ self.tent_vias = True """ cover the vias """ # pragma: no cover + super().__init__() def _configure_plot_ctrl(self, po, output_dir): logger.debug("Configuring plot controller for output") diff --git a/kiplot/out_ibom.py b/kiplot/out_ibom.py index 85c8c929..93c1ebde 100644 --- a/kiplot/out_ibom.py +++ b/kiplot/out_ibom.py @@ -12,9 +12,8 @@ logger = log.get_logger(__name__) class IBoMOptions(BaseOptions): def __init__(self): - super().__init__() with document: - self.output = '%f-%i.%x' + self.output = GS.def_global_output """ Filename for the output, use '' to use the IBoM filename (%i=ibom, %x=html) """ self.dark_mode = False """ Default to dark mode """ @@ -74,6 +73,7 @@ class IBoMOptions(BaseOptions): self.dnp_field = '' """ Name of the extra field that indicates do not populate status. Components with this field not empty will be blacklisted """ # pragma: no cover + super().__init__() def run(self, output_dir, board): check_script(CMD_IBOM, URL_IBOM) diff --git a/kiplot/out_kibom.py b/kiplot/out_kibom.py index ae5908ba..47becf39 100644 --- a/kiplot/out_kibom.py +++ b/kiplot/out_kibom.py @@ -289,7 +289,6 @@ class KiBoMConfig(Optionable): class KiBoMOptions(BaseOptions): def __init__(self): - super().__init__() with document: self.number = 1 """ Number of boards to build (components multiplier) """ @@ -303,10 +302,11 @@ class KiBoMOptions(BaseOptions): You can also define the configuration here, will be stored in `config.kibom.ini` """ self.separator = ',' """ CSV Separator """ - self.output = '%f-%i.%x' + self.output = GS.def_global_output """ filename for the output (%i=bom)""" self.format = 'HTML' """ [HTML,CSV,XML,XLSX] format for the BoM """ # pragma: no cover + super().__init__() def config(self): super().config() diff --git a/kiplot/out_pcbdraw.py b/kiplot/out_pcbdraw.py index 943fb8db..ecf0978c 100644 --- a/kiplot/out_pcbdraw.py +++ b/kiplot/out_pcbdraw.py @@ -73,7 +73,6 @@ class PcbDrawRemap(Optionable): class PcbDrawOptions(BaseOptions): def __init__(self): - super().__init__() with document: self.style = PcbDrawStyle """ [string|dict] PCB style (colors). An internal name, the name of a JSON file or the style options """ @@ -102,8 +101,9 @@ class PcbDrawOptions(BaseOptions): """ [10,1200] dots per inch (resolution) of the generated image """ self.format = 'svg' """ [svg,png,jpg] output format. Only used if no `output` is specified """ - self.output = '%f-%i.%x' + self.output = GS.def_global_output """ name for the generated file """ # pragma: no cover + super().__init__() def config(self): super().config() diff --git a/kiplot/out_pdf_pcb_print.py b/kiplot/out_pdf_pcb_print.py index 5c1274e4..b8a6e819 100644 --- a/kiplot/out_pdf_pcb_print.py +++ b/kiplot/out_pdf_pcb_print.py @@ -14,12 +14,12 @@ logger = log.get_logger(__name__) class PDF_Pcb_PrintOptions(BaseOptions): def __init__(self): - super().__init__() with document: - self.output = '%f-%i.%x' + self.output = GS.def_global_output """ filename for the output PDF (%i=layers, %x=pdf)""" self.output_name = None """ {output} """ # pragma: no cover + super().__init__() def run(self, output_dir, board, layers): check_script(CMD_PCBNEW_PRINT_LAYERS, URL_PCBNEW_PRINT_LAYERS, '1.4.1') diff --git a/kiplot/out_pdf_sch_print.py b/kiplot/out_pdf_sch_print.py index 4a7bc555..933b8c86 100644 --- a/kiplot/out_pdf_sch_print.py +++ b/kiplot/out_pdf_sch_print.py @@ -12,10 +12,10 @@ logger = log.get_logger(__name__) class PDF_Sch_PrintOptions(BaseOptions): def __init__(self): - super().__init__() with document: - self.output = '%f-%i.%x' + self.output = GS.def_global_output """ filename for the output PDF (%i=schematic %x=pdf) """ # pragma: no cover + super().__init__() def run(self, output_dir, board): check_eeschema_do() diff --git a/kiplot/out_position.py b/kiplot/out_position.py index e46d5aca..b7854300 100644 --- a/kiplot/out_position.py +++ b/kiplot/out_position.py @@ -2,12 +2,12 @@ import operator from datetime import datetime from pcbnew import (IU_PER_MM, IU_PER_MILS) from .optionable import BaseOptions +from .gs import GS from kiplot.macros import macros, document, output_class # noqa: F401 class PositionOptions(BaseOptions): def __init__(self): - super().__init__() with document: self.format = 'ASCII' """ [ASCII,CSV] format for the position file """ @@ -15,10 +15,11 @@ class PositionOptions(BaseOptions): """ generate two separated files, one for the top and another for the bottom """ self.only_smd = True """ only include the surface mount components """ - self.output = '%f-%i.%x' + self.output = GS.def_global_output """ output file name (%i='top_pos'|'bottom_pos'|'both_pos', %x='pos'|'csv') """ self.units = 'millimeters' """ [millimeters,inches] units used for the positions """ # pragma: no cover + super().__init__() def _do_position_plot_ascii(self, board, output_dir, columns, modulesStr, maxSizes): topf = None diff --git a/kiplot/out_step.py b/kiplot/out_step.py index 038f07d0..993ac8e3 100644 --- a/kiplot/out_step.py +++ b/kiplot/out_step.py @@ -12,7 +12,6 @@ logger = log.get_logger(__name__) class STEPOptions(BaseOptions): def __init__(self): - super().__init__() with document: self.metric_units = True """ use metric units instead of inches """ @@ -24,8 +23,9 @@ class STEPOptions(BaseOptions): """ used to exclude 3D models for components with 'virtual' attribute """ self.min_distance = -1 """ the minimum distance between points to treat them as separate ones (-1 is KiCad default: 0.01 mm) """ - self.output = '%f-%i.%x' + self.output = GS.def_global_output """ name for the generated STEP file (%i='3D' %x='step') """ # pragma: no cover + super().__init__() @property def origin(self): diff --git a/tests/test_plot/test_position.py b/tests/test_plot/test_position.py index cdf4e447..5cccf279 100644 --- a/tests/test_plot/test_position.py +++ b/tests/test_plot/test_position.py @@ -130,7 +130,7 @@ def test_3Rs_position_unified_csv(): def test_3Rs_position_unified_th_csv(): ctx = context.TestContext('3Rs_position_unified_th_csv', '3Rs', 'simple_position_unified_th_csv', POS_DIR) ctx.run() - expect_position(ctx, ctx.get_pos_both_csv_filename(), ['R1', 'R2', 'R3'], csv=True) + expect_position(ctx, os.path.join(POS_DIR, 'Test_3Rs-both_pos_OK.csv'), ['R1', 'R2', 'R3'], csv=True) ctx.clean_up() diff --git a/tests/test_plot/test_yaml_errors.py b/tests/test_plot/test_yaml_errors.py index 8943e27a..70c221bd 100644 --- a/tests/test_plot/test_yaml_errors.py +++ b/tests/test_plot/test_yaml_errors.py @@ -462,3 +462,25 @@ def test_error_color(): ctx.run(EXIT_BAD_CONFIG) assert ctx.search_err("Invalid color for .?board.?") ctx.clean_up() + + +def test_wrong_global(): + ctx = context.TestContext('WrongGlobal', 'bom', 'error_wrong_global', '') + ctx.run(EXIT_BAD_CONFIG) + assert ctx.search_err("Incorrect .?global.? section") + ctx.clean_up() + + +def test_goutput_not_string(): + ctx = context.TestContext('GOutNotString', 'bom', 'error_goutput_not_string', '') + ctx.run(EXIT_BAD_CONFIG) + assert ctx.search_err("Global .?output.? must be a string") + ctx.clean_up() + + +def test_unk_global(): + ctx = context.TestContext('UnkGlobal', 'bom', 'error_unk_global', '') + ctx.run() + assert ctx.search_err("Unknown global option") + ctx.search_err("WARNING:Unknown global option") + ctx.clean_up() diff --git a/tests/yaml_samples/dxf.kiplot.yaml b/tests/yaml_samples/dxf.kiplot.yaml index b4828c46..d25d431a 100644 --- a/tests/yaml_samples/dxf.kiplot.yaml +++ b/tests/yaml_samples/dxf.kiplot.yaml @@ -15,6 +15,7 @@ outputs: plot_footprint_values: true force_plot_invisible_refs_vals: false tent_vias: true + output: '' # Use KiCad default # DXF options drill_marks: full diff --git a/tests/yaml_samples/error_goutput_not_string.kiplot.yaml b/tests/yaml_samples/error_goutput_not_string.kiplot.yaml new file mode 100644 index 00000000..860fe290 --- /dev/null +++ b/tests/yaml_samples/error_goutput_not_string.kiplot.yaml @@ -0,0 +1,7 @@ +kiplot: + version: 1 + +global: + # Should be a string + output: 1 + diff --git a/tests/yaml_samples/error_unk_global.kiplot.yaml b/tests/yaml_samples/error_unk_global.kiplot.yaml new file mode 100644 index 00000000..4d7e0ebd --- /dev/null +++ b/tests/yaml_samples/error_unk_global.kiplot.yaml @@ -0,0 +1,7 @@ +kiplot: + version: 1 + +global: + # Not valid global + outputs: 1 + diff --git a/tests/yaml_samples/error_wrong_global.kiplot.yaml b/tests/yaml_samples/error_wrong_global.kiplot.yaml new file mode 100644 index 00000000..324c786b --- /dev/null +++ b/tests/yaml_samples/error_wrong_global.kiplot.yaml @@ -0,0 +1,9 @@ +kiplot: + version: 1 + +# A list, should be a dict +global: + - 1 + - 2 + - 3 + diff --git a/tests/yaml_samples/simple_position_unified_th_csv.kiplot.yaml b/tests/yaml_samples/simple_position_unified_th_csv.kiplot.yaml index 6ef66b93..4a0571b9 100644 --- a/tests/yaml_samples/simple_position_unified_th_csv.kiplot.yaml +++ b/tests/yaml_samples/simple_position_unified_th_csv.kiplot.yaml @@ -2,8 +2,10 @@ kiplot: version: 1 -outputs: +global: + output: 'Test_%f-%i_OK.%x' +outputs: - name: 'position' comment: "Pick and place file" type: position