summaryrefslogtreecommitdiff
path: root/pint/registry.py
diff options
context:
space:
mode:
Diffstat (limited to 'pint/registry.py')
-rw-r--r--pint/registry.py101
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,
):