aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2018-07-24 21:01:46 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2018-07-24 21:01:46 +0200
commit44c436ce849f9155706109e767fe7b1666172f7e (patch)
tree3712420d3443fc9a315bbfb07cf962ad301ef40a
parent545263da9dbd60106525fe663db673a35eadc244 (diff)
downloadee-python-44c436ce849f9155706109e767fe7b1666172f7e.tar.gz
ee-python-44c436ce849f9155706109e767fe7b1666172f7e.tar.bz2
ee-python-44c436ce849f9155706109e767fe7b1666172f7e.tar.xz
ee-python-44c436ce849f9155706109e767fe7b1666172f7e.zip
o Starting on some BOM code.
-rw-r--r--demo/doit/dodo.py9
-rw-r--r--src/ee/bom/__init__.py0
-rw-r--r--src/ee/bom/doit.py95
-rw-r--r--src/ee/ds/__init__.py60
-rw-r--r--src/ee/kicad/doit.py10
5 files changed, 153 insertions, 21 deletions
diff --git a/demo/doit/dodo.py b/demo/doit/dodo.py
index 395cbee..1f5fec8 100644
--- a/demo/doit/dodo.py
+++ b/demo/doit/dodo.py
@@ -1,6 +1,9 @@
import ee.kicad.doit
-from ee.kicad.doit import *
+import ee.bom.doit
+# noinspection PyUnresolvedReferences
+from ee.bom.doit import *
from ee.ds import DataSetManager
+from ee.kicad.doit import *
prj = "demo"
sch = "{}.sch".format(prj)
@@ -21,3 +24,7 @@ ee.kicad.doit.init(
kicad_pcb=kicad_pcb,
gerber_dir="gerber",
)
+
+ee.bom.doit.init(
+ data_set_manager=dsm,
+)
diff --git a/src/ee/bom/__init__.py b/src/ee/bom/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/src/ee/bom/__init__.py
diff --git a/src/ee/bom/doit.py b/src/ee/bom/doit.py
new file mode 100644
index 0000000..d7407d8
--- /dev/null
+++ b/src/ee/bom/doit.py
@@ -0,0 +1,95 @@
+from typing import Mapping
+
+from configclass import Config
+
+from ee.ds import DataSetManager
+
+_dsm = None # type: DataSetManager
+
+_data_sets = {}
+
+_config_template = Config({
+})
+
+_config = None # type: Mapping[str, str]
+
+
+def init(data_set_manager: DataSetManager, **kwargs):
+ global _config
+ _config = _config_template.make(kwargs)
+
+ global _dsm
+ _dsm = data_set_manager
+
+
+class BomComponent(object):
+ def __init__(self, ref, mpn):
+ self.ref = ref
+ self.mpn = mpn
+
+ def to_object(self, ds):
+ return ds.create_object("bom-component", self.ref).\
+ set("ref", self.ref).\
+ set("mpn", self.mpn)
+
+
+class MpnBomComponent(object):
+ def __init__(self, ref, mpn):
+ self.ref = ref
+ self.mpn = mpn
+ self.count = 1
+
+ def to_object(self, ds):
+ return ds.create_object("mpn-bom-component", self.ref).\
+ set("ref", self.ref).\
+ set("mpn", self.mpn)
+
+
+def task_bom():
+ out_data_set = "bom"
+ in_data_sets = _data_sets[task_bom]
+
+ def action(count=1):
+ with _dsm.create_ro(in_data_sets) as in_ds:
+ with _dsm.create_rw(out_data_set, clean=True) as output:
+ components = [o for o in in_ds.items() if o.object_type.name == "component"]
+
+ bom_components = {}
+ mpn_bom_components = {}
+
+ for c in components:
+ ref = c.get("ref")
+ mpn = c.get("mpn")
+
+ if not ref:
+ raise Exception("Missing ref")
+
+ if not mpn:
+ output.create_object("message", "bom-{}".format(ref)). \
+ set("level", "error"). \
+ set("message", "Missing required field 'mpn'")
+ continue
+
+ if ref in bom_components:
+ raise Exception("Duplicate ref '{}'".format("ref"))
+
+ bom_components[ref] = BomComponent(ref, mpn)
+
+ mpn_bom_component = mpn_bom_components[ref]
+ if not mpn_bom_component:
+ mpn_bom_component = MpnBomComponent(ref, mpn)
+ mpn_bom_components[ref] = mpn_bom_component
+
+ mpn_bom_component.count += 1
+
+ [c.to_object(output) for c in bom_components.values()]
+ [c.to_object(output) for c in mpn_bom_components.values()]
+
+ return {
+ "file_dep": [_dsm.cookie_for_ds(ds) for ds in in_data_sets],
+ "actions": [action],
+ "targets": [_dsm.cookie_for_ds(out_data_set)],
+ }
+
+
+_data_sets[task_bom] = ["components"]
diff --git a/src/ee/ds/__init__.py b/src/ee/ds/__init__.py
index aff5b64..5899d28 100644
--- a/src/ee/ds/__init__.py
+++ b/src/ee/ds/__init__.py
@@ -2,6 +2,7 @@ import configparser
import csv
import logging
import os
+import shutil
from functools import total_ordering
from pathlib import Path
from typing import MutableMapping, Optional, List, Tuple, Union, Iterator
@@ -64,12 +65,14 @@ class Object(object):
def key(self):
return self._key
- def set(self, key: str, value: str):
+ def set(self, key: str, value: str) -> "Object":
if self._ds._frozen:
raise Exception("This data set is frozen")
idx = self._ot.index_of(key, create=True)
self._data.insert(idx, value)
+ return self
+
def _set_from_object(self, other: "Object"):
for k in other._ot.fields:
self.set(k, other.get(k))
@@ -89,7 +92,7 @@ class Object(object):
class DataSet(object):
- def __init__(self, name):
+ def __init__(self, name: Optional[str] = None):
self._name = name
self._object_types = {} # type: MutableMapping[str, ObjectType]
self._objects_by_type = {} # type: MutableMapping[ObjectType, MutableMapping[str, Object]]
@@ -97,6 +100,8 @@ class DataSet(object):
@property
def name(self):
+ if not self._name:
+ raise Exception("Unnamed data set")
return self._name
def __len__(self):
@@ -210,11 +215,11 @@ class DataSetManager(object):
except KeyError:
return self._basedir / ds_name / "data-set.ini"
- def create_rw(self, name, inputs: List[str] = None) -> "LazyDataSet":
- return LazyDataSet(self, False, name, inputs if inputs else [])
+ def create_rw(self, name, clean: bool) -> "LazyRwDataSet":
+ return LazyRwDataSet(self, name, clean)
- def create_ro(self, inputs: List[str]) -> "LazyDataSet":
- return LazyDataSet(self, True, None, inputs)
+ def create_ro(self, inputs: List[str]) -> "LazyRoDataSet":
+ return LazyRoDataSet(self, inputs)
def add_ds(self, ds_type: str, name: str, object_type: str, path: str = None):
if ds_type == "csv":
@@ -337,27 +342,52 @@ class DataSetManager(object):
with open(path, "w") as f:
ini.write(f)
+ def remove(self, name: str):
+ try:
+ object_type, path = self._csv[name]
+ os.remove(str(path))
+ except KeyError:
+ shutil.rmtree(self._basedir / name)
+
-class LazyDataSet(object):
- def __init__(self, dsm: DataSetManager, freeze: bool, name, inputs):
+class LazyRoDataSet(object):
+ def __init__(self, dsm: DataSetManager, inputs):
self._dsm = dsm
- self._freeze = freeze
- self._name = name
self._inputs = inputs
def __enter__(self) -> DataSet:
# logger.info("enter: name={}, inputs={}".format(self._name, self._inputs))
- ds = DataSet(self._name)
+ ds = DataSet()
for name in self._inputs:
ds = ds.merge(self._dsm.load(name, freeze=True))
- if self._freeze:
- ds.freeze()
+ ds.freeze()
+
+ self._ds = ds
+ return ds
+ def __exit__(self, *args):
+ return False
+
+
+class LazyRwDataSet(object):
+ def __init__(self, dsm: DataSetManager, name, clean):
+ self._dsm = dsm
+ self._name = name
+ self._clean = clean
+
+ def __enter__(self) -> DataSet:
+ cookie = self._dsm.cookie_for_ds(self._name)
+
+ if cookie.exists():
+ if not self._clean:
+ raise IOError("DataSet already exists: {}, cookie={}".format(self._name, cookie))
+ self._dsm.remove(self._name)
+
+ ds = DataSet(self._name)
self._ds = ds
return ds
def __exit__(self, *args):
- if not self._freeze:
- self._dsm.store(self._ds)
+ self._dsm.store(self._ds)
return False
diff --git a/src/ee/kicad/doit.py b/src/ee/kicad/doit.py
index a3f8464..30ca40d 100644
--- a/src/ee/kicad/doit.py
+++ b/src/ee/kicad/doit.py
@@ -25,8 +25,8 @@ _dsm = None # type: DataSetManager
_data_sets = {}
-def change_data_sets_for_task(task, callable):
- _data_sets[task] = callable(_data_sets[task])
+def change_data_sets_for_task(task, _callable):
+ _data_sets[task] = _callable(_data_sets[task])
def init(data_set_manager: DataSetManager, **kwargs):
@@ -92,7 +92,7 @@ def task_kicad_sch_to_data_set():
def action():
from ee.kicad.model import ComponentField
- with _dsm.create_rw(out_data_set) as ds:
+ with _dsm.create_rw(out_data_set, clean=True) as ds:
schematics = ee.kicad.read_schematics(sch)
for c in [c for c in schematics.components]:
o = ds.create_object("kicad-schematic-component", c.timestamp)
@@ -129,7 +129,7 @@ def task_kicad_pcb_to_data_set():
logger.debug("Parsing PCB {}".format(kicad_pcb))
- with _dsm.create_rw(out_data_set, inputs=in_data_sets) as ds:
+ with _dsm.create_rw(out_data_set, clean=True) as ds:
# [ds.delete(o) for o in ds.items(object_type="kicad-pcb-component")]
pcb = ee.kicad.pcb.parse(kicad_pcb) # type: KicadPcb
@@ -179,7 +179,7 @@ def task_kicad_create_component_data_set():
return footprint
- with _dsm.create_rw(out_data_set) as output:
+ with _dsm.create_rw(out_data_set, clean=True) as output:
kicad_sch = [o for o in in_ds.items() if o.object_type.name == "kicad-schematic-component"]
logger.info("processing {} kicad-sch".format(len(kicad_sch)))