From 702d7900b646a9d873e6eaa4c61088c618eba9f1 Mon Sep 17 00:00:00 2001 From: Trygve Laugstøl Date: Tue, 14 May 2019 23:08:20 +0200 Subject: ee.logging: New module to handle logging. Need something better for messages too. create-bom: Resolving parts from their value fact too. --- src/ee/bom.py | 67 ++++++++++++++++++++++++++++++++++++++++++----------------- 1 file changed, 48 insertions(+), 19 deletions(-) (limited to 'src/ee/bom.py') diff --git a/src/ee/bom.py b/src/ee/bom.py index f8cca71..731f5b4 100644 --- a/src/ee/bom.py +++ b/src/ee/bom.py @@ -4,21 +4,32 @@ from pathlib import Path from typing import List, MutableMapping, Optional from ee import EeException +from ee.logging import log from ee.db import ObjDb from ee.part import PartDb, load_db, save_db, Part from ee.project import Project, report, SupplierDescriptor from ee.xml import types +from ee.xml.uris import make_fact_key __all__ = ["create_bom"] +class Hit(object): + def __init__(self, part: Part, method: str): + self.part = part + self.method = method + + class BomPart(object): - def __init__(self, part: types.Part): - self.part = Part(part) + def __init__(self, part: Part): + self.part = part ref = self.part.get_only_schematic_reference() self.ref = ref.referenceProp if ref else None - self.available_from: MutableMapping[str, Part] = {} - self.selected_part = None + self.hits = [] + self.selected_part: Optional[Part] = None + + def add_hit(self, part, method): + self.hits.append(Hit(part, method)) def make_report(out_file, unresolved_parts, bom_parts: ObjDb[BomPart], supplier_parts: ObjDb[Path]): @@ -41,6 +52,7 @@ def create_bom(project: Project, schematic_path: Path, out_path: Path, part_dbs: strategy = pydoc.locate(strategy_name) if not callable(strategy): raise EeException("Not a callable: {}, is a {}".format(strategy_name, type(strategy))) + log.info("Using strategy '{}'".format(strategy_name)) supplier_parts = ObjDb[Part]() supplier_parts.add_unique_index("uri", lambda p: p.uri) @@ -65,40 +77,55 @@ def create_bom(project: Project, schematic_path: Path, out_path: Path, part_dbs: op.part.get_mpns()] if op.part.supplier else None, multiple=True) for sch_part in sch_db.iterparts(): - part = BomPart(sch_part) - part.part = strategy(part.part) - if part.part is None: + part = Part(sch_part) + + part = strategy(part) + if part is None: continue - bom_parts.add(part) + bom_parts.add(BomPart(part)) for bom_part in bom_parts: sch_part_numbers = [pn.valueProp for pn in bom_part.part.get_mpns()] sch_supplier_part_numbers = [spn.valueProp for spn in bom_part.part.get_spns()] + value_fact = bom_part.part.find_fact(make_fact_key("value")) + if value_fact: + value_fact = value_fact.valueProp + for supplier in suppliers: + # Part number search pns = supplier_pn_idx.get(supplier.uri) - spns = supplier_spn_idx.get(supplier.uri) - for sch_pn in sch_part_numbers: for supplier_part in pns.get(sch_pn, []): - bom_part.available_from[supplier_part.uri] = supplier_part + bom_part.add_hit(supplier_part, "pn") + + if value_fact: + for supplier_part in pns.get(value_fact, []): + bom_part.add_hit(supplier_part, "pn_value_fact") + + # Supplier number search + spns = supplier_spn_idx.get(supplier.uri) for sch_spn in sch_supplier_part_numbers: for supplier_part in spns.get(sch_spn, []): - bom_part.available_from[supplier_part.uri] = supplier_part + bom_part.add_hit(supplier_part, "spn") + + if value_fact: + for supplier_part in spns.get(value_fact, []): + bom_part.add_hit(supplier_part, "spn_value_fact") unresolved_parts = [] for bom_part in bom_parts: - af = bom_part.available_from - if len(af) == 0: + if len(bom_part.hits) == 0: unresolved_parts.append(bom_part) - elif len(af) == 1: - bom_part.selected_part = next(iter(af.values())) + elif len(bom_part.hits) == 1: + bom_part.selected_part = bom_part.hits[0].part else: - raise EeException("unimplemented: part ({}) available from multiple suppliers: {}". - format(bom_part.ref, ",".join(af.keys()))) + references = [hit.part.printable_reference for hit in bom_part.hits] + raise EeException("Multiple hits when looking for part: {}". + format(bom_part.ref, ",".join(references))) - bom_parts.add_index("uri", lambda op: op.selected_part.uri if op.selected_part else None) + bom_parts.add_index("uri", lambda bp: bp.selected_part.uri if bp.selected_part else None) bom_parts.add_multi_index("supplier,part", lambda op: ( op.selected_part.supplier, op.selected_part.uri) if op.selected_part else None) @@ -111,6 +138,7 @@ def create_bom(project: Project, schematic_path: Path, out_path: Path, part_dbs: out_parts = PartDb() for bom_part in bom_parts: if not bom_part.selected_part: + log.info("No part selected for {}".format(bom_part.part.printable_reference)) continue supplier_part = bom_part.selected_part @@ -121,4 +149,5 @@ def create_bom(project: Project, schematic_path: Path, out_path: Path, part_dbs: out_parts.add_entry(part, True) + log.info("Found {} of {} parts, missing {}".format(len(out_parts), len(sch_db), len(unresolved_parts))) save_db(out_path, out_parts) -- cgit v1.2.3