From b4eeed35d78f82ea988d70de177d522ca20257ea Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Fri, 14 Jun 2019 21:42:18 +0200 Subject: bom-to-csv: Starting on a generic tool to generate CSV files from BOMs. --- src/ee/part/bom.py | 62 ++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 56 insertions(+), 6 deletions(-) (limited to 'src/ee/part') 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. -- cgit v1.2.3