aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2018-07-22 22:08:56 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2018-07-22 22:08:56 +0200
commit3e5819caef56c449606e27ec80f9d563d519a907 (patch)
tree943dae6b38832f227f2d6391ef55c324856eec2a
parent73fe63ceb6d10e5bed0664100de8709843661d8d (diff)
downloadee-python-3e5819caef56c449606e27ec80f9d563d519a907.tar.gz
ee-python-3e5819caef56c449606e27ec80f9d563d519a907.tar.bz2
ee-python-3e5819caef56c449606e27ec80f9d563d519a907.tar.xz
ee-python-3e5819caef56c449606e27ec80f9d563d519a907.zip
wip.
o Changing the data sources to not implicitly starting as a union of all the input data sets.
-rw-r--r--src/ee/fact/__init__.py114
-rw-r--r--src/ee/kicad/doit.py28
-rw-r--r--src/ee/kicad/pcb/__init__.py1
3 files changed, 99 insertions, 44 deletions
diff --git a/src/ee/fact/__init__.py b/src/ee/fact/__init__.py
index 1bdef0d..02e6b2a 100644
--- a/src/ee/fact/__init__.py
+++ b/src/ee/fact/__init__.py
@@ -3,7 +3,7 @@ import logging
import os
from functools import total_ordering
from pathlib import Path
-from typing import MutableMapping, Optional, Mapping, List
+from typing import MutableMapping, Optional, List, Tuple
logger = logging.getLogger(__name__)
@@ -81,10 +81,9 @@ class Object(object):
class DataSet(object):
def __init__(self, name):
self._name = name
- self._object_types = {}
- self._objects_by_type = {} # type: MutableMapping[str, Mapping[str, Object]]
+ self._object_types = {} # type: MutableMapping[str, ObjectType]
+ self._objects_by_type = {} # type: MutableMapping[ObjectType, MutableMapping[str, Object]]
self._frozen = False
- self._changed = False
@property
def name(self):
@@ -93,38 +92,82 @@ class DataSet(object):
def freeze(self):
self._frozen = True
- def get_object_type(self, object_type: str) -> ObjectType:
+ def _assert_not_frozen(self):
+ if self._frozen:
+ raise Exception("This data set is frozen")
+
+ def _check_object_type(self, object_type: str, create: bool) -> \
+ Optional[Tuple[ObjectType, MutableMapping[str, Object]]]:
try:
- return self._object_types[object_type]
+ ot = self._object_types[object_type]
+ objects = self._objects_by_type[ot]
+ return ot, objects,
except KeyError:
+ if not create:
+ return None
+
+ self._assert_not_frozen()
+
ot = ObjectType(object_type)
self._object_types[object_type] = ot
- self._changed = True
- return ot
+ self._objects_by_type[ot] = objects = {}
+ return ot, objects,
- def get_object(self, object_type: str, key: str) -> Object:
- try:
- objects = self._objects_by_type[object_type]
- except KeyError:
- if self._frozen:
- raise Exception("This data set is frozen")
+ def _check_object(self, object_type: str, key: str, create: bool) -> Optional[Object]:
+ t = self._check_object_type(object_type, create)
- objects = {}
- self._objects_by_type[object_type] = objects
- self._changed = True
+ if not t:
+ return None
+ ot, objects = t
try:
return objects[key]
except KeyError:
- if self._frozen:
- raise Exception("This data set is frozen")
+ self._assert_not_frozen()
+
+ if not create:
+ raise Exception("No such type: {}:{}".format(object_type, key))
- ot = self.get_object_type(object_type)
o = Object(self, ot, key)
objects[key] = o
- self._changed = True
return o
+ def get_object_type(self, object_type: str) -> ObjectType:
+ ot, objects = self._check_object_type(object_type, False)
+
+ if not ot:
+ raise Exception("No such object type: {}".format(object_type))
+
+ return ot
+
+ def get_object(self, object_type: str, key: str) -> Object:
+ o = self._check_object(object_type, key, False)
+
+ if not o:
+ raise Exception("No such object: {}:{}".format(object_type, key))
+
+ return o
+
+ def has_object(self, object_type: str, key: str) -> bool:
+ t = self._check_object_type(object_type, False)
+
+ if t:
+ ot, objects = t
+ return key in objects
+
+ return False
+
+ def get_or_create_object(self, object_type: str, key: str) -> Object:
+ return self._check_object(object_type, key, True)
+
+ def create_object(self, object_type: str, key: str) -> Object:
+ self._assert_not_frozen()
+
+ if self.has_object(object_type, key):
+ raise Exception("Object already exist: {}:{}".format(object_type, key))
+
+ return self._check_object(object_type, key, True)
+
def items(self):
from itertools import chain
return list(chain.from_iterable([objects.values() for objects in self._objects_by_type.values()]))
@@ -133,11 +176,11 @@ class DataSet(object):
ds = DataSet(self._name)
for objects in self._objects_by_type.values():
for o in objects.values():
- ds.get_object(o.object_type.name, o.key)._set_from_object(o)
+ ds.create_object(o.object_type.name, o.key)._set_from_object(o)
for objects in other._objects_by_type.values():
for o in objects.values():
- ds.get_object(o.object_type.name, o.key)._set_from_object(o)
+ ds.get_or_create_object(o.object_type.name, o.key)._set_from_object(o)
return ds
@@ -149,8 +192,11 @@ class DataSetManager(object):
def metafile_for_ds(self, ds_name) -> Path:
return self._basedir / ds_name / "data-set.ini"
- def create_rw(self, name, inputs: List[str]) -> "LazyDataSet":
- return LazyDataSet(self, name, inputs)
+ def create_rw(self, name, inputs: List[str] = None) -> "LazyDataSet":
+ return LazyDataSet(self, False, name, inputs if inputs else [])
+
+ def create_ro(self, inputs: List[str]) -> "LazyDataSet":
+ return LazyDataSet(self, True, None, inputs)
def load(self, name, freeze=False) -> DataSet:
ds_dir = Path(name) if Path(name).is_absolute() else self._basedir / name
@@ -175,7 +221,7 @@ class DataSetManager(object):
key = o_path.name[:-4]
logger.info(" Loading key '{}'".format(key))
ini = self._load_ini(o_path)
- o = ds.get_object(ot, key)
+ o = ds.create_object(ot, key)
for k, v in ini.items("values"):
o.set(k, v)
@@ -229,21 +275,25 @@ class DataSetManager(object):
class LazyDataSet(object):
- def __init__(self, dsm: DataSetManager, name, inputs):
+ def __init__(self, dsm: DataSetManager, freeze: bool, name, inputs):
self._dsm = dsm
+ self._freeze = freeze
self._name = name
self._inputs = inputs
- def __enter__(self):
+ def __enter__(self) -> DataSet:
# 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))
+
+ if self._freeze:
+ ds.freeze()
+
self._ds = ds
- return self._ds
+ return ds
def __exit__(self, *args):
- # logger.info("exit: name={}, inputs={}".format(self._name, self._inputs))
- # logger.info("ds.size={}".format(len(self._ds.items())))
- self._dsm.store(self._ds)
+ if not self._freeze:
+ self._dsm.store(self._ds)
return False
diff --git a/src/ee/kicad/doit.py b/src/ee/kicad/doit.py
index 577eb21..7273076 100644
--- a/src/ee/kicad/doit.py
+++ b/src/ee/kicad/doit.py
@@ -88,7 +88,7 @@ def task_kicad_sch_to_data_set():
with _dsm.create_rw(out_data_set, inputs=in_data_sets) as ds:
schematics = ee.kicad.read_schematics(sch)
for c in [c for c in schematics.components]:
- o = ds.get_object("kicad-schematic-component", c.timestamp)
+ o = ds.create_object("kicad-schematic-component", c.timestamp)
o.set("ref", c.ref)
o.set("ref-type", c.ref_type)
if c.has_ref_num:
@@ -116,24 +116,26 @@ def task_kicad_pcb_to_data_set():
in_data_sets = []
def action():
+ from ee.kicad.pcb import KicadPcb, Module
+
logger.debug("Parsing PCB {}".format(kicad_pcb))
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.parse(kicad_pcb) # type: ee.kicad.pcb.KicadPcb
+ pcb = ee.kicad.pcb.parse(kicad_pcb) # type: KicadPcb
for _m in pcb.modules:
- m = _m # type: ee.kicad.pcb.Module
+ m = _m # type: Module
- o = ds.get_object("kicad-pcb-component", m.tstamp)
+ o = ds.create_object("kicad-pcb-component", m.tstamp)
ref_text = 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("placement-x", x)
+ o.set("placement-y", y)
+ o.set("placement-rotation", rot)
o.set("layer", m.layer)
return {
@@ -151,11 +153,13 @@ def task_kicad_create_component_data_set():
def action(targets, *args, **kwargs):
logger.info("targets={}, args={}, kwargs={}".format(targets, args, kwargs))
- with _dsm.create_rw(out_data_set, inputs=in_data_sets) as ds:
- items = ds.items()
- logger.info("Got {} objects".format(len(items)))
- for o in items:
- logger.info("processing {}".format(o.key))
+ with _dsm.create_ro(in_data_sets) as input:
+ with _dsm.create_rw(out_data_set) as output:
+ items = input.items()
+ logger.info("Got {} objects".format(len(items)))
+ for o in items:
+ ot = o.object_type
+ logger.info("processing {}:{}".format(ot.name, o.key))
return {
"basename": "kicad-create-component-data-set",
diff --git a/src/ee/kicad/pcb/__init__.py b/src/ee/kicad/pcb/__init__.py
index a4ad8ba..a8f96d7 100644
--- a/src/ee/kicad/pcb/__init__.py
+++ b/src/ee/kicad/pcb/__init__.py
@@ -7,6 +7,7 @@ def auto_str(cls):
return str({k: [str(x) for x in v] if isinstance(v, list) else str(v) for k, v in vars(self).items()})
cls.__str__ = __str__
+ cls.__name__ = cls.__name__
return cls