Merge pull request #8 from INTI-CMNB/layer_exclude

Layer exclude
This commit is contained in:
Salvador E. Tropea 2020-09-03 17:31:00 -03:00 committed by GitHub
commit df7b237b0e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 751 additions and 21 deletions

View File

@ -18,7 +18,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Marking components as "Do Not Fit"
- Marking components as "Do Not Change"
- The internal BoM format supports KiBoM and IBoM style variants
- Schematic print to PDF supports variants. Not fitted components are crossed.
- Schematic print to PDF support for variants. Not fitted components are crossed.
- Position (Pick & Place) support for variants.
- All plot formats (gerber, pdf, svg, etc.) support for variants:
- Pads removed from *.Paste
- Drawings removed from *.Adhes
- Components crossed in *.Fab
### Fixed
- Virtual components are always excluded from position files.
## [0.6.2] - 2020-08-25
### Changed

View File

@ -109,6 +109,7 @@ gen_ref:
src/kibot -c tests/yaml_samples/print_pdf_no_inductors_1.kibot.yaml -e tests/board_samples/test_v5.sch -d $(REFDIR)
mv "$(REFDIR)no_inductor/test_v5-schematic_(no_L).pdf" $(REFDIR)
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)
cp -a $(REFILL).ok $(REFILL)
doc:

View File

