Added support for PcbDraw
This commit is contained in:
parent
c468dd44e1
commit
52e6bb1b5f
|
|
@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Added
|
||||
- The layers entry is much more flexible now.
|
||||
Many changes, read the README.md
|
||||
- PcbDraw output.
|
||||
- -e/--schematic option to specify any schematic (not just derived from the PCB
|
||||
name.
|
||||
- -x/--example option to generate a complete configuration example.
|
||||
|
|
|
|||
45
README.md
45
README.md
|
|
@ -321,7 +321,7 @@ Next time you need this list just use an alias, like this:
|
|||
- `map`: [dict|string] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map.
|
||||
Not generated unless a format is specified.
|
||||
* Valid keys:
|
||||
- No available options
|
||||
- `type`: [string='pdf'] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map.
|
||||
- `metric_units`: [boolean=true] use metric units instead of inches.
|
||||
- `minimal_header`: [boolean=false] use a minimal header in the file.
|
||||
- `mirror_y_axis`: [boolean=false] invert the Y axis.
|
||||
|
|
@ -345,7 +345,7 @@ Next time you need this list just use an alias, like this:
|
|||
- `map`: [dict|string] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map.
|
||||
Not generated unless a format is specified.
|
||||
* Valid keys:
|
||||
- No available options
|
||||
- `type`: [string='pdf'] [hpgl,ps,gerber,dxf,svg,pdf] format for a graphical drill map.
|
||||
- `report`: [dict|string] name of the drill report. Not generated unless a name is specified.
|
||||
* Valid keys:
|
||||
- `filename`: [string=''] name of the drill report. Not generated unless a name is specified.
|
||||
|
|
@ -448,7 +448,8 @@ Next time you need this list just use an alias, like this:
|
|||
%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.
|
||||
%T : bom generation time.
|
||||
Extension .html will be added automatically.
|
||||
- `netlist_file`: [string=''] Path to netlist or xml file.
|
||||
- `no_blacklist_virtual`: [boolean=false] Do not blacklist virtual components.
|
||||
- `no_redraw_on_drag`: [boolean=false] Do not redraw pcb on drag by default.
|
||||
|
|
@ -479,6 +480,44 @@ Next time you need this list just use an alias, like this:
|
|||
with a BOM file exported for each variant, separate
|
||||
variants with the ';' (semicolon) character.
|
||||
|
||||
* PcbDraw - Beautiful 2D PCB render
|
||||
* Type: `pcbdraw`
|
||||
* Description: Exports the PCB as a 2D model (SVG, PNG or JPG).
|
||||
Uses configurable colors.
|
||||
Can also render the components if the 2D models are available
|
||||
* Valid keys:
|
||||
- `comment`: [string=''] A comment for documentation purposes.
|
||||
- `dir`: [string='.'] Output directory for the generated files.
|
||||
- `name`: [string=''] Used to identify this particular output definition.
|
||||
- `options`: [dict] Options for the `pcbdraw` output.
|
||||
* Valid keys:
|
||||
- `bottom`: [boolean=false] render the bottom side of the board (default is top side).
|
||||
- `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.
|
||||
- `highlight`: [list(string)] list of components to highlight.
|
||||
- `libs`: [list(string)] list of libraries.
|
||||
- `mirror`: [boolean=false] mirror the board.
|
||||
- `no_drillholes`: [boolean=false] do not make holes transparent.
|
||||
- `output`: [string='%f-%i.%x'] name for the generated file.
|
||||
- `placeholder`: [boolean=false] show placeholder for missing components.
|
||||
- `remap`: [dict|None] replacements for PCB references using components (lib:component).
|
||||
- `show_components`: [string|list(string)] [none,all] list of components to draw, can be also a string for none or all.
|
||||
The default is none.
|
||||
- `style`: [string|dict] PCB style (colors). An internal name, the name of a JSON file or the style options.
|
||||
* Valid keys:
|
||||
- `board`: [string='#4ca06c'] color for the board without copper (covered by solder mask).
|
||||
- `clad`: [string='#9c6b28'] color for the PCB core (not covered by solder mask).
|
||||
- `copper`: [string='#417e5a'] color for the copper zones (covered by solder mask).
|
||||
- `highlight_on_top`: [boolean=false] highlight over the component (not under).
|
||||
- `highlight_padding`: [number=1.5] [0,1000] how much the highlight extends around the component [mm].
|
||||
- `highlight_style`: [string='stroke:none;fill:#ff0000;opacity:0.5;'] SVG code for the highlight style.
|
||||
- `outline`: [string='#000000'] color for the outline.
|
||||
- `pads`: [string='#b5ae30'] color for the exposed pads (metal finish).
|
||||
- `silk`: [string='#f0f0f0'] color for the silk screen.
|
||||
- `vcut`: [string='#bf2600'] color for the V-CUTS.
|
||||
- `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.
|
||||
|
||||
* PDF (Portable Document Format)
|
||||
* Type: `pdf`
|
||||
* Description: Exports the PCB to the most common exhange format. Suitable for printing.
|
||||
|
|
|
|||
|
|
@ -221,7 +221,8 @@ outputs:
|
|||
# %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
|
||||
# %T : bom generation time.
|
||||
# Extension .html will be added automatically
|
||||
name_format: 'ibom'
|
||||
# [string=''] Path to netlist or xml file
|
||||
netlist_file: ''
|
||||
|
|
@ -264,6 +265,64 @@ outputs:
|
|||
# variants with the ';' (semicolon) character
|
||||
variant: ''
|
||||
|
||||
# PcbDraw - Beautiful 2D PCB render:
|
||||
# Uses configurable colors.
|
||||
# Can also render the components if the 2D models are available
|
||||
- name: 'pcbdraw_example'
|
||||
comment: 'Exports the PCB as a 2D model (SVG, PNG or JPG).'
|
||||
type: 'pcbdraw'
|
||||
dir: 'Example/pcbdraw_dir'
|
||||
options:
|
||||
# [boolean=false] render the bottom side of the board (default is top side)
|
||||
bottom: false
|
||||
# [number=300] [10,1200] dots per inch (resolution) of the generated image
|
||||
dpi: 300
|
||||
# [string='svg'] [svg,png,jpg] output format. Only used if no `output` is specified
|
||||
format: 'svg'
|
||||
# [list(string)] list of components to highlight
|
||||
highlight:
|
||||
# [list(string)] list of libraries
|
||||
libs:
|
||||
# [boolean=false] mirror the board
|
||||
mirror: false
|
||||
# [boolean=false] do not make holes transparent
|
||||
no_drillholes: false
|
||||
# [string='%f-%i.%x'] name for the generated file
|
||||
output: '%f-%i.%x'
|
||||
# [boolean=false] show placeholder for missing components
|
||||
placeholder: false
|
||||
# [dict|None] replacements for PCB references using components (lib:component)
|
||||
remap:
|
||||
# [string|list(string)] [none,all] list of components to draw, can be also a string for none or all.
|
||||
# The default is none
|
||||
show_components:
|
||||
# [string|dict] PCB style (colors). An internal name, the name of a JSON file or the style options
|
||||
style:
|
||||
# [string='#4ca06c'] color for the board without copper (covered by solder mask)
|
||||
board: '#4ca06c'
|
||||
# [string='#9c6b28'] color for the PCB core (not covered by solder mask)
|
||||
clad: '#9c6b28'
|
||||
# [string='#417e5a'] color for the copper zones (covered by solder mask)
|
||||
copper: '#417e5a'
|
||||
# [boolean=false] highlight over the component (not under)
|
||||
highlight_on_top: false
|
||||
# [number=1.5] [0,1000] how much the highlight extends around the component [mm]
|
||||
highlight_padding: 1.5
|
||||
# [string='stroke:none;fill:#ff0000;opacity:0.5;'] SVG code for the highlight style
|
||||
highlight_style: 'stroke:none;fill:#ff0000;opacity:0.5;'
|
||||
# [string='#000000'] color for the outline
|
||||
outline: '#000000'
|
||||
# [string='#b5ae30'] color for the exposed pads (metal finish)
|
||||
pads: '#b5ae30'
|
||||
# [string='#f0f0f0'] color for the silk screen
|
||||
silk: '#f0f0f0'
|
||||
# [string='#bf2600'] color for the V-CUTS
|
||||
vcut: '#bf2600'
|
||||
# [boolean=false] render V-CUTS on the Cmts.User layer
|
||||
vcuts: false
|
||||
# [string='visible'] [visible,all,none] using visible only the warnings about components in the visible side are generated
|
||||
warnings: 'visible'
|
||||
|
||||
# PDF (Portable Document Format):
|
||||
# Note that this output isn't the best for documating your project.
|
||||
# This output is what you get from the File/Plot menu in pcbnew.
|
||||
|
|
|
|||
|
|
@ -175,12 +175,14 @@ def trim(docstring):
|
|||
def print_output_options(name, cl, indent):
|
||||
ind_str = indent*' '
|
||||
obj = cl()
|
||||
print(ind_str+'* Valid keys:')
|
||||
num_opts = 0
|
||||
for k, v in obj.get_attrs_gen():
|
||||
if k == 'type':
|
||||
if k == 'type' and indent == 2:
|
||||
# Type is fixed for an output
|
||||
continue
|
||||
if not num_opts:
|
||||
# We found one, put the title
|
||||
print(ind_str+'* Valid keys:')
|
||||
help = getattr(obj, '_help_'+k)
|
||||
if help is None:
|
||||
help = 'Undocumented' # pragma: no cover
|
||||
|
|
@ -194,8 +196,8 @@ def print_output_options(name, cl, indent):
|
|||
num_opts = num_opts+1
|
||||
if isinstance(v, type):
|
||||
print_output_options('', v, indent+4)
|
||||
if num_opts == 0:
|
||||
print(ind_str+' - No available options')
|
||||
# if num_opts == 0:
|
||||
# print(ind_str+' - No available options')
|
||||
|
||||
|
||||
def print_one_out_help(details, n, o):
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ NO_PCBNEW_MODULE = 16
|
|||
CORRUPTED_PCB = 17
|
||||
KICAD2STEP_ERR = 18
|
||||
WONT_OVERWRITE = 19
|
||||
PCBDRAW_ERR = 20
|
||||
|
||||
CMD_EESCHEMA_DO = 'eeschema_do'
|
||||
URL_EESCHEMA_DO = 'https://github.com/INTI-CMNB/kicad-automation-scripts'
|
||||
|
|
@ -33,5 +34,6 @@ URL_KIBOM = 'https://github.com/INTI-CMNB/KiBoM'
|
|||
CMD_IBOM = 'generate_interactive_bom.py'
|
||||
URL_IBOM = 'https://github.com/INTI-CMNB/InteractiveHtmlBom'
|
||||
KICAD2STEP = 'kicad2step'
|
||||
PCBDRAW = 'pcbdraw'
|
||||
EXAMPLE_CFG = 'example.kiplot.yaml'
|
||||
AUTO_SCALE = 0
|
||||
|
|
|
|||
|
|
@ -1,6 +1,10 @@
|
|||
import os
|
||||
import re
|
||||
import inspect
|
||||
from re import (compile)
|
||||
from re import compile
|
||||
from datetime import datetime
|
||||
from .error import KiPlotConfigurationError
|
||||
from .gs import GS
|
||||
from . import log
|
||||
|
||||
logger = log.get_logger(__name__)
|
||||
|
|
@ -138,6 +142,39 @@ class Optionable(object):
|
|||
attrs = self.get_attrs_for()
|
||||
return ((k, v) for k, v in attrs.items() if k[0] != '_')
|
||||
|
||||
def expand_filename(self, name, id='', ext=''):
|
||||
""" Expands %x values in filenames """
|
||||
if GS.board:
|
||||
# This is based on InterativeHtmlBom expansion
|
||||
title_block = GS.board.GetTitleBlock()
|
||||
file_date = title_block.GetDate()
|
||||
if not file_date:
|
||||
file_mtime = os.path.getmtime(GS.pcb_file)
|
||||
file_date = datetime.fromtimestamp(file_mtime).strftime('%Y-%m-%d_%H-%M-%S')
|
||||
pcb_file_name = os.path.splitext(os.path.basename(GS.pcb_file))[0]
|
||||
title = title_block.GetTitle()
|
||||
if not title:
|
||||
title = pcb_file_name
|
||||
revision = title_block.GetRevision()
|
||||
company = title_block.GetCompany()
|
||||
n = datetime.now()
|
||||
today = n.strftime('%Y-%m-%d')
|
||||
time = n.strftime('%H-%M-%S')
|
||||
# Do the replacements
|
||||
name = name.replace('%f', pcb_file_name)
|
||||
name = name.replace('%p', title)
|
||||
name = name.replace('%c', company)
|
||||
name = name.replace('%r', revision)
|
||||
name = name.replace('%d', file_date)
|
||||
name = name.replace('%D', today)
|
||||
name = name.replace('%T', time)
|
||||
name = name.replace('%i', id)
|
||||
name = name.replace('%x', ext)
|
||||
# sanitize the name to avoid characters illegal in file systems
|
||||
name = name.replace('\\', '/')
|
||||
name = re.sub(r'[?%*:|"<>]', '_', name)
|
||||
return name
|
||||
|
||||
|
||||
class BaseOptions(Optionable):
|
||||
""" A class to validate and hold output options.
|
||||
|
|
|
|||
|
|
@ -42,7 +42,8 @@ class IBoMOptions(BaseOptions):
|
|||
%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 """
|
||||
%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
|
||||
|
|
|
|||
|
|
@ -0,0 +1,245 @@
|
|||
import os
|
||||
import re
|
||||
from tempfile import (NamedTemporaryFile)
|
||||
from subprocess import (check_output, STDOUT, CalledProcessError)
|
||||
from .misc import (PCBDRAW, PCBDRAW_ERR)
|
||||
from .error import KiPlotConfigurationError
|
||||
from .gs import (GS)
|
||||
from .optionable import (BaseOptions, Optionable)
|
||||
from kiplot.macros import macros, document, output_class # noqa: F401
|
||||
from . import log
|
||||
|
||||
logger = log.get_logger(__name__)
|
||||
|
||||
|
||||
class PcbDrawStyle(Optionable):
|
||||
_color_re = re.compile(r"#[A-Fa-f0-9]{6}$")
|
||||
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
with document:
|
||||
self.copper = "#417e5a"
|
||||
""" color for the copper zones (covered by solder mask) """
|
||||
self.board = "#4ca06c"
|
||||
""" color for the board without copper (covered by solder mask) """
|
||||
self.silk = "#f0f0f0"
|
||||
""" color for the silk screen """
|
||||
self.pads = "#b5ae30"
|
||||
""" color for the exposed pads (metal finish) """
|
||||
self.outline = "#000000"
|
||||
""" color for the outline """
|
||||
self.clad = "#9c6b28"
|
||||
""" color for the PCB core (not covered by solder mask) """
|
||||
self.vcut = "#bf2600"
|
||||
""" color for the V-CUTS """
|
||||
self.highlight_on_top = False
|
||||
""" highlight over the component (not under) """
|
||||
self.highlight_style = "stroke:none;fill:#ff0000;opacity:0.5;"
|
||||
""" SVG code for the highlight style """
|
||||
self.highlight_padding = 1.5
|
||||
""" [0,1000] how much the highlight extends around the component [mm] """ # pragma: no cover
|
||||
|
||||
def validate_color(self, name):
|
||||
color = getattr(self, name)
|
||||
if not self._color_re.match(color):
|
||||
raise KiPlotConfigurationError('Invalid color for `{}` use `#rrggbb` with hex digits'.format(name))
|
||||
|
||||
def config(self, tree):
|
||||
super().config(tree)
|
||||
self.validate_color('board')
|
||||
self.validate_color('copper')
|
||||
self.validate_color('board')
|
||||
self.validate_color('silk')
|
||||
self.validate_color('pads')
|
||||
self.validate_color('outline')
|
||||
self.validate_color('clad')
|
||||
self.validate_color('vcut')
|
||||
# Not implemented but required
|
||||
self.highlight_offset = 0
|
||||
|
||||
def to_dict(self):
|
||||
return {k.replace('_', '-'): v for k, v in self.get_attrs_gen()}
|
||||
|
||||
|
||||
class PcbDrawRemap(Optionable):
|
||||
""" This class accepts a free form dict.
|
||||
No validation is done. """
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
|
||||
def config(self, tree):
|
||||
self._tree = tree
|
||||
|
||||
|
||||
class PcbDrawOptions(BaseOptions):
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
with document:
|
||||
self.style = PcbDrawStyle
|
||||
""" [string|dict] PCB style (colors). An internal name, the name of a JSON file or the style options """
|
||||
self.libs = Optionable
|
||||
""" [list(string)] list of libraries """
|
||||
self.placeholder = False
|
||||
""" show placeholder for missing components """
|
||||
self.remap = PcbDrawRemap
|
||||
""" [dict|None] replacements for PCB references using components (lib:component) """
|
||||
self.no_drillholes = False
|
||||
""" do not make holes transparent """
|
||||
self.bottom = False
|
||||
""" render the bottom side of the board (default is top side) """
|
||||
self.mirror = False
|
||||
""" mirror the board """
|
||||
self.highlight = Optionable
|
||||
""" [list(string)] list of components to highlight """
|
||||
self.show_components = Optionable
|
||||
""" [string|list(string)] [none,all] list of components to draw, can be also a string for none or all.
|
||||
The default is none """
|
||||
self.vcuts = False
|
||||
""" render V-CUTS on the Cmts.User layer """
|
||||
self.warnings = 'visible'
|
||||
""" [visible,all,none] using visible only the warnings about components in the visible side are generated """
|
||||
self.dpi = 300
|
||||
""" [10,1200] dots per inch (resolution) of the generated image """
|
||||
self.format = 'svg'
|
||||
""" [svg,png,jpg] output format. Only used if no `output` is specified """
|
||||
self.output = '%f-%i.%x'
|
||||
""" name for the generated file """ # pragma: no cover
|
||||
|
||||
def config(self, tree):
|
||||
super().config(tree)
|
||||
# Libs
|
||||
if isinstance(self.libs, type):
|
||||
self.libs = None
|
||||
else:
|
||||
self.libs = ','.join(self.libs)
|
||||
# Highlight
|
||||
if isinstance(self.highlight, type):
|
||||
self.highlight = None
|
||||
else:
|
||||
self.highlight = ','.join(self.highlight)
|
||||
# Filter
|
||||
if isinstance(self.show_components, type):
|
||||
self.show_components = ''
|
||||
elif isinstance(self.show_components, str):
|
||||
if self.show_components == 'none':
|
||||
self.show_components = ''
|
||||
else:
|
||||
self.show_components = None
|
||||
else:
|
||||
self.show_components = ','.join(self.show_components)
|
||||
# Remap
|
||||
if isinstance(self.remap, type):
|
||||
self.remap = None
|
||||
elif isinstance(self.remap, PcbDrawRemap):
|
||||
self.remap = self.remap._tree
|
||||
# Style
|
||||
if isinstance(self.style, type):
|
||||
self.style = None
|
||||
elif isinstance(self.style, PcbDrawStyle):
|
||||
self.style = self.style.to_dict()
|
||||
|
||||
def _create_remap(self):
|
||||
with NamedTemporaryFile(mode='w', delete=False) as f:
|
||||
f.write('{\n')
|
||||
first = True
|
||||
for k, v in self.remap.items():
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
f.write(',\n')
|
||||
f.write(' "{}": "{}"'.format(k, v))
|
||||
f.write('\n}\n')
|
||||
f.close()
|
||||
return f.name
|
||||
|
||||
def _create_style(self):
|
||||
with NamedTemporaryFile(mode='w', delete=False) as f:
|
||||
f.write('{\n')
|
||||
first = True
|
||||
for k, v in self.style.items():
|
||||
if first:
|
||||
first = False
|
||||
else:
|
||||
f.write(',\n')
|
||||
if isinstance(v, str):
|
||||
f.write(' "{}": "{}"'.format(k, v))
|
||||
elif isinstance(v, bool):
|
||||
f.write(' "{}": {}'.format(k, str(v).lower()))
|
||||
else:
|
||||
f.write(' "{}": {}'.format(k, v))
|
||||
f.write('\n}\n')
|
||||
f.close()
|
||||
return f.name
|
||||
|
||||
def run(self, output_dir, board):
|
||||
# Output file name
|
||||
output = self.expand_filename(self.output, 'bottom' if self.bottom else 'top', self.format)
|
||||
output = os.path.abspath(os.path.join(output_dir, output))
|
||||
# Base command with overwrite
|
||||
cmd = [PCBDRAW]
|
||||
# Add user options
|
||||
tmp_style = None
|
||||
if self.style:
|
||||
if isinstance(self.style, str):
|
||||
cmd.extend(['-s', self.style])
|
||||
else:
|
||||
tmp_style = self._create_style()
|
||||
cmd.extend(['-s', tmp_style])
|
||||
if self.libs:
|
||||
cmd.extend(['-l', self.libs])
|
||||
if self.placeholder:
|
||||
cmd.append('--placeholder')
|
||||
if self.no_drillholes:
|
||||
cmd.append('--no-drillholes')
|
||||
if self.bottom:
|
||||
cmd.append('-b')
|
||||
if self.mirror:
|
||||
cmd.append('--mirror')
|
||||
if self.highlight:
|
||||
cmd.extend(['-a', self.highlight])
|
||||
if self.show_components is not None:
|
||||
cmd.extend(['-f', self.show_components])
|
||||
if self.vcuts:
|
||||
cmd.append('-v')
|
||||
if self.warnings == 'all':
|
||||
cmd.append('--warn-back')
|
||||
elif self.warnings == 'none':
|
||||
cmd.append('--silent')
|
||||
if self.dpi:
|
||||
cmd.extend(['--dpi', str(self.dpi)])
|
||||
if self.remap:
|
||||
tmp_remap = self._create_remap()
|
||||
cmd.extend(['-m', tmp_remap])
|
||||
else:
|
||||
tmp_remap = None
|
||||
# The board & output
|
||||
cmd.append(GS.pcb_file)
|
||||
cmd.append(output)
|
||||
# Execute and inform is successful
|
||||
logger.debug('Executing: '+str(cmd))
|
||||
try:
|
||||
cmd_output = check_output(cmd, stderr=STDOUT)
|
||||
except CalledProcessError as e:
|
||||
logger.error('Failed to run %s, error %d', PCBDRAW, e.returncode)
|
||||
if e.output:
|
||||
logger.debug('Output from command: '+e.output.decode())
|
||||
exit(PCBDRAW_ERR)
|
||||
finally:
|
||||
if tmp_remap:
|
||||
os.remove(tmp_remap)
|
||||
if tmp_style:
|
||||
os.remove(tmp_style)
|
||||
logger.debug('Output from command:\n'+cmd_output.decode())
|
||||
|
||||
|
||||
@output_class
|
||||
class PcbDraw(BaseOutput): # noqa: F821
|
||||
""" PcbDraw - Beautiful 2D PCB render
|
||||
Exports the PCB as a 2D model (SVG, PNG or JPG).
|
||||
Uses configurable colors.
|
||||
Can also render the components if the 2D models are available """
|
||||
def __init__(self):
|
||||
super().__init__()
|
||||
with document:
|
||||
self.options = PcbDrawOptions
|
||||
""" [dict] Options for the `pcbdraw` output """ # pragma: no cover
|
||||
|
|
@ -41,7 +41,8 @@ from utils import context
|
|||
prev_dir = os.path.dirname(prev_dir)
|
||||
if prev_dir not in sys.path:
|
||||
sys.path.insert(0, prev_dir)
|
||||
from kiplot.misc import (EXIT_BAD_ARGS, EXIT_BAD_CONFIG, NO_PCB_FILE, NO_SCH_FILE, EXAMPLE_CFG, WONT_OVERWRITE, CORRUPTED_PCB)
|
||||
from kiplot.misc import (EXIT_BAD_ARGS, EXIT_BAD_CONFIG, NO_PCB_FILE, NO_SCH_FILE, EXAMPLE_CFG, WONT_OVERWRITE, CORRUPTED_PCB,
|
||||
PCBDRAW_ERR)
|
||||
|
||||
|
||||
POS_DIR = 'positiondir'
|
||||
|
|
@ -433,3 +434,11 @@ def test_corrupted_pcb():
|
|||
ctx.run(CORRUPTED_PCB)
|
||||
assert ctx.search_err('Error loading PCB file')
|
||||
ctx.clean_up()
|
||||
|
||||
|
||||
def test_pcbdraw_fail():
|
||||
prj = 'bom'
|
||||
ctx = context.TestContext('PcbDrawFail', prj, 'pcbdraw_fail', '')
|
||||
ctx.run(PCBDRAW_ERR)
|
||||
assert ctx.search_err('Failed to run')
|
||||
ctx.clean_up()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,36 @@
|
|||
"""
|
||||
Tests for PcbDraw.
|
||||
|
||||
For debug information use:
|
||||
pytest-3 --log-cli-level debug
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
# 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
|
||||
|
||||
|
||||
OUT_DIR = 'PcbDraw'
|
||||
|
||||
|
||||
def test_pcbdraw_3Rs():
|
||||
prj = '3Rs'
|
||||
ctx = context.TestContext(OUT_DIR, prj, 'pcbdraw', OUT_DIR)
|
||||
ctx.run()
|
||||
ctx.expect_out_file(os.path.join(OUT_DIR, prj+'-top.svg'))
|
||||
ctx.expect_out_file(os.path.join(OUT_DIR, prj+'-bottom.svg'))
|
||||
ctx.clean_up()
|
||||
|
||||
|
||||
def test_pcbdraw_simple():
|
||||
prj = 'bom'
|
||||
ctx = context.TestContext(OUT_DIR+'_simple', prj, 'pcbdraw_simple', OUT_DIR)
|
||||
ctx.run()
|
||||
ctx.expect_out_file(os.path.join(OUT_DIR, prj+'-top.svg'))
|
||||
ctx.expect_out_file(os.path.join(OUT_DIR, prj+'-bottom.svg'))
|
||||
ctx.clean_up()
|
||||
|
|
@ -38,6 +38,8 @@ Tests various errors in the config file
|
|||
- Unknown section
|
||||
- HPGL wrong pen_number
|
||||
- KiBoM wrong format
|
||||
- PcbDraw
|
||||
- Wrong color
|
||||
|
||||
For debug information use:
|
||||
pytest-3 --log-cli-level debug
|
||||
|
|
@ -429,3 +431,10 @@ def test_error_print_pcb_no_layer():
|
|||
ctx.run(EXIT_BAD_CONFIG)
|
||||
assert ctx.search_err("Missing .?layers.? list")
|
||||
ctx.clean_up()
|
||||
|
||||
|
||||
def test_error_color():
|
||||
ctx = context.TestContext('PrPCB', 'bom', 'error_color', '')
|
||||
ctx.run(EXIT_BAD_CONFIG)
|
||||
assert ctx.search_err("Invalid color for .?board.?")
|
||||
ctx.clean_up()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,22 @@
|
|||
kiplot:
|
||||
version: 1
|
||||
|
||||
outputs:
|
||||
- name: PcbDraw
|
||||
comment: "PcbDraw test top"
|
||||
type: pcbdraw
|
||||
dir: PcbDraw
|
||||
options:
|
||||
format: svg
|
||||
style:
|
||||
board: "bogus"
|
||||
copper: "#00406a"
|
||||
silk: "#d5dce4"
|
||||
pads: "#cfb96e"
|
||||
clad: "#72786c"
|
||||
outline: "#000000"
|
||||
vcut: "#bf2600"
|
||||
highlight_on_top: false
|
||||
highlight_style: "stroke:none;fill:#ff0000;opacity:0.5;"
|
||||
highlight_padding: 1.5
|
||||
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
kiplot:
|
||||
version: 1
|
||||
|
||||
outputs:
|
||||
- name: PcbDraw
|
||||
comment: "PcbDraw test top"
|
||||
type: pcbdraw
|
||||
dir: PcbDraw
|
||||
options: &pcb_draw_ops
|
||||
format: svg
|
||||
style:
|
||||
board: "#1b1f44"
|
||||
copper: "#00406a"
|
||||
silk: "#d5dce4"
|
||||
pads: "#cfb96e"
|
||||
clad: "#72786c"
|
||||
outline: "#000000"
|
||||
vcut: "#bf2600"
|
||||
highlight_on_top: false
|
||||
highlight_style: "stroke:none;fill:#ff0000;opacity:0.5;"
|
||||
highlight_padding: 1.5
|
||||
libs:
|
||||
- default
|
||||
- eagle-default
|
||||
remap:
|
||||
L_G1: "LEDs:LED-5MM_green"
|
||||
L_B1: "LEDs:LED-5MM_blue"
|
||||
L_Y1: "LEDs:LED-5MM_yellow"
|
||||
PHOTO1: "yaqwsx:R_PHOTO_7mm"
|
||||
J8: "yaqwsx:Pin_Header_Straight_1x02_circle"
|
||||
'REF**': "dummy:dummy"
|
||||
G***: "dummy:dummy"
|
||||
svg2mod: "dummy:dummy"
|
||||
JP1: "dummy:dummy"
|
||||
JP2: "dummy:dummy"
|
||||
JP3: "dummy:dummy"
|
||||
JP4: "dummy:dummy"
|
||||
no_drillholes: False
|
||||
mirror: False
|
||||
highlight:
|
||||
- L_G1
|
||||
- L_B1
|
||||
- R10
|
||||
- RV1
|
||||
show_components: all
|
||||
vcuts: True
|
||||
warnings: visible
|
||||
dpi: 600
|
||||
|
||||
- name: PcbDraw
|
||||
comment: "PcbDraw test bottom"
|
||||
type: pcbdraw
|
||||
dir: PcbDraw
|
||||
options:
|
||||
<<: *pcb_draw_ops
|
||||
style: set-red-enig
|
||||
bottom: True
|
||||
show_components:
|
||||
- L_G1
|
||||
- L_B1
|
||||
remap:
|
||||
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
kiplot:
|
||||
version: 1
|
||||
|
||||
outputs:
|
||||
- name: PcbDraw
|
||||
comment: "PcbDraw test top"
|
||||
type: pcbdraw
|
||||
dir: PcbDraw
|
||||
options:
|
||||
format: svg
|
||||
style: bogus
|
||||
no_drillholes: True
|
||||
placeholder: True
|
||||
mirror: True
|
||||
vcuts: True
|
||||
warnings: all
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
kiplot:
|
||||
version: 1
|
||||
|
||||
outputs:
|
||||
- name: PcbDraw
|
||||
comment: "PcbDraw test top"
|
||||
type: pcbdraw
|
||||
dir: PcbDraw
|
||||
options: &pcb_draw_ops
|
||||
format: svg
|
||||
no_drillholes: True
|
||||
placeholder: True
|
||||
mirror: True
|
||||
vcuts: True
|
||||
warnings: all
|
||||
|
||||
- name: PcbDraw
|
||||
comment: "PcbDraw test bottom"
|
||||
type: pcbdraw
|
||||
dir: PcbDraw
|
||||
options:
|
||||
<<: *pcb_draw_ops
|
||||
style: set-red-enig
|
||||
bottom: True
|
||||
show_components: none
|
||||
warnings: none
|
||||
|
||||
Loading…
Reference in New Issue