[Quick-Start] No longer use dedicated templates

- Now we use the internal templates
- This is because now they can be configured
This commit is contained in:
Salvador E. Tropea 2023-06-14 13:24:08 -03:00
parent f526812bcc
commit 0fa7b92039
40 changed files with 83 additions and 347 deletions

View File

@ -4,10 +4,6 @@ include README.md
include kibot/resources/report_templates/*.txt
include kibot/resources/kicad_colors/*.json
include kibot/resources/kicad_layouts/*.kicad_wks
include kibot/resources/config_templates/gerber/*.yaml
include kibot/resources/config_templates/bom/*.yaml
include kibot/resources/config_templates/bom/*.yaml
include kibot/resources/config_templates/panelize/*.yaml
include kibot/resources/config_templates/*.yaml
include kibot/resources/images/*.svg
include kibot/resources/images/*.ico

View File

@ -41,7 +41,7 @@ logger = log.get_logger()
# Cache to avoid running external many times to check their versions
script_versions = {}
actions_loaded = False
needed_imports = set()
needed_imports = {}
try:
import yaml
@ -874,10 +874,11 @@ def yaml_dump(f, tree):
f.write(yaml.dump(tree, sort_keys=False))
def register_xmp_import(name):
def register_xmp_import(name, definitions=None):
""" Register an import we need for an example """
global needed_imports
needed_imports.add(name)
assert name not in needed_imports
needed_imports[name] = definitions
def generate_one_example(dest_dir, types):
@ -914,7 +915,7 @@ def generate_one_example(dest_dir, types):
f.write('\n')
# A helper for the internal templates
global needed_imports
needed_imports = set()
needed_imports = {}
# All the outputs
outputs = []
for n, cls in OrderedDict(sorted(outs.items())).items():
@ -926,34 +927,32 @@ def generate_one_example(dest_dir, types):
((o.is_pcb() and o.is_sch()) and (not GS.pcb_file or not GS.sch_file))):
logger.debug('- {}, skipped (PCB: {} SCH: {})'.format(n, o.is_pcb(), o.is_sch()))
continue
# Look for templates
tpls = glob(os.path.join(GS.get_resource_path('config_templates'), n, '*.kibot.yaml'))
if tpls:
# Load the templates
tpl_names = tpls
tpls = []
for t in tpl_names:
tree = yaml.safe_load(open(t))
tpls.append(tree['outputs'])
imps = tree.get('import')
if imps:
needed_imports.update([imp['file'] for imp in imps])
tree = cls.get_conf_examples(n, layers, tpls)
tree = cls.get_conf_examples(n, layers)
if tree:
logger.debug('- {}, generated'.format(n))
if tpls:
logger.debug(' - Templates: {}'.format(tpl_names))
outputs.extend(tree)
else:
logger.debug('- {}, nothing to do'.format(n))
global_defaults = None
if needed_imports:
imports = [{'file': man} for man in sorted(needed_imports)]
imports = []
for n, d in sorted(needed_imports.items()):
if n == 'global':
global_defaults = d
continue
content = {'file': n}
if d:
content['definitions'] = d
imports.append(content)
yaml_dump(f, {'import': imports})
f.write('\n')
if outputs:
yaml_dump(f, {'outputs': outputs})
else:
return None
if global_defaults:
f.write('\n...\n')
yaml_dump(f, {'definitions': global_defaults})
return fname

View File

@ -316,7 +316,7 @@ class AnyLayer(BaseOutput):
return {'layer': la.layer, 'suffix': la.suffix, 'description': la.description}
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
gb = {}
outs = [gb]
name_u = name.upper()

View File

@ -175,7 +175,7 @@ class BaseOutput(RegOutput):
return os.path.abspath(os.path.join(out_dir, name))
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
return None
@staticmethod

View File

@ -641,7 +641,7 @@ class Blender_Export(Base3D):
return 'png'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
if not GS.check_tool(name, 'Blender') or GS.ki5:
return None
has_top = False

View File

@ -185,5 +185,5 @@ class BoardView(BaseOutput): # noqa: F821
""" *[dict] Options for the `boardview` output """
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
return BaseOutput.simple_conf_examples(name, 'Board View export', 'Assembly') # noqa: F821

View File

@ -26,7 +26,7 @@ from .misc import W_BADFIELD, W_NEEDSPCB, DISTRIBUTORS, W_NOPART, W_MISSREF, DIS
from .optionable import Optionable, BaseOptions
from .registrable import RegOutput
from .error import KiPlotConfigurationError
from .kiplot import get_board_comps_data, load_any_sch
from .kiplot import get_board_comps_data, load_any_sch, register_xmp_import
from .kicad.v5_sch import SchematicComponent, SchematicField
from .bom.columnlist import ColumnList, BoMError
from .bom.bom import do_bom
@ -994,32 +994,18 @@ class BoM(BaseOutput): # noqa: F821
return gb
@staticmethod
def process_templates(templates, outs, mpn_fields, dists):
for tpl in templates:
for out in tpl:
if out['type'] == 'bom':
columns = out['options'].get('columns', None)
if columns:
# Rename MPN for something we have, or just remove it
to_remove = None
for c in columns:
fld = c.get('field', '')
if fld.lower() == 'mpn':
if mpn_fields:
c['field'] = 'manf#'
elif dists:
c['field'] = list(dists)[0]+'#'
else:
to_remove = c
if to_remove:
columns.remove(to_remove)
# Currently we have a position example (XYRS)
out['dir'] = 'Position'
if not out['name'].endswith('_xyrs') or GS.pcb_file:
outs.append(out)
def process_templates(mpn_fields, dists):
# Rename MPN for something we have, or just remove it
if mpn_fields:
defs = {'_KIBOT_MPN_FIELD': '- field: manf#'}
elif dists:
defs = {'_KIBOT_MPN_FIELD': '- field: '+list(dists)[0]+'#'}
else:
defs = {}
register_xmp_import('MacroFab_XYRS', defs)
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
outs = []
# Make a list of available fields
fld_names, extra_names = BoMOptions._get_columns()
@ -1092,5 +1078,5 @@ class BoM(BaseOutput): # noqa: F821
# gb['options']['distributors'] = list(dists)
outs.append(gb)
# Add the list of layers to the templates
BoM.process_templates(templates, outs, mpn_fields, dists)
BoM.process_templates(mpn_fields, dists)
return outs

View File

@ -619,7 +619,7 @@ class Diff(BaseOutput): # noqa: F821
return True
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
outs = []
git_command = GS.check_tool(name, 'Git')
if GS.pcb_file and Diff.has_repo(git_command, GS.pcb_file):

View File

@ -171,7 +171,7 @@ class Download_Datasheets(BaseOutput): # noqa: F821
self.options.run(output_dir)
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
has_urls = False
for c in GS.sch.get_components():
if c.datasheet and is_url(c.datasheet):

View File

@ -45,5 +45,5 @@ class DXF_SCH_Print(BaseOutput): # noqa: F821
self._category = 'Schematic/docs'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
return BaseOutput.simple_conf_examples(name, 'Schematic in DXF format', 'Schematic') # noqa: F821

View File

@ -59,7 +59,7 @@ class Excellon(BaseOutput): # noqa: F821
""" *[dict] Options for the `excellon` output """
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
gb = {}
outs = [gb]
name_u = name.upper()

View File

@ -78,5 +78,5 @@ class GenCAD(BaseOutput): # noqa: F821
""" *[dict] Options for the `gencad` output """
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
return BaseOutput.simple_conf_examples(name, 'PCB in GenCAD format', 'Export') # noqa: F821

View File

@ -36,7 +36,7 @@ class Gerb_Drill(BaseOutput): # noqa: F821
""" *[dict] Options for the `gerb_drill` output """
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
gb = {}
outs = [gb]
name_u = name.upper()

View File

@ -8,6 +8,7 @@
import os
from pcbnew import PLOT_FORMAT_GERBER, FromMM, ToMM
from .gs import GS
from .kiplot import register_xmp_import
from .misc import FONT_HELP_TEXT
from .optionable import Optionable
from .out_any_layer import AnyLayer, AnyLayerOptions
@ -116,7 +117,7 @@ class Gerber(AnyLayer):
self._category = 'PCB/fabrication/gerber'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
gb = {}
outs = [gb]
# Create a generic version
@ -128,38 +129,24 @@ class Gerber(AnyLayer):
# Process the templates
# Filter the list of layers using the ones we are interested on
useful = GS.get_useful_layers(USEFUL_LAYERS, layers, include_copper=True)
tpl_layers = [AnyLayer.layer2dict(la) for la in useful]
lcsc_field = Optionable.solve_field_name('_field_lcsc_part', empty_when_none=True)
tpl_layers = []
for la in useful:
tpl_layers.append("- layer: '{}'".format(la.layer))
tpl_layers.append(" suffix: '{}'".format(la.suffix))
tpl_layers.append(" description: '{}'".format(la.description))
tpl_layers = '\n '.join(tpl_layers)
register_xmp_import('global', {'_KIBOT_MANF_DIR_COMP': 'Manufacturers',
'_KIBOT_GERBER_LAYERS': tpl_layers})
# Add the list of layers to the templates
for tpl in templates:
outs_used = []
for out in tpl:
skip = False
if out['type'] == 'gerber':
out['layers'] = tpl_layers
elif out['type'] == 'position':
if not GS.sch:
# We need the schematic for the variant
skip = True
out['run_by_default'] = False
out['options'] = {'pre_transform': ['_kicost_rename', '_rot_footprint']}
if out['type'] == 'bom' and (not GS.sch_file or (out['name'].startswith('JLCPCB') and not lcsc_field)):
skip = True
out['run_by_default'] = False
if out['type'] == 'compress':
out['dir'] = 'Manufacturers'
# We must disable the template and create a new one
# If we don't do it the parent is configured and, in the JLCPCB case, it needs an schematic
out['disable_run_by_default'] = out['extends']
out['extends'] = ''
# Moving files makes the `navigate_results` less powerful
# out['options']['move_files'] = True
if outs_used:
# Compress only the ones we didn't skip
out['options'] = {'files': [{'from_output': f, 'dest': '/'} for f in outs_used]}
for tpl in ['Elecrow', 'FusionPCB', 'JLCPCB', 'PCBWay']:
defs = {'_KIBOT_MANF_DIR': os.path.join('Manufacturers', tpl)}
if tpl == 'JLCPCB':
if not GS.sch:
# We need the schematic for the variant
defs['_KIBOT_POS_ENABLED'] = 'false'
else:
out['dir'] = os.path.join('Manufacturers', out['dir'])
outs.append(out)
if not skip:
outs_used.append(out['name'])
defs['_KIBOT_POS_PRE_TRANSFORM'] = "['_kicost_rename', '_rot_footprint']"
if not GS.sch_file or not Optionable.solve_field_name('_field_lcsc_part', empty_when_none=True):
defs['_KIBOT_BOM_ENABLED'] = 'false'
register_xmp_import(tpl, defs)
return outs

View File

@ -53,5 +53,5 @@ class HPGL_SCH_Print(BaseOutput): # noqa: F821
self._category = 'Schematic/docs'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
return BaseOutput.simple_conf_examples(name, 'Schematic in HPGL format', 'Schematic') # noqa: F821

View File

@ -259,7 +259,7 @@ class IBoM(BaseOutput): # noqa: F821
return self.options.get_dependencies()
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
tool = GS.check_tool(name, 'ibom')
if tool is None:
return None

View File

@ -72,5 +72,5 @@ class Info(BaseOutput): # noqa: F821
""" *[dict] Options for the `info` output """
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
return BaseOutput.simple_conf_examples(name, 'Information about the run', '.') # noqa: F821

View File

@ -419,7 +419,7 @@ class KiKit_Present(BaseOutput):
self._category = 'PCB/docs'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
if not GS.check_tool(name, 'markdown2'):
return None
outs = BaseOutput.simple_conf_examples(name, 'Simple project presentation', 'Presentation')

View File

@ -532,7 +532,7 @@ class Navigate_Results(BaseOutput): # noqa: F821
self.fix_priority_help()
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
outs = BaseOutput.simple_conf_examples(name, 'Web page to browse the results', 'Browse') # noqa: F821
outs[0]['options'] = {'link_from_root': 'index.html', 'skip_not_run': True}
return outs

View File

@ -75,7 +75,7 @@ class Netlist(BaseOutput): # noqa: F821
""" *[dict] Options for the `netlist` output """
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
gb1 = {}
gb1['name'] = 'classic_'+name
gb1['comment'] = 'Schematic netlist in KiCad format'

View File

@ -16,7 +16,7 @@ import json
from tempfile import NamedTemporaryFile
from .error import KiPlotConfigurationError
from .gs import GS
from .kiplot import run_command, config_output
from .kiplot import run_command, config_output, register_xmp_import
from .layer import Layer
from .misc import W_PANELEMPTY, KIKIT_UNIT_ALIASES
from .optionable import PanelOptions
@ -750,12 +750,9 @@ class Panelize(BaseOutput): # noqa: F821
self._category = 'PCB/fabrication'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
if not GS.check_tool(name, 'KiKit'):
return None
outs = []
for tpl in templates:
for out in tpl:
if out['type'] == 'panelize':
outs.append(out)
register_xmp_import('PanelDemo_4x4')
return outs

View File

@ -1223,7 +1223,7 @@ class PCB_Print(BaseOutput): # noqa: F821
self._category = 'PCB/docs'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
outs = []
if len(DRAWING_LAYERS) < 10 and GS.ki6:
DRAWING_LAYERS.extend(['User.'+str(c+1) for c in range(9)])

View File

@ -558,7 +558,7 @@ class PcbDraw(BaseOutput): # noqa: F821
return self.options
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
outs = []
for la in layers:
is_top = la.is_top()

View File

@ -46,5 +46,5 @@ class PDF_SCH_Print(BaseOutput): # noqa: F821
self._category = 'Schematic/docs'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
return BaseOutput.simple_conf_examples(name, 'Schematic in PDF format', 'Schematic') # noqa: F821

View File

@ -324,7 +324,7 @@ class Position(BaseOutput): # noqa: F821
self._category = 'PCB/fabrication/assembly'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
outs = []
has_top = False
has_bottom = False

View File

@ -45,5 +45,5 @@ class PS_SCH_Print(BaseOutput): # noqa: F821
self._category = 'Schematic/docs'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
return BaseOutput.simple_conf_examples(name, 'Schematic in PS format', 'Schematic') # noqa: F821

View File

@ -568,7 +568,7 @@ class QR_Lib(BaseOutput): # noqa: F821
self.fix_priority_help()
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
gb = {}
gb['name'] = 'basic_qr_lib_example'
gb['comment'] = 'QR code symbol and footprint example'

View File

@ -310,7 +310,7 @@ class Render_3D(Base3D): # noqa: F821
return self.options
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
outs = []
has_top = False
has_bottom = False

View File

@ -934,7 +934,7 @@ class Report(BaseOutput): # noqa: F821
self._category = 'PCB/docs'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
pandoc = GS.check_tool(name, 'PanDoc')
gb = {}
outs = [gb]

View File

@ -134,7 +134,7 @@ class Stencil_3D(BaseOutput): # noqa: F821
self._category = 'PCB/fabrication/assembly'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
if not GS.check_tool(name, 'KiKit') or not GS.check_tool(name, 'OpenSCAD'):
return None
return BaseOutput.simple_conf_examples(name, '3D self-registering stencil', 'Assembly') # noqa: F821

View File

@ -134,7 +134,7 @@ class Stencil_For_Jig(BaseOutput): # noqa: F821
self._category = 'PCB/fabrication/assembly'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
if not GS.check_tool(name, 'KiKit') or not GS.check_tool(name, 'OpenSCAD'):
return None
res = BaseOutput.simple_conf_examples(name, 'Steel stencil for alignment jig', 'Assembly') # noqa: F821

View File

@ -101,5 +101,5 @@ class STEP(Base3D):
self._category = 'PCB/3D'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
return Base3D.simple_conf_examples(name, '3D model in STEP format', '3D')

View File

@ -47,5 +47,5 @@ class SVG_SCH_Print(BaseOutput): # noqa: F821
self._category = 'Schematic/docs'
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
return BaseOutput.simple_conf_examples(name, 'Schematic in SVG format', 'Schematic') # noqa: F821

View File

@ -112,5 +112,5 @@ class VRML(BaseOutput): # noqa: F821
""" *[dict] Options for the `vrml` output """
@staticmethod
def get_conf_examples(name, layers, templates):
def get_conf_examples(name, layers):
return Base3D.simple_conf_examples(name, 'PCB in VRML format', '3D')

View File

@ -1,36 +0,0 @@
# MacroFab compatible XYRS
# This is just a template for the quick-start
kibot:
version: 1
import:
- file: MacroFab_XYRS
outputs:
- name: macrofab_xyrs
comment: "Pick and place file, XYRS style"
extends: _macrofab_xyrs
type: bom
options:
columns:
- field: References
name: Designator
- field: Footprint X
name: X-Loc
- field: Footprint Y
name: Y-Loc
- field: Footprint Rot
name: Rotation
- field: Footprint Side
name: Side
- field: Footprint Type
name: Type
- field: Footprint X-Size
name: X-Size
- field: Footprint Y-Size
name: Y-Size
- field: Value
- field: Footprint
- field: Footprint Populate
name: Populate
- field: MPN

View File

@ -1,29 +0,0 @@
# Gerber and drill files for Elecrow, without stencil
# This is just a template for the quick-start
kibot:
version: 1
import:
- file: Elecrow
outputs:
- name: Elecrow_gerbers
comment: Gerbers compatible with Elecrow
type: gerber
dir: Elecrow
extends: _Elecrow_gerbers
disable_run_by_default: true
- name: Elecrow_drill
comment: Drill files compatible with Elecrow
type: excellon
dir: Elecrow
extends: _Elecrow_drill
disable_run_by_default: true
- name: Elecrow
comment: ZIP file for Elecrow
type: compress
dir: Elecrow
extends: _Elecrow_compress
disable_run_by_default: true

View File

@ -1,29 +0,0 @@
# Gerber and drill files for FusionPCB, without stencil
# This is just a template for the quick-start
kibot:
version: 1
import:
- file: FusionPCB
outputs:
- name: FusionPCB_gerbers
comment: Gerbers compatible with FusionPCB
type: gerber
dir: FusionPCB
extends: _FusionPCB_gerbers
disable_run_by_default: true
- name: FusionPCB_drill
comment: Drill files compatible with FusionPCB
type: excellon
dir: FusionPCB
extends: _FusionPCB_drill
disable_run_by_default: true
- name: FusionPCB
comment: ZIP file for FusionPCB
type: compress
dir: FusionPCB
extends: _FusionPCB_compress
disable_run_by_default: true

View File

@ -1,43 +0,0 @@
# Gerber and drill files for JLCPCB, without stencil
# This is just a template for the quick-start
kibot:
version: 1
import:
- file: JLCPCB
outputs:
- name: JLCPCB_gerbers
comment: Gerbers compatible with JLCPCB
type: gerber
dir: JLCPCB
extends: _JLCPCB_gerbers
disable_run_by_default: true
- name: JLCPCB_drill
comment: Drill files compatible with JLCPCB
type: excellon
dir: JLCPCB
extends: _JLCPCB_drill
disable_run_by_default: true
- name: JLCPCB_position
comment: Pick and place file, JLCPCB style
type: position
dir: JLCPCB
extends: _JLCPCB_position
disable_run_by_default: true
- name: JLCPCB_bom
comment: BoM for JLCPCB
type: bom
dir: JLCPCB
extends: _JLCPCB_bom
disable_run_by_default: true
- name: JLCPCB
comment: ZIP file for JLCPCB
type: compress
dir: JLCPCB
extends: _JLCPCB_compress
disable_run_by_default: true

View File

@ -1,29 +0,0 @@
# Gerber and drill files for PCBWay, with stencil (solder paste)
# This is just a template for the quick-start
kibot:
version: 1
import:
- file: PCBWay
outputs:
- name: PCBWay_gerbers
comment: Gerbers compatible with PCBWay
type: gerber
dir: PCBWay
extends: _PCBWay_gerbers
disable_run_by_default: true
- name: PCBWay_drill
comment: Drill files compatible with PCBWay
type: excellon
dir: PCBWay
extends: _PCBWay_drill
disable_run_by_default: true
- name: PCBWay
comment: ZIP file for PCBWay
type: compress
dir: PCBWay
extends: _PCBWay_compress
disable_run_by_default: true

View File

@ -1,63 +0,0 @@
# Example KiBot config file for a basic panel
kibot:
version: 1
outputs:
- name: 'panel'
comment: "Create a 4x4 complex panel"
type: panelize
dir: Panel
options:
title: '+ (Panel)'
units: mm
create_preview: true
configs:
- layout:
rows: 4
cols: 4
space: 2
hbackbone: 5
vbackbone: 5
hboneskip: 1
vboneskip: 1
page:
size: A0
tabs:
type: fixed
width: 3
vcount: 2
hcount: 0
cuts:
type: mousebites
drill: 0.5
spacing: 1mm
offset: 0.2
prolong: 0.5
framing:
type: railstb
width: 5
space: 3
copperfill:
type: hatched
clearance: 2
spacing: 0.5
width: 0.5
tooling:
type: 3hole
hoffset: 2.5
voffset: 2.5
size: 1.5
fiducials:
type: 3fid
hoffset: 5
voffset: 2.5
coppersize: 2
opening: 1
text:
text: "Panel for {boardTitle}"
anchor: mt
voffset: 2.5
hjustify: center
vjustify: center
post:
millradius: 1