From 7e5791fcfa7f671e3680975f5be81e791b3a7f00 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Sat, 5 Sep 2020 17:48:25 -0300 Subject: [PATCH 1/6] Added variants to the IBoM output. --- CHANGELOG.md | 1 + kibot/out_ibom.py | 69 +- tests/board_samples/kibom-variante.kicad_pcb | 908 +++++++++++++++++++ tests/test_plot/test_ibom.py | 49 +- tests/utils/lzstring.py | 433 +++++++++ tests/yaml_samples/ibom_variant_1.kibot.yaml | 74 ++ 6 files changed, 1519 insertions(+), 15 deletions(-) create mode 100644 tests/board_samples/kibom-variante.kicad_pcb create mode 100644 tests/utils/lzstring.py create mode 100644 tests/yaml_samples/ibom_variant_1.kibot.yaml diff --git a/CHANGELOG.md b/CHANGELOG.md index 05c48325..59bd4f7f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Components crossed in *.Fab - STEP (3D) support for variants. - PcbDraw support for variants. +- IBoM support for variants. ### Fixed - Virtual components are always excluded from position files. diff --git a/kibot/out_ibom.py b/kibot/out_ibom.py index 08f74764..e4794376 100644 --- a/kibot/out_ibom.py +++ b/kibot/out_ibom.py @@ -2,8 +2,10 @@ import os from subprocess import (check_output, STDOUT, CalledProcessError) from .misc import (CMD_IBOM, URL_IBOM, BOM_ERROR) from .gs import (GS) -from .kiplot import (check_script) -from .optionable import BaseOptions +from .optionable import BaseOptions, Optionable +from .registrable import RegOutput +from .kiplot import check_script, load_sch +from .fil_base import BaseFilter, apply_fitted_filter from .macros import macros, document, output_class # noqa: F401 from . import log @@ -52,29 +54,63 @@ class IBoMOptions(BaseOptions): """ Include netlist information in output. """ self.sort_order = 'C,R,L,D,U,Y,X,F,SW,A,~,HS,CNN,J,P,NT,MH' """ Default sort order for components. Must contain '~' once """ - self.blacklist = '' - """ List of comma separated blacklisted components or prefixes with *. E.g. 'X1,MH*' """ - self.no_blacklist_virtual = False - """ Do not blacklist virtual components """ - self.blacklist_empty_val = False - """ Blacklist components with empty value """ self.netlist_file = '' """ Path to netlist or xml file """ self.extra_fields = '' """ Comma separated list of extra fields to pull from netlist or xml file """ self.normalize_field_case = False """ Normalize extra field name case. E.g. 'MPN' and 'mpn' will be considered the same field """ + self.blacklist = '' + """ List of comma separated blacklisted components or prefixes with *. E.g. 'X1,MH*'. + IBoM option, avoid using in conjunction with KiBot variants/filters """ + self.no_blacklist_virtual = False + """ Do not blacklist virtual components. + IBoM option, avoid using in conjunction with KiBot variants/filters """ + self.blacklist_empty_val = False + """ Blacklist components with empty value. + IBoM option, avoid using in conjunction with KiBot variants/filters """ self.variant_field = '' - """ Name of the extra field that stores board variant for component """ + """ Name of the extra field that stores board variant for component. + IBoM option, avoid using in conjunction with KiBot variants/filters """ self.variants_whitelist = '' - """ List of board variants to include in the BOM """ + """ List of board variants to include in the BOM. + IBoM option, avoid using in conjunction with KiBot variants/filters """ self.variants_blacklist = '' - """ List of board variants to exclude from the BOM """ + """ List of board variants to exclude from the BOM. + IBoM option, avoid using in conjunction with KiBot variants/filters """ self.dnp_field = '' - """ Name of the extra field that indicates do not populate status. Components with this field not empty will be - blacklisted """ + """ Name of the extra field that indicates do not populate status. + Components with this field not empty will be blacklisted. + IBoM option, avoid using in conjunction with KiBot variants/filters """ + self.variant = '' + """ Board variant to apply. + Avoid using it in conjunction with with IBoM native filtering options """ + self.dnf_filter = Optionable + """ [string|list(string)=''] Name of the filter to mark components as not fitted. + A short-cut to use for simple cases where a variant is an overkill. + Avoid using it in conjunction with with IBoM native filtering options """ super().__init__() + def config(self): + super().config() + self.variant = RegOutput.check_variant(self.variant) + self.dnf_filter = BaseFilter.solve_filter(self.dnf_filter, 'dnf_filter') + + # TODO: move to a base class? + def get_filtered_refs(self): + if not self.dnf_filter and not self.variant: + return [] + load_sch() + # Get the components list from the schematic + comps = GS.sch.get_components() + # Apply the filter + apply_fitted_filter(comps, self.dnf_filter) + # Apply the variant + if self.variant: + # Apply the variant + self.variant.filter(comps) + return [c.ref for c in comps if not c.fitted] + def run(self, output_dir, board): check_script(CMD_IBOM, URL_IBOM) logger.debug('Doing Interactive BoM') @@ -87,9 +123,14 @@ class IBoMOptions(BaseOptions): output = self.expand_filename(output_dir, self.output, 'ibom', 'html') self.name_format = 'ibom' cur = os.path.join(output_dir, 'ibom.html') + # Apply variants/filters + to_remove = ','.join(self.get_filtered_refs()) + if self.blacklist and to_remove: + self.blacklist += ',' + self.blacklist += to_remove # Convert attributes into options for k, v in self.get_attrs_gen(): - if not v or k == 'output': + if not v or k in ['output', 'variant', 'dnf_filter']: continue cmd.append(BaseOutput.attr2longopt(k)) # noqa: F821 if not isinstance(v, bool): # must be str/(int, float) diff --git a/tests/board_samples/kibom-variante.kicad_pcb b/tests/board_samples/kibom-variante.kicad_pcb new file mode 100644 index 00000000..3e3455c1 --- /dev/null +++ b/tests/board_samples/kibom-variante.kicad_pcb @@ -0,0 +1,908 @@ +(kicad_pcb (version 20171130) (host pcbnew 5.1.6+dfsg1-1) + + (general + (thickness 1.6) + (drawings 4) + (tracks 0) + (zones 0) + (modules 20) + (nets 41) + ) + + (page A4) + (layers + (0 F.Cu signal) + (31 B.Cu signal) + (32 B.Adhes user) + (33 F.Adhes user) + (34 B.Paste user) + (35 F.Paste user) + (36 B.SilkS user) + (37 F.SilkS user) + (38 B.Mask user) + (39 F.Mask user) + (40 Dwgs.User user) + (41 Cmts.User user) + (42 Eco1.User user) + (43 Eco2.User user) + (44 Edge.Cuts user) + (45 Margin user) + (46 B.CrtYd user) + (47 F.CrtYd user) + (48 B.Fab user) + (49 F.Fab user) + ) + + (setup + (last_trace_width 0.25) + (trace_clearance 0.2) + (zone_clearance 0.508) + (zone_45_only no) + (trace_min 0.2) + (via_size 0.8) + (via_drill 0.4) + (via_min_size 0.4) + (via_min_drill 0.3) + (uvia_size 0.3) + (uvia_drill 0.1) + (uvias_allowed no) + (uvia_min_size 0.2) + (uvia_min_drill 0.1) + (edge_width 0.1) + (segment_width 0.2) + (pcb_text_width 0.3) + (pcb_text_size 1.5 1.5) + (mod_edge_width 0.15) + (mod_text_size 1 1) + (mod_text_width 0.15) + (pad_size 1.524 1.524) + (pad_drill 0.762) + (pad_to_mask_clearance 0) + (aux_axis_origin 0 0) + (visible_elements FFFFFF7F) + (pcbplotparams + (layerselection 0x010fc_ffffffff) + (usegerberextensions false) + (usegerberattributes true) + (usegerberadvancedattributes true) + (creategerberjobfile true) + (excludeedgelayer true) + (linewidth 0.100000) + (plotframeref false) + (viasonmask false) + (mode 1) + (useauxorigin false) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15.000000) + (psnegative false) + (psa4output false) + (plotreference true) + (plotvalue true) + (plotinvisibletext false) + (padsonsilk false) + (subtractmaskfromsilk false) + (outputformat 1) + (mirror false) + (drillshape 1) + (scaleselection 1) + (outputdirectory "")) + ) + + (net 0 "") + (net 1 "Net-(R1-Pad2)") + (net 2 "Net-(R1-Pad1)") + (net 3 "Net-(R2-Pad2)") + (net 4 "Net-(R2-Pad1)") + (net 5 "Net-(R3-Pad2)") + (net 6 "Net-(R3-Pad1)") + (net 7 "Net-(R4-Pad2)") + (net 8 "Net-(R4-Pad1)") + (net 9 "Net-(R5-Pad2)") + (net 10 "Net-(R5-Pad1)") + (net 11 "Net-(R6-Pad2)") + (net 12 "Net-(R6-Pad1)") + (net 13 "Net-(R7-Pad2)") + (net 14 "Net-(R7-Pad1)") + (net 15 "Net-(R8-Pad2)") + (net 16 "Net-(R8-Pad1)") + (net 17 "Net-(R9-Pad2)") + (net 18 "Net-(R9-Pad1)") + (net 19 "Net-(R10-Pad2)") + (net 20 "Net-(R10-Pad1)") + (net 21 "Net-(R11-Pad2)") + (net 22 "Net-(R11-Pad1)") + (net 23 "Net-(R12-Pad2)") + (net 24 "Net-(R12-Pad1)") + (net 25 "Net-(R13-Pad2)") + (net 26 "Net-(R13-Pad1)") + (net 27 "Net-(R14-Pad2)") + (net 28 "Net-(R14-Pad1)") + (net 29 "Net-(R15-Pad2)") + (net 30 "Net-(R15-Pad1)") + (net 31 "Net-(R16-Pad2)") + (net 32 "Net-(R16-Pad1)") + (net 33 "Net-(R17-Pad2)") + (net 34 "Net-(R17-Pad1)") + (net 35 "Net-(R18-Pad2)") + (net 36 "Net-(R18-Pad1)") + (net 37 "Net-(R19-Pad2)") + (net 38 "Net-(R19-Pad1)") + (net 39 "Net-(R20-Pad2)") + (net 40 "Net-(R20-Pad1)") + + (net_class Default "Esta es la clase de red por defecto." + (clearance 0.2) + (trace_width 0.25) + (via_dia 0.8) + (via_drill 0.4) + (uvia_dia 0.3) + (uvia_drill 0.1) + (add_net "Net-(R1-Pad1)") + (add_net "Net-(R1-Pad2)") + (add_net "Net-(R10-Pad1)") + (add_net "Net-(R10-Pad2)") + (add_net "Net-(R11-Pad1)") + (add_net "Net-(R11-Pad2)") + (add_net "Net-(R12-Pad1)") + (add_net "Net-(R12-Pad2)") + (add_net "Net-(R13-Pad1)") + (add_net "Net-(R13-Pad2)") + (add_net "Net-(R14-Pad1)") + (add_net "Net-(R14-Pad2)") + (add_net "Net-(R15-Pad1)") + (add_net "Net-(R15-Pad2)") + (add_net "Net-(R16-Pad1)") + (add_net "Net-(R16-Pad2)") + (add_net "Net-(R17-Pad1)") + (add_net "Net-(R17-Pad2)") + (add_net "Net-(R18-Pad1)") + (add_net "Net-(R18-Pad2)") + (add_net "Net-(R19-Pad1)") + (add_net "Net-(R19-Pad2)") + (add_net "Net-(R2-Pad1)") + (add_net "Net-(R2-Pad2)") + (add_net "Net-(R20-Pad1)") + (add_net "Net-(R20-Pad2)") + (add_net "Net-(R3-Pad1)") + (add_net "Net-(R3-Pad2)") + (add_net "Net-(R4-Pad1)") + (add_net "Net-(R4-Pad2)") + (add_net "Net-(R5-Pad1)") + (add_net "Net-(R5-Pad2)") + (add_net "Net-(R6-Pad1)") + (add_net "Net-(R6-Pad2)") + (add_net "Net-(R7-Pad1)") + (add_net "Net-(R7-Pad2)") + (add_net "Net-(R8-Pad1)") + (add_net "Net-(R8-Pad2)") + (add_net "Net-(R9-Pad1)") + (add_net "Net-(R9-Pad2)") + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B2F1) + (at 144.64 97.877) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0FCACA) + (attr smd) + (fp_text reference R20 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 39 "Net-(R20-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 40 "Net-(R20-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B2E0) + (at 144.64 94.927) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0FCABF) + (attr smd) + (fp_text reference R19 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 37 "Net-(R19-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 38 "Net-(R19-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B2CF) + (at 140.23 97.877) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0FCAB4) + (attr smd) + (fp_text reference R18 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 35 "Net-(R18-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 36 "Net-(R18-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B2BE) + (at 144.64 91.977) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0FCAA9) + (attr smd) + (fp_text reference R17 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 33 "Net-(R17-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 34 "Net-(R17-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B2AD) + (at 140.23 94.927) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0FA2A1) + (attr smd) + (fp_text reference R16 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 31 "Net-(R16-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 32 "Net-(R16-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B29C) + (at 135.82 97.877) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0FA296) + (attr smd) + (fp_text reference R15 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 29 "Net-(R15-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 30 "Net-(R15-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B28B) + (at 144.64 89.027) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0FA28B) + (attr smd) + (fp_text reference R14 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 27 "Net-(R14-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 28 "Net-(R14-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B27A) + (at 140.23 91.977) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0FA280) + (attr smd) + (fp_text reference R13 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 25 "Net-(R13-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 26 "Net-(R13-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B269) + (at 135.82 94.927) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0F8002) + (attr smd) + (fp_text reference R12 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 23 "Net-(R12-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 24 "Net-(R12-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B258) + (at 131.41 97.877) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0F7FF7) + (attr smd) + (fp_text reference R11 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 21 "Net-(R11-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 22 "Net-(R11-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B247) + (at 140.23 89.027) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0F7FEC) + (attr smd) + (fp_text reference R10 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 19 "Net-(R10-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 20 "Net-(R10-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B236) + (at 135.82 91.977) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0F7FE1) + (attr smd) + (fp_text reference R9 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 17 "Net-(R9-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 18 "Net-(R9-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B225) + (at 131.41 94.927) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0F7361) + (attr smd) + (fp_text reference R8 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 15 "Net-(R8-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 16 "Net-(R8-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B214) + (at 127 97.877) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0F7356) + (attr smd) + (fp_text reference R7 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 13 "Net-(R7-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 14 "Net-(R7-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B203) + (at 135.82 89.027) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0F734B) + (attr smd) + (fp_text reference R6 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 11 "Net-(R6-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 12 "Net-(R6-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B1F2) + (at 131.41 91.977) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5F0F7340) + (attr smd) + (fp_text reference R5 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 9 "Net-(R5-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 10 "Net-(R5-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B1E1) + (at 127 94.927) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5E6A37B2) + (attr smd) + (fp_text reference R4 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 7 "Net-(R4-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 8 "Net-(R4-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B1D0) + (at 131.41 89.027) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5E6A35E1) + (attr smd) + (fp_text reference R3 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 5 "Net-(R3-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 6 "Net-(R3-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B1BF) + (at 127 91.977) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5E6A330D) + (attr smd) + (fp_text reference R2 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 3 "Net-(R2-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 4 "Net-(R2-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F53B1AE) + (at 127 89.027) + (descr "Resistor SMD 0805 (2012 Metric), square (rectangular) end terminal, IPC_7351 nominal, (Body size source: https://docs.google.com/spreadsheets/d/1BsfQQcO9C6DZCsRaXUlFlo91Tg2WpOkGARC1WS5S8t0/edit?usp=sharing), generated with kicad-footprint-generator") + (tags resistor) + (path /5E6A2873) + (attr smd) + (fp_text reference R1 (at 0 -1.65) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10K (at 0 1.65) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 0.5 0.5) (thickness 0.08))) + ) + (fp_line (start -1 0.6) (end -1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start 1 0.6) (end -1 0.6) (layer F.Fab) (width 0.1)) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer F.CrtYd) (width 0.05)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer F.CrtYd) (width 0.05)) + (pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 1 "Net-(R1-Pad2)")) + (pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25) + (net 2 "Net-(R1-Pad1)")) + (model ${KISYS3DMOD}/Resistor_SMD.3dshapes/R_0805_2012Metric.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (gr_line (start 124.46 85.09) (end 124.46 101.6) (layer Edge.Cuts) (width 0.1) (tstamp 5F53B433)) + (gr_line (start 147.193 85.09) (end 124.46 85.09) (layer Edge.Cuts) (width 0.1)) + (gr_line (start 147.32 101.6) (end 147.193 85.09) (layer Edge.Cuts) (width 0.1)) + (gr_line (start 124.46 101.6) (end 147.32 101.6) (layer Edge.Cuts) (width 0.1)) + +) diff --git a/tests/test_plot/test_ibom.py b/tests/test_plot/test_ibom.py index e544000a..b3b42853 100644 --- a/tests/test_plot/test_ibom.py +++ b/tests/test_plot/test_ibom.py @@ -12,12 +12,16 @@ pytest-3 --log-cli-level debug import os import sys +import re +import json +import logging # Look for the 'utils' module from where the script is running prev_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) if prev_dir not in sys.path: sys.path.insert(0, prev_dir) # Utils import from utils import context +from utils.lzstring import LZString prev_dir = os.path.dirname(prev_dir) if prev_dir not in sys.path: sys.path.insert(0, prev_dir) @@ -27,6 +31,24 @@ BOM_DIR = 'BoM' IBOM_OUT = 'bom-ibom.html' +def check_modules(ctx, fname, expected): + with open(ctx.get_out_path(os.path.join(BOM_DIR, fname)), 'rt') as f: + text = f.read() + m = re.search(r'var pcbdata = JSON.parse\(LZString.decompressFromBase64\("(.*)"\)\)', text, re.MULTILINE) + assert m, text + lz = LZString() + js = lz.decompressFromBase64(m.group(1)) + data = json.loads(js) + skipped = data['bom']['skipped'] + modules = [m['ref'] for m in data['modules']] + assert len(modules)-len(skipped) == len(expected) + logging.debug("{} components OK".format(len(expected))) + for m in expected: + assert m in modules + assert modules.index(m) not in skipped + logging.debug("List of components OK") + + def test_ibom(): prj = 'bom' ctx = context.TestContext('BoM_interactive', prj, 'ibom', BOM_DIR) @@ -43,7 +65,9 @@ def test_ibom_no_ops(): prj = 'bom' ctx = context.TestContext('BoM_interactiveNoOps', prj, 'ibom_no_ops', BOM_DIR) ctx.run() - ctx.expect_out_file(os.path.join(BOM_DIR, IBOM_OUT)) + fname = os.path.join(BOM_DIR, IBOM_OUT) + ctx.expect_out_file(fname) + check_modules(ctx, IBOM_OUT, ['C1', 'R1', 'R2']) ctx.clean_up() @@ -72,3 +96,26 @@ def test_ibom_all_ops(): r'"layer_view": "B"', r'"extra_fields": \["EF"\]']) ctx.clean_up() + + +def test_ibom_variant_1(): + prj = 'kibom-variante' + ctx = context.TestContext('test_ibom_variant_1', prj, 'ibom_variant_1', BOM_DIR) + ctx.run(extra_debug=True) + # No variant + logging.debug("* No variant") + check_modules(ctx, prj+'-ibom.html', ['R1', 'R2', 'R3']) + # V1 + logging.debug("* t1_v1 variant") + check_modules(ctx, prj+'-ibom_(V1).html', ['R1', 'R2']) + # V2 + logging.debug("* t1_v2 variant") + check_modules(ctx, prj+'-ibom_(V2).html', ['R1', 'R3']) + # V3 + logging.debug("* t1_v3 variant") + check_modules(ctx, prj+'-ibom_V3.html', ['R1', 'R4']) + # V1,V3 + logging.debug("* `bla bla` variant") + check_modules(ctx, prj+'-ibom_bla_bla.html', ['R1', 'R4']) + ctx.clean_up() + diff --git a/tests/utils/lzstring.py b/tests/utils/lzstring.py new file mode 100644 index 00000000..b70f0534 --- /dev/null +++ b/tests/utils/lzstring.py @@ -0,0 +1,433 @@ +""" +Copyright © 2017 Marcel Dancak +This work is free. You can redistribute it and/or modify it under the +terms of the Do What The Fuck You Want To Public License, Version 2, +as published by Sam Hocevar. See the COPYING file for more details. +""" + +import math + + +keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" +keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$" +baseReverseDic = {}; + +class Object(object): + def __init__(self, **kwargs): + for k, v in kwargs.items(): + setattr(self, k, v) + + +def getBaseValue(alphabet, character): + if alphabet not in baseReverseDic: + baseReverseDic[alphabet] = {} + for i in range(len(alphabet)): + baseReverseDic[alphabet][alphabet[i]] = i + return baseReverseDic[alphabet][character] + + +def _compress(uncompressed, bitsPerChar, getCharFromInt): + if (uncompressed is None): + return "" + + context_dictionary = {} + context_dictionaryToCreate= {} + context_c = "" + context_wc = "" + context_w = "" + context_enlargeIn = 2 # Compensate for the first entry which should not count + context_dictSize = 3 + context_numBits = 2 + context_data = [] + context_data_val = 0 + context_data_position = 0 + + for ii in range(len(uncompressed)): + context_c = uncompressed[ii] + if context_c not in context_dictionary: + context_dictionary[context_c] = context_dictSize + context_dictSize += 1 + context_dictionaryToCreate[context_c] = True + + context_wc = context_w + context_c + if context_wc in context_dictionary: + context_w = context_wc + else: + if context_w in context_dictionaryToCreate: + if ord(context_w[0]) < 256: + for i in range(context_numBits): + context_data_val = (context_data_val << 1) + if context_data_position == bitsPerChar-1: + context_data_position = 0 + context_data.append(getCharFromInt(context_data_val)) + context_data_val = 0 + else: + context_data_position += 1 + value = ord(context_w[0]) + for i in range(8): + context_data_val = (context_data_val << 1) | (value & 1) + if context_data_position == bitsPerChar - 1: + context_data_position = 0 + context_data.append(getCharFromInt(context_data_val)) + context_data_val = 0 + else: + context_data_position += 1 + value = value >> 1 + + else: + value = 1 + for i in range(context_numBits): + context_data_val = (context_data_val << 1) | value + if context_data_position == bitsPerChar - 1: + context_data_position = 0 + context_data.append(getCharFromInt(context_data_val)) + context_data_val = 0 + else: + context_data_position += 1 + value = 0 + value = ord(context_w[0]) + for i in range(16): + context_data_val = (context_data_val << 1) | (value & 1) + if context_data_position == bitsPerChar - 1: + context_data_position = 0 + context_data.append(getCharFromInt(context_data_val)) + context_data_val = 0 + else: + context_data_position += 1 + value = value >> 1 + context_enlargeIn -= 1 + if context_enlargeIn == 0: + context_enlargeIn = math.pow(2, context_numBits) + context_numBits += 1 + del context_dictionaryToCreate[context_w] + else: + value = context_dictionary[context_w] + for i in range(context_numBits): + context_data_val = (context_data_val << 1) | (value & 1) + if context_data_position == bitsPerChar - 1: + context_data_position = 0 + context_data.append(getCharFromInt(context_data_val)) + context_data_val = 0 + else: + context_data_position += 1 + value = value >> 1 + + context_enlargeIn -= 1 + if context_enlargeIn == 0: + context_enlargeIn = math.pow(2, context_numBits) + context_numBits += 1 + + # Add wc to the dictionary. + context_dictionary[context_wc] = context_dictSize + context_dictSize += 1 + context_w = str(context_c) + + # Output the code for w. + if context_w != "": + if context_w in context_dictionaryToCreate: + if ord(context_w[0]) < 256: + for i in range(context_numBits): + context_data_val = (context_data_val << 1) + if context_data_position == bitsPerChar-1: + context_data_position = 0 + context_data.append(getCharFromInt(context_data_val)) + context_data_val = 0 + else: + context_data_position += 1 + value = ord(context_w[0]) + for i in range(8): + context_data_val = (context_data_val << 1) | (value & 1) + if context_data_position == bitsPerChar - 1: + context_data_position = 0 + context_data.append(getCharFromInt(context_data_val)) + context_data_val = 0 + else: + context_data_position += 1 + value = value >> 1 + else: + value = 1 + for i in range(context_numBits): + context_data_val = (context_data_val << 1) | value + if context_data_position == bitsPerChar - 1: + context_data_position = 0 + context_data.append(getCharFromInt(context_data_val)) + context_data_val = 0 + else: + context_data_position += 1 + value = 0 + value = ord(context_w[0]) + for i in range(16): + context_data_val = (context_data_val << 1) | (value & 1) + if context_data_position == bitsPerChar - 1: + context_data_position = 0 + context_data.append(getCharFromInt(context_data_val)) + context_data_val = 0 + else: + context_data_position += 1 + value = value >> 1 + context_enlargeIn -= 1 + if context_enlargeIn == 0: + context_enlargeIn = math.pow(2, context_numBits) + context_numBits += 1 + del context_dictionaryToCreate[context_w] + else: + value = context_dictionary[context_w] + for i in range(context_numBits): + context_data_val = (context_data_val << 1) | (value & 1) + if context_data_position == bitsPerChar - 1: + context_data_position = 0 + context_data.append(getCharFromInt(context_data_val)) + context_data_val = 0 + else: + context_data_position += 1 + value = value >> 1 + + context_enlargeIn -= 1 + if context_enlargeIn == 0: + context_enlargeIn = math.pow(2, context_numBits) + context_numBits += 1 + + # Mark the end of the stream + value = 2 + for i in range(context_numBits): + context_data_val = (context_data_val << 1) | (value & 1) + if context_data_position == bitsPerChar - 1: + context_data_position = 0 + context_data.append(getCharFromInt(context_data_val)) + context_data_val = 0 + else: + context_data_position += 1 + value = value >> 1 + + # Flush the last char + while True: + context_data_val = (context_data_val << 1) + if context_data_position == bitsPerChar - 1: + context_data.append(getCharFromInt(context_data_val)) + break + else: + context_data_position += 1 + + return "".join(context_data) + + +def _decompress(length, resetValue, getNextValue): + dictionary = {} + enlargeIn = 4 + dictSize = 4 + numBits = 3 + entry = "" + result = [] + + data = Object( + val=getNextValue(0), + position=resetValue, + index=1 + ) + + for i in range(3): + dictionary[i] = i + + bits = 0 + maxpower = math.pow(2, 2) + power = 1 + + while power != maxpower: + resb = data.val & data.position + data.position >>= 1 + if data.position == 0: + data.position = resetValue + data.val = getNextValue(data.index) + data.index += 1 + + bits |= power if resb > 0 else 0 + power <<= 1; + + next = bits + if next == 0: + bits = 0 + maxpower = math.pow(2, 8) + power = 1 + while power != maxpower: + resb = data.val & data.position + data.position >>= 1 + if data.position == 0: + data.position = resetValue + data.val = getNextValue(data.index) + data.index += 1 + bits |= power if resb > 0 else 0 + power <<= 1 + c = chr(bits) + elif next == 1: + bits = 0 + maxpower = math.pow(2, 16) + power = 1 + while power != maxpower: + resb = data.val & data.position + data.position >>= 1 + if data.position == 0: + data.position = resetValue; + data.val = getNextValue(data.index) + data.index += 1 + bits |= power if resb > 0 else 0 + power <<= 1 + c = chr(bits) + elif next == 2: + return "" + + # print(bits) + dictionary[3] = c + w = c + result.append(c) + counter = 0 + while True: + counter += 1 + if data.index > length: + return "" + + bits = 0 + maxpower = math.pow(2, numBits) + power = 1 + while power != maxpower: + resb = data.val & data.position + data.position >>= 1 + if data.position == 0: + data.position = resetValue; + data.val = getNextValue(data.index) + data.index += 1 + bits |= power if resb > 0 else 0 + power <<= 1 + + c = bits + if c == 0: + bits = 0 + maxpower = math.pow(2, 8) + power = 1 + while power != maxpower: + resb = data.val & data.position + data.position >>= 1 + if data.position == 0: + data.position = resetValue + data.val = getNextValue(data.index) + data.index += 1 + bits |= power if resb > 0 else 0 + power <<= 1 + + dictionary[dictSize] = chr(bits) + dictSize += 1 + c = dictSize - 1 + enlargeIn -= 1 + elif c == 1: + bits = 0 + maxpower = math.pow(2, 16) + power = 1 + while power != maxpower: + resb = data.val & data.position + data.position >>= 1 + if data.position == 0: + data.position = resetValue; + data.val = getNextValue(data.index) + data.index += 1 + bits |= power if resb > 0 else 0 + power <<= 1 + dictionary[dictSize] = chr(bits) + dictSize += 1 + c = dictSize - 1 + enlargeIn -= 1 + elif c == 2: + return "".join(result) + + + if enlargeIn == 0: + enlargeIn = math.pow(2, numBits) + numBits += 1 + + if c in dictionary: + entry = dictionary[c] + else: + if c == dictSize: + entry = w + w[0] + else: + return None + result.append(entry) + + # Add w+entry[0] to the dictionary. + dictionary[dictSize] = w + entry[0] + dictSize += 1 + enlargeIn -= 1 + + w = entry + if enlargeIn == 0: + enlargeIn = math.pow(2, numBits) + numBits += 1 + + +class LZString(object): + @staticmethod + def compress(uncompressed): + return _compress(uncompressed, 16, chr) + + @staticmethod + def compressToUTF16(uncompressed): + if uncompressed is None: + return "" + return _compress(uncompressed, 15, lambda a: chr(a+32)) + " " + + @staticmethod + def compressToBase64(uncompressed): + if uncompressed is None: + return "" + res = _compress(uncompressed, 6, lambda a: keyStrBase64[a]) + # To produce valid Base64 + end = len(res) % 4 + print (end) + if end > 0: + res += "="*(4 - end) + return res + + @staticmethod + def compressToEncodedURIComponent(uncompressed): + if uncompressed is None: + return "" + return _compress(uncompressed, 6, lambda a: keyStrUriSafe[a]) + + @staticmethod + def decompress(compressed): + if compressed is None: + return "" + if compressed == "": + return None + return _decompress(len(compressed), 32768, lambda index: ord(compressed[index])) + + @staticmethod + def decompressFromUTF16(compressed): + if compressed is None: + return "" + if compressed == "": + return None + return _decompress(len(compressed), 16384, lambda index: compressed[index] - 32) + + @staticmethod + def decompressFromBase64(compressed): + if compressed is None: + return "" + if compressed == "": + return None + return _decompress(len(compressed), 32, lambda index: getBaseValue(keyStrBase64, compressed[index])) + + @staticmethod + def decompressFromEncodedURIComponent(compressed): + if compressed is None: + return "" + if compressed == "": + return None + compressed = compressed.replace(" ", "+") + return _decompress(len(compressed), 32, lambda index: getBaseValue(keyStrUriSafe, compressed[index])) + +# lz = LZString() +# with open('codificado', 'rt') as f: +# res = lz.decompressFromBase64(f.read()) +# with open('decodificado', 'wt') as f: +# f.write(res) + + diff --git a/tests/yaml_samples/ibom_variant_1.kibot.yaml b/tests/yaml_samples/ibom_variant_1.kibot.yaml new file mode 100644 index 00000000..91f88ce1 --- /dev/null +++ b/tests/yaml_samples/ibom_variant_1.kibot.yaml @@ -0,0 +1,74 @@ +# Example KiBot config file +kibot: + version: 1 + + +variants: + - name: 'default' + comment: 'Default KiBoM variant' + type: kibom + + - name: 't1_v1' + comment: 'Test 1 Variant V1' + type: kibom + file_id: '_(V1)' + variant: V1 + + - name: 't1_v2' + comment: 'Test 1 Variant V2' + type: kibom + file_id: '_(V2)' + variant: V2 + + - name: 't1_v3' + comment: 'Test 1 Variant V3' + type: kibom + file_id: '_V3' + variant: V3 + + - name: 'bla bla' + comment: 'Test 1 Variant V1+V3' + type: kibom + file_id: '_bla_bla' + variant: ['V1', 'V3'] + +outputs: + - name: 'bom_internal' + comment: "Bill of Materials in CSV format" + type: ibom + dir: BoM + options: + dnf_filter: '_kibom_dnf_Config' + variant: 'default' + + - name: 'bom_internal_v1' + comment: "Bill of Materials in CSV format for variant t1_v1" + type: ibom + dir: BoM + options: + dnf_filter: '_kibom_dnf_Config' + variant: t1_v1 + + - name: 'bom_internal_v2' + comment: "Bill of Materials in CSV format for variant t1_v2" + type: ibom + dir: BoM + options: + dnf_filter: '_kibom_dnf_Config' + variant: t1_v2 + + - name: 'bom_internal_v3' + comment: "Bill of Materials in CSV format for variant t1_v3" + type: ibom + dir: BoM + options: + dnf_filter: '_kibom_dnf_Config' + variant: t1_v3 + + - name: 'bom_internal_bla_bla' + comment: "Bill of Materials in CSV format for variant `bla bla`" + type: ibom + dir: BoM + options: + dnf_filter: '_kibom_dnf_Config' + variant: 'bla bla' From 6800a747e657f8ed02773f26357138ea086c6e95 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Sat, 5 Sep 2020 18:54:54 -0300 Subject: [PATCH 2/6] Fixed flake8 details --- tests/utils/lzstring.py | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/tests/utils/lzstring.py b/tests/utils/lzstring.py index b70f0534..d341d934 100644 --- a/tests/utils/lzstring.py +++ b/tests/utils/lzstring.py @@ -10,7 +10,8 @@ import math keyStrBase64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=" keyStrUriSafe = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-$" -baseReverseDic = {}; +baseReverseDic = {} + class Object(object): def __init__(self, **kwargs): @@ -26,16 +27,16 @@ def getBaseValue(alphabet, character): return baseReverseDic[alphabet][character] -def _compress(uncompressed, bitsPerChar, getCharFromInt): +def _compress(uncompressed, bitsPerChar, getCharFromInt): # noqa: C901 if (uncompressed is None): return "" context_dictionary = {} - context_dictionaryToCreate= {} + context_dictionaryToCreate = {} context_c = "" context_wc = "" context_w = "" - context_enlargeIn = 2 # Compensate for the first entry which should not count + context_enlargeIn = 2 # Compensate for the first entry which should not count context_dictSize = 3 context_numBits = 2 context_data = [] @@ -116,7 +117,7 @@ def _compress(uncompressed, bitsPerChar, getCharFromInt): if context_enlargeIn == 0: context_enlargeIn = math.pow(2, context_numBits) context_numBits += 1 - + # Add wc to the dictionary. context_dictionary[context_wc] = context_dictSize context_dictSize += 1 @@ -206,12 +207,12 @@ def _compress(uncompressed, bitsPerChar, getCharFromInt): context_data.append(getCharFromInt(context_data_val)) break else: - context_data_position += 1 + context_data_position += 1 return "".join(context_data) -def _decompress(length, resetValue, getNextValue): +def _decompress(length, resetValue, getNextValue): # noqa: C901 dictionary = {} enlargeIn = 4 dictSize = 4 @@ -241,7 +242,7 @@ def _decompress(length, resetValue, getNextValue): data.index += 1 bits |= power if resb > 0 else 0 - power <<= 1; + power <<= 1 next = bits if next == 0: @@ -266,7 +267,7 @@ def _decompress(length, resetValue, getNextValue): resb = data.val & data.position data.position >>= 1 if data.position == 0: - data.position = resetValue; + data.position = resetValue data.val = getNextValue(data.index) data.index += 1 bits |= power if resb > 0 else 0 @@ -292,7 +293,7 @@ def _decompress(length, resetValue, getNextValue): resb = data.val & data.position data.position >>= 1 if data.position == 0: - data.position = resetValue; + data.position = resetValue data.val = getNextValue(data.index) data.index += 1 bits |= power if resb > 0 else 0 @@ -325,7 +326,7 @@ def _decompress(length, resetValue, getNextValue): resb = data.val & data.position data.position >>= 1 if data.position == 0: - data.position = resetValue; + data.position = resetValue data.val = getNextValue(data.index) data.index += 1 bits |= power if resb > 0 else 0 @@ -337,7 +338,6 @@ def _decompress(length, resetValue, getNextValue): elif c == 2: return "".join(result) - if enlargeIn == 0: enlargeIn = math.pow(2, numBits) numBits += 1 @@ -380,7 +380,7 @@ class LZString(object): res = _compress(uncompressed, 6, lambda a: keyStrBase64[a]) # To produce valid Base64 end = len(res) % 4 - print (end) + print(end) if end > 0: res += "="*(4 - end) return res @@ -429,5 +429,3 @@ class LZString(object): # res = lz.decompressFromBase64(f.read()) # with open('decodificado', 'wt') as f: # f.write(res) - - From 1163d28e719f3f563bb83d4e40cb1e3874dd929f Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Sat, 5 Sep 2020 18:56:01 -0300 Subject: [PATCH 3/6] Added "Not " prefix to negation filter names. --- kibot/fil_base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kibot/fil_base.py b/kibot/fil_base.py index 67499310..bf3dfe10 100644 --- a/kibot/fil_base.py +++ b/kibot/fil_base.py @@ -56,7 +56,7 @@ class NotFilter(Registrable): """ A filter that returns the inverted result """ def __init__(self, filter): super().__init__() - self.name = filter.name + self.name = 'Not '+filter.name self.type = '!'+filter.type self.comment = filter.comment self._filter = filter From d719718eca267d625be1a13b1def6e17acc48103 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Sat, 5 Sep 2020 18:58:26 -0300 Subject: [PATCH 4/6] Moved KiBoM default behavior to the KiBoM variant. So it can be applied to other outputs. --- kibot/fil_base.py | 4 +++ kibot/out_bom.py | 10 ++++--- kibot/var_base.py | 11 +------- kibot/var_ibom.py | 4 +++ kibot/var_kibom.py | 28 +++++++++++++++++++ tests/test_plot/test_ibom.py | 1 - .../int_bom_var_t3_csv.kibot.yaml | 7 +---- 7 files changed, 44 insertions(+), 21 deletions(-) diff --git a/kibot/fil_base.py b/kibot/fil_base.py index bf3dfe10..536cf1c6 100644 --- a/kibot/fil_base.py +++ b/kibot/fil_base.py @@ -180,6 +180,10 @@ class BaseFilter(RegFilter): for name in names: if not name: continue + if isinstance(name, Registrable): + # A filter already converted + filters.append(name) + continue if name[0] == '!': invert = True name = name[1:] diff --git a/kibot/out_bom.py b/kibot/out_bom.py index 5b1df47e..b29a0173 100644 --- a/kibot/out_bom.py +++ b/kibot/out_bom.py @@ -12,7 +12,6 @@ from .gs import GS from .optionable import Optionable, BaseOptions from .registrable import RegOutput from .error import KiPlotConfigurationError -from .misc import IFILL_MECHANICAL from .kiplot import get_board_comps_data from .macros import macros, document, output_class # noqa: F401 from .bom.columnlist import ColumnList, BoMError @@ -273,6 +272,9 @@ class BoMOptions(BaseOptions): self.variant.config_field = self.fit_field self.variant.variant = [] self.variant.name = 'default' + # Delegate any filter to the variant + self.variant.set_def_filters(self.exclude_filter, self.dnf_filter, self.dnc_filter) + self.exclude_filter = self.dnf_filter = self.dnc_filter = None self.variant.config() # Fill or adjust any detail def config(self): @@ -303,9 +305,9 @@ class BoMOptions(BaseOptions): if isinstance(self.component_aliases, type): self.component_aliases = DEFAULT_ALIASES # Filters - self.exclude_filter = BaseFilter.solve_filter(self.exclude_filter, 'exclude_filter', IFILL_MECHANICAL) - self.dnf_filter = BaseFilter.solve_filter(self.dnf_filter, 'dnf_filter', '_kibom_dnf_'+self.fit_field) - self.dnc_filter = BaseFilter.solve_filter(self.dnc_filter, 'dnc_filter', '_kibom_dnc_'+self.fit_field) + self.exclude_filter = BaseFilter.solve_filter(self.exclude_filter, 'exclude_filter') + self.dnf_filter = BaseFilter.solve_filter(self.dnf_filter, 'dnf_filter') + self.dnc_filter = BaseFilter.solve_filter(self.dnc_filter, 'dnc_filter') # Variants, make it an object self._normalize_variant() # Field names are handled in lowercase diff --git a/kibot/var_base.py b/kibot/var_base.py index 80b56983..65fa5527 100644 --- a/kibot/var_base.py +++ b/kibot/var_base.py @@ -5,7 +5,7 @@ # Project: KiBot (formerly KiPlot) from .registrable import RegVariant from .optionable import Optionable -from .fil_base import BaseFilter, apply_in_bom_filter, apply_fitted_filter, apply_fixed_filter +from .fil_base import apply_in_bom_filter, apply_fitted_filter, apply_fixed_filter from .macros import macros, document # noqa: F401 @@ -33,15 +33,6 @@ class BaseVariant(RegVariant): """ [string|list(string)=''] Name of the filter to mark components as 'Do Not Change'. Use '_kibom_dnc' for the default KiBoM behavior """ - def config(self): - super().config() - # exclude_filter - self.exclude_filter = BaseFilter.solve_filter(self.exclude_filter, 'exclude_filter') - # dnf_filter - self.dnf_filter = BaseFilter.solve_filter(self.dnf_filter, 'dnf_filter') - # dnc_filter - self.dnc_filter = BaseFilter.solve_filter(self.dnc_filter, 'dnc_filter') - def filter(self, comps, reset): # Apply all the filters apply_in_bom_filter(comps, self.exclude_filter, reset) diff --git a/kibot/var_ibom.py b/kibot/var_ibom.py index 92e34d06..4c71f24f 100644 --- a/kibot/var_ibom.py +++ b/kibot/var_ibom.py @@ -8,6 +8,7 @@ Implements the IBoM variants mechanism. """ from .optionable import Optionable from .gs import GS +from .fil_base import BaseFilter from .macros import macros, document, variant_class # noqa: F401 from . import log @@ -46,6 +47,9 @@ class IBoM(BaseVariant): # noqa: F821 def config(self): super().config() + self.exclude_filter = BaseFilter.solve_filter(self.exclude_filter, 'exclude_filter') + self.dnf_filter = BaseFilter.solve_filter(self.dnf_filter, 'dnf_filter') + self.dnc_filter = BaseFilter.solve_filter(self.dnc_filter, 'dnc_filter') self.variants_blacklist = self._force_list(self.variants_blacklist) self.variants_whitelist = self._force_list(self.variants_whitelist) diff --git a/kibot/var_kibom.py b/kibot/var_kibom.py index 6d7567e1..46583918 100644 --- a/kibot/var_kibom.py +++ b/kibot/var_kibom.py @@ -8,6 +8,8 @@ Implements the KiBoM variants mechanism. """ from .optionable import Optionable from .gs import GS +from .misc import IFILL_MECHANICAL +from .fil_base import BaseFilter from .macros import macros, document, variant_class # noqa: F401 from . import log @@ -22,13 +24,23 @@ class KiBoM(BaseVariant): # noqa: F821 +VARIANT includes the component only if we are using this variant. """ def __init__(self): super().__init__() + self._def_exclude_filter = None + self._def_dnf_filter = None + self._def_dnc_filter = None with document: self.config_field = 'Config' """ Name of the field used to clasify components """ self.variant = Optionable """ [string|list(string)=''] Board variant(s) """ + def set_def_filters(self, exclude_filter, dnf_filter, dnc_filter): + """ Filters delegated to the variant """ + self._def_exclude_filter = exclude_filter + self._def_dnf_filter = dnf_filter + self._def_dnc_filter = dnc_filter + def config(self): + # Now we can let the parent initialize the filters super().config() # Variants, ensure a list if isinstance(self.variant, type): @@ -39,6 +51,22 @@ class KiBoM(BaseVariant): # noqa: F821 else: self.variant = [] self.variant = [v.lower() for v in self.variant] + # Filters priority: + # 1) Defined here + # 2) Delegated from the output format + # 3) KiBoM default behavior + # exclude_filter + if not self._def_exclude_filter: + self._def_exclude_filter = IFILL_MECHANICAL + self.exclude_filter = BaseFilter.solve_filter(self.exclude_filter, 'exclude_filter', self._def_exclude_filter) + # dnf_filter + if not self._def_dnf_filter: + self._def_dnf_filter = '_kibom_dnf_'+self.config_field + self.dnf_filter = BaseFilter.solve_filter(self.dnf_filter, 'dnf_filter', self._def_dnf_filter) + # dnc_filter + if not self._def_dnc_filter: + self._def_dnc_filter = '_kibom_dnc_'+self.config_field + self.dnc_filter = BaseFilter.solve_filter(self.dnc_filter, 'dnc_filter', self._def_dnc_filter) # Config field must be lowercase self.config_field = self.config_field.lower() diff --git a/tests/test_plot/test_ibom.py b/tests/test_plot/test_ibom.py index b3b42853..b7208282 100644 --- a/tests/test_plot/test_ibom.py +++ b/tests/test_plot/test_ibom.py @@ -118,4 +118,3 @@ def test_ibom_variant_1(): logging.debug("* `bla bla` variant") check_modules(ctx, prj+'-ibom_bla_bla.html', ['R1', 'R4']) ctx.clean_up() - diff --git a/tests/yaml_samples/int_bom_var_t3_csv.kibot.yaml b/tests/yaml_samples/int_bom_var_t3_csv.kibot.yaml index 15bbe700..6febf324 100644 --- a/tests/yaml_samples/int_bom_var_t3_csv.kibot.yaml +++ b/tests/yaml_samples/int_bom_var_t3_csv.kibot.yaml @@ -9,15 +9,13 @@ variants: type: kibom file_id: '_(V1)' variant: V1 - dnc_filter: '_kibom_dnc' - dnf_filter: '_kibom_dnf_Config' - exclude_filter: '_mechanical' - name: 't1_v1b' comment: 'Test 1 Variant V1' type: kibom file_id: '_(V1b)' variant: V1 + dnc_filter: '_none' outputs: - name: 'bom_internal_v1' @@ -26,9 +24,6 @@ outputs: dir: BoM options: variant: t1_v1 - dnc_filter: '_none' - dnf_filter: '_none' - exclude_filter: '_none' - name: 'bom_internal_v1b' comment: "Bill of Materials in CSV format for variant t1_v1" From b94a2cb6a43054be7d371ca86c899a031a6074be Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Sat, 5 Sep 2020 18:59:21 -0300 Subject: [PATCH 5/6] Updated the readme and generic example. Explanations about which IBoM options are native. --- README.md | 16 +++++++++++++-- docs/samples/generic_plot.kibot.yaml | 30 ++++++++++++++++++++-------- 2 files changed, 36 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index f1f9f4fb..327d0e6b 100644 --- a/README.md +++ b/README.md @@ -589,13 +589,19 @@ Next time you need this list just use an alias, like this: - `options`: [dict] Options for the `ibom` output. * Valid keys: - `blacklist`: [string=''] List of comma separated blacklisted components or prefixes with *. E.g. 'X1,MH*'. + IBoM option, avoid using in conjunction with KiBot variants/filters. - `blacklist_empty_val`: [boolean=false] Blacklist components with empty value. + IBoM option, avoid using in conjunction with KiBot variants/filters. - `board_rotation`: [number=0] Board rotation in degrees (-180 to 180). Will be rounded to multiple of 5. - `bom_view`: [string='left-right'] [bom-only,left-right,top-bottom] Default BOM view. - `checkboxes`: [string='Sourced,Placed'] Comma separated list of checkbox columns. - `dark_mode`: [boolean=false] Default to dark mode. - - `dnp_field`: [string=''] Name of the extra field that indicates do not populate status. Components with this field not empty will be - blacklisted. + - `dnf_filter`: [string|list(string)=''] Name of the filter to mark components as not fitted. + A short-cut to use for simple cases where a variant is an overkill. + Avoid using it in conjunction with with IBoM native filtering options. + - `dnp_field`: [string=''] Name of the extra field that indicates do not populate status. + Components with this field not empty will be blacklisted. + IBoM option, avoid using in conjunction with KiBot variants/filters. - `extra_fields`: [string=''] Comma separated list of extra fields to pull from netlist or xml file. - `hide_pads`: [boolean=false] Hide footprint pads by default. - `hide_silkscreen`: [boolean=false] Hide silkscreen by default. @@ -615,14 +621,20 @@ Next time you need this list just use an alias, like this: Note that this name is used only when output is ''. - `netlist_file`: [string=''] Path to netlist or xml file. - `no_blacklist_virtual`: [boolean=false] Do not blacklist virtual components. + IBoM option, avoid using in conjunction with KiBot variants/filters. - `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%v.%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`: [string=''] Board variant to apply. + Avoid using it in conjunction with with IBoM native filtering options. - `variant_field`: [string=''] Name of the extra field that stores board variant for component. + IBoM option, avoid using in conjunction with KiBot variants/filters. - `variants_blacklist`: [string=''] List of board variants to exclude from the BOM. + IBoM option, avoid using in conjunction with KiBot variants/filters. - `variants_whitelist`: [string=''] List of board variants to include in the BOM. + IBoM option, avoid using in conjunction with KiBot variants/filters. * KiBoM (KiCad Bill of Materials) * Type: `kibom` diff --git a/docs/samples/generic_plot.kibot.yaml b/docs/samples/generic_plot.kibot.yaml index 0bd0aa91..499cde30 100644 --- a/docs/samples/generic_plot.kibot.yaml +++ b/docs/samples/generic_plot.kibot.yaml @@ -348,9 +348,11 @@ outputs: type: 'ibom' dir: 'Example/ibom_dir' options: - # [string=''] List of comma separated blacklisted components or prefixes with *. E.g. 'X1,MH*' + # [string=''] List of comma separated blacklisted components or prefixes with *. E.g. 'X1,MH*'. + # IBoM option, avoid using in conjunction with KiBot variants/filters blacklist: '' - # [boolean=false] Blacklist components with empty value + # [boolean=false] Blacklist components with empty value. + # IBoM option, avoid using in conjunction with KiBot variants/filters blacklist_empty_val: false # [number=0] Board rotation in degrees (-180 to 180). Will be rounded to multiple of 5 board_rotation: 0 @@ -360,8 +362,13 @@ outputs: 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 + # [string|list(string)=''] Name of the filter to mark components as not fitted. + # A short-cut to use for simple cases where a variant is an overkill. + # Avoid using it in conjunction with with IBoM native filtering options + dnf_filter: '' + # [string=''] Name of the extra field that indicates do not populate status. + # Components with this field not empty will be blacklisted. + # IBoM option, avoid using in conjunction with KiBot variants/filters dnp_field: '' # [string=''] Comma separated list of extra fields to pull from netlist or xml file extra_fields: '' @@ -390,7 +397,8 @@ outputs: name_format: 'ibom' # [string=''] Path to netlist or xml file netlist_file: '' - # [boolean=false] Do not blacklist virtual components + # [boolean=false] Do not blacklist virtual components. + # IBoM option, avoid using in conjunction with KiBot variants/filters no_blacklist_virtual: false # [boolean=false] Do not redraw pcb on drag by default no_redraw_on_drag: false @@ -402,11 +410,17 @@ outputs: 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 + # [string=''] Board variant to apply. + # Avoid using it in conjunction with with IBoM native filtering options + variant: '' + # [string=''] Name of the extra field that stores board variant for component. + # IBoM option, avoid using in conjunction with KiBot variants/filters variant_field: '' - # [string=''] List of board variants to exclude from the BOM + # [string=''] List of board variants to exclude from the BOM. + # IBoM option, avoid using in conjunction with KiBot variants/filters variants_blacklist: '' - # [string=''] List of board variants to include in the BOM + # [string=''] List of board variants to include in the BOM. + # IBoM option, avoid using in conjunction with KiBot variants/filters variants_whitelist: '' # KiBoM (KiCad Bill of Materials): From 59ddbaa41f8136c051560c71429acd0c07becf48 Mon Sep 17 00:00:00 2001 From: "Salvador E. Tropea" Date: Sat, 5 Sep 2020 19:31:29 -0300 Subject: [PATCH 6/6] Adjusted the tests for IBoM's variants support. - Removed the extra filters that aren't needed now. - Added a couple of test cases to cover special situations. --- tests/test_plot/test_ibom.py | 2 +- tests/yaml_samples/ibom_variant_1.kibot.yaml | 7 ++----- tests/yaml_samples/int_bom_var_t3_csv.kibot.yaml | 2 ++ 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/tests/test_plot/test_ibom.py b/tests/test_plot/test_ibom.py index b7208282..fa11d254 100644 --- a/tests/test_plot/test_ibom.py +++ b/tests/test_plot/test_ibom.py @@ -116,5 +116,5 @@ def test_ibom_variant_1(): check_modules(ctx, prj+'-ibom_V3.html', ['R1', 'R4']) # V1,V3 logging.debug("* `bla bla` variant") - check_modules(ctx, prj+'-ibom_bla_bla.html', ['R1', 'R4']) + check_modules(ctx, prj+'-ibom_bla_bla.html', ['R4']) ctx.clean_up() diff --git a/tests/yaml_samples/ibom_variant_1.kibot.yaml b/tests/yaml_samples/ibom_variant_1.kibot.yaml index 91f88ce1..e5f4c816 100644 --- a/tests/yaml_samples/ibom_variant_1.kibot.yaml +++ b/tests/yaml_samples/ibom_variant_1.kibot.yaml @@ -38,7 +38,6 @@ outputs: type: ibom dir: BoM options: - dnf_filter: '_kibom_dnf_Config' variant: 'default' - name: 'bom_internal_v1' @@ -46,7 +45,6 @@ outputs: type: ibom dir: BoM options: - dnf_filter: '_kibom_dnf_Config' variant: t1_v1 - name: 'bom_internal_v2' @@ -54,7 +52,6 @@ outputs: type: ibom dir: BoM options: - dnf_filter: '_kibom_dnf_Config' variant: t1_v2 - name: 'bom_internal_v3' @@ -62,7 +59,6 @@ outputs: type: ibom dir: BoM options: - dnf_filter: '_kibom_dnf_Config' variant: t1_v3 - name: 'bom_internal_bla_bla' @@ -70,5 +66,6 @@ outputs: type: ibom dir: BoM options: - dnf_filter: '_kibom_dnf_Config' variant: 'bla bla' + # This will let only R4 + blacklist: R1 diff --git a/tests/yaml_samples/int_bom_var_t3_csv.kibot.yaml b/tests/yaml_samples/int_bom_var_t3_csv.kibot.yaml index 6febf324..7707c8bb 100644 --- a/tests/yaml_samples/int_bom_var_t3_csv.kibot.yaml +++ b/tests/yaml_samples/int_bom_var_t3_csv.kibot.yaml @@ -9,6 +9,8 @@ variants: type: kibom file_id: '_(V1)' variant: V1 + # This isn't needed is just to be sure we can default to _kibom_dnc_config + dnc_filter: '_kibom_dnc' - name: 't1_v1b' comment: 'Test 1 Variant V1'