diff --git a/CHANGELOG.md b/CHANGELOG.md index bb4928db2..584250078 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - New outputs: - ODB: Exports the PCB in ODB++ format (KiCad 9) (#782) + - IPC2581: Exports the PCB in IPC-2581 (IPC-DPMX) format (KiCad 9) - CLI: - `--variant` to specify which variants will be generated (See #737) - `--defs-from-project` allows using KiCad variables for the preprocessor diff --git a/docs/samples/generic_plot.kibot.yaml b/docs/samples/generic_plot.kibot.yaml index 101bbb5f5..e34c19846 100644 --- a/docs/samples/generic_plot.kibot.yaml +++ b/docs/samples/generic_plot.kibot.yaml @@ -1782,6 +1782,58 @@ outputs: environment: 'names' # [string='%f-%i%I%v.%x'] Filename for the output (%i=info, %x=txt). Affected by global options output: '%f-%i%I%v.%x' + # IPC-DPMX (IPC-2581): + # Only available for KiCad 9 and newer. + # The requested fields are optional + - name: 'ipc2581_example' + comment: 'Exports the PCB in the Digital Product Model Exchange IPC format.' + type: 'ipc2581' + dir: 'Example/ipc2581_dir' + options: + # [boolean=true] Compress the XML file as a *zip* file + compress: true + # [string|list(string)='_null'] Name of the filter to mark components as not fitted. + # Is a short-cut to use for simple cases where a variant is an overkill. + # Can be used to fine-tune a variant for a particular output that needs extra filtering done before the + # variant + dnf_filter: '_null' + # [string|list(string)='_null'] Name of the filter to exclude components from processing. + # Is a short-cut to use for simple cases where a variant is an overkill. + # Can be used to fine-tune a variant for a particular output that needs extra filtering done before the + # variant + exclude_filter: '_null' + # [string='_field_dist_part_number'] Name of the field used for the distributor part number. + # Use the `field_dist_part_number` global variable to define `_field_dist_part_number` + field_dist_part_number: '_field_dist_part_number' + # [string='_field_distributor'] Name of the field used for the distributor. + # Use the `field_distributor` global variable to define `_field_distributor` + field_distributor: '_field_distributor' + # [string=''] Name of the field used as an internal ID. + # Leave empty to create unique IDs + field_internal_id: '' + # [string='_field_manufacturer'] Name of the field used for the manufacturer. + # Use the `field_manufacturer` global variable to define `_field_manufacturer` + field_manufacturer: '_field_manufacturer' + # [string='_field_part_number'] Name of the field used for the manufacturer part number. + # Use the `field_part_number` global variable to define `_field_part_number` + field_part_number: '_field_part_number' + # [string='%f-%i%I%v.%x'] Filename for the output (%i=IPC-2581, %x=zip/xml) + # The extension depends on the compress option. Affected by global options + output: '%f-%i%I%v.%x' + # [string|list(string)='_null'] Name of the filter to transform fields before applying other filters. + # Is a short-cut to use for simple cases where a variant is an overkill. + # Can be used to fine-tune a variant for a particular output that needs extra filtering done before the + # variant + pre_transform: '_null' + # [number=6] Number of decimals used to represent the values + precision: 6 + # [string='millimeters'] [millimeters,inches] Units used for the positions. Affected by global options. + # Note that when using *mils* as global units this option becomes *inches* + units: 'millimeters' + # [string=''] Board variant to apply + variant: '' + # [string='C'] [B,C] Which implementation of the IPC-2581 standard will be generated + version: 'C' # KiBoM (KiCad Bill of Materials): # For more information: https://github.com/INTI-CMNB/KiBoM # Note that this output is provided as a compatibility tool. diff --git a/docs/source/Changelog.rst b/docs/source/Changelog.rst index d927dba1d..da7972ec4 100644 --- a/docs/source/Changelog.rst +++ b/docs/source/Changelog.rst @@ -22,6 +22,7 @@ Added - New outputs: - ODB: Exports the PCB in ODB++ format (KiCad 9) (#782) + - IPC2581: Exports the PCB in IPC-2581 (IPC-DPMX) format (KiCad 9) - CLI: diff --git a/docs/source/configuration/outputs/IPC2581Options.rst b/docs/source/configuration/outputs/IPC2581Options.rst new file mode 100644 index 000000000..7c01ce79d --- /dev/null +++ b/docs/source/configuration/outputs/IPC2581Options.rst @@ -0,0 +1,40 @@ +.. _IPC2581Options: + + +IPC2581Options parameters +~~~~~~~~~~~~~~~~~~~~~~~~~ + +- **output** :index:`: ` [:ref:`string `] (default: ``'%f-%i%I%v.%x'``) Filename for the output (%i=IPC-2581, %x=zip/xml) + The extension depends on the compress option. Affected by global options. +- ``compress`` :index:`: ` [:ref:`boolean `] (default: ``true``) Compress the XML file as a *zip* file. +- ``dnf_filter`` :index:`: ` [:ref:`string ` | :ref:`list(string) `] (default: ``'_null'``) Name of the filter to mark components as not fitted. + Is a short-cut to use for simple cases where a variant is an overkill. |br| + Can be used to fine-tune a variant for a particular output that needs extra filtering done before the + variant. + +- ``exclude_filter`` :index:`: ` [:ref:`string ` | :ref:`list(string) `] (default: ``'_null'``) Name of the filter to exclude components from processing. + Is a short-cut to use for simple cases where a variant is an overkill. |br| + Can be used to fine-tune a variant for a particular output that needs extra filtering done before the + variant. + +- ``field_dist_part_number`` :index:`: ` [:ref:`string `] (default: ``'_field_dist_part_number'``) Name of the field used for the distributor part number. + Use the `field_dist_part_number` global variable to define `_field_dist_part_number`. +- ``field_distributor`` :index:`: ` [:ref:`string `] (default: ``'_field_distributor'``) Name of the field used for the distributor. + Use the `field_distributor` global variable to define `_field_distributor`. +- ``field_internal_id`` :index:`: ` [:ref:`string `] (default: ``''``) Name of the field used as an internal ID. + Leave empty to create unique IDs. +- ``field_manufacturer`` :index:`: ` [:ref:`string `] (default: ``'_field_manufacturer'``) Name of the field used for the manufacturer. + Use the `field_manufacturer` global variable to define `_field_manufacturer`. +- ``field_part_number`` :index:`: ` [:ref:`string `] (default: ``'_field_part_number'``) Name of the field used for the manufacturer part number. + Use the `field_part_number` global variable to define `_field_part_number`. +- ``pre_transform`` :index:`: ` [:ref:`string ` | :ref:`list(string) `] (default: ``'_null'``) Name of the filter to transform fields before applying other filters. + Is a short-cut to use for simple cases where a variant is an overkill. |br| + Can be used to fine-tune a variant for a particular output that needs extra filtering done before the + variant. + +- ``precision`` :index:`: ` [:ref:`number `] (default: ``6``) Number of decimals used to represent the values. +- ``units`` :index:`: ` [:ref:`string `] (default: ``'millimeters'``) (choices: "millimeters", "inches") Units used for the positions. Affected by global options. + Note that when using *mils* as global units this option becomes *inches*. +- ``variant`` :index:`: ` [:ref:`string `] (default: ``''``) Board variant to apply. +- ``version`` :index:`: ` [:ref:`string `] (default: ``'C'``) (choices: "B", "C") Which implementation of the IPC-2581 standard will be generated. + diff --git a/docs/source/configuration/outputs/ipc2581.rst b/docs/source/configuration/outputs/ipc2581.rst new file mode 100644 index 000000000..d375c13c3 --- /dev/null +++ b/docs/source/configuration/outputs/ipc2581.rst @@ -0,0 +1,49 @@ +.. Automatically generated by KiBot, please don't edit this file + +.. index:: + pair: IPC-DPMX (IPC-2581); ipc2581 + +IPC-DPMX (IPC-2581) +~~~~~~~~~~~~~~~~~~~ + +Exports the PCB in the Digital Product Model Exchange IPC format. +Only available for KiCad 9 and newer. |br| +The requested fields are optional + +Type: ``ipc2581`` + +Categories: **PCB/export**, **PCB/fabrication** + +Parameters: + +- **comment** :index:`: ` [:ref:`string `] (default: ``''``) A comment for documentation purposes. It helps to identify the output. +- **dir** :index:`: ` [:ref:`string `] (default: ``'./'``) Output directory for the generated files. + If it starts with `+` the rest is concatenated to the default dir. +- **name** :index:`: ` [:ref:`string `] (default: ``''``) Used to identify this particular output definition. + Avoid using `_` as first character. These names are reserved for KiBot. +- **options** :index:`: ` [:ref:`IPC2581Options parameters `] [:ref:`dict `] (default: empty dict, default values used) Options for the `ipc2581` output. +- **type** :index:`: ` 'ipc2581' +- ``category`` :index:`: ` [:ref:`string ` | :ref:`list(string) `] (default: ``''``) [:ref:`comma separated `] The category for this output. If not specified an internally defined + category is used. |br| + Categories looks like file system paths, i.e. **PCB/fabrication/gerber**. |br| + Using '.' or './' as a category puts the file at the root. |br| + The categories are currently used for `navigate_results` and `navigate_results_rb`. + +- ``disable_run_by_default`` :index:`: ` [:ref:`string ` | :ref:`boolean `] (default: ``''``) Use it to disable the `run_by_default` status of other output. + Useful when this output extends another and you don't want to generate the original. |br| + Use the boolean true value to disable the output you are extending. +- ``extends`` :index:`: ` [:ref:`string `] (default: ``''``) Copy the `options` section from the indicated output. + Used to inherit options from another output of the same type. +- ``groups`` :index:`: ` [:ref:`string ` | :ref:`list(string) `] (default: ``''``) One or more groups to add this output. In order to catch typos + we recommend to add outputs only to existing groups. You can create an empty group if + needed. + +- ``output_id`` :index:`: ` [:ref:`string `] (default: ``''``) Text to use for the %I expansion content. To differentiate variations of this output. +- ``priority`` :index:`: ` [:ref:`number `] (default: ``50``) (range: 0 to 100) Priority for this output. High priority outputs are created first. + Internally we use 10 for low priority, 90 for high priority and 50 for most outputs. +- ``run_by_default`` :index:`: ` [:ref:`boolean `] (default: ``true``) When enabled this output will be created when no specific outputs are requested. + +.. toctree:: + :caption: Used dicts + + IPC2581Options diff --git a/docs/source/configuration/sup_globals.rst b/docs/source/configuration/sup_globals.rst index 2801f3ffe..2bcc0ba64 100644 --- a/docs/source/configuration/sup_globals.rst +++ b/docs/source/configuration/sup_globals.rst @@ -96,9 +96,15 @@ - ``field_current`` :index:`: ` [:ref:`string ` | :ref:`list(string) `] (default: ``['current', 'i']``) Name/s of the field/s used for the current raiting. You can use `_field_current` as field name to use it in most places. + - ``field_dist_part_number`` :index:`: ` [:ref:`string `] (default: ``''``) The name of the schematic field that contains the distributor part number. + You can use `_field_dist_part_number` as field name to use it in most places. + - ``field_distributor`` :index:`: ` [:ref:`string `] (default: ``''``) The name of the schematic field that contains the distributor. + You can use `_field_distributor` as field name to use it in most places. - ``field_lcsc_part`` :index:`: ` [:ref:`string `] (default: ``''``) The name of the schematic field that contains the part number for the LCSC/JLCPCB distributor. When empty KiBot will try to discover it. |br| You can use `_field_lcsc_part` as field name to use it in most places. + - ``field_manufacturer`` :index:`: ` [:ref:`string `] (default: ``''``) The name of the schematic field that contains the manufacturer. + You can use `_field_manufacturer` as field name to use it in most places. - ``field_package`` :index:`: ` [:ref:`string ` | :ref:`list(string) `] (default: ``['package', 'pkg']``) Name/s of the field/s used for the package, not footprint. I.e. 0805, SOT-23, etc. Used for the value split filter. |br| You can use `_field_package` as field name to use it in most places. @@ -212,7 +218,7 @@ - ``time_format`` :index:`: ` [:ref:`string `] (default: ``'%H-%M-%S'``) Format used for the time we started the script. Uses the `strftime` format. - ``time_reformat`` :index:`: ` [:ref:`boolean `] (default: ``true``) Tries to reformat the PCB/SCH date using the `date_format`. This assumes you let KiCad fill this value and hence the time is in ISO format (YY-MM-DD). - - ``units`` :index:`: ` [:ref:`string `] (default: ``''``) (choices: "millimeters", "inches", "mils") Default units. Affects `position`, `bom` and `panelize` outputs and + - ``units`` :index:`: ` [:ref:`string `] (default: ``''``) (choices: "millimeters", "inches", "mils") Default units. Affects `position`, `bom`, `panelize` and 'odb' outputs, and the `erc` and `drc` preflights. Also KiCad 6 dimensions. - ``use_dir_for_preflights`` :index:`: ` [:ref:`boolean `] (default: ``true``) Use the global `dir` as subdir for the preflights. - ``use_os_env_for_expand`` :index:`: ` [:ref:`boolean `] (default: ``true``) In addition to KiCad text variables also use the OS environment variables when expanding `${VARIABLE}`. diff --git a/docs/source/configuration/sup_outputs.rst b/docs/source/configuration/sup_outputs.rst index c1d0603e8..19182cadf 100644 --- a/docs/source/configuration/sup_outputs.rst +++ b/docs/source/configuration/sup_outputs.rst @@ -28,6 +28,7 @@ Notes: outputs/hpgl_sch_print outputs/ibom outputs/info + outputs/ipc2581 outputs/kibom outputs/kicanvas outputs/kicost diff --git a/kibot/globals.py b/kibot/globals.py index 89b26b6a0..769ceef06 100644 --- a/kibot/globals.py +++ b/kibot/globals.py @@ -299,7 +299,7 @@ def __init__(self): """ Tries to reformat the PCB/SCH date using the `date_format`. This assumes you let KiCad fill this value and hence the time is in ISO format (YY-MM-DD) """ self.units = '' - """ [millimeters,inches,mils] Default units. Affects `position`, `bom` and `panelize` outputs and + """ [millimeters,inches,mils] Default units. Affects `position`, `bom`, `panelize` and 'odb' outputs, and the `erc` and `drc` preflights. Also KiCad 6 dimensions """ self.use_dir_for_preflights = True """ Use the global `dir` as subdir for the preflights """ @@ -321,6 +321,15 @@ def __init__(self): self.field_part_number = '' """ The name of the schematic field that contains the manufacturer part number. You can use `_field_part_number` as field name to use it in most places """ + self.field_manufacturer = '' + """ The name of the schematic field that contains the manufacturer. + You can use `_field_manufacturer` as field name to use it in most places """ + self.field_dist_part_number = '' + """ The name of the schematic field that contains the distributor part number. + You can use `_field_dist_part_number` as field name to use it in most places """ + self.field_distributor = '' + """ The name of the schematic field that contains the distributor. + You can use `_field_distributor` as field name to use it in most places """ self.allow_blind_buried_vias = True """ Allow the use of buried vias. This value is only used for KiCad 7+. For KiCad 5 and 6 use the design rules settings, stored in the project """ @@ -528,6 +537,9 @@ def config(self, parent): self.field_temp_coef = Optionable.force_list(self.field_temp_coef) self.field_power = Optionable.force_list(self.field_power) self.field_part_number = Optionable.force_list(self.field_part_number) + self.field_manufacturer = Optionable.force_list(self.field_manufacturer) + self.field_dist_part_number = Optionable.force_list(self.field_dist_part_number) + self.field_distributor = Optionable.force_list(self.field_distributor) # Transfer options to the GS globals for option in filter(lambda x: x[0] != '_', self.__dict__.keys()): gl = 'global_'+option diff --git a/kibot/gs.py b/kibot/gs.py index 8b166fba4..f0aa1fea6 100644 --- a/kibot/gs.py +++ b/kibot/gs.py @@ -170,7 +170,10 @@ class GS(object): global_extra_pth_drill = None global_field_3D_model = None global_field_current = None + global_field_dist_part_number = None + global_field_distributor = None global_field_lcsc_part = None + global_field_manufacturer = None global_field_package = None global_field_part_number = None global_field_power = None diff --git a/kibot/kiplot.py b/kibot/kiplot.py index 5aecb1174..951dae3b2 100644 --- a/kibot/kiplot.py +++ b/kibot/kiplot.py @@ -1,8 +1,8 @@ # -*- coding: utf-8 -*- -# Copyright (c) 2020-2024 Salvador E. Tropea -# Copyright (c) 2020-2024 Instituto Nacional de TecnologĂ­a Industrial +# Copyright (c) 2020-2025 Salvador E. Tropea +# Copyright (c) 2020-2025 Instituto Nacional de TecnologĂ­a Industrial # Copyright (c) 2018 John Beard -# License: GPL-3.0 +# License: AGPL-3.0 # Project: KiBot (formerly KiPlot) # Adapted from: https://github.com/johnbeard/kiplot """ @@ -19,6 +19,7 @@ from glob import glob from importlib.util import spec_from_file_location, module_from_spec +from .bom.columnlist import ColumnList from .gs import GS from .registrable import RegOutput from .misc import (PLOT_ERROR, CORRUPTED_PCB, EXIT_BAD_ARGS, CORRUPTED_SCH, version_str2tuple, @@ -1334,6 +1335,14 @@ def generate_examples(start_dir, dry, types): Popen(['x-www-browser', index]) +def get_columns(): + """ Create a list of valid columns """ + if GS.sch: + cols = deepcopy(ColumnList.COLUMNS_DEFAULT) + return (GS.sch.get_field_names(cols), ColumnList.COLUMNS_EXTRA) + return (ColumnList.COLUMNS_DEFAULT, ColumnList.COLUMNS_EXTRA) + + # To avoid circular dependencies: Optionable needs it, but almost everything needs Optionable GS.load_board = load_board GS.load_sch = load_sch diff --git a/kibot/optionable.py b/kibot/optionable.py index ca32dbad8..3e9b7dce6 100644 --- a/kibot/optionable.py +++ b/kibot/optionable.py @@ -693,18 +693,25 @@ def solve_field_name(field, empty_when_none=False): field = Optionable._solve_field_name(field, empty_when_none) logger.debug('Using {} as LCSC field name'.format(field)) return field + field_or_empty = '' if empty_when_none else field if rest == 'package': - return GS.global_field_package[0] if GS.global_field_package else field + return GS.global_field_package[0] if GS.global_field_package else field_or_empty if rest == 'power': - return GS.global_field_power[0] if GS.global_field_power else field + return GS.global_field_power[0] if GS.global_field_power else field_or_empty if rest == 'temp_coef': - return GS.global_field_temp_coef[0] if GS.global_field_temp_coef else field + return GS.global_field_temp_coef[0] if GS.global_field_temp_coef else field_or_empty if rest == 'tolerance': - return GS.global_field_tolerance[0] if GS.global_field_tolerance else field + return GS.global_field_tolerance[0] if GS.global_field_tolerance else field_or_empty if rest == 'voltage': - return GS.global_field_voltage[0] if GS.global_field_voltage else field + return GS.global_field_voltage[0] if GS.global_field_voltage else field_or_empty if rest == 'part_number': - return GS.global_field_part_number[0] if GS.global_field_part_number else field + return GS.global_field_part_number[0] if GS.global_field_part_number else field_or_empty + if rest == 'manufacturer': + return GS.global_field_manufacturer[0] if GS.global_field_manufacturer else field_or_empty + if rest == 'dist_part_number': + return GS.global_field_dist_part_number[0] if GS.global_field_dist_part_number else field_or_empty + if rest == 'distributor': + return GS.global_field_distributor[0] if GS.global_field_distributor else field_or_empty return field diff --git a/kibot/out_bom.py b/kibot/out_bom.py index 4904f9acc..bc699c21a 100644 --- a/kibot/out_bom.py +++ b/kibot/out_bom.py @@ -21,7 +21,6 @@ downloader: python """ import csv -from copy import deepcopy import os import re from .gs import GS @@ -29,7 +28,8 @@ from .optionable import Optionable, BaseOptions from .registrable import RegOutput from .error import KiPlotConfigurationError -from .kiplot import get_board_comps_data, load_any_sch, register_xmp_import, expand_fields, run_command, load_board +from .kiplot import (get_board_comps_data, load_any_sch, register_xmp_import, expand_fields, run_command, load_board, + get_columns) from .kicad.v5_sch import SchematicComponent, SchematicField from .bom.columnlist import ColumnList, BoMError from .bom.bom import do_bom @@ -634,14 +634,6 @@ def __init__(self): super().__init__() self._no_conflict_example = ['Config', 'Part'] - @staticmethod - def _get_columns(): - """ Create a list of valid columns """ - if GS.sch: - cols = deepcopy(ColumnList.COLUMNS_DEFAULT) - return (GS.sch.get_field_names(cols), ColumnList.COLUMNS_EXTRA) - return (ColumnList.COLUMNS_DEFAULT, ColumnList.COLUMNS_EXTRA) - def _guess_format(self): """ Figure out the format """ if self.format == 'Auto': @@ -806,7 +798,7 @@ def config(self, parent): no_conflict = set(self.no_conflict) self._no_conflict = no_conflict # Columns - (valid_columns, extra_columns) = self._get_columns() + (valid_columns, extra_columns) = get_columns() self.create_default_columns(valid_columns) (self._columns, self._column_levels, self._column_comments, self._column_rename, self._join) = self.process_columns_config(self.columns, valid_columns, extra_columns, self.group_fields) @@ -1131,7 +1123,7 @@ def process_templates(mpn_fields, dists): def get_conf_examples(name, layers): outs = [] # Make a list of available fields - fld_names, extra_names = BoMOptions._get_columns() + fld_names, extra_names = get_columns() fld_names_l = [f.lower() for f in fld_names] fld_set = set(fld_names_l) logger.debug(' - Available fields {}'.format(fld_names_l)) diff --git a/tests/GUI/cfg_out/0003.kibot.yaml b/tests/GUI/cfg_out/0003.kibot.yaml index 885b169dc..d8e7cdb84 100644 --- a/tests/GUI/cfg_out/0003.kibot.yaml +++ b/tests/GUI/cfg_out/0003.kibot.yaml @@ -194,6 +194,11 @@ outputs: comment: Records information about the current run options: output: output.info.options.dict +- name: output.ipc2581 + type: ipc2581 + comment: Exports the PCB in the Digital Product Model Exchange IPC format + options: + output: output.ipc2581.options.dict - name: output.kibom type: kibom comment: Used to generate the BoM in HTML or CSV format using the KiBoM plug-in diff --git a/tests/GUI/outputs b/tests/GUI/outputs index 40393bd2e..b3e7520e6 100644 --- a/tests/GUI/outputs +++ b/tests/GUI/outputs @@ -5071,6 +5071,192 @@ ] ] ], + "ipc2581": [ + [ + "name", + [ + "DataTypeString" + ], + null + ], + [ + "type", + [ + "DataTypeString" + ], + null + ], + [ + "dir", + [ + "DataTypeString" + ], + null + ], + [ + "comment", + [ + "DataTypeString" + ], + null + ], + [ + "extends", + [ + "DataTypeString" + ], + null + ], + [ + "run_by_default", + [ + "DataTypeBoolean" + ], + null + ], + [ + "disable_run_by_default", + [ + "DataTypeString", + "DataTypeBoolean" + ], + null + ], + [ + "output_id", + [ + "DataTypeString" + ], + null + ], + [ + "category", + [ + "DataTypeListStringSingular" + ], + null + ], + [ + "priority", + [ + "DataTypeNumber" + ], + null + ], + [ + "groups", + [ + "DataTypeListStringSingular" + ], + null + ], + [ + "options", + [ + "DataTypeDict" + ], + [ + [ + "output", + [ + "DataTypeString" + ], + null + ], + [ + "compress", + [ + "DataTypeBoolean" + ], + null + ], + [ + "precision", + [ + "DataTypeNumber" + ], + null + ], + [ + "units", + [ + "DataTypeChoice" + ], + null + ], + [ + "version", + [ + "DataTypeChoice" + ], + null + ], + [ + "field_part_number", + [ + "DataTypeString" + ], + null + ], + [ + "field_manufacturer", + [ + "DataTypeString" + ], + null + ], + [ + "field_dist_part_number", + [ + "DataTypeString" + ], + null + ], + [ + "field_distributor", + [ + "DataTypeString" + ], + null + ], + [ + "field_internal_id", + [ + "DataTypeString" + ], + null + ], + [ + "variant", + [ + "DataTypeString" + ], + null + ], + [ + "pre_transform", + [ + "DataTypeListStringSingular" + ], + null + ], + [ + "exclude_filter", + [ + "DataTypeListStringSingular" + ], + null + ], + [ + "dnf_filter", + [ + "DataTypeListStringSingular" + ], + null + ] + ] + ] + ], "kibom": [ [ "name", diff --git a/tests/GUI/stats b/tests/GUI/stats index d5fe8038f..41aa70b3e 100644 --- a/tests/GUI/stats +++ b/tests/GUI/stats @@ -1,13 +1,13 @@ -50 outputs types with a total of 2028 different parameters -Single type parameters: 1845 (91 %) -Multi type parameters: 183 (9 %) -Average parameters: 41 +51 outputs types with a total of 2054 different parameters +Single type parameters: 1870 (91 %) +Multi type parameters: 184 (9 %) +Average parameters: 40 Maximum number of parameters: 217 Minimum number of parameters: 14 Histogram: 0- 9: 10- 19: ***** - 20- 29: ********************* + 20- 29: ********************** 30- 39: ******** 40- 49: ******** 50- 59: ** @@ -45,6 +45,7 @@ Outputs sorted by parameters: - ps_sch_print: 25 - qr_lib: 25 - svg_sch_print: 25 +- ipc2581: 26 - kiri: 26 - navigate_results: 26 - navigate_results_rb: 26 @@ -78,13 +79,13 @@ Outputs sorted by parameters: - pcb_print: 116 - bom: 149 - panelize: 217 -Average depth: 2.56 +Average depth: 2.549019607843137 Maximum depth: 5 Minimum depth: 2 Histogram: 0: 1: -2: ***************************** +2: ****************************** 3: *************** 4: ***** 5: * @@ -97,6 +98,7 @@ Outputs sorted by depth: - hpgl_sch_print: 2 - ibom: 2 - info: 2 +- ipc2581: 2 - kicanvas: 2 - kiri: 2 - navigate_results: 2 @@ -141,12 +143,12 @@ Outputs sorted by depth: - bom: 5 -------------------------------------------------------------------------------- 14 different data types -- String: 884 -- Boolean: 506 -- Number: 284 -- ListStringSingular: 272 -- Choice: 103 -- Dict: 85 +- String: 898 +- Boolean: 509 +- Number: 286 +- ListStringSingular: 277 +- Choice: 105 +- Dict: 86 - ListDictOrString: 24 - ListDict: 20 - Combo: 14 @@ -157,12 +159,12 @@ Outputs sorted by depth: - NumberChoice: 1 -------------------------------------------------------------------------------- Used as single data type: -- String: 723 -- Boolean: 444 -- ListStringSingular: 269 -- Number: 190 -- Choice: 100 -- Dict: 72 +- String: 736 +- Boolean: 446 +- ListStringSingular: 274 +- Number: 192 +- Choice: 102 +- Dict: 73 - ListDict: 20 - ListString: 9 ['blender_export.options.pcb3d.highlight', 'bom.options.group_fields', 'bom.options.group_fields_fallbacks', 'bom.options.no_conflict', 'kibom.options.conf.group_fields', 'pcbdraw.options.libs', 'pcbdraw.options.highlight', 'render_3d.options.highlight', 'vrml.options.highlight'] - ListDictOrString: 7 ['bom.options.columns', 'bom.options.cost_extra_columns', 'bom.options.xlsx.specs_columns', 'excellon.options.table.columns', 'gerb_drill.options.table.columns', 'kibom.options.conf.columns', 'position.options.columns'] @@ -174,7 +176,7 @@ Used as single data type: -------------------------------------------------------------------------------- 11 different data type combinations - Number,String: 92 -- Boolean,String: 56 +- Boolean,String: 57 - Combo,ListDictOrString: 12 - Dict,String: 7 ['blender_export.options.pcb3d', 'excellon.options.report', 'excellon.options.table', 'gerb_drill.options.report', 'gerb_drill.options.table', 'kibom.options.conf', 'pcbdraw.options.style'] - ListDictOrString,String: 5 ['bom.options.columns.join', 'bom.options.cost_extra_columns.join', 'bom.options.xlsx.specs_columns.join', 'panelize.options.configs', 'pcb_print.options.include_table.outputs'] @@ -397,16 +399,16 @@ Used as single data type: - Number,String: 15 ================================================================================ ================================================================================ -89 totals types with a total of 2403 different parameters -Single type parameters: 2196 (91 %) -Multi type parameters: 207 (9 %) +90 totals types with a total of 2429 different parameters +Single type parameters: 2221 (91 %) +Multi type parameters: 208 (9 %) Average parameters: 27 Maximum number of parameters: 217 Minimum number of parameters: 1 Histogram: 0- 9: ************************ 10- 19: ************** - 20- 29: ************************** + 20- 29: *************************** 30- 39: ********* 40- 49: ******** 50- 59: ** @@ -482,6 +484,7 @@ Totals sorted by parameters: - ps_sch_print: 25 - qr_lib: 25 - svg_sch_print: 25 +- ipc2581: 26 - kiri: 26 - navigate_results: 26 - navigate_results_rb: 26 @@ -516,13 +519,13 @@ Totals sorted by parameters: - pcb_print: 116 - bom: 149 - panelize: 217 -Average depth: 2.202247191011236 +Average depth: 2.2 Maximum depth: 5 Minimum depth: 1 Histogram: 0: 1: ***************** -2: ******************************************** +2: ********************************************* 3: ********************** 4: ***** 5: * @@ -552,6 +555,7 @@ Totals sorted by depth: - hpgl_sch_print: 2 - ibom: 2 - info: 2 +- ipc2581: 2 - kicanvas: 2 - kiri: 2 - navigate_results: 2 @@ -618,12 +622,12 @@ Totals sorted by depth: - bom: 5 -------------------------------------------------------------------------------- 14 different data types -- String: 1037 -- Boolean: 606 -- Number: 334 -- ListStringSingular: 301 -- Choice: 135 -- Dict: 96 +- String: 1051 +- Boolean: 609 +- Number: 336 +- ListStringSingular: 306 +- Choice: 137 +- Dict: 97 - ListDict: 30 - ListDictOrString: 27 - Combo: 14 @@ -634,12 +638,12 @@ Totals sorted by depth: - NumberChoice: 1 -------------------------------------------------------------------------------- Used as single data type: -- String: 860 -- Boolean: 536 -- ListStringSingular: 298 -- Number: 225 -- Choice: 132 -- Dict: 75 +- String: 873 +- Boolean: 538 +- ListStringSingular: 303 +- Number: 227 +- Choice: 134 +- Dict: 76 - ListDict: 30 - ListString: 12 - ListDictSingular: 11 @@ -651,7 +655,7 @@ Used as single data type: -------------------------------------------------------------------------------- 11 different data type combinations - Number,String: 107 -- Boolean,String: 56 +- Boolean,String: 57 - Combo,ListDictOrString: 12 - Boolean,Dict: 10 ['pcb_print.options.include_table', 'pcb_print.options.drill', 'include_table.include_table', 'draw_fancy_stackup.draw_fancy_stackup', 'draw_stackup.draw_stackup', 'drc.drc', 'erc.erc', 'run_drc.run_drc', 'run_erc.run_erc', 'update_xml.update_xml'] - Dict,String: 7 ['blender_export.options.pcb3d', 'excellon.options.report', 'excellon.options.table', 'gerb_drill.options.report', 'gerb_drill.options.table', 'kibom.options.conf', 'pcbdraw.options.style'] diff --git a/tests/test_plot/test_misc.py b/tests/test_plot/test_misc.py index d0ef6e114..18d3e43f6 100644 --- a/tests/test_plot/test_misc.py +++ b/tests/test_plot/test_misc.py @@ -2077,6 +2077,7 @@ def test_report_variant_t1(test_dir): ctx.clean_up() +# ODB++ export using kicad-cli on KiCad 9+ @pytest.mark.skipif(not context.ki9(), reason="Needs KiCad 9") def test_odb_zip(test_dir): prj = 'light_control' @@ -2084,3 +2085,13 @@ def test_odb_zip(test_dir): ctx.run() ctx.expect_out_file(prj+'-odb.zip', sub=True) ctx.clean_up(keep_project=True) + + +# IPC-2581 export using kicad-cli on KiCad 9+ +@pytest.mark.skipif(not context.ki9(), reason="Needs KiCad 9") +def test_ipc2581_xml(test_dir): + prj = 'light_control' + ctx = context.TestContext(test_dir, prj, 'ipc2581_xml_mils', 'Export') + ctx.run() + ctx.expect_out_file(prj+'-IPC-2581.xml', sub=True) + ctx.clean_up(keep_project=True) diff --git a/tests/yaml_samples/ipc2581_xml_mils.kibot.yaml b/tests/yaml_samples/ipc2581_xml_mils.kibot.yaml new file mode 100644 index 000000000..40cf50bba --- /dev/null +++ b/tests/yaml_samples/ipc2581_xml_mils.kibot.yaml @@ -0,0 +1,21 @@ +kibot: + version: 1 + +globals: + units: mils + field_part_number: MPN + field_manufacturer: MFR + field_dist_part_number: 'digikey#' + +outputs: + - name: ipc2581_xml_mils + comment: "PCB in IPC-2581 format" + type: ipc2581 + dir: Export + options: + compress: false + + - name: 'navigate' + comment: "Browse the results" + type: navigate_results_rb + run_by_default: false diff --git a/tests/yaml_samples/ipc2581_zip_mm.kibot.yaml b/tests/yaml_samples/ipc2581_zip_mm.kibot.yaml new file mode 100644 index 000000000..c753b04e1 --- /dev/null +++ b/tests/yaml_samples/ipc2581_zip_mm.kibot.yaml @@ -0,0 +1,13 @@ +kibot: + version: 1 + +outputs: + - name: ipc2581_zip_mm + comment: "PCB in IPC-2581 format" + type: ipc2581 + dir: Export + + - name: 'navigate' + comment: "Browse the results" + type: navigate_results_rb + run_by_default: false