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.py62
1 files changed, 56 insertions, 6 deletions
diff --git a/src/ee/part/bom.py b/src/ee/part/bom.py
index 83ae348..0bf284a 100644
--- a/src/ee/part/bom.py
+++ b/src/ee/part/bom.py
@@ -1,22 +1,37 @@
import re
import sys
+from functools import total_ordering
from itertools import groupby
from pathlib import Path
-from typing import List
+from typing import List, Optional, MutableMapping
from ee import EeException
from ee.db import ObjDb
+from ee.logging import log
from ee.part import Part, load_db
-__all__ = ["load_bom"]
+__all__ = [
+ "load_bom",
+ "check_bom",
+ "BomLine",
+ "generate_bom",
+ "split_ref",
+ "join_refs",
+]
-def uri_fn(part: Part):
- return part.uri
+@total_ordering
+class BomLine(object):
+ def __init__(self, uri, part: Part):
+ self.uri = uri
+ self.part = part
+ self.refs = []
+ def add_ref(self, ref):
+ self.refs.append(ref)
-def supplier_fn(part: Part):
- return part.supplier
+ def __lt__(self, other):
+ return self.uri < other.uri
class BomItem(object):
@@ -26,6 +41,12 @@ class BomItem(object):
def load_bom(bom_path: Path, part_files: List[Path]) -> (ObjDb[Part](), ObjDb[Part]()):
+ def uri_fn(part: Part):
+ return part.uri
+
+ def supplier_fn(part: Part):
+ return part.supplier
+
bom: ObjDb[Part] = ObjDb[Part]()
for xml in load_db(bom_path).iterparts():
@@ -46,6 +67,35 @@ def check_bom(bom: ObjDb[Part](), parts: ObjDb[Part]()):
pass
+def generate_bom(allow_incomplete, bom_parts: ObjDb[Part], supplier_parts: ObjDb[Part], group_by_ref=True) -> \
+ Optional[List[BomLine]]:
+ lines: MutableMapping[str, BomLine] = {}
+
+ uri_idx = supplier_parts.index("uri")
+
+ for part in bom_parts.values:
+ pr = part.get_only_part_reference()
+
+ if allow_incomplete and pr is None:
+ log.debug("Skipping part without part reference: {}".format(part.printable_reference))
+ continue
+ elif pr is None:
+ log.warn("Unresolved part: {}".format(part.printable_reference))
+ return
+
+ part_uri = pr.part_uriProp
+
+ if part_uri not in lines:
+ supplier_part = uri_idx.get_single(part_uri)
+ lines[part_uri] = line = BomLine(part_uri, supplier_part)
+ else:
+ line = lines[part_uri]
+
+ line.add_ref(part.get_exactly_one_schematic_reference().referenceProp)
+
+ return sorted(lines.values())
+
+
def split_ref(ref):
"""Split "C12" into a tuple that's useful for sorting by component reference.