diff options
Diffstat (limited to 'src/ee/digikey/functions.py')
-rw-r--r-- | src/ee/digikey/functions.py | 157 |
1 files changed, 157 insertions, 0 deletions
diff --git a/src/ee/digikey/functions.py b/src/ee/digikey/functions.py new file mode 100644 index 0000000..047fad1 --- /dev/null +++ b/src/ee/digikey/functions.py @@ -0,0 +1,157 @@ +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 + + +def default(**kwargs): + function_factories = [ + normalize_facts, + ] + + 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 |