aboutsummaryrefslogtreecommitdiff
path: root/src/ee/bom.py
diff options
context:
space:
mode:
authorTrygve Laugstøl <trygvis@inamo.no>2019-05-14 23:08:20 +0200
committerTrygve Laugstøl <trygvis@inamo.no>2019-05-14 23:08:20 +0200
commit702d7900b646a9d873e6eaa4c61088c618eba9f1 (patch)
tree144689c62b77622cefee5b47d6bb0d91095082f0 /src/ee/bom.py
parent2cdf0c4b9865f025e52938fb9b772cc79319db09 (diff)
downloadee-python-702d7900b646a9d873e6eaa4c61088c618eba9f1.tar.gz
ee-python-702d7900b646a9d873e6eaa4c61088c618eba9f1.tar.bz2
ee-python-702d7900b646a9d873e6eaa4c61088c618eba9f1.tar.xz
ee-python-702d7900b646a9d873e6eaa4c61088c618eba9f1.zip
ee.logging: New module to handle logging. Need something better for
messages too. create-bom: Resolving parts from their value fact too.
Diffstat (limited to 'src/ee/bom.py')
-rw-r--r--src/ee/bom.py67
1 files changed, 48 insertions, 19 deletions
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)