import re from pathlib import Path from typing import List, Tuple, Union, Mapping, Callable, Any from ee import EeVal, EeException from ee.part import PartDb, load_db, save_db from ee.xml import types, uris __all__ = ["normalize_facts"] # TODO: this should be moved to a generic normalizer def handle_tolerance(tolerance: types.Fact, capacitance: types.Fact) -> List[types.Fact]: cap_value = float(EeVal.parse(capacitance.valueProp)) s = tolerance.valueProp print("tolerance: {}".format(s)) is_plus_minus = s.startswith("±") s = s[1:] if is_plus_minus else s is_percent = s.endswith("%") is_farad = s.endswith("F") print("tolerance={}, is_plus_minus={}, is_farad={}, is_percent={}".format( tolerance.valueProp, is_plus_minus, is_farad, is_percent)) print("capacitance={}".format(EeVal.parse(capacitance.valueProp))) low_pct = low_value = None high_pct = high_value = None facts = [] # type: List[Tuple[str, str, Union[str, EeVal]]] if is_farad: s = s[0:-1] if is_farad else s try: farad = EeVal.parse(s) except EeException: farad = None elif is_percent: s = s[0:-1] pct_value = int(s) if is_plus_minus: low_pct = high_pct = str(pct_value) pct = float(pct_value) / 100 low_value = EeVal(value=cap_value * (1 - pct), exp=1, unit="F") high_value = EeVal(value=cap_value * (1 + pct), exp=1, unit="F") else: raise EeException("bad combination") if low_pct: facts.append(("tolerance-percent-lower", "Tolerance, lower (%)", low_pct)) if high_pct: facts.append(("tolerance-percent-upper", "Tolerance, upper (%)", high_pct)) if low_value: facts.append(("tolerance-lower", "Tolerance, lower", low_value)) if high_value: facts.append(("tolerance-upper", "Tolerance, upper", high_value)) if low_pct and low_pct == high_pct: facts.append(("tolerance-percent", "Tolerance (±%)", low_pct)) return [types.Fact(key=uris.make_fact_key(key), label=label, value=str(value)) for key, label, value in facts] def re_parser(pattern, kis: List[Tuple[str, int]]): r = re.compile(pattern) def parse(value): m = r.match(value) if not m: return return [(k, m.group(i)) for k, i in kis] return parse def no_parser(key): def parse(value): return key, value return parse def ee_val_parser(key): def parse(value): return key, EeVal.parse(value) return parse _operating_temperature_re = re.compile("-([0-9]+)°C ~ ([0-9])+°C") _height_seated_re = re.compile("([0-9]+\\.[0-9]+)\" \\(([0-9]+\\.[0-9]+)mm\\)") _land_size_re = re.compile("([0-9]+\\.[0-9]+)\" L x ([0-9]+\\.[0-9]+)\" W " "\\(([0-9]+\\.[0-9]+)mm x ([0-9]+\\.[0-9]+)mm\\)") # 0.260" L x 0.260" W (6.60mm x 6.60mm) parsers: Mapping[int, Callable[[str], Any]] = { 3: no_parser("tolerance"), 1471: ee_val_parser("voltage-input-min"), # Voltage - Input (Min) 573: ee_val_parser("voltage-input-max"), # Voltage - Input (Max) 1429: ee_val_parser("voltage-output-max"), # Voltage - Output (Max) 252: re_parser(_operating_temperature_re, [("temperature-min", 1), ("temperature-max", 2)]), 1686: re_parser(_operating_temperature_re, [("temperature-junction-min", 1), ("temperature-junction-max", 2)]), 1500: re_parser(_height_seated_re, [("part-height", 2)]), 884: re_parser(_land_size_re, [("land-size-x", 3), ("land-size-y", 4)]), 2049: ee_val_parser("capacitance"), 2079: ee_val_parser("voltage-rating"), } def normalize_facts(in_path: Path, out_path: Path): in_db = load_db(in_path) out_parts = PartDb() for part in in_db.iterparts(): # type: types.Part fact_list: types.FactList = part.factsProp if fact_list is None: continue in_facts: List[types.Fact] = fact_list.factProp out_facts = [] for f in in_facts: key = uris.parse_digikey_fact_key(f.keyProp) value = f.valueProp if value == "-": continue parser = parsers.get(key) if parser is not None: res = parser(value) if res is not None: if isinstance(res, list): results = res else: results = [res] facts = [types.Fact(key=uris.make_fact_key(key), value=value) for key, value in results] out_facts.extend(facts) part.factsProp.factProp = out_facts out_parts.add_entry(part, True) print("Saving {} work parts".format(out_parts.size())) save_db(out_path, out_parts, sort=True)