Added support for variants to the PcbDraw output.

This commit is contained in:
Salvador E. Tropea 2020-09-04 18:08:22 -03:00
parent dab7baa2d4
commit d09400d49d
12 changed files with 161 additions and 19 deletions

View File

@ -25,6 +25,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Drawings removed from *.Adhes - Drawings removed from *.Adhes
- Components crossed in *.Fab - Components crossed in *.Fab
- STEP (3D) support for variants. - STEP (3D) support for variants.
- PcbDraw support for variants.
### Fixed ### Fixed
- Virtual components are always excluded from position files. - Virtual components are always excluded from position files.

View File

@ -110,6 +110,8 @@ gen_ref:
mv "$(REFDIR)no_inductor/test_v5-schematic_(no_L).pdf" $(REFDIR) mv "$(REFDIR)no_inductor/test_v5-schematic_(no_L).pdf" $(REFDIR)
rmdir $(REFDIR)no_inductor/ rmdir $(REFDIR)no_inductor/
src/kibot -b tests/board_samples/kibom-variant_4.kicad_pcb -c tests/yaml_samples/pdf_variant_1.kibot.yaml -d $(REFDIR) src/kibot -b tests/board_samples/kibom-variant_4.kicad_pcb -c tests/yaml_samples/pdf_variant_1.kibot.yaml -d $(REFDIR)
src/kibot -b tests/board_samples/kibom-variant_3.kicad_pcb -c tests/yaml_samples/pcbdraw_variant_1.kibot.yaml -d $(REFDIR)
src/kibot -b tests/board_samples/kibom-variant_3.kicad_pcb -c tests/yaml_samples/pcbdraw_variant_2.kibot.yaml -d $(REFDIR)
cp -a $(REFILL).ok $(REFILL) cp -a $(REFILL).ok $(REFILL)
doc: doc:

View File

