aboutsummaryrefslogtreecommitdiff
path: root/src/ee/db.py
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2019-03-28 16:38:50 +0100
committerTrygve Laugstøl <trygvis@inamo.no>2019-03-28 16:43:14 +0100
commitfa85d46af0b91477cf354947df628af0dc0d2800 (patch)
treeb18b775d232560f57eaeb3f43d0861b98201d4ef /src/ee/db.py
parent52401b170d8f1c9deaa153acca76e7d6060a06df (diff)
downloadee-python-fa85d46af0b91477cf354947df628af0dc0d2800.tar.gz
ee-python-fa85d46af0b91477cf354947df628af0dc0d2800.tar.bz2
ee-python-fa85d46af0b91477cf354947df628af0dc0d2800.tar.xz
ee-python-fa85d46af0b91477cf354947df628af0dc0d2800.zip
ee.xsd:
o Renaming <part-uri> to <part-reference>. o Adding <supplier> on <part>, removing from <supplier-part-number>. A part can have exactly one part. create-order: o Creating anonymous part objects, with two references, one schematic reference and one part-uri reference to the selected part. o Redoing how the order is calculated with the new ObjDb structure. ee.part.Part: o Absorbing bom_file_utils into Part. Much better wrapper object around the xml goop.
Diffstat (limited to 'src/ee/db.py')
-rw-r--r--src/ee/db.py117
1 files changed, 97 insertions, 20 deletions
diff --git a/src/ee/db.py b/src/ee/db.py
index e471278..57533ef 100644
--- a/src/ee/db.py
+++ b/src/ee/db.py
@@ -1,4 +1,4 @@
-from typing import TypeVar, Generic, Callable, MutableMapping, List, Iterable, Union, Any
+from typing import TypeVar, Generic, Callable, MutableMapping, List, Iterable, Union, Any, Mapping
K = TypeVar('K')
V = TypeVar('V')
@@ -34,9 +34,11 @@ class Index(Generic[K, V]):
class ListIndex(Index[K, V]):
- def __init__(self, key_callable: KeyCallable):
+ def __init__(self, name, key_callable: KeyCallable, multiple=False):
+ self.name = name
self.idx: MutableMapping[K, V] = {}
self.key_callable = key_callable
+ self.multiple = multiple
def add(self, value: V):
keys = self.key_callable(value)
@@ -44,6 +46,9 @@ class ListIndex(Index[K, V]):
if keys is None:
return
+ if not self.multiple:
+ keys = [keys]
+
for key in keys:
if key is None:
continue
@@ -54,8 +59,9 @@ class ListIndex(Index[K, V]):
else:
self.idx[key] = [value]
- def get(self, key: K) -> Iterable[V]:
- return [self.idx[key]]
+ def get(self, key: K) -> List[V]:
+ items = self.idx.get(key, None)
+ return self.idx[key] if items is not None else []
def clear(self):
return self.idx.clear()
@@ -71,12 +77,15 @@ class ListIndex(Index[K, V]):
class UniqueIndex(Index[K, V]):
- def __init__(self, key_callable: KeyCallable):
+ def __init__(self, name, key_callable: KeyCallable, multiple=False):
+ self.name = name
self.idx: MutableMapping[K, V] = {}
self.key_callable = key_callable
+ self.multiple = multiple
def get(self, key: K) -> Iterable[V]:
- return [self.idx[key]]
+ items = self.idx.get(key, None)
+ return [self.idx[key]] if items is not None else []
def get_single(self, key: K) -> V:
return self.idx[key]
@@ -84,16 +93,75 @@ class UniqueIndex(Index[K, V]):
def add(self, value: V):
keys = self.key_callable(value)
- if not isinstance(keys, Iterable):
+ if keys is None:
+ return
+
+ if not self.multiple:
keys = [keys]
for key in keys:
- key = self.key_callable(value)
present = self.idx.get(key, None)
if present is not None:
- raise KeyError("Duplicate part in index: {}".format(key))
+ raise KeyError("Duplicate key in index '{}': key={}, value={}".format(self.name, key, repr(value)))
+
+ self.idx[key] = value
+
+ def clear(self):
+ return self.idx.clear()
+
+ def __iter__(self):
+ return self.idx.__iter__()
+
+ def items(self):
+ return self.idx.items()
+
+ def values(self):
+ return self.idx.values()
+
+
+class MultiIndex(Index[K, V]):
+ def __init__(self, name, key_callable: KeyCallable, multiple=False):
+ self.name = name
+ self.idx: MutableMapping[K, V] = {}
+ self.key_callable = key_callable
+ self.multiple = multiple
+
+ # TODO: this should return a new index
+ def get(self, key: K) -> Mapping[K, V]:
+ items = self.idx.get(key, None)
+ return self.idx[key] if items is not None else {}
- self.idx[key] = True
+ def get_single(self, key: K) -> V:
+ return self.idx[key]
+
+ def add(self, value: V):
+ keys = self.key_callable(value)
+
+ if keys is None:
+ return
+
+ if not self.multiple:
+ keys = [keys]
+
+ for tpl in keys:
+ if not isinstance(tpl, tuple):
+ raise KeyError("The key must be a tuple, index='{}', key='{}'".format(self.name, repr(tpl)))
+
+ parent_idx = self.idx
+ for sub_key in tpl[0:-1]:
+ if sub_key is None:
+ raise KeyError("Got None sub-key: index='{}', key='{}'".format(self.name, repr(tpl)))
+ idx = parent_idx.get(sub_key, None)
+ if idx is None:
+ idx = {}
+ parent_idx[sub_key] = idx
+ parent_idx = idx
+
+ values = parent_idx.get(tpl[-1], None)
+ if values is None:
+ values = []
+ parent_idx[tpl[-1]] = values
+ values.append(value)
def clear(self):
return self.idx.clear()
@@ -125,19 +193,28 @@ class ObjDb(Generic[V]):
def __len__(self) -> int:
return len(self.values)
- def add_index(self, name, key_callable: KeyCallable) -> ListIndex[Any, V]:
- idx = ListIndex(key_callable)
- self._indexes[name] = idx
+ def add_index(self, name, key_callable: KeyCallable, **kwargs) -> ListIndex[Any, V]:
+ idx = ListIndex(name, key_callable, **kwargs)
+ return self._add(name, idx)
+
+ def add_unique_index(self, name, key_callable: KeyCallable, **kwargs) -> UniqueIndex[Any, V]:
+ idx = UniqueIndex(name, key_callable, **kwargs)
+ return self._add(name, idx)
+
+ def add_multi_index(self, name, key_callable: KeyCallable, **kwargs) -> MultiIndex[Any, V]:
+ idx = MultiIndex(name, key_callable, **kwargs)
+ return self._add(name, idx)
+
+ def index(self, name) -> Index:
+ return self._indexes[name]
+
+ def _add(self, name, idx):
+ if name in self._indexes:
+ raise KeyError("Index already exist: {}".format(name))
for value in self.values:
idx.add(value)
- return idx
-
- def add_unique_index(self, name, key_callable: KeyCallable) -> UniqueIndex[Any, V]:
- idx = UniqueIndex(key_callable)
self._indexes[name] = idx
- return idx
- def index(self, name) -> Index:
- return self._indexes[name]
+ return idx