From a30b71772e7eb831e8d87759172a02e79f9673c4 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Tue, 17 Jul 2018 12:23:58 +0200 Subject: wip. pcb. --- demo/doit/demo/demo.pro | 33 ---- src/ee/fact/__init__.py | 50 +++--- src/ee/kicad/doit.py | 97 +++++++--- src/ee/kicad/pcb/__init__.py | 40 +++-- test/doit/schematics/schematic-1.kicad_pcb | 280 +++++++++++++++++++++++++++++ test/doit/schematics/schematic-1.pro | 7 + test/doit/schematics/schematic-1.sch | 22 +-- test/doit/test_doit.py | 14 +- 8 files changed, 426 insertions(+), 117 deletions(-) delete mode 100644 demo/doit/demo/demo.pro create mode 100644 test/doit/schematics/schematic-1.kicad_pcb create mode 100644 test/doit/schematics/schematic-1.pro diff --git a/demo/doit/demo/demo.pro b/demo/doit/demo/demo.pro deleted file mode 100644 index 152769c..0000000 --- a/demo/doit/demo/demo.pro +++ /dev/null @@ -1,33 +0,0 @@ -update=22/05/2015 07:44:53 -version=1 -last_client=kicad -[general] -version=1 -RootSch= -BoardNm= -[pcbnew] -version=1 -LastNetListRead= -UseCmpFile=1 -PadDrill=0.600000000000 -PadDrillOvalY=0.600000000000 -PadSizeH=1.500000000000 -PadSizeV=1.500000000000 -PcbTextSizeV=1.500000000000 -PcbTextSizeH=1.500000000000 -PcbTextThickness=0.300000000000 -ModuleTextSizeV=1.000000000000 -ModuleTextSizeH=1.000000000000 -ModuleTextSizeThickness=0.150000000000 -SolderMaskClearance=0.000000000000 -SolderMaskMinWidth=0.000000000000 -DrawSegmentWidth=0.200000000000 -BoardOutlineThickness=0.100000000000 -ModuleOutlineThickness=0.150000000000 -[cvpcb] -version=1 -NetIExt=net -[eeschema] -version=1 -LibDir= -[eeschema/libraries] diff --git a/src/ee/fact/__init__.py b/src/ee/fact/__init__.py index 959e755..1bdef0d 100644 --- a/src/ee/fact/__init__.py +++ b/src/ee/fact/__init__.py @@ -1,12 +1,13 @@ -from typing import Optional, Mapping, List import configparser +import logging import os -from pathlib import Path from functools import total_ordering -import logging +from pathlib import Path +from typing import MutableMapping, Optional, Mapping, List logger = logging.getLogger(__name__) + @total_ordering class ObjectType(object): def __init__(self, name: str): @@ -14,28 +15,20 @@ class ObjectType(object): self._fields = [] self._objects = {} - def __eq__(self, o: object) -> bool: - other = o # type ObjectType + def __eq__(self, o) -> bool: + other = o # type: ObjectType return isinstance(o, ObjectType) and self._name == other._name def __lt__(self, o: object) -> bool: if not isinstance(o, ObjectType): return True - other = o # type ObjectType - return (self._name) < (self._name) + other = o # type: ObjectType + return self._name < other._name def __hash__(self) -> int: return self._name.__hash__() - def by_key(self, key: str) -> "Object": - try: - return self._objects[key] - except ValueError: - o = Object(self, key, {}, {}) - self._objects[key] = o - return o - @property def name(self): return self._name @@ -54,6 +47,7 @@ class ObjectType(object): self._fields.append(field) return len(self._fields) - 1 + class Object(object): def __init__(self, ds: "DataSet", ot: ObjectType, key: str): self._ds = ds @@ -81,13 +75,14 @@ class Object(object): def get(self, key: str) -> Optional[str]: idx = self._ot.index_of(key) - return self._data[idx] + return self._data[idx] if idx < len(self._data) else None + class DataSet(object): def __init__(self, name): self._name = name self._object_types = {} - self._objects_by_type = {} # type: Mapping[str, Mapping[str, Object]] + self._objects_by_type = {} # type: MutableMapping[str, Mapping[str, Object]] self._frozen = False self._changed = False @@ -146,6 +141,7 @@ class DataSet(object): return ds + class DataSetManager(object): def __init__(self, basedir: Path): self._basedir = Path(basedir) @@ -181,7 +177,7 @@ class DataSetManager(object): ini = self._load_ini(o_path) o = ds.get_object(ot, key) for k, v in ini.items("values"): - o.set(k, v) + o.set(k, v) if freeze: ds.freeze() @@ -212,11 +208,13 @@ class DataSetManager(object): ini.add_section("values") for k in ot.fields: v = o.get(k) - ini.set("values", k, v) + if v: + ini.set("values", k, str(v)) self._store_ini(ini, ot_dir / "{}.ini".format(key)) - def _blank_ini(self): - return configparser.ConfigParser(interpolation = None) + @staticmethod + def _blank_ini(): + return configparser.ConfigParser(interpolation=None) def _load_ini(self, path: Path): ini = self._blank_ini() @@ -224,10 +222,12 @@ class DataSetManager(object): raise IOError("Could not load ini file: {}".format(path)) return ini - def _store_ini(self, ini, path): + @staticmethod + def _store_ini(ini, path): with open(path, "w") as f: ini.write(f) + class LazyDataSet(object): def __init__(self, dsm: DataSetManager, name, inputs): self._dsm = dsm @@ -235,7 +235,7 @@ class LazyDataSet(object): self._inputs = inputs def __enter__(self): -# logger.info("enter: name={}, inputs={}".format(self._name, self._inputs)) + # logger.info("enter: name={}, inputs={}".format(self._name, self._inputs)) ds = DataSet(self._name) for name in self._inputs: ds = ds.merge(self._dsm.load(name, freeze=True)) @@ -243,7 +243,7 @@ class LazyDataSet(object): return self._ds def __exit__(self, *args): -# logger.info("exit: name={}, inputs={}".format(self._name, self._inputs)) -# logger.info("ds.size={}".format(len(self._ds.items()))) + # logger.info("exit: name={}, inputs={}".format(self._name, self._inputs)) + # logger.info("ds.size={}".format(len(self._ds.items()))) self._dsm.store(self._ds) return False diff --git a/src/ee/kicad/doit.py b/src/ee/kicad/doit.py index 10de885..fcbcaef 100644 --- a/src/ee/kicad/doit.py +++ b/src/ee/kicad/doit.py @@ -1,13 +1,14 @@ +import logging import os.path -from doit.exceptions import TaskFailed -from doit.tools import check_timestamp_unchanged -from configclass import Config from typing import List + +from configclass import Config + from ee.fact import DataSetManager -import logging logger = logging.getLogger(__name__) + class KicadDoitTasks(object): config = Config({ "sch": None, @@ -15,7 +16,7 @@ class KicadDoitTasks(object): "gerber_dir": None, "gerber_zip": None, "data_set_dir": None, - }) + }) def __init__(self, *args, **kwargs): self.config = self.config.make(kwargs) @@ -24,7 +25,6 @@ class KicadDoitTasks(object): logger.info("_task: args={}, kwars={}".format(args, kwargs)) def tasks(self, *args, **kwargs): - import ee.kicad kicad_pcb = self.config["kicad_pcb"] sch = self.config["sch"] tasks = [] @@ -32,24 +32,32 @@ class KicadDoitTasks(object): dsm = DataSetManager(self.config["data_set_dir"]) gerber_dir = self.config["gerber_dir"] - if gerber_dir: - tasks.append(task_kicad_gerber()) + gerber_zip = self.config["gerber_zip"] + if kicad_pcb and gerber_dir: + tasks.append(task_kicad_gerber(kicad_pcb, gerber_dir, gerber_zip)) - sch_ds = task_kicad_sch_to_data_set(dsm, sch, \ - in_data_sets=[], \ - out_data_set="kicad-sch-data-set") \ - if sch else None + sch_ds = task_kicad_sch_to_data_set(dsm, sch, + in_data_sets=[], + out_data_set="kicad-sch-data-set") \ + if sch else None - component_ds = task_kicad_create_component_data_set(dsm, \ - in_data_sets=sch_ds["targets"], \ - out_data_set="raw-component") \ - if sch_ds else None + component_ds = task_kicad_create_component_data_set(dsm, + in_data_sets=sch_ds["targets"], + out_data_set="raw-component") \ + if sch_ds else None - return (t for t in [sch_ds, component_ds] if t is not None) + pcb_ds = task_kicad_pcb_to_data_set(dsm, kicad_pcb, in_data_sets=[], out_data_set="kicad-pcb") \ + if kicad_pcb else None -def task_kicad_gerber(name="kicad-gerber"): - gerber_zip = self.config["gerber_zip"] or "{}.zip".format(gerber_dir) - #logger.info("gerber_zip={}".format(gerber_zip)) + tasks = [sch_ds, component_ds, pcb_ds] + return (t for t in tasks if t) + + +def task_kicad_gerber(kicad_pcb: str, gerber_dir: str, gerber_zip: str, name="kicad-gerber"): + import ee.kicad + + gerber_zip = len(gerber_zip) or "{}.zip".format(gerber_dir) + # logger.info("gerber_zip={}".format(gerber_zip)) eg = next((p for p in (os.path.join(p, "export_gerber.py") for p in ee.kicad.__path__) if os.path.isfile(p)), None) if not eg: @@ -63,6 +71,7 @@ def task_kicad_gerber(name="kicad-gerber"): "--output-directory", gerber_dir, "--protel-extensions", ]) + def make_zip(): import zipfile from pathlib import Path @@ -79,12 +88,12 @@ def task_kicad_gerber(name="kicad-gerber"): "file_dep": [kicad_pcb], } -def task_kicad_sch_to_data_set(dsm: DataSetManager, sch, in_data_sets: List[str], out_data_set, name="kicad-sch-to-data-set"): + +def task_kicad_sch_to_data_set(dsm: DataSetManager, sch, in_data_sets: List[str], out_data_set, + name="kicad-sch-to-data-set"): def action(): import ee.kicad - from ee.kicad.model import Component, ComponentField - import csv - import configparser + from ee.kicad.model import ComponentField with dsm.create_rw(out_data_set, inputs=in_data_sets) as ds: schematics = ee.kicad.read_schematics(sch) @@ -109,10 +118,46 @@ def task_kicad_sch_to_data_set(dsm: DataSetManager, sch, in_data_sets: List[str] "targets": [dsm.metafile_for_ds(out_data_set)], } -def task_kicad_create_component_data_set(dsm: DataSetManager, in_data_sets: List[str], out_data_set, name="kicad-create-component-data-set"): + +def task_kicad_pcb_to_data_set(dsm: DataSetManager, pcb_path, in_data_sets: List[str], out_data_set, + name="kicad-pcb-to-data-set"): + def action(): + import ee.kicad.pcb + from ee.kicad.pcb import FpText + + with dsm.create_rw(out_data_set, inputs=in_data_sets) as ds: + # [ds.delete(o) for o in ds.items(object_type="kicad-pcb-component")] + + pcb: ee.kicad.pcb.KicadPcb = ee.kicad.pcb.parse(pcb_path) + for _m in pcb.modules: + m: ee.kicad.pcb.Module = _m + logger.info("attrs") + for s in dir(m): + logger.info(s) + + o = ds.get_object("kicad-pcb-component", m.tstamp) + + ref_text: FpText = next((t for t in m.fp_texts if t.kind == "reference"), None) + o.set("reference", ref_text.value) + + x, y, rot = m.at + o.set("at-x", x) + o.set("at-y", y) + o.set("at-rot", rot) + o.set("layer", m.layer) + + return { + "name": name, + "file_dep": [pcb_path] + [dsm.metafile_for_ds(ds) for ds in in_data_sets], + "actions": [action], + "targets": [dsm.metafile_for_ds(out_data_set)], + } + + +def task_kicad_create_component_data_set(dsm: DataSetManager, in_data_sets: List[str], out_data_set, + name="kicad-create-component-data-set"): def action(*args, **kwargs): logger.info("args={}, kwargs={}".format(args, kwargs)) - import ee.fact as fact with dsm.create_rw(out_data_set, inputs=in_data_sets) as ds: items = ds.items() diff --git a/src/ee/kicad/pcb/__init__.py b/src/ee/kicad/pcb/__init__.py index 79987e6..25689ef 100644 --- a/src/ee/kicad/pcb/__init__.py +++ b/src/ee/kicad/pcb/__init__.py @@ -49,18 +49,21 @@ class Pad(object): @auto_str class FpText(object): def __init__(self, **kwargs): + self.kind = None # type: str + self.value = None # type: str for k, v in kwargs.items(): setattr(self, k, v) -def parse(path): + +def parse(path) -> KicadPcb: count = 0 p = sexpr.parse(path) #p = sexpr.logging_parser(p) - (event, token) = next(p) - assert event == sexpr.EVENT_LPAREN + (e, t) = next(p) + assert e == sexpr.EVENT_LPAREN - (event, token) = next(p) - assert event == sexpr.EVENT_TEXT and token == "kicad_pcb" + (e, t) = next(p) + assert e == sexpr.EVENT_TEXT and t == "kicad_pcb" idx = 0 def _consume(): @@ -134,10 +137,14 @@ def parse(path): pads = [] fp_texts = [] - args = {} - args["footprint"] = _parse_text() - args["pads"] = pads - args["fp_texts"] = fp_texts + args = { + "footprint": _parse_text(), + "pads": pads, + "fp_texts": fp_texts, + "layer": None, + "tedit": None, + "tstamp": None, + } (event, token) = next(p) while event == sexpr.EVENT_TEXT: @@ -145,12 +152,12 @@ def parse(path): while event == sexpr.EVENT_LPAREN: (event, token) = next(p) - if token == "layer": - args[token] = _parse_text(rparen = True) + if token in ["layer", "tedit", "tstamp"]: + args[token] = _parse_text(rparen=True) elif token == "at": args[token] = _parse_at() elif token == "attr": - args[token] = [_parse_text(rparen = True)] + args[token] = [_parse_text(rparen=True)] elif token == "pad": pads.append(_parse_pad()) elif token == "fp_text": @@ -163,8 +170,9 @@ def parse(path): def _parse_pad(): texts = [] - args = {} - args["footprint"] = _parse_text() + args = { + "footprint": _parse_text() + } (event, token) = next(p) while event == sexpr.EVENT_TEXT: @@ -182,7 +190,7 @@ def parse(path): return Pad(**args) - def _parse_fp_text(): + def _parse_fp_text() -> FpText: args = { "kind": _parse_text(), "value": _parse_text(), @@ -202,7 +210,7 @@ def parse(path): x = _parse_text(to=float) y = _parse_text(to=float) rot = _parse_text(to=float, optional = True, rparen = True) - return (x, y, rot or 0) + return x, y, rot or 0 kicad_pcb = _parse_kicad_pcb() assert next(p, None) == None diff --git a/test/doit/schematics/schematic-1.kicad_pcb b/test/doit/schematics/schematic-1.kicad_pcb new file mode 100644 index 0000000..861eed1 --- /dev/null +++ b/test/doit/schematics/schematic-1.kicad_pcb @@ -0,0 +1,280 @@ +(kicad_pcb (version 20171130) (host pcbnew 5.0.0-rc3+dfsg1-2) + + (general + (thickness 1.6) + (drawings 0) + (tracks 13) + (zones 0) + (modules 3) + (nets 4) + ) + + (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) + (segment_width 0.2) + (edge_width 0.15) + (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) + (pcb_text_width 0.3) + (pcb_text_size 1.5 1.5) + (mod_edge_width 0.15) + (mod_text_size 0.000001 0.000001) + (mod_text_width 0.15) + (pad_size 1.4 1.4) + (pad_drill 0.6) + (pad_to_mask_clearance 0.2) + (aux_axis_origin 0 0) + (visible_elements FFFFFF7F) + (pcbplotparams + (layerselection 0x010fc_ffffffff) + (usegerberextensions false) + (usegerberattributes false) + (usegerberadvancedattributes false) + (creategerberjobfile false) + (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 GND) + (net 2 "Net-(BT1-Pad1)") + (net 3 "Net-(C1-Pad1)") + + (net_class Default "This is the default net class." + (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 GND) + (add_net "Net-(BT1-Pad1)") + (add_net "Net-(C1-Pad1)") + ) + + (module Battery:BatteryHolder_Keystone_103_1x20mm (layer F.Cu) (tedit 5787C32C) (tstamp 5B59DAE3) + (at 145.975001 79.779834) + (descr http://www.keyelco.com/product-pdf.cfm?p=719) + (tags "Keystone type 103 battery holder") + (path /5B431438) + (fp_text reference BT1 (at 0 -4.3) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 9V (at 15 13) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text user + (at 2.75 0) (layer F.SilkS) + (effects (font (size 1.5 1.5) (thickness 0.15))) + ) + (fp_text user %R (at 0 0) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_arc (start 15.2 0) (end 4.01 3.6) (angle -162.5) (layer F.CrtYd) (width 0.05)) + (fp_arc (start 15.2 0) (end 4.01 -3.6) (angle 162.5) (layer F.CrtYd) (width 0.05)) + (fp_arc (start 3.5 3.8) (end 3.5 3.25) (angle 70) (layer F.CrtYd) (width 0.05)) + (fp_arc (start 3.5 -3.8) (end 3.5 -3.25) (angle -70) (layer F.CrtYd) (width 0.05)) + (fp_arc (start 15.2 0) (end 4.25 3.5) (angle -162.5) (layer F.SilkS) (width 0.12)) + (fp_arc (start 3.5 3.8) (end 3.5 3) (angle 70) (layer F.SilkS) (width 0.12)) + (fp_arc (start 15.2 0) (end 4.25 -3.5) (angle 162.5) (layer F.SilkS) (width 0.12)) + (fp_arc (start 3.5 -3.8) (end 3.5 -3) (angle -70) (layer F.SilkS) (width 0.12)) + (fp_arc (start 3.5 3.8) (end 3.5 2.9) (angle 70) (layer F.Fab) (width 0.1)) + (fp_arc (start 15.2 0) (end 4.35 3.5) (angle -162.5) (layer F.Fab) (width 0.1)) + (fp_arc (start 15.2 0) (end 4.35 -3.5) (angle 162.5) (layer F.Fab) (width 0.1)) + (fp_arc (start 15.2 0) (end 5.2 1.3) (angle -180) (layer F.Fab) (width 0.1)) + (fp_line (start -2.45 -3.25) (end 3.5 -3.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start -2.45 3.25) (end 3.5 3.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start -2.45 3.25) (end -2.45 -3.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start -2.2 -3) (end 3.5 -3) (layer F.SilkS) (width 0.12)) + (fp_line (start -2.2 3) (end -2.2 -3) (layer F.SilkS) (width 0.12)) + (fp_line (start -2.2 3) (end 3.5 3) (layer F.SilkS) (width 0.12)) + (fp_arc (start 15.2 0) (end 9 1.3) (angle -170) (layer F.Fab) (width 0.1)) + (fp_arc (start 15.2 0) (end 13.3 1.3) (angle -150) (layer F.Fab) (width 0.1)) + (fp_line (start 23.5712 7.7216) (end 22.6568 6.8834) (layer F.Fab) (width 0.1)) + (fp_line (start 23.5712 -7.7216) (end 22.6314 -6.858) (layer F.Fab) (width 0.1)) + (fp_arc (start 15.2 0) (end 13.3 -1.3) (angle 150) (layer F.Fab) (width 0.1)) + (fp_arc (start 15.2 0) (end 9 -1.3) (angle 170) (layer F.Fab) (width 0.1)) + (fp_arc (start 15.2 0) (end 5.2 -1.3) (angle 180) (layer F.Fab) (width 0.1)) + (fp_line (start 3.5306 -2.9) (end -1.7 -2.9) (layer F.Fab) (width 0.1)) + (fp_line (start -1.7 2.9) (end 3.5306 2.9) (layer F.Fab) (width 0.1)) + (fp_line (start -2.1 -2.5) (end -2.1 2.5) (layer F.Fab) (width 0.1)) + (fp_line (start 0 1.3) (end 16.2 1.3) (layer F.Fab) (width 0.1)) + (fp_line (start 16.2 -1.3) (end 0 -1.3) (layer F.Fab) (width 0.1)) + (fp_arc (start 3.5 -3.8) (end 3.5 -2.9) (angle -70) (layer F.Fab) (width 0.1)) + (fp_arc (start 16.2 0) (end 16.2 -1.3) (angle 180) (layer F.Fab) (width 0.1)) + (fp_line (start 0 -1.3) (end 0 1.3) (layer F.Fab) (width 0.1)) + (fp_arc (start -1.7 2.5) (end -2.1 2.5) (angle -90) (layer F.Fab) (width 0.1)) + (fp_arc (start -1.7 -2.5) (end -2.1 -2.5) (angle 90) (layer F.Fab) (width 0.1)) + (pad 2 thru_hole circle (at 20.49 0) (size 3 3) (drill 1.5) (layers *.Cu *.Mask) + (net 1 GND)) + (pad 1 thru_hole rect (at 0 0) (size 3 3) (drill 1.5) (layers *.Cu *.Mask) + (net 2 "Net-(BT1-Pad1)")) + (model ${KISYS3DMOD}/Battery.3dshapes/BatteryHolder_Keystone_103_1x20mm.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Capacitor_THT:CP_Axial_L18.0mm_D8.0mm_P25.00mm_Horizontal (layer F.Cu) (tedit 5AE50EF2) (tstamp 5B59DB0A) + (at 201.5 64.75 270) + (descr "CP, Axial series, Axial, Horizontal, pin pitch=25mm, , length*diameter=18*8mm^2, Electrolytic Capacitor, , http://www.vishay.com/docs/28325/021asm.pdf") + (tags "CP Axial series Axial Horizontal pin pitch 25mm length 18mm diameter 8mm Electrolytic Capacitor") + (path /5B4314AB) + (fp_text reference C1 (at 12.5 -5.12 270) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 1u (at 12.5 5.12 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start 3.5 -4) (end 3.5 4) (layer F.Fab) (width 0.1)) + (fp_line (start 21.5 -4) (end 21.5 4) (layer F.Fab) (width 0.1)) + (fp_line (start 3.5 -4) (end 5.18 -4) (layer F.Fab) (width 0.1)) + (fp_line (start 5.18 -4) (end 6.08 -3.1) (layer F.Fab) (width 0.1)) + (fp_line (start 6.08 -3.1) (end 6.98 -4) (layer F.Fab) (width 0.1)) + (fp_line (start 6.98 -4) (end 21.5 -4) (layer F.Fab) (width 0.1)) + (fp_line (start 3.5 4) (end 5.18 4) (layer F.Fab) (width 0.1)) + (fp_line (start 5.18 4) (end 6.08 3.1) (layer F.Fab) (width 0.1)) + (fp_line (start 6.08 3.1) (end 6.98 4) (layer F.Fab) (width 0.1)) + (fp_line (start 6.98 4) (end 21.5 4) (layer F.Fab) (width 0.1)) + (fp_line (start 0 0) (end 3.5 0) (layer F.Fab) (width 0.1)) + (fp_line (start 25 0) (end 21.5 0) (layer F.Fab) (width 0.1)) + (fp_line (start 5.2 0) (end 7 0) (layer F.Fab) (width 0.1)) + (fp_line (start 6.1 -0.9) (end 6.1 0.9) (layer F.Fab) (width 0.1)) + (fp_line (start 1.28 -2.6) (end 3.08 -2.6) (layer F.SilkS) (width 0.12)) + (fp_line (start 2.18 -3.5) (end 2.18 -1.7) (layer F.SilkS) (width 0.12)) + (fp_line (start 3.38 -4.12) (end 3.38 4.12) (layer F.SilkS) (width 0.12)) + (fp_line (start 21.62 -4.12) (end 21.62 4.12) (layer F.SilkS) (width 0.12)) + (fp_line (start 3.38 -4.12) (end 5.18 -4.12) (layer F.SilkS) (width 0.12)) + (fp_line (start 5.18 -4.12) (end 6.08 -3.22) (layer F.SilkS) (width 0.12)) + (fp_line (start 6.08 -3.22) (end 6.98 -4.12) (layer F.SilkS) (width 0.12)) + (fp_line (start 6.98 -4.12) (end 21.62 -4.12) (layer F.SilkS) (width 0.12)) + (fp_line (start 3.38 4.12) (end 5.18 4.12) (layer F.SilkS) (width 0.12)) + (fp_line (start 5.18 4.12) (end 6.08 3.22) (layer F.SilkS) (width 0.12)) + (fp_line (start 6.08 3.22) (end 6.98 4.12) (layer F.SilkS) (width 0.12)) + (fp_line (start 6.98 4.12) (end 21.62 4.12) (layer F.SilkS) (width 0.12)) + (fp_line (start 1.44 0) (end 3.38 0) (layer F.SilkS) (width 0.12)) + (fp_line (start 23.56 0) (end 21.62 0) (layer F.SilkS) (width 0.12)) + (fp_line (start -1.45 -4.25) (end -1.45 4.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start -1.45 4.25) (end 26.45 4.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start 26.45 4.25) (end 26.45 -4.25) (layer F.CrtYd) (width 0.05)) + (fp_line (start 26.45 -4.25) (end -1.45 -4.25) (layer F.CrtYd) (width 0.05)) + (fp_text user %R (at 12.5 0 270) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (pad 1 thru_hole rect (at 0 0 270) (size 2.4 2.4) (drill 1.2) (layers *.Cu *.Mask) + (net 3 "Net-(C1-Pad1)")) + (pad 2 thru_hole oval (at 25 0 270) (size 2.4 2.4) (drill 1.2) (layers *.Cu *.Mask) + (net 1 GND)) + (model ${KISYS3DMOD}/Capacitor_THT.3dshapes/CP_Axial_L18.0mm_D8.0mm_P25.00mm_Horizontal.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (module Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_Horizontal (layer F.Cu) (tedit 5AE5139B) (tstamp 5B59DB1D) + (at 183.5 53.5 180) + (descr "Resistor, Axial_DIN0204 series, Axial, Horizontal, pin pitch=5.08mm, 0.167W, length*diameter=3.6*1.6mm^2, http://cdn-reichelt.de/documents/datenblatt/B400/1_4W%23YAG.pdf") + (tags "Resistor Axial_DIN0204 series Axial Horizontal pin pitch 5.08mm 0.167W length 3.6mm diameter 1.6mm") + (path /5B431328) + (fp_text reference R1 (at 2.54 -1.92 180) (layer F.SilkS) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_text value 10k (at 2.54 1.92 180) (layer F.Fab) + (effects (font (size 1 1) (thickness 0.15))) + ) + (fp_line (start 0.74 -0.8) (end 0.74 0.8) (layer F.Fab) (width 0.1)) + (fp_line (start 0.74 0.8) (end 4.34 0.8) (layer F.Fab) (width 0.1)) + (fp_line (start 4.34 0.8) (end 4.34 -0.8) (layer F.Fab) (width 0.1)) + (fp_line (start 4.34 -0.8) (end 0.74 -0.8) (layer F.Fab) (width 0.1)) + (fp_line (start 0 0) (end 0.74 0) (layer F.Fab) (width 0.1)) + (fp_line (start 5.08 0) (end 4.34 0) (layer F.Fab) (width 0.1)) + (fp_line (start 0.62 -0.92) (end 4.46 -0.92) (layer F.SilkS) (width 0.12)) + (fp_line (start 0.62 0.92) (end 4.46 0.92) (layer F.SilkS) (width 0.12)) + (fp_line (start -0.95 -1.05) (end -0.95 1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start -0.95 1.05) (end 6.03 1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start 6.03 1.05) (end 6.03 -1.05) (layer F.CrtYd) (width 0.05)) + (fp_line (start 6.03 -1.05) (end -0.95 -1.05) (layer F.CrtYd) (width 0.05)) + (fp_text user %R (at 2.54 0 180) (layer F.Fab) + (effects (font (size 0.72 0.72) (thickness 0.108))) + ) + (pad 1 thru_hole circle (at 0 0 180) (size 1.4 1.4) (drill 0.7) (layers *.Cu *.Mask) + (net 3 "Net-(C1-Pad1)")) + (pad 2 thru_hole oval (at 5.08 0 180) (size 1.4 1.4) (drill 0.7) (layers *.Cu *.Mask) + (net 2 "Net-(BT1-Pad1)")) + (model ${KISYS3DMOD}/Resistor_THT.3dshapes/R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_Horizontal.wrl + (at (xyz 0 0 0)) + (scale (xyz 1 1 1)) + (rotate (xyz 0 0 0)) + ) + ) + + (segment (start 167.965 81.279833) (end 174.529833 81.279833) (width 0.25) (layer B.Cu) (net 1)) + (segment (start 166.465001 79.779834) (end 167.965 81.279833) (width 0.25) (layer B.Cu) (net 1)) + (segment (start 174.529833 81.279833) (end 189 95.75) (width 0.25) (layer B.Cu) (net 1)) + (segment (start 195.5 95.75) (end 201.5 89.75) (width 0.25) (layer B.Cu) (net 1)) + (segment (start 189 95.75) (end 195.5 95.75) (width 0.25) (layer B.Cu) (net 1)) + (segment (start 145.975001 78.029834) (end 145.75 77.804833) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 145.975001 79.779834) (end 145.975001 78.029834) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 145.75 77.804833) (end 145.75 62.75) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 155 53.5) (end 178.42 53.5) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 145.75 62.75) (end 155 53.5) (width 0.25) (layer F.Cu) (net 2)) + (segment (start 201.5 63.3) (end 201.5 64.75) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 191.7 53.5) (end 201.5 63.3) (width 0.25) (layer F.Cu) (net 3)) + (segment (start 183.5 53.5) (end 191.7 53.5) (width 0.25) (layer F.Cu) (net 3)) + +) diff --git a/test/doit/schematics/schematic-1.pro b/test/doit/schematics/schematic-1.pro new file mode 100644 index 0000000..dd201c7 --- /dev/null +++ b/test/doit/schematics/schematic-1.pro @@ -0,0 +1,7 @@ +update=22/05/2015 07:44:53 +version=1 +last_client=kicad +[general] +version=1 +RootSch= +BoardNm= diff --git a/test/doit/schematics/schematic-1.sch b/test/doit/schematics/schematic-1.sch index a805e83..9efffc4 100644 --- a/test/doit/schematics/schematic-1.sch +++ b/test/doit/schematics/schematic-1.sch @@ -14,34 +14,34 @@ Comment3 "" Comment4 "" $EndDescr $Comp -L Device:R R? +L Device:R R1 U 1 1 5B431328 P 4400 2600 -F 0 "R?" V 4193 2600 50 0000 C CNN +F 0 "R1" V 4193 2600 50 0000 C CNN F 1 "10k" V 4284 2600 50 0000 C CNN -F 2 "" V 4330 2600 50 0001 C CNN +F 2 "Resistor_THT:R_Axial_DIN0204_L3.6mm_D1.6mm_P5.08mm_Horizontal" V 4330 2600 50 0001 C CNN F 3 "~" H 4400 2600 50 0001 C CNN 1 4400 2600 0 1 1 0 $EndComp $Comp -L Device:Battery_Cell BT? +L Device:Battery_Cell BT1 U 1 1 5B431438 P 3700 2900 -F 0 "BT?" H 3818 2996 50 0000 L CNN +F 0 "BT1" H 3818 2996 50 0000 L CNN F 1 "9V" H 3818 2905 50 0000 L CNN -F 2 "" V 3700 2960 50 0001 C CNN +F 2 "Battery:BatteryHolder_Keystone_103_1x20mm" V 3700 2960 50 0001 C CNN F 3 "~" V 3700 2960 50 0001 C CNN 1 3700 2900 1 0 0 -1 $EndComp $Comp -L Device:C C? +L Device:C C1 U 1 1 5B4314AB P 5000 2850 -F 0 "C?" H 5115 2896 50 0000 L CNN +F 0 "C1" H 5115 2896 50 0000 L CNN F 1 "1u" H 5115 2805 50 0000 L CNN -F 2 "" H 5038 2700 50 0001 C CNN +F 2 "Capacitor_THT:CP_Axial_L18.0mm_D8.0mm_P25.00mm_Horizontal" H 5038 2700 50 0001 C CNN F 3 "~" H 5000 2850 50 0001 C CNN 1 5000 2850 1 0 0 -1 @@ -51,10 +51,10 @@ Wire Wire Line Wire Wire Line 5000 3100 5000 3000 $Comp -L power:GND #PWR? +L power:GND #PWR0101 U 1 1 5B4315FE P 3700 3200 -F 0 "#PWR?" H 3700 2950 50 0001 C CNN +F 0 "#PWR0101" H 3700 2950 50 0001 C CNN F 1 "GND" H 3705 3027 50 0000 C CNN F 2 "" H 3700 3200 50 0001 C CNN F 3 "" H 3700 3200 50 0001 C CNN diff --git a/test/doit/test_doit.py b/test/doit/test_doit.py index 7708ca7..a379c97 100644 --- a/test/doit/test_doit.py +++ b/test/doit/test_doit.py @@ -1,37 +1,39 @@ -import logging import os import os.path -import pytest -import logging filedir = os.path.dirname(os.path.abspath(__file__)) schematics_dir = os.path.join(filedir, "schematics") + def find_task(tasks, name: str): t = next((t for t in tasks if t["name"] == name), None) - assert(t is not None) + assert t is not None, "Could not find task named {}".format(name) return t + def exec_task(task): targets = task["targets"] for a in task["actions"]: if isinstance(a, str): cmd = a % dict(targets=" ".join(targets)) ret = os.system(cmd) - assert(ret == 0) + assert (ret == 0) else: a() + def test_doit(tmpdir, caplog): from ee.kicad.doit import KicadDoitTasks args = dict( sch=os.path.join(schematics_dir, "schematic-1.sch"), + kicad_pcb=os.path.join(schematics_dir, "schematic-1.kicad_pcb"), data_set_dir=os.path.join(tmpdir, "ee"), ) tasks = list(KicadDoitTasks(**args).tasks()) - assert(len(tasks) > 1) + assert (len(tasks) > 1) exec_task(find_task(tasks, "kicad-sch-to-data-set")) + exec_task(find_task(tasks, "kicad-pcb-to-data-set")) exec_task(find_task(tasks, "kicad-create-component-data-set")) # thirdparty/olinuxino/HARDWARE/A64-OLinuXino/A64-OLinuXino_Rev_C/A64-OlinuXino_Rev_C.sch -- cgit v1.2.3