Source code for pint.compat

"""
    pint.compat
    ~~~~~~~~~~~

    Compatibility layer.

    :copyright: 2013 by Pint Authors, see AUTHORS for more details.
    :license: BSD, see LICENSE for more details.
"""
import tokenize
from decimal import Decimal
from io import BytesIO
from numbers import Number


def missing_dependency(package, display_name=None):
    display_name = display_name or package

    def _inner(*args, **kwargs):
        raise Exception(
            "This feature requires %s. Please install it by running:\n"
            "pip install %s" % (display_name, package)
        )

    return _inner


def tokenizer(input_string):
    for tokinfo in tokenize.tokenize(BytesIO(input_string.encode("utf-8")).readline):
        if tokinfo.type != tokenize.ENCODING:
            yield tokinfo


# TODO: remove this warning after v0.10
[docs]class BehaviorChangeWarning(UserWarning): pass
try: import numpy as np from numpy import ndarray HAS_NUMPY = True NUMPY_VER = np.__version__ NUMERIC_TYPES = (Number, Decimal, ndarray, np.number) def _to_magnitude(value, force_ndarray=False, force_ndarray_like=False): if isinstance(value, (dict, bool)) or value is None: raise TypeError("Invalid magnitude for Quantity: {0!r}".format(value)) elif isinstance(value, str) and value == "": raise ValueError("Quantity magnitude cannot be an empty string.") elif isinstance(value, (list, tuple)): return np.asarray(value) if force_ndarray or ( force_ndarray_like and not is_duck_array_type(type(value)) ): return np.asarray(value) return value def _test_array_function_protocol(): # Test if the __array_function__ protocol is enabled try: class FakeArray: def __array_function__(self, *args, **kwargs): return np.concatenate([FakeArray()]) return True except ValueError: return False HAS_NUMPY_ARRAY_FUNCTION = _test_array_function_protocol() NP_NO_VALUE = np._NoValue except ImportError: np = None class ndarray: pass HAS_NUMPY = False NUMPY_VER = "0" NUMERIC_TYPES = (Number, Decimal) HAS_NUMPY_ARRAY_FUNCTION = False NP_NO_VALUE = None def _to_magnitude(value, force_ndarray=False, force_ndarray_like=False): if force_ndarray or force_ndarray_like: raise ValueError( "Cannot force to ndarray or ndarray-like when NumPy is not present." ) elif isinstance(value, (dict, bool)) or value is None: raise TypeError("Invalid magnitude for Quantity: {0!r}".format(value)) elif isinstance(value, str) and value == "": raise ValueError("Quantity magnitude cannot be an empty string.") elif isinstance(value, (list, tuple)): raise TypeError( "lists and tuples are valid magnitudes for " "Quantity only when NumPy is present." ) return value try: from uncertainties import ufloat HAS_UNCERTAINTIES = True except ImportError: ufloat = None HAS_UNCERTAINTIES = False try: from babel import Locale as Loc from babel import units as babel_units babel_parse = Loc.parse HAS_BABEL = hasattr(babel_units, "format_unit") except ImportError: HAS_BABEL = False if not HAS_BABEL: babel_parse = babel_units = missing_dependency("Babel") # noqa: F811 # Define location of pint.Quantity in NEP-13 type cast hierarchy by defining upcast # types using guarded imports upcast_types = [] # pint-pandas (PintArray) try: from pintpandas import PintArray upcast_types.append(PintArray) except ImportError: pass # Pandas (Series) try: from pandas import Series upcast_types.append(Series) except ImportError: pass # xarray (DataArray, Dataset, Variable) try: from xarray import DataArray, Dataset, Variable upcast_types += [DataArray, Dataset, Variable] except ImportError: pass
[docs]def is_upcast_type(other): """Check if the type object is a upcast type using preset list. Parameters ---------- other : object Returns ------- bool """ return other in upcast_types
[docs]def is_duck_array_type(other): """Check if the type object represents a (non-Quantity) duck array type. Parameters ---------- other : object Returns ------- bool """ # TODO (NEP 30): replace duck array check with hasattr(other, "__duckarray__") return other is ndarray or ( not hasattr(other, "_magnitude") and not hasattr(other, "_units") and HAS_NUMPY_ARRAY_FUNCTION and hasattr(other, "__array_function__") and hasattr(other, "ndim") and hasattr(other, "dtype") )
[docs]def eq(lhs, rhs, check_all): """Comparison of scalars and arrays. Parameters ---------- lhs : object left-hand side rhs : object right-hand side check_all : bool if True, reduce sequence to single bool. Returns ------- bool or array_like of bool """ out = lhs == rhs if check_all and isinstance(out, ndarray): return np.all(out) return out