import argparse from itertools import * from functools import total_ordering from colors import color import ee.digikey as dk from ee.digikey import SearchResponseTypes, DigikeyProduct from ee.tools import mk_parents @total_ordering class Query(object): def __init__(self, is_mpn, query): self.is_mpn = is_mpn self.query = query def __eq__(self, other): return (self.is_mpn, self.query) == (other.is_mpn, other.query) def __lt__(self, other): return (self.is_mpn, self.query) < (other.is_mpn, other.query) def __hash__(self): return hash((self.is_mpn, self.query)) parser = argparse.ArgumentParser(description="Download facts about parts from Digi-Key") parser.add_argument("--out", required=True, metavar="OUTPUT_DIRECTORY", dest="out", action="store", help="A directory to store fact files") parser.add_argument("--part", nargs="+", help="the parts to download fact for") parser.add_argument("--sch") parser.add_argument("--force", dest="force", action="store", help="Always download fact even if there is a local file") args = parser.parse_args() digikey = dk.Digikey() client = dk.DigikeyClient(digikey, on_download=lambda s: print(color(s, 'grey'))) repo = dk.DigikeyRepository(digikey, args.out) def on_product(product: DigikeyProduct): repo.save(product) parts = [] if args.part: [parts.append(Query(True, p)) for p in args.part] if args.sch: from ee.kicad import read_schematic, to_bom sch = read_schematic(args.sch) for c in to_bom(sch): digikey = c.get_field("digikey") if digikey: parts.append(Query(False, digikey.value)) mpn = c.get_field("mpn") if mpn: parts.append(Query(True, mpn.value)) parts = sorted(set(parts)) for q in parts: p = q.query if repo.has_product(mpn = p if q.is_mpn else None, dpn = p if not q.is_mpn else None) and not args.force: print(color("Already have facts for {}".format(p), "white")) continue print(color("Searching for {}".format(p), "white")) response = client.search(p) todos = [] if response.response_type == SearchResponseTypes.SINGLE: p = response.products[0] print(color("Direct match mpn/dpn: {}/{}".format(p.mpn, p.part_number), "white")) on_product(p) elif response.response_type == SearchResponseTypes.MANY: hits = [(mpn, list(products)) for mpn, products in groupby(sorted(response.products, key=lambda p: p.mpn), lambda p: p.mpn)] if len(hits) == 1: (mpn, products) = hits[0] part_number = products[0].part_number print(color("Got many results, but they all point to the same part: {}. Will use {} for downloading attributes.".format(mpn, ", ".join([p.part_number for p in products])), "white")) todos.append(part_number) else: for k, g in hits: print(color("Got many results with many parts: {}: {}".format(k, list(g)), "white")) on_product(list(g)[0]) elif response.response_type == SearchResponseTypes.TOO_MANY: print(color("Too many results ({}), select a category first".format(response.count), 'red')) elif response.response_type == SearchResponseTypes.NO_MATCHES: print(color("Part not found", "orange")) for part_number in todos: response = client.search(part_number) if response.response_type == SearchResponseTypes.SINGLE: p = response.products[0] print(color("Downloaded {}".format(p.mpn), "white")) on_product(p) else: print("Got response of type {} when really expecting a single product.".format(response.response_type))