"""Functions to parse the weigth string into a dictionary that represents the weight in g """ import logging from typing import Optional import re from helpers.misc import convert_units UNIT_CONVERSIONS = {"pounds": 453.592, "ounces": 28.3495, "g": 1, "kg": 1000} def parse_weight(weight: Optional[str]) -> Optional[float]: """Parse a weigth string into a dictionary representing the weight unit and value""" if weight is None: return None expr = r"(?P\d*[.,]?\d*)\s+(?P[a-zA-Z]*)" # strip is needed to prevent the regex from lazily # matching just from the first whitespace separator, # this could happen because the number part in the # expression is technically all optional, to avoid # an expression too complex and unreadable if match := re.search(expr, weight.strip()): match_value = match.group("value") try: value = float(match_value) except ValueError: logging.error("could not parse value `%s` as a float for a weight") return None unit = match.group("unit").lower() return convert_units(value, unit, unit_conversions=UNIT_CONVERSIONS) return None def dimensional_weight( height: Optional[float], width: Optional[float], depth: Optional[float] ) -> Optional[float]: """The dimensional weight (in kg) is calculated as: Length * Height * Width (in cm) / 5000. We'll return it in g here""" if None in [height, width, depth]: return None dimensional_weight_kg = height * width * depth / 5000 return convert_units( value=dimensional_weight_kg, unit="kg", unit_conversions=UNIT_CONVERSIONS )