diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 120c8f5d..d8d1d384 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -52,10 +52,6 @@ repos: # rev: 22.1.0 # hooks: # - id: black - - repo: https://github.com/Lucas-C/pre-commit-hooks-bandit - rev: v1.0.5 - hooks: - - id: python-bandit-vulnerability-check - repo: https://github.com/fsouza/autoflake8 rev: v0.3.1 hooks: @@ -87,4 +83,8 @@ repos: # rev: v0.931 # hooks: # - id: mypy + - repo: https://github.com/Lucas-C/pre-commit-hooks-bandit + rev: v1.0.5 + hooks: + - id: python-bandit-vulnerability-check # TODO: mdformat --wrap 75 README.md --number diff --git a/experiments/kicad/Print_Layer/layers.kicad_pcb b/experiments/kicad/Print_Layer/layers.kicad_pcb new file mode 100644 index 00000000..c322765b --- /dev/null +++ b/experiments/kicad/Print_Layer/layers.kicad_pcb @@ -0,0 +1,153 @@ +(kicad_pcb (version 20211014) (generator pcbnew) + + (general + (thickness 4.69) + ) + + (paper "A4") + (layers + (0 "F.Cu" signal) + (1 "In1.Cu" signal) + (2 "In2.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) + (50 "User.1" user) + (51 "User.2" user) + (52 "User.3" user) + (53 "User.4" user) + (54 "User.5" user) + (55 "User.6" user) + (56 "User.7" user) + (57 "User.8" user) + (58 "User.9" user) + ) + + (setup + (stackup + (layer "F.SilkS" (type "Top Silk Screen")) + (layer "F.Paste" (type "Top Solder Paste")) + (layer "F.Mask" (type "Top Solder Mask") (thickness 0.01)) + (layer "F.Cu" (type "copper") (thickness 0.035)) + (layer "dielectric 1" (type "core") (thickness 1.51) (material "FR4") (epsilon_r 4.5) (loss_tangent 0.02)) + (layer "In1.Cu" (type "copper") (thickness 0.035)) + (layer "dielectric 2" (type "prepreg") (thickness 1.51) (material "FR4") (epsilon_r 4.5) (loss_tangent 0.02)) + (layer "In2.Cu" (type "copper") (thickness 0.035)) + (layer "dielectric 3" (type "core") (thickness 1.51) (material "FR4") (epsilon_r 4.5) (loss_tangent 0.02)) + (layer "B.Cu" (type "copper") (thickness 0.035)) + (layer "B.Mask" (type "Bottom Solder Mask") (thickness 0.01)) + (layer "B.Paste" (type "Bottom Solder Paste")) + (layer "B.SilkS" (type "Bottom Silk Screen")) + (copper_finish "None") + (dielectric_constraints no) + ) + (pad_to_mask_clearance 0) + (pcbplotparams + (layerselection 0x00010fc_ffffffff) + (disableapertmacros false) + (usegerberextensions false) + (usegerberattributes true) + (usegerberadvancedattributes true) + (creategerberjobfile true) + (svguseinch false) + (svgprecision 6) + (excludeedgelayer true) + (plotframeref false) + (viasonmask false) + (mode 1) + (useauxorigin false) + (hpglpennumber 1) + (hpglpenspeed 20) + (hpglpendiameter 15.000000) + (dxfpolygonmode true) + (dxfimperialunits true) + (dxfusepcbnewfont true) + (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 "") + + (gr_line (start 78 94) (end 78 34) (layer "F.Cu") (width 1) (tstamp 262f85ee-a49a-4194-bdee-29ac02a484ec)) + (gr_line (start 70 40) (end 130 40) (layer "F.Cu") (width 1) (tstamp 77da69f1-4a7e-4daf-b100-27fb75871e8c)) + (gr_line (start 80 94) (end 80 34) (layer "In1.Cu") (width 1) (tstamp fa1503a0-19c0-4e06-a1de-65c87d9f3046)) + (gr_line (start 70 42) (end 130 42) (layer "In1.Cu") (width 1) (tstamp fb7c97ee-bfba-49df-b0a6-949d8c1dbc80)) + (gr_line (start 82 94) (end 82 34) (layer "In2.Cu") (width 1) (tstamp 09c5b2e9-fadc-49a8-867f-ed662ece0465)) + (gr_line (start 70 44) (end 130 44) (layer "In2.Cu") (width 1) (tstamp ea4e4e6a-929c-474e-821a-a752170b4f9c)) + (gr_line (start 84 94) (end 84 34) (layer "B.Cu") (width 1) (tstamp 54c8435a-0b4b-47ec-b2ba-919fa8bf92bd)) + (gr_line (start 70 46) (end 130 46) (layer "B.Cu") (width 1) (tstamp d312a4d8-3900-420d-83df-acf2d1616827)) + (gr_line (start 70 50) (end 130 50) (layer "B.Adhes") (width 1) (tstamp db8a60a1-6c78-42ba-b45c-08cf72ddf99e)) + (gr_line (start 88 94) (end 88 34) (layer "B.Adhes") (width 1) (tstamp e3da7779-0ea1-46dc-90c1-3da0eae63ac3)) + (gr_line (start 70 48) (end 130 48) (layer "F.Adhes") (width 1) (tstamp 2c93e68b-23e0-4a8f-845c-7911d3abc09e)) + (gr_line (start 86 94) (end 86 34) (layer "F.Adhes") (width 1) (tstamp 959a520e-05e4-488b-a17d-dfb714eea3cc)) + (gr_line (start 70 54) (end 130 54) (layer "B.Paste") (width 1) (tstamp 69029636-79e5-47ae-bb14-9bc5dbdeb2b4)) + (gr_line (start 92 94) (end 92 34) (layer "B.Paste") (width 1) (tstamp b5ffc3b0-893d-4977-bac8-ca0fd10d098d)) + (gr_line (start 90 94) (end 90 34) (layer "F.Paste") (width 1) (tstamp 364ea6d5-81d6-485d-af85-ad66a6d4fe3f)) + (gr_line (start 70 52) (end 130 52) (layer "F.Paste") (width 1) (tstamp 52c6d709-bf2c-4bb8-aab3-486121f784ad)) + (gr_line (start 96 94) (end 96 34) (layer "B.SilkS") (width 1) (tstamp 4c0f28bd-4fdd-4e3f-866b-0af6e20563d6)) + (gr_line (start 70 58) (end 130 58) (layer "B.SilkS") (width 1) (tstamp de4d9514-3cb5-4e56-aa34-9a36cc7ab2fb)) + (gr_line (start 70 56) (end 130 56) (layer "F.SilkS") (width 1) (tstamp 55366e14-cec9-493d-901d-448b04d2f286)) + (gr_line (start 94 94) (end 94 34) (layer "F.SilkS") (width 1) (tstamp ac400113-5b0c-4ba3-90f5-fba5c1ab46ed)) + (gr_line (start 70 62) (end 130 62) (layer "B.Mask") (width 1) (tstamp 004f1cac-5431-476d-8d12-f0d7e1d2971c)) + (gr_line (start 100 94) (end 100 34) (layer "B.Mask") (width 1) (tstamp 61d13227-ea38-4175-a5c0-8f75a3d5765d)) + (gr_line (start 70 60) (end 130 60) (layer "F.Mask") (width 1) (tstamp 5aeb1e78-7ed8-446f-a1fa-e72019642e8e)) + (gr_line (start 98 94) (end 98 34) (layer "F.Mask") (width 1) (tstamp 92927a9e-f25b-41ba-9c93-2d6e3e6c1f89)) + (gr_line (start 70 64) (end 130 64) (layer "Dwgs.User") (width 1) (tstamp c457d6bc-d372-4e5a-9060-512765531115)) + (gr_line (start 102 94) (end 102 34) (layer "Dwgs.User") (width 1) (tstamp ed719640-2001-4a0b-956b-2fc557f849a0)) + (gr_line (start 104 94) (end 104 34) (layer "Cmts.User") (width 1) (tstamp 65648dec-894d-4846-9000-a3f37128d377)) + (gr_line (start 70 66) (end 130 66) (layer "Cmts.User") (width 1) (tstamp 8bcf2b99-1928-47d5-9785-f90fe779323f)) + (gr_line (start 106 94) (end 106 34) (layer "Eco1.User") (width 1) (tstamp 725ddd62-c356-4053-88dd-d8de16f6d111)) + (gr_line (start 70 68) (end 130 68) (layer "Eco1.User") (width 1) (tstamp 883e7763-c7c3-4085-8e36-b949c37033d0)) + (gr_line (start 108 94) (end 108 34) (layer "Eco2.User") (width 1) (tstamp 8d9916ee-e2bd-408c-960d-d9bae62b28e4)) + (gr_line (start 70 70) (end 130 70) (layer "Eco2.User") (width 1) (tstamp c898c915-89f5-4003-9fb8-8b0c3f06dfe7)) + (gr_line (start 110 94) (end 110 34) (layer "Edge.Cuts") (width 1) (tstamp 196afe34-74fd-48ae-9b9f-d7a341cb4cdd)) + (gr_line (start 70 72) (end 130 72) (layer "Edge.Cuts") (width 1) (tstamp 925356e8-9fe3-4fca-8329-eba967a76629)) + (gr_line (start 70 74) (end 130 74) (layer "Margin") (width 1) (tstamp da88cf57-0975-4f67-b828-34f4f4c6151f)) + (gr_line (start 112 94) (end 112 34) (layer "Margin") (width 1) (tstamp e36b28a4-7427-4708-a63e-3fe312e8d49f)) + (gr_line (start 116 94) (end 116 34) (layer "B.CrtYd") (width 1) (tstamp aef028c9-bd4b-4984-aea9-019dcc39d7ec)) + (gr_line (start 70 78) (end 130 78) (layer "B.CrtYd") (width 1) (tstamp f8978d6f-bc80-4d45-99fe-9eda6ceed8ec)) + (gr_line (start 70 76) (end 130 76) (layer "F.CrtYd") (width 1) (tstamp 84164d3c-90bc-45b0-ac63-7f7a93843cb3)) + (gr_line (start 114 94) (end 114 34) (layer "F.CrtYd") (width 1) (tstamp e10a8197-feb1-49a8-8ce1-531c3527f182)) + (gr_line (start 120 94) (end 120 34) (layer "B.Fab") (width 1) (tstamp 2a77a72e-d058-40b9-a6e8-cfe4c97e7ab1)) + (gr_line (start 70 82) (end 130 82) (layer "B.Fab") (width 1) (tstamp 96916265-4653-41c3-9a80-f6775aa2b630)) + (gr_line (start 70 80) (end 130 80) (layer "F.Fab") (width 1) (tstamp 1a253373-7aaa-4800-82a0-f05224ca4a7a)) + (gr_line (start 118 94) (end 118 34) (layer "F.Fab") (width 1) (tstamp c00a6ff3-d367-48aa-9987-c597c23d6ece)) + (gr_line (start 70 84) (end 130 84) (layer "User.1") (width 1) (tstamp 1e5a4a4f-7ec1-4d5e-aab0-77eebafcd5cd)) + (gr_line (start 122 94) (end 122 34) (layer "User.1") (width 1) (tstamp 75e54a73-a71d-4649-833f-7b284b918c88)) + (gr_line (start 124 94) (end 124 34) (layer "User.2") (width 1) (tstamp 63775781-01d0-47bd-b139-79a50fca0217)) + (gr_line (start 70 86) (end 130 86) (layer "User.2") (width 1) (tstamp 7505eede-a417-42c3-88a2-1fe21ee21a2a)) + (gr_text "F.Cu\nIn1.Cu\nIn2.Cu\nB.Cu\nF.Adhes\nB.Adhes\nF.Paste\nB.Paste\nF.SilkS\nB.SilkS\nF.Mask\nB.Mask\nDwgs.User\nCmts.User\nEco1.User\nEco2.User\nEdge.Cuts\nMargin\nF.CrtYd\nB.CrtYd\nF.Fab\nB.Fab\nUser.1\nUser.2" (at 69 63) (layer "F.Cu") (tstamp 82c3fcff-0c4d-46ec-9117-fd4b044c0976) + (effects (font (size 1.25 1.5) (thickness 0.25)) (justify right)) + ) + (gr_text "F.Cu\nIn1.Cu\nIn2.Cu\nB.Cu\nF.Adhes\nB.Adhes\nF.Paste\nB.Paste\nF.SilkS\nB.SilkS\nF.Mask\nB.Mask\nDwgs.User\nCmts.User\nEco1.User\nEco2.User\nEdge.Cuts\nMargin\nF.CrtYd\nB.CrtYd\nF.Fab\nB.Fab\nUser.1\nUser.2" (at 101 33 90) (layer "F.Cu") (tstamp f231041b-336c-4b9b-9f86-123f9dc12d97) + (effects (font (size 1.25 1.5) (thickness 0.25)) (justify left)) + ) + +) diff --git a/experiments/kicad/Print_Layer/layers.pdf b/experiments/kicad/Print_Layer/layers.pdf new file mode 100644 index 00000000..71281dc8 Binary files /dev/null and b/experiments/kicad/Print_Layer/layers.pdf differ diff --git a/kibot/layer.py b/kibot/layer.py index 9a94788b..74b40ff1 100644 --- a/kibot/layer.py +++ b/kibot/layer.py @@ -15,6 +15,29 @@ from . import log logger = log.get_logger() +LAYER_ORDER = ['F.Cu', 'F.Mask', 'F.SilkS', 'F.Paste', 'F.Adhes', 'F.CrtYd', 'F.Fab', 'Dwgs.User', 'Cmts.User', 'Eco1.User', + 'Eco2.User', 'Edge.Cuts', 'Margin', 'User.1', 'User.2', 'User.3', 'User.4', 'User.5', 'User.6', 'User.7', + 'User.8', 'User.9', 'In1.Cu', 'In2.Cu', 'In3.Cu', 'In4.Cu', 'In5.Cu', 'In6.Cu', 'In7.Cu', 'In8.Cu', 'In9.Cu', + 'In10.Cu', 'In11.Cu', 'In12.Cu', 'In13.Cu', 'In14.Cu', 'In15.Cu', 'In16.Cu', 'In17.Cu', 'In18.Cu', 'In19.Cu', + 'In20.Cu', 'In21.Cu', 'In22.Cu', 'In23.Cu', 'In24.Cu', 'In25.Cu', 'In26.Cu', 'In27.Cu', 'In28.Cu', 'In29.Cu', + 'In30.Cu', 'B.Cu', 'B.Mask', 'B.SilkS', 'B.Paste', 'B.Adhes', 'B.CrtYd', 'B.Fab'] +LAYER_PRIORITY = {} + + +def create_print_priority(board): + """ Fills LAYER_PRIORITY. This is used to sort layers for printing. + It is the way KiCad sorts the layers. + We do it as soon as we have a valid board. """ + global LAYER_PRIORITY + if len(LAYER_PRIORITY) > 0: + return + LAYER_PRIORITY = {board.GetLayerID(name): c for c, name in enumerate(LAYER_ORDER)} + + +def get_priority(id): + return LAYER_PRIORITY.get(id, 1e6) + + class Layer(Optionable): """ A layer description """ # Default names @@ -151,6 +174,7 @@ class Layer(Optionable): layer_cnt = 2 if board: layer_cnt = board.GetCopperLayerCount() + create_print_priority(board) # Get the list of used layers from the board # Used for 'all' but also to validate the layer names if Layer._pcb_layers is None: diff --git a/kibot/out_pcb_print.py b/kibot/out_pcb_print.py index c0a7c436..1293a237 100644 --- a/kibot/out_pcb_print.py +++ b/kibot/out_pcb_print.py @@ -16,14 +16,17 @@ from .optionable import Optionable from .out_base import VariantOptions from .kicad.color_theme import load_color_theme from .macros import macros, document, output_class # noqa: F401 -from .layer import Layer +from .layer import Layer, get_priority from . import PyPDF2 from . import log logger = log.get_logger() # TODO: -# - Opciones de out_pdf y out_any_layer +# - Cache de colores +# - Frame en k5? +# - SVG? +# - rsvg-convert -f pdf -o pp.pdf simple_2layer-F_Cu.svg def hex_to_rgb(value): @@ -216,6 +219,8 @@ class PagesOptions(Optionable): """ Cover the vias """ self.black_holes = True """ Change the drill holes to be black instead of white """ + self.sort_layers = False + """ Try to sort the layers in the same order that uses KiCad for printing """ self.layers = LayerOptions """ [list(dict)] List of layers printed in this page. Order is important, the last goes on top """ @@ -225,6 +230,8 @@ class PagesOptions(Optionable): raise KiPlotConfigurationError("Missing `layers` list") # Fill the ID member for all the layers self.layers = Layer.solve(self.layers) + if self.sort_layers: + self.layers.sort(key=lambda x: get_priority(x._id), reverse=True) if self.sheet_reference_color: self.validate_color('sheet_reference_color')