import os.path from doit.exceptions import TaskFailed from doit.tools import check_timestamp_unchanged from configclass import Config class KicadDoitTasks(object): config = Config({ "sch": None, "kicad_pcb": None, "gerber_dir": None, "gerber_zip": None, "kicad_sch_object_set_dir": None, "component_object_set_dir": None, }) def __init__(self, *args, **kwargs): self.config = self.config.make(kwargs) def echo(*args, **kwargs): print("_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 = [] gerber_dir = self.config["gerber_dir"] if gerber_dir: gerber_zip = self.config["gerber_zip"] or "{}.zip".format(gerber_dir) #print("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: raise Exception("Could not find export_gerber.py") # TODO: replace with python mkdir = "mkdir -p {}".format(gerber_dir) export_gerber = " ".join([ eg, "--pcb", kicad_pcb, "--output-directory", gerber_dir, "--protel-extensions", ]) def make_zip(): import zipfile from pathlib import Path with zipfile.ZipFile(gerber_zip, "w") as z: for p in Path(gerber_dir).iterdir(): if not p.is_file(): continue z.write(p, arcname=p.relative_to(gerber_dir)) tasks.append({ "name": "kicad_gerber", "targets": [gerber_zip], "actions": [mkdir, export_gerber, make_zip], "file_dep": [kicad_pcb], }) kicad_sch_object_set_dir = self.config["kicad_sch_object_set_dir"] component_object_set_dir = self.config["component_object_set_dir"] if sch and kicad_sch_object_set_dir: tasks.append(task_create_kicad_sch_objects(sch, kicad_sch_object_set_dir)) if kicad_sch_object_set_dir and component_object_set_dir: tasks.append(task_kicad_sch_to_component_object(kicad_sch_object_set_dir, component_object_set_dir)) for t in tasks: yield t def task_create_kicad_sch_objects(sch, os_dir, name="create-kicad-sch-objects"): def action(): import ee.kicad from ee.kicad.model import Component, ComponentField import csv import configparser import ee.fact as fact schematics = ee.kicad.read_schematics(sch) cs = [c for c in schematics.components] os.makedirs(os_dir, exist_ok=True) # TODO: remove directory? oset = fact.ObjectSet() oset.read(os_dir) for c in cs: o = oset.create_object(c.timestamp) o.set("ref", c.ref) o.set("ref-type", c.ref_type) if c.has_ref_num: o.set("ref-num", str(c.ref_num)) o.set("value", c.value) if c.footprint: o.set("footprint", c.footprint) for f in c.fields: if f.value and f.name not in ComponentField.names: o.set(f.name, str(f.value)) oset.write(os_dir) return { "name": name, "file_dep": [sch], "actions": [action], "targets": [os.path.join(os_dir, "object-set.ini")], } def task_kicad_sch_to_component_object(kicad_sch_os_dir, component_os_dir, name="kicad-sch-to-component-object"): def action(): import ee.fact as fact kicad_sch_os = fact.ObjectSet() kicad_sch_os.read(kicad_sch_os_dir) os.makedirs(component_os_dir, exist_ok=True) component_os = fact.ObjectSet() component_os.read(component_os_dir) for o in kicad_sch_os.items(): print("processing {}".format(o.key)) component_os.write(component_os_dir) return { "name": name, "file_dep": [os.path.join(kicad_sch_os_dir, "object-set.ini")], "actions": [action], "targets": [os.path.join(component_os_dir, "object-set.ini")], }