@ -725,6 +725,8 @@ Next time you need this list just use an alias, like this:
- `options`: [dict] Options for the `pcbdraw` output. - `options`: [dict] Options for the `pcbdraw` output.
* Valid keys: * Valid keys:
- `bottom`: [boolean=false] render the bottom side of the board (default is top side). - `bottom`: [boolean=false] render the bottom side of the board (default is top side).
- `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.
- `dpi`: [number=300] [10,1200] dots per inch (resolution) of the generated image. - `dpi`: [number=300] [10,1200] dots per inch (resolution) of the generated image.
- `format`: [string='svg'] [svg,png,jpg] output format. Only used if no `output` is specified. - `format`: [string='svg'] [svg,png,jpg] output format. Only used if no `output` is specified.
- `highlight`: [list(string)=[]] list of components to highlight. - `highlight`: [list(string)=[]] list of components to highlight.
@ -734,7 +736,7 @@ Next time you need this list just use an alias, like this:
- `output`: [string='%f-%i%v.%x'] name for the generated file. Affected by global options. - `output`: [string='%f-%i%v.%x'] name for the generated file. Affected by global options.
- `placeholder`: [boolean=false] show placeholder for missing components. - `placeholder`: [boolean=false] show placeholder for missing components.
- `remap`: [dict|None] replacements for PCB references using components (lib:component). - `remap`: [dict|None] replacements for PCB references using components (lib:component).
- `show_components`: [string|list(string)=none] [none,all] list of components to draw, can be also a string for none or all. - `show_components`: [list(string)|string=none] [none,all] list of components to draw, can be also a string for none or all.
The default is none. The default is none.
- `style`: [string|dict] PCB style (colors). An internal name, the name of a JSON file or the style options. - `style`: [string|dict] PCB style (colors). An internal name, the name of a JSON file or the style options.
* Valid keys: * Valid keys:
@ -748,6 +750,7 @@ Next time you need this list just use an alias, like this:
- `pads`: [string='#b5ae30'] color for the exposed pads (metal finish). - `pads`: [string='#b5ae30'] color for the exposed pads (metal finish).
- `silk`: [string='#f0f0f0'] color for the silk screen. - `silk`: [string='#f0f0f0'] color for the silk screen.
- `vcut`: [string='#bf2600'] color for the V-CUTS. - `vcut`: [string='#bf2600'] color for the V-CUTS.
- `variant`: [string=''] Board variant to apply.
- `vcuts`: [boolean=false] render V-CUTS on the Cmts.User layer. - `vcuts`: [boolean=false] render V-CUTS on the Cmts.User layer.
- `warnings`: [string='visible'] [visible,all,none] using visible only the warnings about components in the visible side are generated. - `warnings`: [string='visible'] [visible,all,none] using visible only the warnings about components in the visible side are generated.

View File

@ -531,6 +531,9 @@ outputs:
options: options:
# [boolean=false] render the bottom side of the board (default is top side) # [boolean=false] render the bottom side of the board (default is top side)
bottom: false bottom: false
# [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
dnf_filter: ''
# [number=300] [10,1200] dots per inch (resolution) of the generated image # [number=300] [10,1200] dots per inch (resolution) of the generated image
dpi: 300 dpi: 300
# [string='svg'] [svg,png,jpg] output format. Only used if no `output` is specified # [string='svg'] [svg,png,jpg] output format. Only used if no `output` is specified
@ -549,7 +552,7 @@ outputs:
placeholder: false placeholder: false
# [dict|None] replacements for PCB references using components (lib:component) # [dict|None] replacements for PCB references using components (lib:component)
remap: remap:
# [string|list(string)=none] [none,all] list of components to draw, can be also a string for none or all. # [list(string)|string=none] [none,all] list of components to draw, can be also a string for none or all.
# The default is none # The default is none
show_components: none show_components: none
# [string|dict] PCB style (colors). An internal name, the name of a JSON file or the style options # [string|dict] PCB style (colors). An internal name, the name of a JSON file or the style options
@ -574,6 +577,8 @@ outputs:
silk: '#f0f0f0' silk: '#f0f0f0'
# [string='#bf2600'] color for the V-CUTS # [string='#bf2600'] color for the V-CUTS
vcut: '#bf2600' vcut: '#bf2600'
# [string=''] Board variant to apply
variant: ''
# [boolean=false] render V-CUTS on the Cmts.User layer # [boolean=false] render V-CUTS on the Cmts.User layer
vcuts: false vcuts: false
# [string='visible'] [visible,all,none] using visible only the warnings about components in the visible side are generated # [string='visible'] [visible,all,none] using visible only the warnings about components in the visible side are generated

View File

@ -13,7 +13,10 @@ from .misc import PCBDRAW, PCBDRAW_ERR, URL_PCBDRAW
from .kiplot import check_script from .kiplot import check_script
from .error import KiPlotConfigurationError from .error import KiPlotConfigurationError
from .gs import (GS) from .gs import (GS)
from .optionable import (BaseOptions, Optionable) from .optionable import BaseOptions, Optionable
from .registrable import RegOutput
from .kiplot import load_sch
from .fil_base import BaseFilter, apply_fitted_filter
from .macros import macros, document, output_class # noqa: F401 from .macros import macros, document, output_class # noqa: F401
from . import log from . import log
@ -136,6 +139,11 @@ class PcbDrawOptions(BaseOptions):
""" [svg,png,jpg] output format. Only used if no `output` is specified """ """ [svg,png,jpg] output format. Only used if no `output` is specified """
self.output = GS.def_global_output self.output = GS.def_global_output
""" name for the generated file """ """ name for the generated file """
self.variant = ''
""" Board variant to apply """
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 """
super().__init__() super().__init__()
def config(self): def config(self):
@ -150,10 +158,15 @@ class PcbDrawOptions(BaseOptions):
self.highlight = None self.highlight = None
else: else:
self.highlight = ','.join(self.highlight) self.highlight = ','.join(self.highlight)
# Variants
self.variant = RegOutput.check_variant(self.variant)
self.dnf_filter = BaseFilter.solve_filter(self.dnf_filter, 'dnf_filter')
# Filter # Filter
if isinstance(self.show_components, type): if isinstance(self.show_components, type):
self.show_components = '' self.show_components = ''
elif isinstance(self.show_components, str): elif isinstance(self.show_components, str):
if self.variant or self.dnf_filter:
logger.warning('Ambiguous list of components to show `{}` vs variant/filter'.format(self.show_components))
if self.show_components == 'none': if self.show_components == 'none':
self.show_components = '' self.show_components = ''
else: else:
@ -204,6 +217,39 @@ class PcbDrawOptions(BaseOptions):
f.close() f.close()
return f.name return f.name
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 c.fitted]
def _append_output(self, cmd, output):
svg = None
if self.format == 'svg':
cmd.append(output)
else:
# PNG and JPG outputs are unreliable
if shutil.which(SVG2PNG) is None:
logger.warning('`{}` not installed, using unreliable PNG/JPG conversion'.format(SVG2PNG))
logger.warning('If you experiment problems install `librsvg2-bin` or equivalent')
cmd.append(output)
elif shutil.which(CONVERT) is None:
logger.warning('`{}` not installed, using unreliable PNG/JPG conversion'.format(CONVERT))
logger.warning('If you experiment problems install `imagemagick` or equivalent')
cmd.append(output)
else:
svg = _get_tmp_name('.svg')
cmd.append(svg)
return svg
def run(self, output_dir, board): def run(self, output_dir, board):
check_script(PCBDRAW, URL_PCBDRAW, '0.6.0') check_script(PCBDRAW, URL_PCBDRAW, '0.6.0')
# Output file name # Output file name
@ -231,6 +277,10 @@ class PcbDrawOptions(BaseOptions):
if self.highlight: if self.highlight:
cmd.extend(['-a', self.highlight]) cmd.extend(['-a', self.highlight])
if self.show_components is not None: if self.show_components is not None:
to_add = ','.join(self.get_filtered_refs())
if self.show_components and to_add:
self.show_components += ','
self.show_components += to_add
cmd.extend(['-f', self.show_components]) cmd.extend(['-f', self.show_components])
if self.vcuts: if self.vcuts:
cmd.append('-v') cmd.append('-v')
@ -247,22 +297,7 @@ class PcbDrawOptions(BaseOptions):
tmp_remap = None tmp_remap = None
# The board & output # The board & output
cmd.append(GS.pcb_file) cmd.append(GS.pcb_file)
svg = None svg = self._append_output(cmd, output)
if self.format == 'svg':
cmd.append(output)
else:
# PNG and JPG outputs are unreliable
if shutil.which(SVG2PNG) is None:
logger.warning('`{}` not installed, using unreliable PNG/JPG conversion'.format(SVG2PNG))
logger.warning('If you experiment problems install `librsvg2-bin` or equivalent')
cmd.append(output)
elif shutil.which(CONVERT) is None:
logger.warning('`{}` not installed, using unreliable PNG/JPG conversion'.format(CONVERT))
logger.warning('If you experiment problems install `imagemagick` or equivalent')
cmd.append(output)
else:
svg = _get_tmp_name('.svg')
cmd.append(svg)
# Execute and inform is successful # Execute and inform is successful
_run_command(cmd, tmp_remap, tmp_style) _run_command(cmd, tmp_remap, tmp_style)
if svg is not None: if svg is not None:

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

View File

@ -69,6 +69,7 @@ def test_pcbdraw_miss_rsvg(caplog, monkeypatch):
o.style = '' o.style = ''
o.remap = None o.remap = None
o.format = 'jpg' o.format = 'jpg'
o.config()
cov.load() cov.load()
cov.start() cov.start()
o.run('', None) o.run('', None)
@ -87,6 +88,7 @@ def test_pcbdraw_miss_convert(caplog, monkeypatch):
o.style = '' o.style = ''
o.remap = None o.remap = None
o.format = 'jpg' o.format = 'jpg'
o.config()
cov.load() cov.load()
cov.start() cov.start()
o.run('', None) o.run('', None)
@ -94,3 +96,37 @@ def test_pcbdraw_miss_convert(caplog, monkeypatch):
cov.save() cov.save()
assert 'using unreliable PNG/JPG' in caplog.text, caplog.text assert 'using unreliable PNG/JPG' in caplog.text, caplog.text
assert 'imagemagick' in caplog.text, caplog.text assert 'imagemagick' in caplog.text, caplog.text
def test_pcbdraw_variant_1():
prj = 'kibom-variant_3'
ctx = context.TestContext('test_pcbdraw_variant_1', prj, 'pcbdraw_variant_1', '')
ctx.run()
# Check all outputs are there
fname = prj+'-top.png'
ctx.expect_out_file(fname)
ctx.compare_image(fname)
ctx.clean_up()
def test_pcbdraw_variant_2():
prj = 'kibom-variant_3'
ctx = context.TestContext('test_pcbdraw_variant_2', prj, 'pcbdraw_variant_2', '')
ctx.run()
# Check all outputs are there
fname = prj+'-top-C1.png'
ctx.expect_out_file(fname)
ctx.compare_image(fname)
ctx.clean_up()
def test_pcbdraw_variant_3():
prj = 'kibom-variant_3'
ctx = context.TestContext('test_pcbdraw_variant_1', prj, 'pcbdraw_variant_3', '')
ctx.run()
# Check all outputs are there
fname = prj+'-top.png'
ctx.expect_out_file(fname)
ctx.compare_image(fname)
assert ctx.search_err("Ambiguous list of components to show .?none.? vs variant/filter")
ctx.clean_up()

View File

@ -13,6 +13,7 @@ outputs:
mirror: True mirror: True
vcuts: True vcuts: True
warnings: all warnings: all
show_components: all
- name: PcbDraw - name: PcbDraw
comment: "PcbDraw test bottom" comment: "PcbDraw test bottom"

View File

@ -0,0 +1,18 @@
# Example KiBot config file
kibot:
version: 1
variants:
- name: 'default'
comment: 'Default variant'
type: ibom
variants_blacklist: T2,T3
outputs:
- name: 'pcbdraw_default'
comment: "PcbDraw w/variant"
type: pcbdraw
options:
variant: default
format: png

View File

@ -0,0 +1,22 @@
# Example KiBot config file
kibot:
version: 1
variants:
- name: 'default'
comment: 'Default variant'
type: ibom
file_id: '-C1'
variants_blacklist: T2,T3
outputs:
- name: 'pcbdraw_default'
comment: "PcbDraw w/variant"
type: pcbdraw
options:
variant: default
format: png
# This isn't a good idea, but works
show_components:
- 'C1'

View File

@ -0,0 +1,19 @@
# Example KiBot config file
kibot:
version: 1
variants:
- name: 'default'
comment: 'Default variant'
type: ibom
variants_blacklist: T2,T3
outputs:
- name: 'pcbdraw_default'
comment: "PcbDraw w/variant"
type: pcbdraw
options:
variant: default
format: png
# This is incoherent: all or filtered?
show_components: none