diff options
-rw-r--r-- | .github/workflows/ci.yml | 6 | ||||
-rw-r--r-- | .pre-commit-config.yaml | 6 | ||||
-rw-r--r-- | CHANGES | 14 | ||||
-rw-r--r-- | docs/user/angular_frequency.rst | 4 | ||||
-rw-r--r-- | pint/default_en.txt | 8 | ||||
-rw-r--r-- | pint/facets/numpy/numpy_func.py | 1 | ||||
-rw-r--r-- | pint/facets/plain/registry.py | 2 | ||||
-rw-r--r-- | pint/formatting.py | 2 | ||||
-rw-r--r-- | pint/testsuite/helpers.py | 6 | ||||
-rw-r--r-- | pint/testsuite/test_formatting.py | 15 | ||||
-rw-r--r-- | pint/testsuite/test_issues.py | 24 | ||||
-rw-r--r-- | pint/testsuite/test_umath.py | 68 | ||||
-rw-r--r-- | setup.cfg | 1 |
13 files changed, 116 insertions, 41 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 37444db..c74cbac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -64,7 +64,7 @@ jobs: - name: Install dependencies run: | sudo apt install -y graphviz - pip install pytest pytest-cov pytest-subtests + pip install pytest pytest-cov pytest-subtests packaging pip install . - name: Install pytest-mpl @@ -139,7 +139,7 @@ jobs: - name: Install dependencies run: | # sudo apt install -y graphviz - pip install pytest pytest-cov pytest-subtests + pip install pytest pytest-cov pytest-subtests packaging pip install . # - name: Install pytest-mpl @@ -191,7 +191,7 @@ jobs: - name: Install dependencies run: | - pip install pytest pytest-cov pytest-subtests + pip install pytest pytest-cov pytest-subtests packaging pip install . - name: Run Tests diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index e625f3b..83587c6 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,7 +1,7 @@ exclude: '^pint/_vendor' repos: - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 + rev: v4.4.0 hooks: - id: trailing-whitespace - id: end-of-file-fixer @@ -14,7 +14,7 @@ repos: rev: 5.10.1 hooks: - id: isort -- repo: https://gitlab.com/pycqa/flake8 - rev: 3.9.2 +- repo: https://github.com/pycqa/flake8 + rev: 6.0.0 hooks: - id: flake8 @@ -4,9 +4,21 @@ Pint Changelog 0.21 (unreleased) ----------------- +- Fix error when when re-registering a formatter. + (PR #1629) +- Add new SI prefixes: ronna-, ronto-, quetta-, quecto-. + (PR #1652) +- Implementation for numpy.positive added for Quantity. + (PR #1663) +- Changed frequency to angular frequency in the docs. + (PR #1668) - Avoid addition of spurious trailing zeros when converting units and non-int-type is - Decimal (Issue #1621). + Decimal (PR #1625). +### Breaking Changes + +- Support percent and ppm units. Support the `%` symbol. + (Issue #1277) 0.20.1 (2022-10-27) ------------------- diff --git a/docs/user/angular_frequency.rst b/docs/user/angular_frequency.rst index beebb92..0bafd05 100644 --- a/docs/user/angular_frequency.rst +++ b/docs/user/angular_frequency.rst @@ -12,8 +12,8 @@ By default, pint treats angle quantities as `dimensionless`, so allows conversio >> from pint import UnitRegistry >>> ureg = UnitRegistry() - >>> frequency = ureg('60rpm') - >>> frequency.to('Hz') + >>> angular_frequency = ureg('60rpm') + >>> angular_frequency.to('Hz') <Quantity(6.28318531, 'hertz')> pint follows the conventions of SI. The SI BIPM Brochure (Bureau International des Poids et Mesures) states: diff --git a/pint/default_en.txt b/pint/default_en.txt index a62f5ab..ed4f3d8 100644 --- a/pint/default_en.txt +++ b/pint/default_en.txt @@ -62,6 +62,8 @@ #### PREFIXES #### # decimal prefixes +quecto- = 1e-30 = q- +ronto- = 1e-27 = r- yocto- = 1e-24 = y- zepto- = 1e-21 = z- atto- = 1e-18 = a- @@ -84,6 +86,8 @@ peta- = 1e15 = P- exa- = 1e18 = E- zetta- = 1e21 = Z- yotta- = 1e24 = Y- +ronna- = 1e27 = R- +quetta- = 1e30 = Q- # binary_prefixes kibi- = 2**10 = Ki- @@ -144,6 +148,10 @@ byte = 8 * bit = B = octet # byte = 8 * bit = _ = octet ## NOTE: B (byte) symbol can conflict with Bell +# Ratios +percent = 0.01 = % +ppm = 1e-6 + # Length angstrom = 1e-10 * meter = Å = ångström = Å micron = micrometer = µ = μ diff --git a/pint/facets/numpy/numpy_func.py b/pint/facets/numpy/numpy_func.py index 2c07281..7bce41e 100644 --- a/pint/facets/numpy/numpy_func.py +++ b/pint/facets/numpy/numpy_func.py @@ -421,6 +421,7 @@ matching_input_copy_units_output_ufuncs = [ "nextafter", "trunc", "absolute", + "positive", "negative", "maximum", "minimum", diff --git a/pint/facets/plain/registry.py b/pint/facets/plain/registry.py index 8b98965..ffa6fb4 100644 --- a/pint/facets/plain/registry.py +++ b/pint/facets/plain/registry.py @@ -229,6 +229,8 @@ class PlainRegistry(metaclass=RegistryMeta): self.force_ndarray = force_ndarray self.force_ndarray_like = force_ndarray_like self.preprocessors = preprocessors or [] + # use a default preprocessor to support "%" + self.preprocessors.insert(0, lambda string: string.replace("%", " percent ")) #: mode used to fill in the format defaults self.separate_format_defaults = separate_format_defaults diff --git a/pint/formatting.py b/pint/formatting.py index 8d59756..554b381 100644 --- a/pint/formatting.py +++ b/pint/formatting.py @@ -157,7 +157,7 @@ def register_unit_format(name): def wrapper(func): if name in _FORMATTERS: - raise ValueError(f"format {name:!r} already exists") # or warn instead + raise ValueError(f"format {name!r} already exists") # or warn instead _FORMATTERS[name] = func return wrapper diff --git a/pint/testsuite/helpers.py b/pint/testsuite/helpers.py index d72b5a3..0348a45 100644 --- a/pint/testsuite/helpers.py +++ b/pint/testsuite/helpers.py @@ -1,9 +1,9 @@ import doctest import pickle import re -from distutils.version import LooseVersion import pytest +from packaging.version import parse as version_parse from pint.testing import assert_allclose as assert_quantity_almost_equal # noqa: F401 from pint.testing import assert_equal as assert_quantity_equal # noqa: F401 @@ -113,7 +113,7 @@ def requires_numpy_previous_than(version): if not HAS_NUMPY: return pytest.mark.skip("Requires NumPy") return pytest.mark.skipif( - not LooseVersion(NUMPY_VER) < LooseVersion(version), + not version_parse(NUMPY_VER) < version_parse(version), reason="Requires NumPy < %s" % version, ) @@ -122,7 +122,7 @@ def requires_numpy_at_least(version): if not HAS_NUMPY: return pytest.mark.skip("Requires NumPy") return pytest.mark.skipif( - not LooseVersion(NUMPY_VER) >= LooseVersion(version), + not version_parse(NUMPY_VER) >= version_parse(version), reason="Requires NumPy >= %s" % version, ) diff --git a/pint/testsuite/test_formatting.py b/pint/testsuite/test_formatting.py index d287948..48e770b 100644 --- a/pint/testsuite/test_formatting.py +++ b/pint/testsuite/test_formatting.py @@ -52,3 +52,18 @@ def test_split_format(format, default, flag, expected): result = fmt.split_format(format, default, flag) assert result == expected + + +def test_register_unit_format(func_registry): + @fmt.register_unit_format("custom") + def format_custom(unit, registry, **options): + return "<formatted unit>" + + quantity = 1.0 * func_registry.meter + assert f"{quantity:custom}" == "1.0 <formatted unit>" + + with pytest.raises(ValueError, match="format 'custom' already exists"): + + @fmt.register_unit_format("custom") + def format_custom_redefined(unit, registry, **options): + return "<overwritten>" diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py index 72663c1..1643bfc 100644 --- a/pint/testsuite/test_issues.py +++ b/pint/testsuite/test_issues.py @@ -8,6 +8,7 @@ import pytest from pint import Context, DimensionalityError, UnitRegistry, get_application_registry from pint.compat import np from pint.facets.plain.unit import UnitsContainer +from pint.testing import assert_equal from pint.testsuite import QuantityTestCase, helpers from pint.util import ParserHelper @@ -856,6 +857,29 @@ class TestIssues(QuantityTestCase): np.array((0.04, 0.09)), ) + def test_issue1277(self, module_registry): + ureg = module_registry + assert ureg("%") == ureg("percent") + assert ureg("%") == ureg.percent + assert ureg("ppm") == ureg.ppm + + a = ureg.Quantity("10 %") + b = ureg.Quantity("100 ppm") + c = ureg.Quantity("0.5") + + assert f"{a}" == "10 percent" + assert f"{a:~}" == "10 %" + assert f"{b}" == "100 ppm" + assert f"{b:~}" == "100 ppm" + + assert_equal(a, 0.1) + assert_equal(1000 * b, a) + assert_equal(c, 5 * a) + + assert_equal((1 * ureg.meter) / (1 * ureg.kilometer), 0.1 * ureg.percent) + assert c.to("percent").m == 50 + # assert c.to("%").m == 50 # TODO: fails. + @helpers.requires_uncertainties() def test_issue_1300(self): module_registry = UnitRegistry() diff --git a/pint/testsuite/test_umath.py b/pint/testsuite/test_umath.py index a3e69c7..6f32ab5 100644 --- a/pint/testsuite/test_umath.py +++ b/pint/testsuite/test_umath.py @@ -279,34 +279,43 @@ class TestMathUfuncs(TestUFuncs): http://docs.scipy.org/doc/numpy/reference/ufuncs.html#math-operations - add(x1, x2[, out]) Add arguments element-wise. - subtract(x1, x2[, out]) Subtract arguments, element-wise. - multiply(x1, x2[, out]) Multiply arguments element-wise. - divide(x1, x2[, out]) Divide arguments element-wise. - logaddexp(x1, x2[, out]) Logarithm of the sum of exponentiations of the inputs. - logaddexp2(x1, x2[, out]) Logarithm of the sum of exponentiations of the inputs in plain-2. - true_divide(x1, x2[, out]) Returns a true division of the inputs, element-wise. - floor_divide(x1, x2[, out]) Return the largest integer smaller or equal to the division of the inputs. - negative(x[, out]) Returns an array with the negative of each element of the original array. - power(x1, x2[, out]) First array elements raised to powers from second array, element-wise. NOT IMPLEMENTED - remainder(x1, x2[, out]) Return element-wise remainder of division. - mod(x1, x2[, out]) Return element-wise remainder of division. - fmod(x1, x2[, out]) Return the element-wise remainder of division. - absolute(x[, out]) Calculate the absolute value element-wise. - rint(x[, out]) Round elements of the array to the nearest integer. - sign(x[, out]) Returns an element-wise indication of the sign of a number. - conj(x[, out]) Return the complex conjugate, element-wise. - exp(x[, out]) Calculate the exponential of all elements in the input array. - exp2(x[, out]) Calculate 2**p for all p in the input array. - log(x[, out]) Natural logarithm, element-wise. - log2(x[, out]) Base-2 logarithm of x. - log10(x[, out]) Return the plain 10 logarithm of the input array, element-wise. - expm1(x[, out]) Calculate exp(x) - 1 for all elements in the array. - log1p(x[, out]) Return the natural logarithm of one plus the input array, element-wise. - sqrt(x[, out]) Return the positive square-root of an array, element-wise. - square(x[, out]) Return the element-wise square of the input. - reciprocal(x[, out]) Return the reciprocal of the argument, element-wise. - ones_like(x[, out]) Returns an array of ones with the same shape and type as a given array. + add(x1, x2, /[, out, where, casting, order, ...] Add arguments element-wise. + subtract(x1, x2, /[, out, where, casting, ...] Subtract arguments, element-wise. + multiply(x1, x2, /[, out, where, casting, ...] Multiply arguments element-wise. + matmul(x1, x2, /[, out, casting, order, ...] Matrix product of two arrays. + divide(x1, x2, /[, out, where, casting, ...] Divide arguments element-wise. + logaddexp(x1, x2, /[, out, where, casting, ...] Logarithm of the sum of exponentiations of the inputs. + logaddexp2(x1, x2, /[, out, where, casting, ...] Logarithm of the sum of exponentiations of the inputs in base-2. + true_divide(x1, x2, /[, out, where, ...] Divide arguments element-wise. + floor_divide(x1, x2, /[, out, where, ...] Return the largest integer smaller or equal to the division of the inputs. + negative(x, /[, out, where, casting, order, ...] Numerical negative, element-wise. + positive(x, /[, out, where, casting, order, ...] Numerical positive, element-wise. + power(x1, x2, /[, out, where, casting, ...] First array elements raised to powers from second array, element-wise. + float_power(x1, x2, /[, out, where, ...] First array elements raised to powers from second array, element-wise. + remainder(x1, x2, /[, out, where, casting, ...] Returns the element-wise remainder of division. + mod(x1, x2, /[, out, where, casting, order, ...] Returns the element-wise remainder of division. + fmod(x1, x2, /[, out, where, casting, ...] Returns the element-wise remainder of division. + divmod(x1, x2[, out1, out2], / [[, out, ...] Return element-wise quotient and remainder simultaneously. + absolute(x, /[, out, where, casting, order, ...] Calculate the absolute value element-wise. + fabs(x, /[, out, where, casting, order, ...] Compute the absolute values element-wise. + rint(x, /[, out, where, casting, order, ...] Round elements of the array to the nearest integer. + sign(x, /[, out, where, casting, order, ...] Returns an element-wise indication of the sign of a number. + heaviside(x1, x2, /[, out, where, casting, ...] Compute the Heaviside step function. + conj(x, /[, out, where, casting, order, ...] Return the complex conjugate, element-wise. + conjugate(x, /[, out, where, casting, ...] Return the complex conjugate, element-wise. + exp(x, /[, out, where, casting, order, ...] Calculate the exponential of all elements in the input array. + exp2(x, /[, out, where, casting, order, ...] Calculate 2**p for all p in the input array. + log(x, /[, out, where, casting, order, ...] Natural logarithm, element-wise. + log2(x, /[, out, where, casting, order, ...] Base-2 logarithm of x. + log10(x, /[, out, where, casting, order, ...] Return the base 10 logarithm of the input array, element-wise. + expm1(x, /[, out, where, casting, order, ...] Calculate exp(x) - 1 for all elements in the array. + log1p(x, /[, out, where, casting, order, ...] Return the natural logarithm of one plus the input array, element-wise. + sqrt(x, /[, out, where, casting, order, ...] Return the non-negative square-root of an array, element-wise. + square(x, /[, out, where, casting, order, ...] Return the element-wise square of the input. + cbrt(x, /[, out, where, casting, order, ...] Return the cube-root of an array, element-wise. + reciprocal(x, /[, out, where, casting, ...] Return the reciprocal of the argument, element-wise. + gcd(x1, x2, /[, out, where, casting, order, ...] Returns the greatest common divisor of |x1| and |x2| + lcm(x1, x2, /[, out, where, casting, order, ...] Returns the lowest common multiple of |x1| and |x2| Parameters ---------- @@ -364,6 +373,9 @@ class TestMathUfuncs(TestUFuncs): def test_negative(self): self._test1(np.negative, (self.qless, self.q1), ()) + def test_positive(self): + self._test1(np.positive, (self.qless, self.q1), ()) + def test_remainder(self): self._test2( np.remainder, @@ -43,6 +43,7 @@ test = pytest-mpl pytest-cov pytest-subtests + packaging [options.package_data] pint = default_en.txt; constants_en.txt; py.typed |