diff options
Diffstat (limited to 'pint/registry.py')
-rw-r--r-- | pint/registry.py | 101 |
1 files changed, 100 insertions, 1 deletions
diff --git a/pint/registry.py b/pint/registry.py index 9379770..99873ed 100644 --- a/pint/registry.py +++ b/pint/registry.py @@ -84,6 +84,19 @@ from .util import ( _BLOCK_RE = re.compile(r" |\(") +@functools.lru_cache() +def pattern_to_regex(pattern): + if hasattr(pattern, "finditer"): + pattern = pattern.pattern + + # Replace "{unit_name}" match string with float regex with unit_name as group + pattern = re.sub( + r"{(\w+)}", r"(?P<\1>[+-]?[0-9]+(?:.[0-9]+)?(?:[Ee][+-]?[0-9]+)?)", pattern + ) + + return re.compile(pattern) + + class RegistryMeta(type): """This is just to call after_init at the right time instead of asking the developer to do it when subclassing. @@ -161,6 +174,9 @@ class BaseRegistry(metaclass=RegistryMeta): #: type: Dict[str, (SourceIterator -> None)] _parsers = None + #: Babel.Locale instance or None + fmt_locale = None + #: List to be used in addition of units when dir(registry) is called. #: Also used for autocompletion in IPython. _dir = [ @@ -207,7 +223,7 @@ class BaseRegistry(metaclass=RegistryMeta): self.auto_reduce_dimensions = auto_reduce_dimensions #: Default locale identifier string, used when calling format_babel without explicit locale. - self.fmt_locale = self.set_fmt_locale(fmt_locale) + self.set_fmt_locale(fmt_locale) #: Numerical type used for non integer values. self.non_int_type = non_int_type @@ -871,6 +887,33 @@ class BaseRegistry(metaclass=RegistryMeta): src_dim = self._get_dimensionality(input_units) return self._cache.dimensional_equivalents[src_dim] + def is_compatible_with(self, obj1, obj2, *contexts, **ctx_kwargs): + """ check if the other object is compatible + + Parameters + ---------- + obj1, obj2 + The objects to check against each other. Treated as + dimensionless if not a Quantity, Unit or str. + *contexts : str or pint.Context + Contexts to use in the transformation. + **ctx_kwargs : + Values for the Context/s + + Returns + ------- + bool + """ + if isinstance(obj1, (self.Quantity, self.Unit)): + return obj1.is_compatible_with(obj2, *contexts, **ctx_kwargs) + + if isinstance(obj1, str): + return self.parse_expression(obj1).is_compatible_with( + obj2, *contexts, **ctx_kwargs + ) + + return not isinstance(obj2, (self.Quantity, self.Unit)) + def convert(self, value, src, dst, inplace=False): """Convert value from some source to destination units. @@ -1114,6 +1157,62 @@ class BaseRegistry(metaclass=RegistryMeta): else: raise Exception("unknown token type") + def parse_pattern( + self, input_string, pattern, case_sensitive=True, use_decimal=False, many=False + ): + """Parse a string with a given regex pattern and returns result. + + Parameters + ---------- + input_string : + + pattern_string: + The regex parse string + case_sensitive : + (Default value = True) + use_decimal : + (Default value = False) + many : + Match many results + (Default value = False) + + + Returns + ------- + + """ + + if not input_string: + return self.Quantity(1) + + # Parse string + pattern = pattern_to_regex(pattern) + matched = re.finditer(pattern, input_string) + + # Extract result(s) + results = [] + for match in matched: + # Extract units from result + match = match.groupdict() + + # Parse units + units = [] + for unit, value in match.items(): + # Construct measure by multiplying value by unit + units.append( + float(value) + * self.parse_expression(unit, case_sensitive, use_decimal) + ) + + # Add to results + results.append(units) + + # Return first match only + if not many: + return results[0] + + return results + def parse_expression( self, input_string, case_sensitive=True, use_decimal=False, **values, ): |