def as_value(token, trait, value_field="number", unit_field="units"): """Convert token values and units to trait fields.""" units = as_list(token.group.get(unit_field, [])) trait.units = squash(units) if units else None values = [] for i, val in enumerate(as_list(token.group.get(value_field, []))): val = to_positive_float(val) if val is None: return False if i < len(units): unit = units[i] else: unit = units[-1] if units else None values.append(convert_units(val, unit)) if not values: return False trait.value = squash(values) trait.units_inferred = not bool(trait.units) return True
def convert(token): """Convert parsed tokens into a result.""" trait = Trait(start=token.start, end=token.end) if token.group.get("total"): trait.value = to_positive_int(token.group["total"]) if token.group.get("subcount"): trait.value = sum( to_positive_int(c) for c in as_list(token.group["subcount"])) if token.group.get("subcount") and token.group.get("sub"): for count, sub in zip(as_list(token.group["subcount"]), as_list(token.group.get("sub"))): count = "1" if count == "!" else count sub = SUB.get(sub[0].lower(), sub) setattr(trait, sub, to_positive_int(count)) elif token.group.get("side"): side = token.group["side"].lower() trait.side = SUB.get(side, side) return trait if all(x < 1000 for x in as_list(trait.value)) else None
def compound(token): """Handle a pattern like: 4 ft 9 in.""" trait = Trait(start=token.start, end=token.end) trait.units = [token.group["feet"], token.group["inches"]] trait.units_inferred = False trait.is_flag_missing(token, "key", rename="ambiguous_key") fts = convert_units(to_positive_float(token.group["ft"]), "ft") ins = [ convert_units(to_positive_float(i), "in") for i in as_list(token.group["in"]) ] value = [round(fts + i, 2) for i in ins] trait.value = squash(value) add_flags(token, trait) return trait
def compound(token): """Convert a compound weight like: 2 lbs. 3.1 - 4.5 oz.""" trait = Trait(start=token.start, end=token.end) trait.units = [token.group["pounds"], token.group["ounces"]] trait.units_inferred = False trait.is_flag_missing(token, "key", rename="ambiguous_key") lbs = convert_units(to_positive_float(token.group["lbs"]), "lbs") ozs = [ convert_units(to_positive_float(oz), "ozs") for oz in as_list(token.group["ozs"]) ] value = [round(lbs + oz, 2) for oz in ozs] trait.value = squash(value) add_flags(token, trait) return trait
def convert_count(token): """Convert parsed tokens into a result.""" trait = Trait(start=token.start, end=token.end) trait.value = to_positive_int(token.group.get("value")) count1 = to_positive_int(token.group.get("count1")) count2 = to_positive_int(token.group.get("count2")) side1 = SUB.get(token.group.get("side1", " ").lower()[0], "side1") side2 = SUB.get(token.group.get("side2", " ").lower()[0], "side2") if not trait.value: trait.value = count1 + count2 if count1 or side1 != "side1": setattr(trait, side1, count1) if count2 or side2 != "side2": setattr(trait, side2, count2) return trait if all(x < 1000 for x in as_list(trait.value)) else None
def convert_many(token): """Convert several values.""" values = token.group["value"] units = as_list(token.group.get("len_units", [])) traits = [] for i, value in enumerate(values): trait = Trait(start=token.start, end=token.end) if i < len(units): trait.units = units[i] trait.units_inferred = False else: trait.units = units[-1] if units else None trait.units_inferred = True trait.value = convert_units.convert_units(to_positive_float(value), trait.units) if trait.value > TOO_BIG: continue add_flags(token, trait) traits.append(trait) return traits
def convert(token): """Convert parsed token into a trait product.""" trait = simple(token, units="len_units") return trait if all(x < TOO_BIG for x in as_list(trait.value)) else None
def transfer(self, token, names): """Move fields from a token to the trait if they exist in the token.""" for name in names: if name in token.group: values = [v.lower() for v in as_list(token.group[name])] setattr(self, name, squash(values))