From 89197dad4f5f427faa7fba12971b20037ad5ba71 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Fri, 14 Jun 2019 10:40:31 +0200 Subject: split-parts-by-supplier: rename to split-bom-by-supplier. digikey-create-bom: Implementing CSV generation for Digi-Key. --- src/ee/part/__init__.py | 2 +- src/ee/part/bom.py | 110 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 src/ee/part/bom.py (limited to 'src/ee/part') 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 -- cgit v1.2.3