Skip to content

Commit

Permalink
Add cache to parse_unit_name
Browse files Browse the repository at this point in the history
  • Loading branch information
hgrecco committed Jul 15, 2023
1 parent 2d649ea commit 3538fdc
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 11 deletions.
24 changes: 24 additions & 0 deletions pint/compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,14 @@
import math
import tokenize
from decimal import Decimal
import functools
from importlib import import_module
from io import BytesIO
from numbers import Number
from collections.abc import Mapping
from typing import Any, NoReturn, Callable, Optional, Union
from collections.abc import Generator, Iterable
import warnings


if sys.version_info >= (3, 10):
Expand Down Expand Up @@ -362,3 +364,25 @@ def zero_or_nan(obj: Any, check_all: bool) -> Union[bool, Iterable[bool]]:
if check_all and is_duck_array_type(type(out)):
return out.all()
return out


def deprecated(msg: str):
def _inner(func: Callable[..., Any]):
"""This is a decorator which can be used to mark functions
as deprecated. It will result in a warning being emitted
when the function is used."""

@functools.wraps(func)
def _new_func(*args: Any, **kwargs: Any):
warnings.simplefilter("always", DeprecationWarning) # turn off filter
warnings.warn(
f"Call to deprecated function {func.__name__}.\n{msg}",
category=DeprecationWarning,
stacklevel=2,
)
warnings.simplefilter("default", DeprecationWarning) # reset filter
return func(*args, **kwargs)

return _new_func

return _inner
11 changes: 9 additions & 2 deletions pint/facets/context/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,13 @@
from ..._typing import F, Magnitude
from ...errors import UndefinedUnitError
from ...util import find_connected_nodes, find_shortest_path, logger, UnitsContainer
from ..plain import GenericPlainRegistry, UnitDefinition, QuantityT, UnitT
from ..plain import (
GenericPlainRegistry,
UnitDefinition,
QuantityT,
UnitT,
RegistryCache,
)
from .definitions import ContextDefinition
from . import objects

Expand All @@ -30,11 +36,12 @@ class ContextCacheOverlay:
active contexts which contain unit redefinitions.
"""

def __init__(self, registry_cache) -> None:
def __init__(self, registry_cache: RegistryCache) -> None:
self.dimensional_equivalents = registry_cache.dimensional_equivalents
self.root_units = {}
self.dimensionality = registry_cache.dimensionality
self.parse_unit = registry_cache.parse_unit
self.parse_unit_name = registry_cache.parse_unit_name


class GenericContextRegistry(
Expand Down
9 changes: 8 additions & 1 deletion pint/facets/plain/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,14 +19,21 @@
UnitDefinition,
)
from .objects import PlainQuantity, PlainUnit
from .registry import PlainRegistry, GenericPlainRegistry, QuantityT, UnitT
from .registry import (
PlainRegistry,
GenericPlainRegistry,
QuantityT,
UnitT,
RegistryCache,
)
from .quantity import MagnitudeT

__all__ = [
"GenericPlainRegistry",
"PlainUnit",
"PlainQuantity",
"PlainRegistry",
"RegistryCache",
"AliasDefinition",
"DefaultsDefinition",
"DimensionDefinition",
Expand Down
44 changes: 36 additions & 8 deletions pint/facets/plain/registry.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
- parse_unit_name: Parse a unit to identify prefix, unit name and suffix
by walking the list of prefix and suffix.
Result is cached: NO
Result is cached: YES
- parse_units: Parse a units expression and returns a UnitContainer with
the canonical names.
The expression can only contain products, ratios and powers of units;
Expand Down Expand Up @@ -131,6 +131,11 @@ def __init__(self) -> None:
#: Cache the unit name associated to user input. ('mV' -> 'millivolt')
self.parse_unit: dict[str, UnitsContainer] = {}

#: Maps (string and case insensitive) to (prefix, unit name, suffix)
self.parse_unit_name: dict[
tuple[str, bool], tuple[tuple[str, str, str], ...]
] = {}

def __eq__(self, other: Any):
if not isinstance(other, self.__class__):
return False
Expand All @@ -139,6 +144,7 @@ def __eq__(self, other: Any):
"root_units",
"dimensionality",
"parse_unit",
"parse_unit_name",
)
return all(getattr(self, attr) == getattr(other, attr) for attr in attrs)

Expand Down Expand Up @@ -1040,8 +1046,14 @@ def _convert(

return value

# @deprecated("Use parse_single_unit")
def parse_unit_name(
self, unit_name: str, case_sensitive: Optional[bool] = None
) -> tuple[tuple[str, str, str], ...]:
return self.parse_single_unit(unit_name, case_sensitive)

def parse_single_unit(
self, unit_name: str, case_sensitive: Optional[bool] = None
) -> tuple[tuple[str, str, str], ...]:
"""Parse a unit to identify prefix, unit name and suffix
by walking the list of prefix and suffix.
Expand All @@ -1061,17 +1073,33 @@ def parse_unit_name(
tuple of tuples (str, str, str)
all non-equivalent combinations of (prefix, unit name, suffix)
"""
return self._dedup_candidates(
self._parse_unit_name(unit_name, case_sensitive=case_sensitive)
)

def _parse_unit_name(
self, unit_name: str, case_sensitive: Optional[bool] = None
) -> Generator[tuple[str, str, str], None, None]:
"""Helper of parse_unit_name."""
case_sensitive = (
self.case_sensitive if case_sensitive is None else case_sensitive
)

return self._parse_single_unit(unit_name, case_sensitive)

def _parse_single_unit(
self, unit_name: str, case_sensitive: bool
) -> tuple[tuple[str, str, str], ...]:
"""Helper of parse_unit_name."""

key = (unit_name, case_sensitive)
this_cache = self._cache.parse_unit_name
if key in this_cache:
return this_cache[key]

out = this_cache[key] = self._dedup_candidates(
self._yield_potential_units(unit_name, case_sensitive=case_sensitive)
)
return out

def _yield_potential_units(
self, unit_name: str, case_sensitive: bool
) -> Generator[tuple[str, str, str], None, None]:
"""Helper of parse_unit_name."""

stw = unit_name.startswith
edw = unit_name.endswith
for suffix, prefix in itertools.product(self._suffixes, self._prefixes):
Expand Down

0 comments on commit 3538fdc

Please sign in to comment.