@ -437,6 +437,8 @@ Next time you need this list just use an alias, like this:
- `name`: [string=''] Used to identify this particular output definition.
- `options`: [dict] Options for the `dxf` output.
* Valid keys:
- `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.
- `drill_marks`: [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale).
- `exclude_edge_layer`: [boolean=true] do not include the PCB edge layer.
- `exclude_pads_from_silkscreen`: [boolean=false] do not plot the component pads in the silk screen.
@ -450,6 +452,7 @@ Next time you need this list just use an alias, like this:
- `sketch_plot`: [boolean=false] don't fill objects, just draw the outline.
- `tent_vias`: [boolean=true] cover the vias.
- `use_aux_axis_as_origin`: [boolean=false] use the auxiliar axis as origin for coordinates.
- `variant`: [string=''] Board variant(s) to apply.
* Excellon drill format
* Type: `excellon`
@ -519,6 +522,8 @@ Next time you need this list just use an alias, like this:
* Valid keys:
- `create_gerber_job_file`: [boolean=true] creates a file with information about all the generated gerbers.
You can use it in gerbview to load all gerbers at once.
- `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.
- `exclude_edge_layer`: [boolean=true] do not include the PCB edge layer.
- `exclude_pads_from_silkscreen`: [boolean=false] do not plot the component pads in the silk screen.
- `force_plot_invisible_refs_vals`: [boolean=false] include references and values even when they are marked as invisible.
@ -535,6 +540,7 @@ Next time you need this list just use an alias, like this:
- `use_gerber_net_attributes`: [boolean=true] include netlist metadata.
- `use_gerber_x2_attributes`: [boolean=true] use the extended X2 format.
- `use_protel_extensions`: [boolean=false] use legacy Protel file extensions.
- `variant`: [string=''] Board variant(s) to apply.
* HPGL (Hewlett & Packard Graphics Language)
* Type: `hpgl`
@ -552,6 +558,8 @@ Next time you need this list just use an alias, like this:
- `name`: [string=''] Used to identify this particular output definition.
- `options`: [dict] Options for the `hpgl` output.
* Valid keys:
- `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.
- `drill_marks`: [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale).
- `exclude_edge_layer`: [boolean=true] do not include the PCB edge layer.
- `exclude_pads_from_silkscreen`: [boolean=false] do not plot the component pads in the silk screen.
@ -567,6 +575,7 @@ Next time you need this list just use an alias, like this:
- `scaling`: [number=0] scale factor (0 means autoscaling).
- `sketch_plot`: [boolean=false] don't fill objects, just draw the outline.
- `tent_vias`: [boolean=true] cover the vias.
- `variant`: [string=''] Board variant(s) to apply.
* IBoM (Interactive HTML BoM)
* Type: `ibom`
@ -750,6 +759,8 @@ Next time you need this list just use an alias, like this:
* Valid keys:
- `comment`: [string=''] A comment for documentation purposes.
- `dir`: [string='.'] Output directory for the generated files.
- `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.
- `drill_marks`: [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale).
- `exclude_edge_layer`: [boolean=true] do not include the PCB edge layer.
- `exclude_pads_from_silkscreen`: [boolean=false] do not plot the component pads in the silk screen.
@ -763,6 +774,8 @@ Next time you need this list just use an alias, like this:
- `name`: [string=''] Used to identify this particular output definition.
- `options`: [dict] Options for the `pdf` output.
* Valid keys:
- `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.
- `drill_marks`: [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale).
- `exclude_edge_layer`: [boolean=true] do not include the PCB edge layer.
- `exclude_pads_from_silkscreen`: [boolean=false] do not plot the component pads in the silk screen.
@ -775,11 +788,13 @@ Next time you need this list just use an alias, like this:
- `plot_footprint_values`: [boolean=true] include the footprint values.
- `plot_sheet_reference`: [boolean=false] currently without effect.
- `tent_vias`: [boolean=true] cover the vias.
- `variant`: [string=''] Board variant(s) to apply.
- `output`: [string='%f-%i%v.%x'] output file name, the default KiCad name if empty. Affected by global options.
- `plot_footprint_refs`: [boolean=true] include the footprint references.
- `plot_footprint_values`: [boolean=true] include the footprint values.
- `plot_sheet_reference`: [boolean=false] currently without effect.
- `tent_vias`: [boolean=true] cover the vias.
- `variant`: [string=''] Board variant(s) to apply.
* PDF PCB Print (Portable Document Format)
* Type: `pdf_pcb_print`
@ -853,6 +868,8 @@ Next time you need this list just use an alias, like this:
- `options`: [dict] Options for the `ps` output.
* Valid keys:
- `a4_output`: [boolean=true] force A4 paper size.
- `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.
- `drill_marks`: [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale).
- `exclude_edge_layer`: [boolean=true] do not include the PCB edge layer.
- `exclude_pads_from_silkscreen`: [boolean=false] do not plot the component pads in the silk screen.
@ -869,6 +886,7 @@ Next time you need this list just use an alias, like this:
- `scaling`: [number=1] scale factor (0 means autoscaling).
- `sketch_plot`: [boolean=false] don't fill objects, just draw the outline.
- `tent_vias`: [boolean=true] cover the vias.
- `variant`: [string=''] Board variant(s) to apply.
- `width_adjust`: [number=0] this width factor is intended to compensate PS printers/plotters that do not strictly obey line width settings.
Only used to plot pads and tracks.
@ -923,6 +941,8 @@ Next time you need this list just use an alias, like this:
- `name`: [string=''] Used to identify this particular output definition.
- `options`: [dict] Options for the `svg` output.
* Valid keys:
- `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.
- `drill_marks`: [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale).
- `exclude_edge_layer`: [boolean=true] do not include the PCB edge layer.
- `exclude_pads_from_silkscreen`: [boolean=false] do not plot the component pads in the silk screen.
@ -935,6 +955,7 @@ Next time you need this list just use an alias, like this:
- `plot_footprint_values`: [boolean=true] include the footprint values.
- `plot_sheet_reference`: [boolean=false] currently without effect.
- `tent_vias`: [boolean=true] cover the vias.
- `variant`: [string=''] Board variant(s) to apply.
* SVG Schematic Print
* Type: `svg_sch_print`

View File

@ -156,6 +156,9 @@ outputs:
type: 'dxf'
dir: 'Example/dxf_dir'
options:
# [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: ''
# [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale)
drill_marks: 'full'
# [boolean=true] do not include the PCB edge layer
@ -182,6 +185,8 @@ outputs:
tent_vias: true
# [boolean=false] use the auxiliar axis as origin for coordinates
use_aux_axis_as_origin: false
# [string=''] Board variant(s) to apply
variant: ''
layers: all
# Excellon drill format:
@ -252,6 +257,9 @@ outputs:
# [boolean=true] creates a file with information about all the generated gerbers.
# You can use it in gerbview to load all gerbers at once
create_gerber_job_file: true
# [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: ''
# [boolean=true] do not include the PCB edge layer
exclude_edge_layer: true
# [boolean=false] do not plot the component pads in the silk screen
@ -284,6 +292,8 @@ outputs:
use_gerber_x2_attributes: true
# [boolean=false] use legacy Protel file extensions
use_protel_extensions: false
# [string=''] Board variant(s) to apply
variant: ''
layers: all
# HPGL (Hewlett & Packard Graphics Language):
@ -293,6 +303,9 @@ outputs:
type: 'hpgl'
dir: 'Example/hpgl_dir'
options:
# [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: ''
# [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale)
drill_marks: 'full'
# [boolean=true] do not include the PCB edge layer
@ -323,6 +336,8 @@ outputs:
sketch_plot: false
# [boolean=true] cover the vias
tent_vias: true
# [string=''] Board variant(s) to apply
variant: ''
layers: all
# IBoM (Interactive HTML BoM):
@ -572,6 +587,9 @@ outputs:
type: 'pdf'
dir: 'Example/pdf_dir'
options:
# [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: ''
# [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale)
drill_marks: 'full'
# [boolean=true] do not include the PCB edge layer
@ -596,6 +614,8 @@ outputs:
plot_sheet_reference: false
# [boolean=true] cover the vias
tent_vias: true
# [string=''] Board variant(s) to apply
variant: ''
layers: all
# PDF PCB Print (Portable Document Format):
@ -659,6 +679,9 @@ outputs:
options:
# [boolean=true] force A4 paper size
a4_output: true
# [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: ''
# [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale)
drill_marks: 'full'
# [boolean=true] do not include the PCB edge layer
@ -691,6 +714,8 @@ outputs:
sketch_plot: false
# [boolean=true] cover the vias
tent_vias: true
# [string=''] Board variant(s) to apply
variant: ''
# [number=0] this width factor is intended to compensate PS printers/plotters that do not strictly obey line width settings.
# Only used to plot pads and tracks
width_adjust: 0
@ -739,6 +764,9 @@ outputs:
type: 'svg'
dir: 'Example/svg_dir'
options:
# [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: ''
# [string='full'] what to use to indicate the drill places, can be none, small or full (for real scale)
drill_marks: 'full'
# [boolean=true] do not include the PCB edge layer
@ -763,6 +791,8 @@ outputs:
plot_sheet_reference: false
# [boolean=true] cover the vias
tent_vias: true
# [string=''] Board variant(s) to apply
variant: ''
layers: all
# SVG Schematic Print:

View File

@ -48,6 +48,10 @@ AUTO_SCALE = 0
# Internal filter names
IFILL_MECHANICAL = '_mechanical'
# KiCad 5 GUI values for the attribute
UI_THT = 0
UI_SMD = 1
UI_VIRTUAL = 2
# Supported values for "do not fit"
DNF = {

View File

@ -6,18 +6,44 @@
# Project: KiBot (formerly KiPlot)
# Adapted from: https://github.com/johnbeard/kiplot
import os
from pcbnew import (GERBER_JOBFILE_WRITER, PLOT_CONTROLLER, IsCopperLayer)
from pcbnew import GERBER_JOBFILE_WRITER, PLOT_CONTROLLER, IsCopperLayer, LSET, wxPoint, EDGE_MODULE
from .out_base import (BaseOutput)
from .error import (PlotError, KiPlotConfigurationError)
from .optionable import BaseOptions
from .optionable import BaseOptions, Optionable
from .registrable import RegOutput
from .layer import Layer
from .gs import GS
from .misc import UI_VIRTUAL
from .kiplot import load_sch
from .macros import macros, document # noqa: F401
from .fil_base import BaseFilter, apply_fitted_filter
from . import log
logger = log.get_logger(__name__)
class Rect(object):
""" What KiCad returns isn't a real wxWidget's wxRect.
Here I add what I really need """
def __init__(self):
self.x1 = None
self.y1 = None
self.x2 = None
self.y2 = None
def Union(self, wxRect):
if self.x1 is None:
self.x1 = wxRect.x
self.y1 = wxRect.y
self.x2 = wxRect.x+wxRect.width
self.y2 = wxRect.y+wxRect.height
else:
self.x1 = min(self.x1, wxRect.x)
self.y1 = min(self.y1, wxRect.y)
self.x2 = max(self.x2, wxRect.x+wxRect.width)
self.y2 = max(self.y2, wxRect.y+wxRect.height)
class AnyLayerOptions(BaseOptions):
""" Base class for: DXF, Gerber, HPGL, PDF, PS and SVG """
def __init__(self):
@ -38,8 +64,18 @@ class AnyLayerOptions(BaseOptions):
""" output file name, the default KiCad name if empty """
self.tent_vias = True
""" cover the vias """
self.variant = ''
""" Board variant(s) 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__()
def config(self):
super().config()
self.variant = RegOutput.check_variant(self.variant)
self.dnf_filter = BaseFilter.solve_filter(self.dnf_filter, 'dnf_filter')
def _configure_plot_ctrl(self, po, output_dir):
logger.debug("Configuring plot controller for output")
po.SetOutputDirectory(output_dir)
@ -55,23 +91,139 @@ class AnyLayerOptions(BaseOptions):
# We'll come back to this on a per-layer basis
po.SetSkipPlotNPTH_Pads(False)
@staticmethod
def cross_module(m, rect, layer):
seg1 = EDGE_MODULE(m)
m.Add(seg1)
seg1.SetWidth(120000)
seg1.SetStart(wxPoint(rect.x1, rect.y1))
seg1.SetEnd(wxPoint(rect.x2, rect.y2))
seg1.SetLayer(layer)
seg2 = EDGE_MODULE(m)
m.Add(seg2)
seg2.SetWidth(120000)
seg2.SetStart(wxPoint(rect.x1, rect.y2))
seg2.SetEnd(wxPoint(rect.x2, rect.y1))
seg2.SetLayer(layer)
return [seg1, seg2]
def filter_components(self, board):
# Apply the variants and filters
exclude = None
if hasattr(self, 'variant') and (self.dnf_filter or self.variant):
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)
comps_hash = {c.ref: c for c in comps}
# Remove from solder past layers the filtered components
exclude = LSET()
exclude.addLayer(board.GetLayerID('F.Paste'))
exclude.addLayer(board.GetLayerID('B.Paste'))
old_layers = []
fadhes = board.GetLayerID('F.Adhes')
badhes = board.GetLayerID('B.Adhes')
old_fadhes = []
old_badhes = []
ffab = board.GetLayerID('F.Fab')
bfab = board.GetLayerID('B.Fab')
extra_ffab_lines = []
extra_bfab_lines = []
for m in board.GetModules():
ref = m.GetReference()
# Rectangle containing the drawings, no text
frect = Rect()
brect = Rect()
c = comps_hash.get(ref, None)
if (c and not c.fitted) or m.GetAttributes() == UI_VIRTUAL:
# Remove all pads from *.Paste
old_c_layers = []
for p in m.Pads():
pad_layers = p.GetLayerSet()
old_c_layers.append(pad_layers.FmtHex())
pad_layers.removeLayerSet(exclude)
p.SetLayerSet(pad_layers)
old_layers.append(old_c_layers)
# Remove any graphical item in the *.Adhes layers
# Also: meassure the *.Fab drawings size
for gi in m.GraphicalItems():
l_gi = gi.GetLayer()
if l_gi == fadhes:
gi.SetLayer(-1)
old_fadhes.append(gi)
if l_gi == badhes:
gi.SetLayer(-1)
old_badhes.append(gi)
if gi.GetClass() == 'MGRAPHIC':
if l_gi == ffab:
frect.Union(gi.GetBoundingBox().getWxRect())
if l_gi == bfab:
brect.Union(gi.GetBoundingBox().getWxRect())
# Cross the graphics in *.Fab
if frect.x1 is not None:
extra_ffab_lines.append(self.cross_module(m, frect, ffab))
else:
extra_ffab_lines.append(None)
if brect.x1 is not None:
extra_bfab_lines.append(self.cross_module(m, brect, bfab))
else:
extra_bfab_lines.append(None)
# Store the data to undo the above actions
self.comps_hash = comps_hash
self.old_layers = old_layers
self.old_fadhes = old_fadhes
self.old_badhes = old_badhes
self.extra_ffab_lines = extra_ffab_lines
self.extra_bfab_lines = extra_bfab_lines
return exclude
def unfilter_components(self, board):
for m in board.GetModules():
ref = m.GetReference()
c = self.comps_hash.get(ref, None)
if (c and not c.fitted) or m.GetAttributes() == UI_VIRTUAL:
restore = self.old_layers.pop(0)
for p in m.Pads():
pad_layers = p.GetLayerSet()
res = restore.pop(0)
pad_layers.ParseHex(res, len(res))
p.SetLayerSet(pad_layers)
restore = self.extra_ffab_lines.pop(0)
if restore:
for line in restore:
m.Remove(line)
restore = self.extra_bfab_lines.pop(0)
if restore:
for line in restore:
m.Remove(line)
fadhes = board.GetLayerID('F.Adhes')
for gi in self.old_fadhes:
gi.SetLayer(fadhes)
badhes = board.GetLayerID('B.Adhes')
for gi in self.old_badhes:
gi.SetLayer(badhes)
def run(self, output_dir, board, layers):
# fresh plot controller
plot_ctrl = PLOT_CONTROLLER(board)
# set up plot options for the whole output
po = plot_ctrl.GetPlotOptions()
self._configure_plot_ctrl(po, output_dir)
# Gerber Job files aren't automagically created
# We need to assist KiCad
create_job = po.GetCreateGerberJobFile()
if create_job:
jobfile_writer = GERBER_JOBFILE_WRITER(board)
plot_ctrl.SetColorMode(True)
# Apply the variants and filters
exclude = self.filter_components(board)
# Plot every layer in the output
layers = Layer.solve(layers)
# plot every layer in the output
for la in layers:
suffix = la.suffix
desc = la.description
@ -82,13 +234,12 @@ class AnyLayerOptions(BaseOptions):
# a copper layer
is_cu = IsCopperLayer(id)
po.SetSkipPlotNPTH_Pads(is_cu)
# Plot single layer to file
logger.debug("Opening plot file for layer `{}` format `{}`".format(la, self._plot_format))
if not plot_ctrl.OpenPlotfile(suffix, self._plot_format, desc):
# Shouldn't happen
raise PlotError("OpenPlotfile failed!") # pragma: no cover
# Compute the current file name and the one we want
k_filename = plot_ctrl.GetPlotFileName()
if self.output:
filename = self.expand_filename(output_dir, self.output, suffix, os.path.splitext(k_filename)[1][1:])
@ -101,9 +252,12 @@ class AnyLayerOptions(BaseOptions):
os.rename(k_filename, filename)
if create_job:
jobfile_writer.AddGbrFile(id, os.path.basename(filename))
# Create the job file
if create_job:
jobfile_writer.CreateJobFile(self.expand_filename(output_dir, po.gerber_job_file, 'job', 'gbrjob'))
# Restore the eliminated layers
if exclude:
self.unfilter_components(board)
def read_vals_from_po(self, po):
# excludeedgelayer

View File

@ -11,16 +11,13 @@ from pcbnew import (IU_PER_MM, IU_PER_MILS)
from .optionable import BaseOptions, Optionable
from .registrable import RegOutput
from .gs import GS
from .misc import UI_SMD, UI_VIRTUAL
from .kiplot import load_sch
from .macros import macros, document, output_class # noqa: F401
from .fil_base import BaseFilter, apply_fitted_filter
from . import log
logger = log.get_logger(__name__)
# KiCad 5 GUI values for the attribute
UI_THT = 0
UI_SMD = 1
UI_VIRTUAL = 2
class PositionOptions(BaseOptions):
@ -167,8 +164,6 @@ class PositionOptions(BaseOptions):
# Apply any filter or variant data
if comps:
c = comps_hash.get(ref, None)
if c:
logger.debug("{} {} {}".format(ref, c.fitted, c.in_bom))
if c and not c.fitted:
continue
# If passed check the position options

View File

@ -138,6 +138,7 @@
(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_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1))
(fp_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 0.5 0.5) (thickness 0.08)))
)
@ -171,6 +172,7 @@
(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_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1))
(fp_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 0.5 0.5) (thickness 0.08)))
)
@ -207,6 +209,7 @@
(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_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1))
(fp_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 0.5 0.5) (thickness 0.08)))
)
@ -242,6 +245,7 @@
(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_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1))
(fp_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 0.5 0.5) (thickness 0.08)))
)
@ -278,6 +282,7 @@
(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_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1))
(fp_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 0.5 0.5) (thickness 0.08)))
)

View File

@ -0,0 +1,308 @@
(kicad_pcb (version 20171130) (host pcbnew 5.1.6+dfsg1-1)
(general
(thickness 1.6)
(drawings 5)
(tracks 0)
(zones 0)
(modules 5)
(nets 9)
)
(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 139.89 89.63)
(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-(C1-Pad2)")
(net 2 "Net-(C1-Pad1)")
(net 3 "Net-(C2-Pad2)")
(net 4 "Net-(C2-Pad1)")
(net 5 "Net-(R1-Pad2)")
(net 6 "Net-(R1-Pad1)")
(net 7 "Net-(R2-Pad2)")
(net 8 "Net-(R2-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-(C1-Pad1)")
(add_net "Net-(C1-Pad2)")
(add_net "Net-(C2-Pad1)")
(add_net "Net-(C2-Pad2)")
(add_net "Net-(R1-Pad1)")
(add_net "Net-(R1-Pad2)")
(add_net "Net-(R2-Pad1)")
(add_net "Net-(R2-Pad2)")
)
(module Resistor_SMD:R_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F503C4A)
(at 148.555 89.154)
(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 /5F43D144)
(attr smd)
(fp_text reference R3 (at 0 -1.65) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value 1k (at 0 1.65) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1))
(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))
(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 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_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 0.5 0.5) (thickness 0.08)))
)
(pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
(pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers F.Cu F.Paste F.Mask) (roundrect_rratio 0.25))
(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 5F496A8B)
(at 141.57 90.58)
(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 /5F43D4BB)
(fp_text reference R2 (at 0 -1.65) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value 1000 (at 1.178 2.13) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1))
(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))
(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 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_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 0.5 0.5) (thickness 0.08)))
)
(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-(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 8 "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 5F503C2A)
(at 141.57 87.63)
(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 /5F43D144)
(attr smd)
(fp_text reference R1 (at 0 -1.65) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value 1k (at 0 1.65) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1))
(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))
(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 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_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 0.5 0.5) (thickness 0.08)))
)
(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-(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 6 "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))
)
)
(module Capacitor_SMD:C_0805_2012Metric (layer B.Cu) (tedit 5B36C52B) (tstamp 5F496A69)
(at 137.16 90.58)
(descr "Capacitor 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 capacitor)
(path /5F43CE1C)
(fp_text reference C2 (at 0 1.65) (layer B.SilkS)
(effects (font (size 1 1) (thickness 0.15)) (justify mirror))
)
(fp_text value "1000 pF" (at -0.508 -2.13) (layer B.Fab)
(effects (font (size 1 1) (thickness 0.15)) (justify mirror))
)
(fp_circle (center 0 0) (end 0.4 0) (layer B.Adhes) (width 0.1))
(fp_line (start 1.68 -0.95) (end -1.68 -0.95) (layer B.CrtYd) (width 0.05))
(fp_line (start 1.68 0.95) (end 1.68 -0.95) (layer B.CrtYd) (width 0.05))
(fp_line (start -1.68 0.95) (end 1.68 0.95) (layer B.CrtYd) (width 0.05))
(fp_line (start -1.68 -0.95) (end -1.68 0.95) (layer B.CrtYd) (width 0.05))
(fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer B.SilkS) (width 0.12))
(fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer B.SilkS) (width 0.12))
(fp_line (start 1 -0.6) (end -1 -0.6) (layer B.Fab) (width 0.1))
(fp_line (start 1 0.6) (end 1 -0.6) (layer B.Fab) (width 0.1))
(fp_line (start -1 0.6) (end 1 0.6) (layer B.Fab) (width 0.1))
(fp_line (start -1 -0.6) (end -1 0.6) (layer B.Fab) (width 0.1))
(fp_text user %R (at 0 0) (layer B.Fab)
(effects (font (size 0.5 0.5) (thickness 0.08)) (justify mirror))
)
(pad 2 smd roundrect (at 0.9375 0) (size 0.975 1.4) (layers B.Cu B.Paste B.Mask) (roundrect_rratio 0.25)
(net 3 "Net-(C2-Pad2)"))
(pad 1 smd roundrect (at -0.9375 0) (size 0.975 1.4) (layers B.Cu B.Paste B.Mask) (roundrect_rratio 0.25)
(net 4 "Net-(C2-Pad1)"))
(model ${KISYS3DMOD}/Capacitor_SMD.3dshapes/C_0805_2012Metric.wrl
(at (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)
(module Capacitor_SMD:C_0805_2012Metric (layer F.Cu) (tedit 5B36C52B) (tstamp 5F496A58)
(at 137.16 87.63)
(descr "Capacitor 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 capacitor)
(path /5F43BEC2)
(attr virtual)
(fp_text reference C1 (at 0 -1.65) (layer F.SilkS)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_text value 1nF (at 0 1.65) (layer F.Fab)
(effects (font (size 1 1) (thickness 0.15)))
)
(fp_circle (center 0 0) (end 0.4 0) (layer F.Adhes) (width 0.1))
(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))
(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 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_text user %R (at 0 0) (layer F.Fab)
(effects (font (size 0.5 0.5) (thickness 0.08)))
)
(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-(C1-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-(C1-Pad1)"))
(model ${KISYS3DMOD}/Capacitor_SMD.3dshapes/C_0805_2012Metric.wrl
(at (xyz 0 0 0))
(scale (xyz 1 1 1))
(rotate (xyz 0 0 0))
)
)
(gr_text "Bogus component.\nNot in schematic." (at 161.163 89.281) (layer Cmts.User)
(effects (font (size 1.5 1.5) (thickness 0.3)))
)
(gr_line (start 133.35 83.82) (end 133.35 93.98) (layer Edge.Cuts) (width 0.1) (tstamp 5F496ACC))
(gr_line (start 146.05 83.82) (end 133.35 83.82) (layer Edge.Cuts) (width 0.1))
(gr_line (start 146.05 93.98) (end 146.05 83.82) (layer Edge.Cuts) (width 0.1))
(gr_line (start 133.35 93.98) (end 146.05 93.98) (layer Edge.Cuts) (width 0.1))
)

View File

@ -0,0 +1,68 @@
EESchema Schematic File Version 4
EELAYER 30 0
EELAYER END
$Descr A4 11693 8268
encoding utf-8
Sheet 1 1
Title "KiBom Test Schematic"
Date "2020-03-12"
Rev "A"
Comp "https://github.com/SchrodingersGat/KiBom"
Comment1 ""
Comment2 ""
Comment3 ""
Comment4 ""
$EndDescr
Text Notes 500 750 0 79 ~ 0
This schematic serves as a test-file for the KiBot export script.\nHere we implement the IBoM variants style.
$Comp
L Device:C C1
U 1 1 5F43BEC2
P 1000 1700
F 0 "C1" H 1115 1746 50 0000 L CNN
F 1 "1nF" H 1115 1655 50 0000 L CNN
F 2 "Capacitor_SMD:C_0805_2012Metric" H 1038 1550 50 0001 C CNN
F 3 "~" H 1000 1700 50 0001 C CNN
F 4 "T2" H 1000 1700 50 0001 C CNN "Config"
1 1000 1700
1 0 0 -1
$EndComp
$Comp
L Device:C C2
U 1 1 5F43CE1C
P 1450 1700
F 0 "C2" H 1565 1746 50 0000 L CNN
F 1 "1000 pF" H 1565 1655 50 0000 L CNN
F 2 "Capacitor_SMD:C_0805_2012Metric" H 1488 1550 50 0001 C CNN
F 3 "~" H 1450 1700 50 0001 C CNN
F 4 "T3" H 1450 1700 50 0001 C CNN "Config"
1 1450 1700
1 0 0 -1
$EndComp
$Comp
L Device:R R1
U 1 1 5F43D144
P 2100 1700
F 0 "R1" H 2170 1746 50 0000 L CNN
F 1 "1k" H 2170 1655 50 0000 L CNN
F 2 "Resistor_SMD:R_0805_2012Metric" V 2030 1700 50 0001 C CNN
F 3 "~" H 2100 1700 50 0001 C CNN
F 4 "default" H 2100 1700 50 0001 C CNN "Config"
1 2100 1700
1 0 0 -1
$EndComp
$Comp
L Device:R R2
U 1 1 5F43D4BB
P 2500 1700
F 0 "R2" H 2570 1746 50 0000 L CNN
F 1 "1000" H 2570 1655 50 0000 L CNN
F 2 "Resistor_SMD:R_0805_2012Metric" V 2430 1700 50 0001 C CNN
F 3 "~" H 2500 1700 50 0001 C CNN
F 4 "T1" H 2500 1700 50 0001 C CNN "Config"
1 2500 1700
1 0 0 -1
$EndComp
Text Notes 5950 3200 0 118 ~ 0
The test tests the following \nvariants matrix:\n production test default\nC1 X\nC2 X X\nR1 X X X\nR2 X X\n\nproduction: blacklist T2\ntest: blacklist T1\ndefault: whitelist T1,default \n blacklist T2,T3
$EndSCHEMATC

Binary file not shown.

Binary file not shown.

View File

@ -19,6 +19,27 @@ from kibot.misc import (PLOT_ERROR)
GERBER_DIR = 'gerberdir'
ALL_LAYERS = ['B_Adhes',
'B_CrtYd',
'B_Cu',
'B_Fab',
'B_Mask',
'B_Paste',
'B_SilkS',
'Cmts_User',
'Dwgs_User',
'Eco1_User',
'Eco2_User',
'Edge_Cuts',
'F_Adhes',
'F_CrtYd',
'F_Cu',
'F_Fab',
'F_Mask',
'F_Paste',
'F_SilkS',
'Margin',
]
def test_gerber_2layer():
@ -58,3 +79,40 @@ def test_gerber_inner_wrong():
ctx.run(PLOT_ERROR)
assert ctx.search_err('is not valid for this board')
ctx.clean_up()
def compose_fname(dir, prefix, layer, suffix, ext='gbr'):
return os.path.join(dir, prefix+'-'+layer+suffix+'.'+ext)
def check_layers_exist(ctx, dir, prefix, layers, suffix):
for layer in layers:
ctx.expect_out_file(compose_fname(dir, prefix, layer, suffix))
ctx.expect_out_file(compose_fname(dir, prefix, 'job', suffix, 'gbrjob'))
def check_components(ctx, dir, prefix, layers, suffix, exclude, include):
for layer in layers:
fname = compose_fname(dir, prefix, layer, suffix)
inc = [r'%TO\.C,{}\*%'.format(v) for v in include]
ctx.search_in_file(fname, inc)
exc = [r'%TO\.C,{}\*%'.format(v) for v in exclude]
ctx.search_not_in_file(fname, exc)
def test_gerber_variant_1():
prj = 'kibom-variant_3'
ctx = context.TestContext('test_gerber_variant_1', prj, 'gerber_variant_1', GERBER_DIR)
ctx.run()
# C1 is virtual, not included for all cases
# R3 is a component added to the PCB, included in all cases
# variant: default directory: gerber components: R1, R2 and R3
check_layers_exist(ctx, 'gerber', prj, ALL_LAYERS, '')
check_components(ctx, 'gerber', prj, ['F_Paste', 'F_Adhes'], '', ['C1', 'C2'], ['R1', 'R2', 'R3'])
# variant: production directory: production components: R1, R2, R3 and C2
check_layers_exist(ctx, 'production', prj, ALL_LAYERS, '_(production)')
check_components(ctx, 'production', prj, ['F_Paste', 'F_Adhes'], '_(production)', ['C1'], ['R1', 'R2', 'R3', 'C2'])
# variant: test directory: test components: R1, R3 and C2
check_layers_exist(ctx, 'test', prj, ALL_LAYERS, '_(test)')
check_components(ctx, 'test', prj, ['F_Paste', 'F_Adhes'], '_(test)', ['C1', 'R2'], ['R1', 'R3', 'C2'])
ctx.clean_up()

View File

@ -22,13 +22,11 @@ def test_pdf():
prj = 'simple_2layer'
ctx = context.TestContext('Plot_PDF', prj, 'pdf', PS_DIR)
ctx.run()
f_cu = ctx.get_gerber_filename('F_Cu', '.pdf')
f_silk = ctx.get_gerber_filename('B_Silks', '.pdf')
ctx.expect_out_file(f_cu)
ctx.expect_out_file(f_silk)
ctx.dont_expect_out_file(ctx.get_gerber_job_filename())
ctx.clean_up()
@ -36,7 +34,20 @@ def test_pdf_refill():
prj = 'zone-refill'
ctx = context.TestContext('Plot_PDF_Refill', prj, 'pdf_zone-refill', '')
ctx.run()
b_cu = ctx.get_gerber_filename('B_Cu', '.pdf')
ctx.expect_out_file(b_cu)
ctx.compare_image(b_cu)
ctx.clean_up()
def test_pdf_variant_1():
prj = 'kibom-variant_4'
ctx = context.TestContext('test_pdf_variant_1', prj, 'pdf_variant_1', '')
ctx.run()
fname = prj+'-F_Fab.pdf'
ctx.expect_out_file(fname)
ctx.compare_image(fname)
fname = prj+'-B_Fab.pdf'
ctx.expect_out_file(fname)
ctx.compare_image(fname)
ctx.clean_up()

View File

@ -304,9 +304,11 @@ class TestContext(object):
with open(self.get_out_path(file)) as f:
txt = f.read()
for t in texts:
logging.debug('- r"'+t+'"')
msg = '- r"'+t+'"'
m = re.search(t, txt, re.MULTILINE)
assert m is None
assert m is None, msg
logging.debug(msg+' OK')
# logging.debug(' '+m.group(0))
def compare_image(self, image, reference=None, diff='diff.png', ref_out_dir=False):
""" For images and single page PDFs """

View File

@ -0,0 +1,47 @@
# Example KiBot config file
kibot:
version: 1
variants:
- name: 'production'
comment: 'Production variant'
type: ibom
file_id: '_(production)'
variants_blacklist: T2
- name: 'test'
comment: 'Test variant'
type: ibom
file_id: '_(test)'
variants_blacklist: T1
- name: 'default'
comment: 'Default variant'
type: ibom
variants_blacklist: T2,T3
outputs:
- name: 'gerber'
comment: "Gerber"
type: gerber
dir: gerber
layers: all
options:
variant: default
- name: 'gerber_production'
comment: "Gerber for production"
type: gerber
dir: production
layers: all
options:
variant: production
- name: 'gerber_test'
comment: "Gerber for test"
type: gerber
dir: test
layers: all
options:
variant: test

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: 'pdf_default'
comment: "PDF w/variant"
type: pdf
layers: [ F.Fab, B.Fab ]
options:
variant: default