import re from typing import List, Tuple, Union, Mapping, Callable, Any from ee import EeVal, EeException from ee.part import Part 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"), } # noinspection PyUnusedLocal def normalize_facts(**kwargs): parsers: Mapping[str, Callable[[str], Any]] = {uris.make_digikey_fact_key(k): v for k, v in _parsers.items()} def on_part(part: Part) -> Part: for dk_key, parser in parsers.items(): value = part.facts.get_value(dk_key) if value is None or value == "-": continue res = parser(value) if res is not None: if isinstance(res, list): for key, value in res: key = uris.make_fact_key(key) part.facts.add(key, value) else: key, value = res key = uris.make_fact_key(key) part.facts.add(key, value) return part return on_part # noinspection PyUnusedLocal def map_footprint(footprint_mappings=None, **kwargs): # noinspection PyProtectedMember from ee.part._utils import map_footprint return map_footprint(footprint_mappings, "digikey-to-common", uris.make_digikey_fact_key(16)) def default(**kwargs): function_factories = [ normalize_facts, map_footprint, ] functions = [factory(**kwargs) for factory in function_factories] functions = [f for f in functions if f is not None] def on_part(part: Part) -> Part: for f in functions: part = f(part) return part return on_part