diff --git a/CHANGELOG.md b/CHANGELOG.md index 892a04ecb..f785d1b91 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - General things: - Some basic preprocessing, now you can parametrize the YAML config. (See #233 #243) + - Environment and text variables now can be used as 3D model aliases. + (See #261) + - Environment and text variables expansion is now recursive. + So in `${VAR}` the *VAR* can contain `${OTHER_VAR}` - New outputs: - PCB_Variant: saves a PCB with filters and variants applied. - File_Copy: used to copy files to the output directory. (#279) diff --git a/README.md b/README.md index 6f6f9db59..ce476bc24 100644 --- a/README.md +++ b/README.md @@ -652,6 +652,7 @@ global: Uses the `strftime` format. - `date_time_format`: [string='%Y-%m-%d_%H-%M-%S'] Format used for the PCB and schematic date when using the file timestamp. Uses the `strftime` format. - `dir`: [string=''] Default pattern for the output directories. + - `disable_3d_alias_as_env`: [boolean=false] Disable the use of environment and text variables as 3D models aliases. - `drc_exclusions_workaround`: [boolean=false] KiCad 6 introduced DRC exclusions. They are stored in the project but ignored by the Python API. This is reported as bug number 11562 (https://gitlab.com/kicad/code/kicad/-/issues/11562). If you really need exclusions enable this option, this will use the GUI version of the DRC (slower). diff --git a/kibot/globals.py b/kibot/globals.py index a90cf50c3..ae3b861fb 100644 --- a/kibot/globals.py +++ b/kibot/globals.py @@ -112,6 +112,8 @@ def __init__(self): """ Format used for the PCB and schematic date when using the file timestamp. Uses the `strftime` format """ self.dir = '' """ Default pattern for the output directories """ + self.disable_3d_alias_as_env = False + """ Disable the use of environment and text variables as 3D models aliases """ self.drc_exclusions_workaround = False """ KiCad 6 introduced DRC exclusions. They are stored in the project but ignored by the Python API. This is reported as bug number 11562 (https://gitlab.com/kicad/code/kicad/-/issues/11562). diff --git a/kibot/gs.py b/kibot/gs.py index ec6667f19..8df0a646c 100644 --- a/kibot/gs.py +++ b/kibot/gs.py @@ -107,6 +107,7 @@ class GS(object): global_date_time_format = None global_drc_exclusions_workaround = None global_dir = None + global_disable_3d_alias_as_env = None global_drill_size_increment = None global_edge_connector = None global_edge_plating = None diff --git a/kibot/kicad/config.py b/kibot/kicad/config.py index 6844f84c7..fa571597d 100644 --- a/kibot/kicad/config.py +++ b/kibot/kicad/config.py @@ -25,7 +25,7 @@ import sysconfig from ..gs import GS from .. import log -from ..misc import W_NOCONFIG, W_NOKIENV, W_NOLIBS, W_NODEFSYMLIB, MISSING_WKS +from ..misc import W_NOCONFIG, W_NOKIENV, W_NOLIBS, W_NODEFSYMLIB, MISSING_WKS, W_MAXDEPTH # Check python version to determine which version of ConfirParser to import if sys.version_info.major >= 3: @@ -37,6 +37,7 @@ logger = log.get_logger() SYM_LIB_TABLE = 'sym-lib-table' KICAD_COMMON = 'kicad_common' +MAXDEPTH = 20 reported = set() @@ -62,16 +63,28 @@ def expand_env(val, env, extra_env, used_extra=None): if used_extra is None: used_extra = [False] used_extra[0] = False - for var in re.findall(r'\$\{(\S+?)\}', val): - if var in env: - val = val.replace('${'+var+'}', env[var]) - elif var in extra_env: - val = val.replace('${'+var+'}', extra_env[var]) - used_extra[0] = True - else: - if var not in reported: - logger.error('Unable to expand `{}` in `{}`'.format(var, val)) - reported.add(var) + success = replaced = True + depth = 0 + ori_val = val + while success and replaced and depth < MAXDEPTH: + replaced = False + depth += 1 + if depth == MAXDEPTH: + logger.warning(W_MAXDEPTH+'Too much nested variables replacements, possible loop ({})'.format(ori_val)) + success = False + for var in re.findall(r'\$\{(\S+?)\}', val): + if var in env: + val = val.replace('${'+var+'}', env[var]) + replaced = True + elif var in extra_env: + val = val.replace('${'+var+'}', extra_env[var]) + used_extra[0] = True + replaced = True + else: + success = False + if var not in reported: + logger.error('Unable to expand `{}` in `{}`'.format(var, val)) + reported.add(var) return val diff --git a/kibot/misc.py b/kibot/misc.py index 0041a3fbc..26529eab2 100644 --- a/kibot/misc.py +++ b/kibot/misc.py @@ -225,6 +225,7 @@ W_DOWNTOOL = '(W093) ' W_NOPREFLIGHTS = '(W094) ' W_NOPART = '(W095) ' +W_MAXDEPTH = '(W096) ' # Somehow arbitrary, the colors are real, but can be different PCB_MAT_COLORS = {'fr1': "937042", 'fr2': "949d70", 'fr3': "adacb4", 'fr4': "332B16", 'fr5': "6cc290"} PCB_FINISH_COLORS = {'hal': "8b898c", 'hasl': "8b898c", 'imag': "8b898c", 'enig': "cfb96e", 'enepig': "cfb96e", diff --git a/kibot/out_base_3d.py b/kibot/out_base_3d.py index e40b4a8ef..08d306a7f 100644 --- a/kibot/out_base_3d.py +++ b/kibot/out_base_3d.py @@ -16,6 +16,25 @@ logger = log.get_logger() +def do_expand_env(fname, used_extra, extra_debug): + full_name = KiConf.expand_env(fname, used_extra) + if extra_debug: + logger.debug("- Expanded {} -> {}".format(fname, full_name)) + if os.path.isfile(full_name) or ':' not in fname or GS.global_disable_3d_alias_as_env: + return full_name + # Is it using ALIAS:xxxxx? + ind = fname.index(':') + alias_name = fname[:ind] + rest = fname[ind+1:] + new_fname = '${'+alias_name+'}'+os.path.sep+rest + new_full_name = KiConf.expand_env(new_fname, used_extra) + if extra_debug: + logger.debug("- Expanded {} -> {}".format(new_fname, new_full_name)) + if os.path.isfile(new_full_name): + return new_full_name + return full_name + + class Base3DOptions(VariantOptions): def __init__(self): with document: @@ -73,9 +92,7 @@ def download_models(self): logger.debug("- Skipping {} (disabled)".format(m3d.m_Filename)) continue used_extra = [False] - full_name = KiConf.expand_env(m3d.m_Filename, used_extra) - if extra_debug: - logger.debug("- Expanded {} -> {}".format(m3d.m_Filename, full_name)) + full_name = do_expand_env(m3d.m_Filename, used_extra, extra_debug) if not os.path.isfile(full_name): # Missing 3D model if self.download and (m3d.m_Filename.startswith('${KISYS3DMOD}/') or diff --git a/tests/board_samples/kicad_6/bom_w_prj.kicad_pcb b/tests/board_samples/kicad_6/bom_w_prj.kicad_pcb new file mode 100644 index 000000000..e5421f726 --- /dev/null +++ b/tests/board_samples/kicad_6/bom_w_prj.kicad_pcb @@ -0,0 +1,201 @@ +(kicad_pcb (version 20201002) (generator pcbnew) + + (general + (thickness 1.6) + ) + + (paper "A4") + (layers + (0 "F.Cu" signal) + (31 "B.Cu" signal) + (32 "B.Adhes" user "B.Adhesive") + (33 "F.Adhes" user "F.Adhesive") + (34 "B.Paste" user) + (35 "F.Paste" user) + (36 "B.SilkS" user "B.Silkscreen") + (37 "F.SilkS" user "F.Silkscreen") + (38 "B.Mask" user) + (39 "F.Mask" user) + (40 "Dwgs.User" user "User.Drawings") + (41 "Cmts.User" user "User.Comments") + (42 "Eco1.User" user "User.Eco1") + (43 "Eco2.User" user "User.Eco2") + (44 "Edge.Cuts" user) + (45 "Margin" user) + (46 "B.CrtYd" user "B.Courtyard") + (47 "F.CrtYd" user "F.Courtyard") + (48 "B.Fab" user) + (49 "F.Fab" user) + ) + + (setup + (aux_axis_origin 148.4 80.2) + (pcbplotparams + (layerselection 0x00010fc_ffffffff) + (disableapertmacros false) + (usegerberextensions false) + (usegerberattributes false) + (usegerberadvancedattributes false) + (creategerberjobfile false) + (svguseinch false) + (svgprecision 6) + (excludeedgelayer true) + (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) + (sketchpadsonfab false) + (subtractmaskfromsilk false) + (outputformat 1) + (mirror false) + (drillshape 1) + (scaleselection 1) + (outputdirectory "") + ) + ) + + + (net 0 "") + (net 1 "GND") + (net 2 "Net-(C1-Pad1)") + (net 3 "VCC") + + (module "Capacitor_SMD:C_0805_2012Metric" (layer "F.Cu") (tedit 5B36C52B) (tstamp 00000000-0000-0000-0000-00005ebea01d) + (at 146.3 78.6) + (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 "/00000000-0000-0000-0000-00005ebe91ac") + (attr smd) + (fp_text reference "C1" (at 0 -1.65) (layer "F.SilkS") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp c974f755-f11c-4e72-9337-9b1b03ad46d6) + ) + (fp_text value "1uF" (at 0 1.65) (layer "F.Fab") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp 2b79ad18-d7d7-43df-ab38-e75b2da12556) + ) + (fp_text user "${REFERENCE}" (at 0 0) (layer "F.Fab") + (effects (font (size 0.5 0.5) (thickness 0.08))) + (tstamp 5db96da7-af8d-43d8-8dc7-a398bfc8659a) + ) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer "F.SilkS") (width 0.12) (tstamp 3076b8ca-409a-4abb-8543-19f45b2d32e7)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer "F.SilkS") (width 0.12) (tstamp a32b7c78-669e-4058-9e8f-159773d391d1)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer "F.CrtYd") (width 0.05) (tstamp 5298dbf1-ff20-463f-b22f-955b234f027b)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer "F.CrtYd") (width 0.05) (tstamp 5ee42af7-ef65-46ec-93e1-21c0e6077de0)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer "F.CrtYd") (width 0.05) (tstamp 9aaa51e5-eb42-4e37-9164-e5b31a4cd652)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer "F.CrtYd") (width 0.05) (tstamp e610961e-a821-4b86-8c7d-d4cb27796910)) + (fp_line (start -1 0.6) (end -1 -0.6) (layer "F.Fab") (width 0.1) (tstamp 1ffd0374-60f5-4975-8863-7ed9f29dac0e)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer "F.Fab") (width 0.1) (tstamp 26a053d6-55aa-4839-adb7-568fd5c066bb)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer "F.Fab") (width 0.1) (tstamp 8367eaee-e0ca-41eb-bc30-e532a8b59fdd)) + (fp_line (start 1 0.6) (end -1 0.6) (layer "F.Fab") (width 0.1) (tstamp e3a76526-d318-4ed9-8120-844abbdc3456)) + (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)") (tstamp 34fb9d00-02b1-48b3-a790-0112e6a08449)) + (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 "GND") (tstamp 0336c0d4-c4f4-4020-8380-287f839c852a)) + (model "${KISYS3DMOD}/Capacitor_SMD.3dshapes/C_0805_2012Metric.step" + (offset (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 00000000-0000-0000-0000-00005ebea02e) + (at 146.3 81.55 180) + (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 "/00000000-0000-0000-0000-00005ebe8a2e") + (attr smd) + (fp_text reference "R1" (at 0 -1.65) (layer "F.SilkS") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp 7ef0f81b-f6e6-4f07-b717-38c4b1e50a5e) + ) + (fp_text value "100" (at 0 1.65) (layer "F.Fab") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp 8cd4eec9-ceb5-4b8f-83f2-9a146ee7ddd5) + ) + (fp_text user "${REFERENCE}" (at 0 0) (layer "F.Fab") + (effects (font (size 0.5 0.5) (thickness 0.08))) + (tstamp 93acb41a-3723-4469-9dee-a34acc325774) + ) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer "F.SilkS") (width 0.12) (tstamp 39441d2f-6110-4320-92bb-88f09b0de90b)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer "F.SilkS") (width 0.12) (tstamp ae28541a-0239-4867-9639-a73e46808278)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer "F.CrtYd") (width 0.05) (tstamp 752a50bd-195a-4ad5-acdb-d18c11a301e4)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer "F.CrtYd") (width 0.05) (tstamp 757c5363-13ba-436b-9db8-e5dc02596d27)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer "F.CrtYd") (width 0.05) (tstamp 91e75b42-fb6a-4a6b-be78-4013b6183b9a)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer "F.CrtYd") (width 0.05) (tstamp c76bc75f-8181-4476-9973-7173e45c68ed)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer "F.Fab") (width 0.1) (tstamp 337d7915-43e4-4835-8aab-ff527c0de866)) + (fp_line (start 1 0.6) (end -1 0.6) (layer "F.Fab") (width 0.1) (tstamp 656d7de6-1e65-4eb7-8002-7e680bef80b9)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer "F.Fab") (width 0.1) (tstamp ba9a410d-1c13-461f-b6a8-eeb7c4c46e58)) + (fp_line (start -1 0.6) (end -1 -0.6) (layer "F.Fab") (width 0.1) (tstamp fe5b7a7b-9594-494a-8fe7-df5ac5e9fd07)) + (pad "1" smd roundrect (at -0.9375 0 180) (size 0.975 1.4) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) + (net 3 "VCC") (tstamp ee158b8c-0101-4c4c-b5ce-76e87c497fb9)) + (pad "2" smd roundrect (at 0.9375 0 180) (size 0.975 1.4) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) + (net 2 "Net-(C1-Pad1)") (tstamp b67e7460-96bc-4aa0-8593-880eb3320d89)) + (model "ALIAS1:R_0805_2012Metrico.step" + (offset (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 00000000-0000-0000-0000-00005ebea03f) + (at 150.71 78.6 180) + (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 "/00000000-0000-0000-0000-00005ebe8e9e") + (attr smd) + (fp_text reference "R2" (at 0 -1.65) (layer "F.SilkS") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp 9d088aec-c53e-413e-8715-779a6ee7e407) + ) + (fp_text value "200" (at 0 1.65) (layer "F.Fab") + (effects (font (size 1 1) (thickness 0.15))) + (tstamp abf3504c-c638-4bb0-8898-7b38d0241a11) + ) + (fp_text user "${REFERENCE}" (at 0 0) (layer "F.Fab") + (effects (font (size 0.5 0.5) (thickness 0.08))) + (tstamp 730e1bed-bd81-4343-85e9-17d6a47cb046) + ) + (fp_line (start -0.258578 -0.71) (end 0.258578 -0.71) (layer "F.SilkS") (width 0.12) (tstamp 7613df36-4992-4dd5-b97e-1f17e43e73c6)) + (fp_line (start -0.258578 0.71) (end 0.258578 0.71) (layer "F.SilkS") (width 0.12) (tstamp b6f74bca-cdeb-4109-905d-6a81777da69b)) + (fp_line (start -1.68 0.95) (end -1.68 -0.95) (layer "F.CrtYd") (width 0.05) (tstamp 0e6314c1-5679-49cb-898a-296f9477855a)) + (fp_line (start 1.68 0.95) (end -1.68 0.95) (layer "F.CrtYd") (width 0.05) (tstamp 434bf54a-a88a-45dc-a569-a0a5b81a7096)) + (fp_line (start 1.68 -0.95) (end 1.68 0.95) (layer "F.CrtYd") (width 0.05) (tstamp ea59c7f6-51a1-4630-b89e-075386e527c9)) + (fp_line (start -1.68 -0.95) (end 1.68 -0.95) (layer "F.CrtYd") (width 0.05) (tstamp ee5f10ba-08e8-4cb5-8185-dae7f54c20a3)) + (fp_line (start -1 0.6) (end -1 -0.6) (layer "F.Fab") (width 0.1) (tstamp 5c2f40eb-308c-4cc2-9669-44b6645a7910)) + (fp_line (start -1 -0.6) (end 1 -0.6) (layer "F.Fab") (width 0.1) (tstamp 608be37a-af03-4e73-9e8e-c1bb3353eaf4)) + (fp_line (start 1 -0.6) (end 1 0.6) (layer "F.Fab") (width 0.1) (tstamp a384a468-0937-4800-9a3b-e63b6186898c)) + (fp_line (start 1 0.6) (end -1 0.6) (layer "F.Fab") (width 0.1) (tstamp dc5732f3-4764-4a19-a8e3-24308ca8b363)) + (pad "1" smd roundrect (at -0.9375 0 180) (size 0.975 1.4) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) + (net 2 "Net-(C1-Pad1)") (tstamp 55440b89-8f8a-483a-9b2b-9ccc95708f75)) + (pad "2" smd roundrect (at 0.9375 0 180) (size 0.975 1.4) (layers "F.Cu" "F.Paste" "F.Mask") (roundrect_rratio 0.25) + (net 1 "GND") (tstamp 3d8a4e48-dfd4-4c64-8dd3-885d6a7ed460)) + (model "${KICAD6_3DMODEL_DIR}/Resistor_SMD.3dshapes/R_0805_2012Metric.step" + (offset (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (gr_line (start 153 84) (end 153 76) (layer "Edge.Cuts") (width 0.05) (tstamp 00000000-0000-0000-0000-00005ebea29b)) + (gr_line (start 144 76) (end 144 84) (layer "Edge.Cuts") (width 0.05) (tstamp bb3326cd-028c-43fb-af47-5975412a67c7)) + (gr_line (start 153 76) (end 144 76) (layer "Edge.Cuts") (width 0.05) (tstamp d534140b-6f16-4b83-8893-ef4b026f6ec9)) + (gr_line (start 144 84) (end 153 84) (layer "Edge.Cuts") (width 0.05) (tstamp ea655683-6135-4d3f-a322-1186e1a703b2)) + + (segment (start 147.2375 78.6) (end 149.7725 78.6) (width 0.25) (layer "F.Cu") (net 1) (tstamp 4ebf58f7-8428-4480-b240-bb7d3c895103)) + (segment (start 150.62249 77.57499) (end 151.161973 78.114473) (width 0.25) (layer "F.Cu") (net 2) (tstamp 4ed009e2-b8f5-47d8-ba45-e73cbf2524c2)) + (segment (start 145.3625 78.6) (end 145.3625 79.3) (width 0.25) (layer "F.Cu") (net 2) (tstamp 5505e502-12b2-42b0-9e88-71997ebbcbde)) + (segment (start 151.161973 78.114473) (end 151.6475 78.6) (width 0.25) (layer "F.Cu") (net 2) (tstamp 5e3899fa-1efc-49c7-bd03-0723e6564f66)) + (segment (start 145.3625 78.6) (end 146.38751 77.57499) (width 0.25) (layer "F.Cu") (net 2) (tstamp 88b2a9f5-ec07-44cc-be7d-6243af8d21a7)) + (segment (start 145.3625 79.3) (end 145.3625 81.55) (width 0.25) (layer "F.Cu") (net 2) (tstamp a49ce2ce-5d29-415b-a41f-07567cbabb0f)) + (segment (start 146.38751 77.57499) (end 150.62249 77.57499) (width 0.25) (layer "F.Cu") (net 2) (tstamp fd90cb38-571b-4f7c-8630-139c123989e3)) + +) diff --git a/tests/board_samples/kicad_6/bom_w_prj.kicad_pro b/tests/board_samples/kicad_6/bom_w_prj.kicad_pro new file mode 100644 index 000000000..09e8ad423 --- /dev/null +++ b/tests/board_samples/kicad_6/bom_w_prj.kicad_pro @@ -0,0 +1,221 @@ +{ + "board": { + "design_settings": { + "defaults": { + "board_outline_line_width": 0.049999999999999996, + "copper_line_width": 0.19999999999999998, + "copper_text_italic": false, + "copper_text_size_h": 1.5, + "copper_text_size_v": 1.5, + "copper_text_thickness": 0.3, + "copper_text_upright": false, + "courtyard_line_width": 0.049999999999999996, + "dimension_precision": 4, + "dimension_units": 3, + "dimensions": { + "arrow_length": 1270000, + "extension_offset": 500000, + "keep_text_aligned": true, + "suppress_zeroes": false, + "text_position": 0, + "units_format": 1 + }, + "fab_line_width": 0.09999999999999999, + "fab_text_italic": false, + "fab_text_size_h": 1.0, + "fab_text_size_v": 1.0, + "fab_text_thickness": 0.15, + "fab_text_upright": false, + "other_line_width": 0.09999999999999999, + "other_text_italic": false, + "other_text_size_h": 1.0, + "other_text_size_v": 1.0, + "other_text_thickness": 0.15, + "other_text_upright": false, + "pads": { + "drill": 0.762, + "height": 1.524, + "width": 1.524 + }, + "silk_line_width": 0.12, + "silk_text_italic": false, + "silk_text_size_h": 1.0, + "silk_text_size_v": 1.0, + "silk_text_thickness": 0.15, + "silk_text_upright": false, + "zones": { + "45_degree_only": true, + "min_clearance": 0.508 + } + }, + "diff_pair_dimensions": [ + { + "gap": 0.0, + "via_gap": 0.0, + "width": 0.0 + } + ], + "drc_exclusions": [], + "meta": { + "filename": "board_design_settings.json", + "version": 2 + }, + "rule_severities": { + "annular_width": "error", + "clearance": "error", + "copper_edge_clearance": "error", + "courtyards_overlap": "error", + "diff_pair_gap_out_of_range": "error", + "diff_pair_uncoupled_length_too_long": "error", + "drill_out_of_range": "error", + "duplicate_footprints": "warning", + "extra_footprint": "warning", + "footprint_type_mismatch": "error", + "hole_clearance": "error", + "hole_near_hole": "error", + "invalid_outline": "error", + "item_on_disabled_layer": "error", + "items_not_allowed": "error", + "length_out_of_range": "error", + "malformed_courtyard": "error", + "microvia_drill_out_of_range": "error", + "missing_courtyard": "ignore", + "missing_footprint": "warning", + "net_conflict": "warning", + "npth_inside_courtyard": "ignore", + "padstack": "error", + "pth_inside_courtyard": "ignore", + "shorting_items": "error", + "silk_over_copper": "warning", + "silk_overlap": "warning", + "skew_out_of_range": "error", + "through_hole_pad_without_hole": "error", + "too_many_vias": "error", + "track_dangling": "warning", + "track_width": "error", + "tracks_crossing": "error", + "unconnected_items": "error", + "unresolved_variable": "error", + "via_dangling": "warning", + "zone_has_empty_net": "error", + "zones_intersect": "error" + }, + "rules": { + "allow_blind_buried_vias": false, + "allow_microvias": false, + "max_error": 0.005, + "min_clearance": 0.0, + "min_copper_edge_clearance": 0.024999999999999998, + "min_hole_clearance": 0.25, + "min_hole_to_hole": 0.25, + "min_microvia_diameter": 0.19999999999999998, + "min_microvia_drill": 0.09999999999999999, + "min_silk_clearance": 0.0, + "min_through_hole_diameter": 0.2032, + "min_track_width": 0.127, + "min_via_annular_width": 0.049999999999999996, + "min_via_diameter": 0.4572, + "use_height_for_length_calcs": true + }, + "track_widths": [ + 0.0, + 0.1524, + 0.3048, + 0.635 + ], + "via_dimensions": [ + { + "diameter": 0.0, + "drill": 0.0 + }, + { + "diameter": 0.508, + "drill": 0.254 + }, + { + "diameter": 0.889, + "drill": 0.508 + } + ], + "zones_allow_external_fillets": false, + "zones_use_no_outline": true + }, + "layer_presets": [] + }, + "boards": [], + "cvpcb": { + "equivalence_files": [] + }, + "libraries": { + "pinned_footprint_libs": [], + "pinned_symbol_libs": [] + }, + "meta": { + "filename": "light_control.kicad_pro", + "version": 1 + }, + "net_settings": { + "classes": [ + { + "bus_width": 12.0, + "clearance": 0.1524, + "diff_pair_gap": 0.25, + "diff_pair_via_gap": 0.25, + "diff_pair_width": 0.2, + "line_style": 0, + "microvia_diameter": 0.3, + "microvia_drill": 0.1, + "name": "Default", + "pcb_color": "rgba(0, 0, 0, 0.000)", + "schematic_color": "rgba(0, 0, 0, 0.000)", + "track_width": 0.1524, + "via_diameter": 0.508, + "via_drill": 0.254, + "wire_width": 6.0 + }, + { + "bus_width": 12.0, + "clearance": 0.1524, + "diff_pair_gap": 0.25, + "diff_pair_via_gap": 0.25, + "diff_pair_width": 0.2, + "line_style": 0, + "microvia_diameter": 0.3, + "microvia_drill": 0.1, + "name": "Power", + "nets": [], + "pcb_color": "rgba(0, 0, 0, 0.000)", + "schematic_color": "rgba(0, 0, 0, 0.000)", + "track_width": 0.635, + "via_diameter": 0.889, + "via_drill": 0.508, + "wire_width": 6.0 + } + ], + "meta": { + "version": 2 + }, + "net_colors": null + }, + "pcbnew": { + "last_paths": { + "gencad": "", + "idf": "", + "netlist": "", + "specctra_dsn": "", + "step": "", + "vrml": "" + }, + "page_layout_descr_file": "" + }, + "schematic": { + "legacy_lib_dir": "", + "legacy_lib_list": [] + }, + "sheets": [], + "text_variables": { + "ALIAS1": "${KIPRJMOD}/../../data/metrico/Resistor_SMD.3dshapes", + "MYVAR": "tests/data", + "PRUEBITA": "Hola!" + } +} \ No newline at end of file diff --git a/tests/test_plot/test_step.py b/tests/test_plot/test_step.py index 2392f1199..954ebc9da 100644 --- a/tests/test_plot/test_step.py +++ b/tests/test_plot/test_step.py @@ -76,6 +76,23 @@ def test_step_gl_env(test_dir): ctx.clean_up() +@pytest.mark.slow +@pytest.mark.kicad2step +@pytest.mark.skipif(context.ki5(), reason="uses text variables") +def test_step_alias_1(test_dir): + prj = 'bom_w_prj' + ctx = context.TestContext(test_dir, prj, 'step_alias', STEP_DIR) + ctx.run(extra_debug=True) + # Check all outputs are there + name = prj+'-3D.step' + ctx.expect_out_file_d(name) + # Check the R and C 3D models are there + ctx.search_in_file_d(name, ['R_0805_2012Metric', 'R_0805_2012Metrico', 'C_0805_2012Metric']) + ctx.search_err(['Missing 3D model for R1: `(.*)R_0805_2012Metrico', + 'Failed to download `(.*)R_0805_2012Metrico'], invert=True) + ctx.clean_up(keep_project=True) + + @pytest.mark.slow @pytest.mark.kicad2step def test_step_variant_1(test_dir): diff --git a/tests/yaml_samples/step_alias.kibot.yaml b/tests/yaml_samples/step_alias.kibot.yaml new file mode 100644 index 000000000..cfff7a7f9 --- /dev/null +++ b/tests/yaml_samples/step_alias.kibot.yaml @@ -0,0 +1,24 @@ +kiplot: + version: 1 + +global: + disable_3d_alias_as_env: false + +preflight: + set_text_variables: + - variable: 'ALIAS1' + text: '${KIPRJMOD}/../../data/metrico/Resistor_SMD.3dshapes' + # The following error is detected and informed as a warning + # text: '${ALIAS1}/../../data/metrico/Resistor_SMD.3dshapes' + +outputs: + - name: Step + comment: "Generate 3D model (STEP)" + type: step + dir: 3D + options: + metric_units: true + origin: drill # "grid" or "drill" o "X,Y" i.e. 3.2,-10 + #no_virtual: false # exclude 3D models for components with 'virtual' attribute + #min_distance: 0.01 # Minimum distance between points to treat them as separate ones (default 0.01 mm) + #output: project.step