aboutsummaryrefslogtreecommitdiff
path: root/src/ee/digikey/doit.py
diff options
context:
space:
mode:
Diffstat (limited to 'src/ee/digikey/doit.py')
-rw-r--r--src/ee/digikey/doit.py87
1 files changed, 87 insertions, 0 deletions
diff --git a/src/ee/digikey/doit.py b/src/ee/digikey/doit.py
new file mode 100644
index 0000000..74259bb
--- /dev/null
+++ b/src/ee/digikey/doit.py
@@ -0,0 +1,87 @@
+import logging
+
+import ee.digikey as dk
+from ee.doit import DoItConfig
+from ee.ds import DataSet
+
+logger = logging.getLogger(__name__)
+
+doit_config = DoItConfig()
+
+
+def resolve_schematic_components(output: DataSet, in_ds: DataSet):
+ def find(field, value):
+ return [o for o in output.items() if o.object_type.name == "digikey-part-stub" and o.get(field) == value]
+
+ def save(p: dk.DigikeyProduct):
+ logger.info("Found part, dpn={}, mpn={}".format(p.part_number, p.mpn))
+
+ return output.create_object("digikey-part-stub", p.part_number, replace=True). \
+ set("part-number", p.part_number). \
+ set("mpn", p.mpn). \
+ set("description", p.description). \
+ set("quantity-available", p.quantity_available). \
+ set("url", p.url)
+
+ digikey = dk.Digikey()
+ client = dk.DigikeyClient(digikey, on_download=logger.info)
+
+ components = [o for o in in_ds.items() if o.object_type.name == "component"]
+
+ for mpn in sorted({c.get("mpn") for c in components if c.get("mpn")}):
+ # TODO: support searching by value and digikey part number directly. Priority should be "digikey", "mpn" and
+ # "value", first field present should be used.
+
+ dk_components = find("mpn", mpn)
+
+ if len(dk_components):
+ logger.info("Already resolved {} to {}".format(mpn, ", ".join([c.get("mpn") for c in dk_components])))
+ continue
+
+ logger.info("Looking up {}".format(mpn))
+ response = client.search(mpn)
+
+ if response.response_type == dk.SearchResponseTypes.SINGLE:
+ save(response.products[0])
+ elif response.response_type == dk.SearchResponseTypes.MANY:
+ # A search for "FOO" might return products "FOO" and "FOOZ" so we pick out the ones with the matching mpn
+ # This will often be more than one product, but digikey shows the same part in different packagings.
+ viable_products = [p for p in response.products if p.mpn == mpn]
+
+ if len(viable_products) == 0:
+ logger.warning("BUG: Got multiple hits ({}) but didn't find anyone that matched the MPN. Strange!".
+ format(len(response.products)))
+ else:
+ if len(viable_products) == 1:
+ part = viable_products[0]
+ else:
+ # Pick the first one, should be as good as any
+ part = sorted(viable_products, key=lambda x: x.part_number)[0]
+
+ logger.info("Got multiple hits ({})".format(len(viable_products)))
+
+ save(part)
+ elif response.response_type == dk.SearchResponseTypes.TOO_MANY:
+ logger.warning("to many matches")
+ elif response.response_type == dk.SearchResponseTypes.NO_MATCHES:
+ logger.warning("no matches")
+
+
+def task_digikey_resolve_schematic_components():
+ out_data_set, in_data_sets = doit_config.data_sets_for(task_digikey_resolve_schematic_components)
+
+ def action():
+ in_ds = doit_config.dsm.load_data_sets(in_data_sets)
+
+ with doit_config.dsm.create_rw(out_data_set, clean=False) as output:
+ resolve_schematic_components(output, in_ds)
+
+ return dict(
+ file_dep=[doit_config.dsm.cookie_for_ds(ds) for ds in in_data_sets],
+ actions=[action],
+ targets=[doit_config.dsm.cookie_for_ds(out_data_set)],
+ )
+
+
+doit_config.set_data_sets_for(task_digikey_resolve_schematic_components,
+ "digikey-resolved-parts", "components")