aboutsummaryrefslogtreecommitdiff
path: root/src/ee/part
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2019-06-14 10:40:31 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2019-06-14 10:40:31 +0200
commit89197dad4f5f427faa7fba12971b20037ad5ba71 (patch)
tree0124db8c8eec7f70b7169c2aa2fd67bc6c1adeb8 /src/ee/part
parentd203763f31428bee3edba4383d37f992b0f8e186 (diff)
downloadee-python-89197dad4f5f427faa7fba12971b20037ad5ba71.tar.gz
ee-python-89197dad4f5f427faa7fba12971b20037ad5ba71.tar.bz2
ee-python-89197dad4f5f427faa7fba12971b20037ad5ba71.tar.xz
ee-python-89197dad4f5f427faa7fba12971b20037ad5ba71.zip
split-parts-by-supplier: rename to split-bom-by-supplier.
digikey-create-bom: Implementing CSV generation for Digi-Key.
Diffstat (limited to 'src/ee/part')
-rw-r--r--src/ee/part/__init__.py2
-rw-r--r--src/ee/part/bom.py110
2 files changed, 111 insertions, 1 deletions
diff --git a/src/ee/part/__init__.py b/src/ee/part/__init__.py
index c18dd02..deeab95 100644
--- a/src/ee/part/__init__.py
+++ b/src/ee/part/__init__.py
@@ -309,7 +309,7 @@ class Part(object):
def get_exactly_one_spn(self) -> types.SupplierPartNumber:
spns = self.get_spns()
if len(spns) == 0:
- raise EeException("This part does not contain any manufacturer part numbers{}".
+ raise EeException("This part does not contain any supplier part numbers{}".
format(", uri=" + self.uri if self.uri else ""))
if len(spns) != 1:
raise EeException("This part does not contain exactly one spn: {}".
diff --git a/src/ee/part/bom.py b/src/ee/part/bom.py
new file mode 100644
index 0000000..83ae348
--- /dev/null
+++ b/src/ee/part/bom.py
@@ -0,0 +1,110 @@
+import re
+import sys
+from itertools import groupby
+from pathlib import Path
+from typing import List
+
+from ee import EeException
+from ee.db import ObjDb
+from ee.part import Part, load_db
+
+__all__ = ["load_bom"]
+
+
+def uri_fn(part: Part):
+ return part.uri
+
+
+def supplier_fn(part: Part):
+ return part.supplier
+
+
+class BomItem(object):
+ def __init__(self, references, part: Part):
+ self.references = references
+ self.part = part
+
+
+def load_bom(bom_path: Path, part_files: List[Path]) -> (ObjDb[Part](), ObjDb[Part]()):
+ bom: ObjDb[Part] = ObjDb[Part]()
+
+ for xml in load_db(bom_path).iterparts():
+ bom.add(Part(xml))
+
+ parts: ObjDb[Part] = ObjDb[Part]()
+ parts.add_unique_index("uri", uri_fn)
+ parts.add_index("supplier", supplier_fn)
+
+ for part_file in part_files:
+ for xml in load_db(part_file).iterparts():
+ parts.add(Part(xml))
+
+ return bom, parts
+
+
+def check_bom(bom: ObjDb[Part](), parts: ObjDb[Part]()):
+ pass
+
+
+def split_ref(ref):
+ """Split "C12" into a tuple that's useful for sorting by component reference.
+
+ For example: "C12" => ("C", 12, None). "Cfoo" => ("C", sys.maxsize, "").
+ """
+ m = split_ref.r.match(ref)
+ if not m:
+ return ref, sys.maxsize, ""
+ groups = m.groups()
+ ref = groups[0]
+ val = groups[1]
+ rest = groups[2]
+ try:
+ return ref, int(val), rest
+ except ValueError:
+ pass
+
+ return ref, val, rest
+
+
+split_ref.r = re.compile("([A-Za-z]+)([0-9]+)(.*)")
+
+
+def join_refs(refs: List[str], max=None) -> str:
+ refs = [ref.strip() for ref in refs]
+
+ rs = sorted([split_ref(ref) for ref in refs])
+
+ for r in rs:
+ if r[1] is None:
+ raise EeException("Bad ref, must match '[A-Z]+[0-9]+'.")
+
+ s = ""
+ for kind, items in groupby(rs, lambda x: x[0]):
+ items = list(items)
+
+ groups = []
+ start = cur = items[0][1]
+
+ for r in items[1:]:
+ num = r[1]
+
+ if cur + 1 != num:
+ groups.append([start, cur])
+ start = cur = num
+ else:
+ cur = num
+
+ groups.append([start, cur])
+
+ parts = []
+ for start, end in groups:
+ if start == end:
+ parts.append(str(start))
+ elif start + 1 == end:
+ parts.append("{},{}".format(start, end))
+ else:
+ parts.append("{}-{}".format(start, end))
+
+ s += kind + ",".join(parts)
+
+ return s