aboutsummaryrefslogtreecommitdiff
path: root/src/ee/part/bom.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/ee/part/bom.py')
-rw-r--r--src/ee/part/bom.py110
1 files changed, 110 insertions, 0 deletions
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