Moved repeated code related to variants to a base class.

This commit is contained in:
Salvador E. Tropea 2020-09-06 17:36:29 -03:00
parent f7e8033a09
commit 64f50d2a07
10 changed files with 175 additions and 270 deletions

View File

@ -452,7 +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.
- `variant`: [string=''] Board variant to apply.
* Excellon drill format
* Type: `excellon`
@ -540,7 +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.
- `variant`: [string=''] Board variant to apply.
* HPGL (Hewlett & Packard Graphics Language)
* Type: `hpgl`
@ -575,7 +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.
- `variant`: [string=''] Board variant to apply.
* IBoM (Interactive HTML BoM)
* Type: `ibom`
@ -640,6 +640,8 @@ Next time you need this list just use an alias, like this:
* Type: `kibom`
* Description: Used to generate the BoM in HTML or CSV format using the KiBoM plug-in.
For more information: https://github.com/INTI-CMNB/KiBoM
Note that this output is provided as a compatibility tool.
We recommend using the `bom` output instead.
This output is what you get from the 'Tools/Generate Bill of Materials' menu in eeschema.
* Valid keys:
- `comment`: [string=''] A comment for documentation purposes.
@ -724,6 +726,7 @@ Next time you need this list just use an alias, like this:
are output to the BoM. To specify multiple variants,
with a BOM file exported for each variant, separate
variants with the ';' (semicolon) character.
This isn't related to the KiBot concept of variants.
* PcbDraw - Beautiful 2D PCB render
* Type: `pcbdraw`
@ -803,13 +806,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.
- `variant`: [string=''] Board variant 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.
- `variant`: [string=''] Board variant to apply.
* PDF PCB Print (Portable Document Format)
* Type: `pdf_pcb_print`
@ -845,7 +848,8 @@ Next time you need this list just use an alias, like this:
- `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.
- `output`: [string='%f-%i%v.%x'] filename for the output PDF (%i=schematic %x=pdf). Affected by global options.
- `variant`: [string=''] Board variant(s), used to determine which components are crossed..
- `variant`: [string=''] Board variant to apply.
Not fitted components are crossed.
* Pick & place
* Type: `position`
@ -901,7 +905,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.
- `variant`: [string=''] Board variant 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.
@ -918,7 +922,7 @@ Next time you need this list just use an alias, like this:
* 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.
- `variant`: [string=''] Board variant(s) to apply.
- `variant`: [string=''] Board variant to apply.
* STEP (ISO 10303-21 Clear Text Encoding of the Exchange Structure)
* Type: `step`
@ -973,7 +977,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.
- `variant`: [string=''] Board variant to apply.
* SVG Schematic Print
* Type: `svg_sch_print`

View File

@ -185,7 +185,7 @@ 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
# [string=''] Board variant to apply
variant: ''
layers: all
@ -292,7 +292,7 @@ outputs:
use_gerber_x2_attributes: true
# [boolean=false] use legacy Protel file extensions
use_protel_extensions: false
# [string=''] Board variant(s) to apply
# [string=''] Board variant to apply
variant: ''
layers: all
@ -336,7 +336,7 @@ outputs:
sketch_plot: false
# [boolean=true] cover the vias
tent_vias: true
# [string=''] Board variant(s) to apply
# [string=''] Board variant to apply
variant: ''
layers: all
@ -425,6 +425,8 @@ outputs:
# KiBoM (KiCad Bill of Materials):
# For more information: https://github.com/INTI-CMNB/KiBoM
# Note that this output is provided as a compatibility tool.
# We recommend using the `bom` output instead.
# This output is what you get from the 'Tools/Generate Bill of Materials' menu in eeschema.
- name: 'kibom_example'
comment: 'Used to generate the BoM in HTML or CSV format using the KiBoM plug-in.'
@ -532,7 +534,8 @@ outputs:
# [string=''] Board variant(s), used to determine which components
# are output to the BoM. To specify multiple variants,
# with a BOM file exported for each variant, separate
# variants with the ';' (semicolon) character
# variants with the ';' (semicolon) character.
# This isn't related to the KiBot concept of variants
variant: ''
# PcbDraw - Beautiful 2D PCB render:
@ -633,7 +636,7 @@ outputs:
plot_sheet_reference: false
# [boolean=true] cover the vias
tent_vias: true
# [string=''] Board variant(s) to apply
# [string=''] Board variant to apply
variant: ''
layers: all
@ -663,7 +666,8 @@ outputs:
dnf_filter: ''
# [string='%f-%i%v.%x'] filename for the output PDF (%i=schematic %x=pdf). Affected by global options
output: '%f-%i%v.%x'
# [string=''] Board variant(s), used to determine which components are crossed.
# [string=''] Board variant to apply.
# Not fitted components are crossed
variant: ''
# Pick & place:
@ -733,7 +737,7 @@ outputs:
sketch_plot: false
# [boolean=true] cover the vias
tent_vias: true
# [string=''] Board variant(s) to apply
# [string=''] Board variant 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
@ -751,7 +755,7 @@ outputs:
# [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=''] Board variant(s) to apply
# [string=''] Board variant to apply
variant: ''
# STEP (ISO 10303-21 Clear Text Encoding of the Exchange Structure):
@ -815,7 +819,7 @@ outputs:
plot_sheet_reference: false
# [boolean=true] cover the vias
tent_vias: true
# [string=''] Board variant(s) to apply
# [string=''] Board variant to apply
variant: ''
layers: all

View File

@ -9,14 +9,11 @@ import os
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, Optionable
from .registrable import RegOutput
from .layer import Layer
from .gs import GS
from .misc import UI_VIRTUAL
from .kiplot import load_sch
from .out_base import VariantOptions
from .macros import macros, document # noqa: F401
from .fil_base import BaseFilter, apply_fitted_filter
from . import log
logger = log.get_logger(__name__)
@ -44,7 +41,7 @@ class Rect(object):
self.y2 = max(self.y2, wxRect.y+wxRect.height)
class AnyLayerOptions(BaseOptions):
class AnyLayerOptions(VariantOptions):
""" Base class for: DXF, Gerber, HPGL, PDF, PS and SVG """
def __init__(self):
with document:
@ -64,18 +61,8 @@ 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)
@ -108,78 +95,69 @@ class AnyLayerOptions(BaseOptions):
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
""" Apply the variants and filters """
if not self._comps:
return None
comps_hash = self.get_refs_hash()
# 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):
@ -209,6 +187,7 @@ class AnyLayerOptions(BaseOptions):
gi.SetLayer(badhes)
def run(self, output_dir, board, layers):
super().run(output_dir, board)
# fresh plot controller
plot_ctrl = PLOT_CONTROLLER(board)
# set up plot options for the whole output

View File

@ -3,8 +3,11 @@
# Copyright (c) 2020 Instituto Nacional de Tecnología Industrial
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
from .gs import GS
from .kiplot import load_sch
from .registrable import RegOutput
from .optionable import Optionable
from .optionable import Optionable, BaseOptions
from .fil_base import BaseFilter, apply_fitted_filter
from .macros import macros, document # noqa: F401
from . import log
@ -64,3 +67,51 @@ class BoMRegex(Optionable):
""" {column} """
self.regexp = None
""" {regex} """
class VariantOptions(BaseOptions):
""" BaseOptions plus generic support for variants. """
def __init__(self):
super().__init__()
with document:
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 """
self._comps = None
def config(self):
super().config()
self.variant = RegOutput.check_variant(self.variant)
self.dnf_filter = BaseFilter.solve_filter(self.dnf_filter, 'dnf_filter')
def get_refs_hash(self):
if not self._comps:
return None
return {c.ref: c for c in self._comps}
def get_fitted_refs(self):
if not self._comps:
return []
return [c.ref for c in self._comps if c.fitted]
def get_not_fitted_refs(self):
if not self._comps:
return []
return [c.ref for c in self._comps if not c.fitted]
def run(self, output_dir, board):
""" Makes the list of components available """
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)
self._comps = comps

View File

@ -2,17 +2,16 @@ import os
from subprocess import (check_output, STDOUT, CalledProcessError)
from .misc import (CMD_IBOM, URL_IBOM, BOM_ERROR)
from .gs import (GS)
from .optionable import BaseOptions, Optionable
from .registrable import RegOutput
from .kiplot import check_script, load_sch
from .fil_base import BaseFilter, apply_fitted_filter
from .kiplot import check_script
from .out_base import VariantOptions
from .macros import macros, document, output_class # noqa: F401
from . import log
logger = log.get_logger(__name__)
WARNING_MIX = "Avoid using it in conjunction with with IBoM native filtering options"
class IBoMOptions(BaseOptions):
class IBoMOptions(VariantOptions):
def __init__(self):
with document:
self.output = GS.def_global_output
@ -82,36 +81,12 @@ class IBoMOptions(BaseOptions):
""" Name of the extra field that indicates do not populate status.
Components with this field not empty will be blacklisted.
IBoM option, avoid using in conjunction with KiBot variants/filters """
self.variant = ''
""" Board variant to apply.
Avoid using it in conjunction with with IBoM native filtering options """
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.
Avoid using it in conjunction with with IBoM native filtering options """
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')
# TODO: move to a base class?
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 not c.fitted]
self.add_to_doc('variant', WARNING_MIX)
self.add_to_doc('dnf_filter', WARNING_MIX)
def run(self, output_dir, board):
super().run(output_dir, board)
check_script(CMD_IBOM, URL_IBOM)
logger.debug('Doing Interactive BoM')
# Tell ibom we don't want to use the screen
@ -124,7 +99,7 @@ class IBoMOptions(BaseOptions):
self.name_format = 'ibom'
cur = os.path.join(output_dir, 'ibom.html')
# Apply variants/filters
to_remove = ','.join(self.get_filtered_refs())
to_remove = ','.join(self.get_not_fitted_refs())
if self.blacklist and to_remove:
self.blacklist += ','
self.blacklist += to_remove

View File

@ -13,10 +13,8 @@ from .misc import PCBDRAW, PCBDRAW_ERR, URL_PCBDRAW
from .kiplot import check_script
from .error import KiPlotConfigurationError
from .gs import (GS)
from .optionable import BaseOptions, Optionable
from .registrable import RegOutput
from .kiplot import load_sch
from .fil_base import BaseFilter, apply_fitted_filter
from .optionable import Optionable
from .out_base import VariantOptions
from .macros import macros, document, output_class # noqa: F401
from . import log
@ -107,7 +105,7 @@ def _run_command(cmd, tmp_remap=False, tmp_style=False):
logger.debug('Output from command:\n'+cmd_output.decode())
class PcbDrawOptions(BaseOptions):
class PcbDrawOptions(VariantOptions):
def __init__(self):
with document:
self.style = PcbDrawStyle
@ -139,11 +137,6 @@ class PcbDrawOptions(BaseOptions):
""" [svg,png,jpg] output format. Only used if no `output` is specified """
self.output = GS.def_global_output
""" 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__()
def config(self):
@ -158,9 +151,6 @@ class PcbDrawOptions(BaseOptions):
self.highlight = None
else:
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
if isinstance(self.show_components, type):
self.show_components = ''
@ -217,20 +207,6 @@ class PcbDrawOptions(BaseOptions):
f.close()
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':
@ -251,6 +227,7 @@ class PcbDrawOptions(BaseOptions):
return svg
def run(self, output_dir, board):
super().run(output_dir, board)
check_script(PCBDRAW, URL_PCBDRAW, '0.6.0')
# Output file name
output = self.expand_filename(output_dir, self.output, 'bottom' if self.bottom else 'top', self.format)
@ -277,7 +254,7 @@ class PcbDrawOptions(BaseOptions):
if self.highlight:
cmd.extend(['-a', self.highlight])
if self.show_components is not None:
to_add = ','.join(self.get_filtered_refs())
to_add = ','.join(self.get_fitted_refs())
if self.show_components and to_add:
self.show_components += ','
self.show_components += to_add

View File

@ -9,42 +9,25 @@ from shutil import rmtree
from .gs import (GS)
from .kiplot import check_eeschema_do, exec_with_retry
from .misc import (CMD_EESCHEMA_DO, PDF_SCH_PRINT)
from .optionable import BaseOptions, Optionable
from .registrable import RegOutput
from .out_base import VariantOptions
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__)
class PDF_Sch_PrintOptions(BaseOptions):
class PDF_Sch_PrintOptions(VariantOptions):
def __init__(self):
with document:
self.output = GS.def_global_output
""" filename for the output PDF (%i=schematic %x=pdf) """
self.variant = ''
""" Board variant(s), used to determine which components are crossed. """
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')
self.add_to_doc('variant', "Not fitted components are crossed")
def run(self, output_dir, board):
super().run(output_dir, board)
check_eeschema_do()
if self.variant or self.dnf_filter:
# 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:
self.variant.filter(comps)
if self._comps:
# Save it to a temporal dir
sch_dir = mkdtemp(prefix='tmp-kibot-pdf_sch_print-')
fname = GS.sch.save_variant(sch_dir)

View File

@ -8,19 +8,16 @@
import operator
from datetime import datetime
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 .out_base import VariantOptions
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__)
class PositionOptions(BaseOptions):
class PositionOptions(VariantOptions):
def __init__(self):
with document:
self.format = 'ASCII'
@ -33,18 +30,8 @@ class PositionOptions(BaseOptions):
""" output file name (%i='top_pos'|'bottom_pos'|'both_pos', %x='pos'|'csv') """
self.units = 'millimeters'
""" [millimeters,inches] units used for the positions """
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__()
def config(self):
super().config()
self.variant = RegOutput.check_variant(self.variant)
self.dnf_filter = BaseFilter.solve_filter(self.dnf_filter, 'dnf_filter')
def _do_position_plot_ascii(self, board, output_dir, columns, modulesStr, maxSizes):
topf = None
botf = None
@ -137,18 +124,7 @@ class PositionOptions(BaseOptions):
bothf.close()
def run(self, output_dir, board):
comps = None
if 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}
super().run(output_dir, board)
columns = ["Ref", "Val", "Package", "PosX", "PosY", "Rot", "Side"]
colcount = len(columns)
# Note: the parser already checked the units are milimeters or inches
@ -158,11 +134,12 @@ class PositionOptions(BaseOptions):
else: # self.units == 'inches':
conv = 0.001 / IU_PER_MILS
# Format all strings
comps_hash = self.get_refs_hash()
modules = []
for m in sorted(board.GetModules(), key=operator.methodcaller('GetReference')):
ref = m.GetReference()
# Apply any filter or variant data
if comps:
if comps_hash:
c = comps_hash.get(ref, None)
if c and not c.fitted:
continue

View File

@ -4,40 +4,16 @@
# License: GPL-3.0
# Project: KiBot (formerly KiPlot)
from .gs import GS
from .optionable import BaseOptions, Optionable
from .registrable import RegOutput
from .out_base import VariantOptions
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__)
class Sch_Variant_Options(BaseOptions):
class Sch_Variant_Options(VariantOptions):
def __init__(self):
with document:
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 run(self, output_dir, board):
if self.dnf_filter or self.variant:
# 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)
super().run(output_dir, board)
# Create the schematic
GS.sch.save_variant(output_dir)

View File

@ -10,17 +10,14 @@ from tempfile import NamedTemporaryFile
from .error import KiPlotConfigurationError
from .misc import (KICAD2STEP, KICAD2STEP_ERR)
from .gs import (GS)
from .optionable import BaseOptions, Optionable
from .registrable import RegOutput
from .kiplot import load_sch
from .fil_base import BaseFilter, apply_fitted_filter
from .out_base import VariantOptions
from .macros import macros, document, output_class # noqa: F401
from . import log
logger = log.get_logger(__name__)
class STEPOptions(BaseOptions):
class STEPOptions(VariantOptions):
def __init__(self):
with document:
self.metric_units = True
@ -35,18 +32,8 @@ class STEPOptions(BaseOptions):
""" the minimum distance between points to treat them as separate ones (-1 is KiCad default: 0.01 mm) """
self.output = GS.def_global_output
""" name for the generated STEP file (%i='3D' %x='step') """
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__()
def config(self):
super().config()
self.variant = RegOutput.check_variant(self.variant)
self.dnf_filter = BaseFilter.solve_filter(self.dnf_filter, 'dnf_filter')
@property
def origin(self):
return self._origin
@ -58,18 +45,9 @@ class STEPOptions(BaseOptions):
self._origin = val
def filter_components(self):
if not self.dnf_filter and not self.variant:
if not self._comps:
return GS.pcb_file
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}
comps_hash = self.get_refs_hash()
# Remove the 3D models for not fitted components
rem_models = []
for m in GS.board.GetModules():
@ -98,6 +76,7 @@ class STEPOptions(BaseOptions):
return fname
def run(self, output_dir, board):
super().run(output_dir, board)
# Output file name
output = self.expand_filename(output_dir, self.output, '3D', 'step')
# Make units explicit