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, "components_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], }) components_dir = self.config["components_dir"] if sch and components_dir: tasks.append(task_sch_to_component_files(sch, components_dir)) for t in tasks: yield t def task_sch_to_component_files(sch, components_dir): def action(): import ee.kicad from ee.kicad.model import Component, ComponentField import csv import configparser from ee.fact import Fact schematics = ee.kicad.read_schematics(sch) cs = [c for c in schematics.components] os.makedirs(components_dir, exist_ok=True) # TODO: remove directory? for c in cs: path = os.path.join(components_dir, "{}.ini".format(c.timestamp)) ini = configparser.ConfigParser(interpolation = None) if os.path.isfile(path) and ini.read(path) != [path]: print("Could not load component file: {}".format(path)) return False # if ini.has_section("kicad-schematic"): # ini.remove_section("kicad-schematic") # ini.add_section("kicad-schematic") # ini.set("kicad-schematic", "ref", c.ref) # ini.set("kicad-schematic", "ref-type", c.ref_type) fact = Fact("schematic-symbol") ks = fact.view("kicad-schematic") ks.set("ref", c.ref) ks.set("ref-type", c.ref_type) if c.has_ref_num: # ini.set("kicad-schematic", "ref-num", str(c.ref_num)) ks.set("ref-num", str(c.ref_num)) # ini.set("kicad-schematic", "value", c.value) ks.set("value", c.value) if c.footprint: # ini.set("kicad-schematic", "footprint", c.footprint) ks.set("footprint", c.footprint) fields = [f for f in c.fields if f.value and f.name not in ComponentField.names] if fields: # if ini.has_section("kicad-fields"): # ini.remove_section("kicad-fields") # ini.add_section("kicad-fields") kf = fact.kv("kicad-fields") for f in fields: kf.set(f.name, str(f.value)) with open(path, "w", newline="") as f: # ini.write(f) fact.write(f) component_files_cookie = "{}/components.cookie".format(components_dir) gen_cookie = "date > %(targets)s" return { "name": "sch_to_component_files", "file_dep": [sch], "actions": [action, gen_cookie], "targets": [component_files_cookie], }