Added support for all the missing IBoM options.
Note that variants_blacklist and variants_whitelist needs a fresh IBoM. These options didn't work and crashed IBoM. It was reported as a result of the tests included in this commit.
This commit is contained in:
parent
d48f258c33
commit
c82c2f0c39
23
CHANGELOG.md
23
CHANGELOG.md
|
|
@ -17,6 +17,29 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
--help-output)
|
||||
- Help for the supported preflights (--help-preflights)
|
||||
- Better YAML validation.
|
||||
- Added the following InteractiveHtmlBom options:
|
||||
- dark_mode
|
||||
- hide_pads
|
||||
- show_fabrication
|
||||
- hide_silkscreen
|
||||
- highlight_pin1
|
||||
- no_redraw_on_drag
|
||||
- board_rotation
|
||||
- checkboxes
|
||||
- bom_view
|
||||
- layer_view
|
||||
- include_tracks
|
||||
- include_nets
|
||||
- sort_order
|
||||
- no_blacklist_virtual
|
||||
- blacklist_empty_val
|
||||
- netlist_file
|
||||
- extra_fields
|
||||
- normalize_field_case
|
||||
- variant_field
|
||||
- variants_whitelist
|
||||
- variants_blacklist
|
||||
- dnp_field
|
||||
|
||||
### Fixed
|
||||
- The `sketch_plot` option is now implemented.
|
||||
|
|
|
|||
|
|
@ -301,13 +301,10 @@ def print_output_options(name, cl):
|
|||
obj = cl('', name, '')
|
||||
print(' * Options:')
|
||||
num_opts = 0
|
||||
attrs = BaseOutput.get_attrs_for(obj)
|
||||
for k, v in attrs.items():
|
||||
if k[0] != '_':
|
||||
help_attr = '_help_'+k
|
||||
help = attrs.get(help_attr)
|
||||
print(' - {}: {}.'.format(k, help.rstrip() if help else 'Undocumented'))
|
||||
num_opts = num_opts+1
|
||||
for k, v in BaseOutput.get_attrs_gen(obj):
|
||||
help = getattr(obj, '_help_'+k)
|
||||
print(' - {}: {}.'.format(k, help.rstrip() if help else 'Undocumented'))
|
||||
num_opts = num_opts+1
|
||||
if num_opts == 0:
|
||||
print(' - No available options')
|
||||
|
||||
|
|
|
|||
|
|
@ -49,8 +49,19 @@ class BaseOutput(object):
|
|||
|
||||
@staticmethod
|
||||
def get_attrs_for(obj):
|
||||
""" Returns all attributes """
|
||||
return dict(inspect.getmembers(obj, filter))
|
||||
|
||||
@staticmethod
|
||||
def get_attrs_gen(obj):
|
||||
""" Returns a (key, val) iterator on public attributes """
|
||||
attrs = BaseOutput.get_attrs_for(obj)
|
||||
return ((k, v) for k, v in attrs.items() if k[0] != '_')
|
||||
|
||||
@staticmethod
|
||||
def attr2longopt(attr):
|
||||
return '--'+attr.replace('_', '-')
|
||||
|
||||
@staticmethod
|
||||
def register(name, aclass):
|
||||
BaseOutput._registered[name] = aclass
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@ import os
|
|||
from subprocess import (check_output, STDOUT, CalledProcessError)
|
||||
from .misc import (CMD_IBOM, URL_IBOM, BOM_ERROR)
|
||||
from .kiplot import (GS, check_script)
|
||||
from .error import KiPlotConfigurationError
|
||||
from kiplot.macros import macros, document, output_class # noqa: F401
|
||||
from . import log
|
||||
|
||||
|
|
@ -19,10 +20,84 @@ class IBoM(BaseOutput): # noqa: F821
|
|||
self._sch_related = True
|
||||
# Options
|
||||
with document:
|
||||
self.blacklist = ''
|
||||
""" regular expression for the components to exclude (using the Config field) """
|
||||
self.dark_mode = False
|
||||
""" Default to dark mode """
|
||||
self.hide_pads = False
|
||||
""" Hide footprint pads by default """
|
||||
self.show_fabrication = False
|
||||
""" Show fabrication layer by default """
|
||||
self.hide_silkscreen = False
|
||||
""" Hide silkscreen by default """
|
||||
self.highlight_pin1 = False
|
||||
""" Highlight pin1 by default """
|
||||
self.no_redraw_on_drag = False
|
||||
""" Do not redraw pcb on drag by default """
|
||||
self.board_rotation = 0
|
||||
""" Board rotation in degrees (-180 to 180). Will be rounded to multiple of 5 """
|
||||
self.checkboxes = 'Sourced,Placed'
|
||||
""" Comma separated list of checkbox columns """
|
||||
self._bom_view = 'left-right'
|
||||
""" Default BOM view {bom-only,left-right,top-bottom} """
|
||||
self._layer_view = 'FB'
|
||||
""" Default layer view {F,FB,B} """
|
||||
self.name_format = 'ibom'
|
||||
""" format of the output name, example: %f_%r_iBoM will contain the revision and _iBoM """ # pragma: no cover
|
||||
""" Output file name format supports substitutions:
|
||||
%f : original pcb file name without extension.
|
||||
%p : pcb/project title from pcb metadata.
|
||||
%c : company from pcb metadata.
|
||||
%r : revision from pcb metadata.
|
||||
%d : pcb date from metadata if available, file modification date otherwise.
|
||||
%D : bom generation date.
|
||||
%T : bom generation time. Extension .html will be added automatically """
|
||||
self.include_tracks = False
|
||||
""" Include track/zone information in output. F.Cu and B.Cu layers only """
|
||||
self.include_nets = False
|
||||
""" 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.variant_field = ''
|
||||
""" Name of the extra field that stores board variant for component """
|
||||
self.variants_whitelist = ''
|
||||
""" List of board variants to include in the BOM """
|
||||
self.variants_blacklist = ''
|
||||
""" List of board variants to exclude from the BOM """
|
||||
self.dnp_field = ''
|
||||
""" Name of the extra field that indicates do not populate status. Components with this field not empty will be
|
||||
blacklisted """ # pragma: no cover
|
||||
|
||||
@property
|
||||
def bom_view(self):
|
||||
return self._bom_view
|
||||
|
||||
@bom_view.setter
|
||||
def bom_view(self, val):
|
||||
valid = ['bom-only', 'left-right', 'top-bottom']
|
||||
if val not in valid:
|
||||
raise KiPlotConfigurationError("`bom_view` must be any of "+str(valid))
|
||||
self._bom_view = val
|
||||
|
||||
@property
|
||||
def layer_view(self):
|
||||
return self._layer_view
|
||||
|
||||
@layer_view.setter
|
||||
def layer_view(self, val):
|
||||
valid = ['F', 'FB', 'B']
|
||||
if val not in valid:
|
||||
raise KiPlotConfigurationError("`layer_view` must be any of "+str(valid))
|
||||
self._layer_view = val
|
||||
|
||||
def run(self, output_dir, board):
|
||||
check_script(CMD_IBOM, URL_IBOM)
|
||||
|
|
@ -30,12 +105,14 @@ class IBoM(BaseOutput): # noqa: F821
|
|||
# Tell ibom we don't want to use the screen
|
||||
os.environ['INTERACTIVE_HTML_BOM_NO_DISPLAY'] = ''
|
||||
cmd = [CMD_IBOM, GS.pcb_file, '--dest-dir', output_dir, '--no-browser', ]
|
||||
if self.blacklist:
|
||||
cmd.append('--blacklist')
|
||||
cmd.append(self.blacklist)
|
||||
if self.name_format:
|
||||
cmd.append('--name-format')
|
||||
cmd.append(self.name_format)
|
||||
# Convert attributes into options
|
||||
for k, v in BaseOutput.get_attrs_gen(self): # noqa: F821
|
||||
if not v:
|
||||
continue
|
||||
cmd.append(BaseOutput.attr2longopt(k)) # noqa: F821
|
||||
if not isinstance(v, bool): # must be str/(int, float)
|
||||
cmd.append(str(v))
|
||||
# Run the command
|
||||
logger.debug('Running: '+str(cmd))
|
||||
try:
|
||||
cmd_output = check_output(cmd, stderr=STDOUT)
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ if prev_dir not in sys.path:
|
|||
from kiplot.misc import (BOM_ERROR)
|
||||
|
||||
BOM_DIR = 'BoM'
|
||||
IBOM_OUT = 'ibom.html'
|
||||
|
||||
|
||||
def test_ibom():
|
||||
|
|
@ -42,7 +43,7 @@ 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.html'))
|
||||
ctx.expect_out_file(os.path.join(BOM_DIR, IBOM_OUT))
|
||||
ctx.clean_up()
|
||||
|
||||
|
||||
|
|
@ -50,3 +51,24 @@ def test_ibom_fail():
|
|||
ctx = context.TestContext('BoM_interactiveFail', 'bom_no_xml', 'ibom', BOM_DIR)
|
||||
ctx.run(BOM_ERROR)
|
||||
ctx.clean_up()
|
||||
|
||||
|
||||
def test_ibom_all_ops():
|
||||
prj = 'bom'
|
||||
ctx = context.TestContext('BoM_interactiveAll', prj, 'ibom_all_ops', BOM_DIR)
|
||||
ctx.run()
|
||||
out = os.path.join(BOM_DIR, IBOM_OUT)
|
||||
ctx.expect_out_file(out)
|
||||
# These options are transferred as defaults:
|
||||
ctx.search_in_file(out, [r'"dark_mode": true',
|
||||
r'"show_pads": false',
|
||||
r'"show_fabrication": true',
|
||||
r'"show_silkscreen": false',
|
||||
r'"highlight_pin1": true',
|
||||
r'"redraw_on_drag": false',
|
||||
r'"board_rotation": 18.0', # 90/5
|
||||
r'"checkboxes": "Sourced,Placed,Bogus"',
|
||||
r'"bom_view": "top-bottom"',
|
||||
r'"layer_view": "B"',
|
||||
r'"extra_fields": \["EF"\]'])
|
||||
ctx.clean_up()
|
||||
|
|
|
|||
|
|
@ -8,6 +8,27 @@ outputs:
|
|||
type: ibom
|
||||
dir: BoM
|
||||
options:
|
||||
blacklist: 'DNF*'
|
||||
hide_pads: false
|
||||
show_fabrication: false
|
||||
hide_silkscreen: false
|
||||
highlight_pin1: false
|
||||
no_redraw_on_drag: false
|
||||
board_rotation: 0
|
||||
checkboxes: 'Sourced,Placed'
|
||||
bom_view: 'left-right'
|
||||
layer_view: 'FB'
|
||||
name_format: '%f_iBoM'
|
||||
include_tracks: false
|
||||
include_nets: false
|
||||
sort_order: 'C,R,L,D,U,Y,X,F,SW,A,~,HS,CNN,J,P,NT,MH'
|
||||
blacklist: 'DNF*'
|
||||
no_blacklist_virtual: false
|
||||
blacklist_empty_val: false
|
||||
netlist_file: ''
|
||||
extra_fields: ''
|
||||
normalize_field_case: false
|
||||
variant_field: ''
|
||||
variants_whitelist: ''
|
||||
variants_blacklist: ''
|
||||
dnp_field: ''
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,35 @@
|
|||
# Example KiPlot config file
|
||||
kiplot:
|
||||
version: 1
|
||||
|
||||
outputs:
|
||||
- name: 'interactive_bom'
|
||||
comment: "Interactive Bill of Materials (HTML)"
|
||||
type: ibom
|
||||
dir: BoM
|
||||
options:
|
||||
dark_mode: true
|
||||
hide_pads: true
|
||||
show_fabrication: true
|
||||
hide_silkscreen: true
|
||||
highlight_pin1: true
|
||||
no_redraw_on_drag: true
|
||||
board_rotation: 90
|
||||
checkboxes: 'Sourced,Placed,Bogus'
|
||||
bom_view: 'top-bottom'
|
||||
layer_view: 'B'
|
||||
name_format: 'ibom'
|
||||
include_tracks: true
|
||||
include_nets: true
|
||||
sort_order: 'C,R,L,D,U,Y,X,F,SW,A,~,HS,CNN,J,P,NT,MH'
|
||||
blacklist: 'DNF*'
|
||||
no_blacklist_virtual: true
|
||||
blacklist_empty_val: true
|
||||
netlist_file: 'tests/board_samples/bom.xml'
|
||||
extra_fields: 'EF'
|
||||
normalize_field_case: true
|
||||
variant_field: 'DL'
|
||||
variants_whitelist: 'bla,ble,bli'
|
||||
variants_blacklist: 'blo,blu'
|
||||
dnp_field: 'DNP'
|
||||
|
||||
Loading…
Reference in New Issue