Added support for variants to the PcbDraw output.
This commit is contained in:
parent
dab7baa2d4
commit
d09400d49d
|
|
@ -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.
|
||||||
|
|
|
||||||
2
Makefile
2
Makefile
|
|
@ -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:
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 |
|
|
@ -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()
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
@ -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'
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
Loading…
Reference in New Issue