From 7035daf5f1f9516b578a6cd9588a181a7ea349ba Mon Sep 17 00:00:00 2001 From: Merrin Macleod Date: Sun, 30 Jun 2024 23:34:43 +1200 Subject: [PATCH 01/18] =?UTF-8?q?=F0=9F=8E=A8=20Fix=20styling=20of=20docs?= =?UTF-8?q?=20headings=20in=20dark=20mode=20(#2026)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/_static/style.css | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/docs/_static/style.css b/docs/_static/style.css index b2bc297d6..a2ac3f7fd 100644 --- a/docs/_static/style.css +++ b/docs/_static/style.css @@ -38,8 +38,14 @@ pre, code { .sd-card .sd-card-header { border: none; - color: #150458 !important; + color: #150458; font-size: var(--pst-font-size-h5); font-weight: bold; padding: 2.5rem 0rem 0.5rem 0rem; } + +html[data-theme=dark] { + .sd-card .sd-card-header { + color: #FFF; + } +} From 74e2e6a095f3df0bcb3ce95365efe2f1f7786acc Mon Sep 17 00:00:00 2001 From: Haris Musaefenidc Date: Mon, 8 Jul 2024 14:05:22 +0200 Subject: [PATCH 02/18] =?UTF-8?q?Add=20permille=20units=20with=20=E2=80=B0?= =?UTF-8?q?=20symbol=20(#2033)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGES | 2 +- pint/default_en.txt | 1 + pint/facets/plain/registry.py | 3 +++ pint/testsuite/test_issues.py | 18 ++++++++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 53e5a5fc5..e2999fddb 100644 --- a/CHANGES +++ b/CHANGES @@ -4,7 +4,7 @@ Pint Changelog 0.25 (unreleased) ----------------- -- Nothing added yet. +- Support permille units and `‰` symbol (PR #2033, Issue #1963) 0.24.1 (2024-06-24) diff --git a/pint/default_en.txt b/pint/default_en.txt index 45f241f18..68160a983 100644 --- a/pint/default_en.txt +++ b/pint/default_en.txt @@ -150,6 +150,7 @@ byte = 8 * bit = B = octet # Ratios percent = 0.01 = % +permille = 0.001 = ‰ ppm = 1e-6 # Length diff --git a/pint/facets/plain/registry.py b/pint/facets/plain/registry.py index 09fd220ee..c5c0be783 100644 --- a/pint/facets/plain/registry.py +++ b/pint/facets/plain/registry.py @@ -255,6 +255,9 @@ def __init__( # use a default preprocessor to support "%" self.preprocessors.insert(0, lambda string: string.replace("%", " percent ")) + # use a default preprocessor to support permille "‰" + self.preprocessors.insert(0, lambda string: string.replace("‰", " permille ")) + #: mode used to fill in the format defaults self.separate_format_defaults = separate_format_defaults diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py index 97eca3cde..c4e42eacc 100644 --- a/pint/testsuite/test_issues.py +++ b/pint/testsuite/test_issues.py @@ -884,6 +884,24 @@ def test_issue1277(self, module_registry): assert c.to("percent").m == 50 # assert c.to("%").m == 50 # TODO: fails. + def test_issue1963(self, module_registry): + ureg = module_registry + assert ureg("‰") == ureg("permille") + assert ureg("‰") == ureg.permille + + a = ureg.Quantity("10 ‰") + b = ureg.Quantity("100 ppm") + c = ureg.Quantity("0.5") + + assert f"{a}" == "10 permille" + assert f"{a:~}" == "10 ‰" + + assert_equal(a, 0.01) + assert_equal(1e2 * b, a) + assert_equal(c, 50 * a) + + assert_equal((1 * ureg.milligram) / (1 * ureg.gram), ureg.permille) + @pytest.mark.xfail @helpers.requires_uncertainties() def test_issue_1300(self): From 6483353b66bbd1e923b0682ed2c9496b7c3f8205 Mon Sep 17 00:00:00 2001 From: Tom Gillespie Date: Mon, 8 Jul 2024 08:10:59 -0400 Subject: [PATCH 03/18] ensure uncertainties does not depend on numpy (#2001) --- pint/compat.py | 5 ++++- pint/testsuite/test_issues.py | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/pint/compat.py b/pint/compat.py index 32ad04afb..b968803ce 100644 --- a/pint/compat.py +++ b/pint/compat.py @@ -75,7 +75,8 @@ class BehaviorChangeWarning(UserWarning): try: from uncertainties import UFloat, ufloat - from uncertainties import unumpy as unp + + unp = None HAS_UNCERTAINTIES = True except ImportError: @@ -92,6 +93,8 @@ class BehaviorChangeWarning(UserWarning): HAS_NUMPY = True NUMPY_VER = np.__version__ if HAS_UNCERTAINTIES: + from uncertainties import unumpy as unp + NUMERIC_TYPES = (Number, Decimal, ndarray, np.number, UFloat) else: NUMERIC_TYPES = (Number, Decimal, ndarray, np.number) diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py index c4e42eacc..f726a950c 100644 --- a/pint/testsuite/test_issues.py +++ b/pint/testsuite/test_issues.py @@ -940,6 +940,7 @@ def test_issue_1400(self, sess_registry): assert q2.format_babel("~", locale="es_ES") == "3,1 W/cm" assert q2.format_babel("", locale="es_ES") == "3,1 vatios por centímetro" + @helpers.requires_numpy() @helpers.requires_uncertainties() def test_issue1611(self, module_registry): from numpy.testing import assert_almost_equal From bffbbc21d93ce19bac1af94d4ac8939851e15e9a Mon Sep 17 00:00:00 2001 From: SPKorhonen Date: Mon, 8 Jul 2024 17:13:45 +0300 Subject: [PATCH 04/18] =?UTF-8?q?Add=20=E2=84=93=20as=20alternative=20for?= =?UTF-8?q?=20liter=20(#2014)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGES | 1 + pint/default_en.txt | 2 +- pint/testsuite/test_issues.py | 3 +++ 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index e2999fddb..37ca16b87 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ Pint Changelog 0.25 (unreleased) ----------------- +- Added ℓ as alternative for liter - Support permille units and `‰` symbol (PR #2033, Issue #1963) diff --git a/pint/default_en.txt b/pint/default_en.txt index 68160a983..c87c5f0d5 100644 --- a/pint/default_en.txt +++ b/pint/default_en.txt @@ -222,7 +222,7 @@ hectare = 100 * are = ha # Volume [volume] = [length] ** 3 -liter = decimeter ** 3 = l = L = litre +liter = decimeter ** 3 = l = L = ℓ = litre cubic_centimeter = centimeter ** 3 = cc lambda = microliter = λ stere = meter ** 3 diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py index f726a950c..760b886f7 100644 --- a/pint/testsuite/test_issues.py +++ b/pint/testsuite/test_issues.py @@ -408,6 +408,9 @@ def test_micro_creation_U03bc(self, module_registry): def test_micro_creation_U00b5(self, module_registry): module_registry.Quantity(2, "µm") + def test_liter_creation_U2113(self, module_registry): + module_registry.Quantity(2, "ℓ") + @helpers.requires_numpy def test_issue171_real_imag(self, module_registry): qr = [1.0, 2.0, 3.0, 4.0] * module_registry.meter From f9c381c1e89ffb7ce9e6268516f9291ca5351d6f Mon Sep 17 00:00:00 2001 From: SPKorhonen Date: Mon, 8 Jul 2024 17:24:38 +0300 Subject: [PATCH 05/18] Added "mu" and "mc" prefixes. (#2013) --- CHANGES | 1 + pint/default_en.txt | 2 +- pint/testsuite/conftest.py | 2 +- pint/testsuite/test_issues.py | 6 ++++++ 4 files changed, 9 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 37ca16b87..208dbad06 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,7 @@ Pint Changelog 0.25 (unreleased) ----------------- +- Added mu and mc as alternatives for SI micro prefix - Added ℓ as alternative for liter - Support permille units and `‰` symbol (PR #2033, Issue #1963) diff --git a/pint/default_en.txt b/pint/default_en.txt index c87c5f0d5..4250a48cb 100644 --- a/pint/default_en.txt +++ b/pint/default_en.txt @@ -72,7 +72,7 @@ pico- = 1e-12 = p- nano- = 1e-9 = n- # The micro (U+00B5) and Greek mu (U+03BC) are both valid prefixes, # and they often use the same glyph. -micro- = 1e-6 = µ- = μ- = u- +micro- = 1e-6 = µ- = μ- = u- = mu- = mc- milli- = 1e-3 = m- centi- = 1e-2 = c- deci- = 1e-1 = d- diff --git a/pint/testsuite/conftest.py b/pint/testsuite/conftest.py index 775480f0b..0a42f44af 100644 --- a/pint/testsuite/conftest.py +++ b/pint/testsuite/conftest.py @@ -14,7 +14,7 @@ femto- = 1e-15 = f- pico- = 1e-12 = p- nano- = 1e-9 = n- -micro- = 1e-6 = µ- = μ- = u- +micro- = 1e-6 = µ- = μ- = u- = mu- = mc- milli- = 1e-3 = m- centi- = 1e-2 = c- deci- = 1e-1 = d- diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py index 760b886f7..847f269f0 100644 --- a/pint/testsuite/test_issues.py +++ b/pint/testsuite/test_issues.py @@ -408,6 +408,12 @@ def test_micro_creation_U03bc(self, module_registry): def test_micro_creation_U00b5(self, module_registry): module_registry.Quantity(2, "µm") + def test_micro_creation_mu(self, module_registry): + module_registry.Quantity(2, "mug") + + def test_micro_creation_mc(self, module_registry): + module_registry.Quantity(2, "mcg") + def test_liter_creation_U2113(self, module_registry): module_registry.Quantity(2, "ℓ") From b2fc74a7d6038d206d158804daa32e1698f89c26 Mon Sep 17 00:00:00 2001 From: Pratyush Das Date: Mon, 8 Jul 2024 21:40:58 +0700 Subject: [PATCH 06/18] Fix cli uncertainty package import (#2032) --- CHANGES | 2 ++ docs/dev/pint-convert.rst | 27 +++++++++++++++------------ pint/pint_convert.py | 28 ++++++++++++++++++++-------- 3 files changed, 37 insertions(+), 20 deletions(-) mode change 100755 => 100644 pint/pint_convert.py diff --git a/CHANGES b/CHANGES index 208dbad06..5ee199f2c 100644 --- a/CHANGES +++ b/CHANGES @@ -4,8 +4,10 @@ Pint Changelog 0.25 (unreleased) ----------------- +- Fix the default behaviour for pint-convert (cli) for importing uncertainties package - Added mu and mc as alternatives for SI micro prefix - Added ℓ as alternative for liter +- Fix the default behaviour for pint-convert (cli) for importing uncertainties package (PR #2032, Issue #2016) - Support permille units and `‰` symbol (PR #2033, Issue #1963) diff --git a/docs/dev/pint-convert.rst b/docs/dev/pint-convert.rst index dbb0804f4..4ba0ad888 100644 --- a/docs/dev/pint-convert.rst +++ b/docs/dev/pint-convert.rst @@ -77,36 +77,39 @@ With the `uncertainties` package, the experimental uncertainty in the physical constants is considered, and the result is given in compact notation, with the uncertainty in the last figures in parentheses: +The uncertainty can be enabled with `-U` (by default it is not enabled): + +.. code-block:: console + + $ pint-convert -p 20 -U Eh eV + 1 hartree = 27.211386245988(52) eV + .. code-block:: console - $ pint-convert Eh eV + $ pint-convert -U Eh eV 1 hartree = 27.21138624599(5) eV The precision is limited by both the maximum number of significant digits (`-p`) and the maximum number of uncertainty digits (`-u`, 2 by default):: - $ pint-convert -p 20 Eh eV + $ pint-convert -U -p 20 Eh eV 1 hartree = 27.211386245988(52) eV - $ pint-convert -p 20 -u 4 Eh eV + $ pint-convert -U -p 20 -u 4 Eh eV 1 hartree = 27.21138624598847(5207) eV -The uncertainty can be disabled with `-U`): - -.. code-block:: console - - $ pint-convert -p 20 -U Eh eV - 1 hartree = 27.211386245988471444 eV - Correlations between experimental constants are also known, and taken into -account. Use `-C` to disable it: +account if uncertainties `-U` is enabled. Use `-C` to disable it: .. code-block:: console $ pint-convert --sys atomic m_p + 1 proton_mass = 1836.15267344 m_e + + $ pint-convert -U --sys atomic m_p 1 proton_mass = 1836.15267344(11) m_e - $ pint-convert --sys atomic -C m_p + $ pint-convert -U --sys atomic -C m_p 1 proton_mass = 1836.15267344(79) m_e Again, note that results may differ slightly, usually in the last figure, from diff --git a/pint/pint_convert.py b/pint/pint_convert.py old mode 100755 new mode 100644 index bf9097237..0934588b8 --- a/pint/pint_convert.py +++ b/pint/pint_convert.py @@ -42,10 +42,10 @@ ) parser.add_argument( "-U", - "--no-unc", + "--with-unc", dest="unc", - action="store_false", - help="ignore uncertainties in constants", + action="store_true", + help="consider uncertainties in constants", ) parser.add_argument( "-C", @@ -77,7 +77,12 @@ def _set(key: str, value): if args.unc: - import uncertainties + try: + import uncertainties + except ImportError: + raise Exception( + "Failed to import uncertainties library!\n Please install uncertainties package" + ) # Measured constants subject to correlation # R_i: Rydberg constant @@ -103,9 +108,14 @@ def _set(key: str, value): [0.00194, 0.97560, 0.98516, 0.98058, 1.0, 0.51521], # m_p [0.00233, 0.52445, 0.52959, 0.52714, 0.51521, 1.0], ] # m_n - (R_i, g_e, m_u, m_e, m_p, m_n) = uncertainties.correlated_values_norm( - [R_i, g_e, m_u, m_e, m_p, m_n], corr - ) + try: + (R_i, g_e, m_u, m_e, m_p, m_n) = uncertainties.correlated_values_norm( + [R_i, g_e, m_u, m_e, m_p, m_n], corr + ) + except AttributeError: + raise Exception( + "Correlation cannot be calculated!\n Please install numpy package" + ) else: R_i = uncertainties.ufloat(*R_i) g_e = uncertainties.ufloat(*g_e) @@ -160,6 +170,7 @@ def _set(key: str, value): def convert(u_from, u_to=None, unc=None, factor=None): + prec_unc = 0 q = ureg.Quantity(u_from) fmt = f".{args.prec}g" if unc: @@ -171,7 +182,8 @@ def convert(u_from, u_to=None, unc=None, factor=None): if factor: q *= ureg.Quantity(factor) nq *= ureg.Quantity(factor).to_base_units() - prec_unc = use_unc(nq.magnitude, fmt, args.prec_unc) + if args.unc: + prec_unc = use_unc(nq.magnitude, fmt, args.prec_unc) if prec_unc > 0: fmt = f".{prec_unc}uS" else: From 1e46b2ee8f439703606757472769c10fb7586d83 Mon Sep 17 00:00:00 2001 From: mutricyl <118692416+mutricyl@users.noreply.github.com> Date: Fri, 12 Jul 2024 15:49:42 +0200 Subject: [PATCH 07/18] 2035 pandas3 (#2036) --- pint/compat.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pint/compat.py b/pint/compat.py index b968803ce..4b4cbab92 100644 --- a/pint/compat.py +++ b/pint/compat.py @@ -240,6 +240,8 @@ def _to_magnitude(value, force_ndarray=False, force_ndarray_like=False): "xarray.core.variable.Variable", "pandas.core.series.Series", "pandas.core.frame.DataFrame", + "pandas.Series", + "pandas.DataFrame", "xarray.core.dataarray.DataArray", ) From 5f2a76a42c44f0077908be212c5445a657da639a Mon Sep 17 00:00:00 2001 From: Pratyush Das Date: Sat, 13 Jul 2024 17:24:56 +0700 Subject: [PATCH 08/18] [DOC] Update changelog (#2034) --- CHANGES | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 5ee199f2c..bfe99d479 100644 --- a/CHANGES +++ b/CHANGES @@ -4,10 +4,9 @@ Pint Changelog 0.25 (unreleased) ----------------- -- Fix the default behaviour for pint-convert (cli) for importing uncertainties package +- Fix the default behaviour for pint-convert (cli) for importing uncertainties package (PR #2032, Issue #2016) - Added mu and mc as alternatives for SI micro prefix - Added ℓ as alternative for liter -- Fix the default behaviour for pint-convert (cli) for importing uncertainties package (PR #2032, Issue #2016) - Support permille units and `‰` symbol (PR #2033, Issue #1963) From 0faac0760cf36a72d23463d5012644d751b4c8d7 Mon Sep 17 00:00:00 2001 From: andrewgsavage Date: Sun, 28 Jul 2024 01:12:52 +0100 Subject: [PATCH 09/18] add error for prefixed non multi units (#1998) --- CHANGES | 2 ++ pint/facets/plain/registry.py | 12 +++++++++++- pint/testsuite/test_unit.py | 5 +++++ 3 files changed, 18 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index bfe99d479..15d479972 100644 --- a/CHANGES +++ b/CHANGES @@ -45,6 +45,8 @@ Pint Changelog (PR #1949) - Fix unhandled TypeError when auto_reduce_dimensions=True and non_int_type=Decimal (PR #1853) +- Creating prefixed offset units now raises an error. + (PR #1998) - Improved error message in `get_dimensionality()` when non existent units are passed. (PR #1874, Issue #1716) diff --git a/pint/facets/plain/registry.py b/pint/facets/plain/registry.py index c5c0be783..325f2c315 100644 --- a/pint/facets/plain/registry.py +++ b/pint/facets/plain/registry.py @@ -60,7 +60,12 @@ UnitLike, ) from ...compat import Self, TypeAlias, deprecated -from ...errors import DimensionalityError, RedefinitionError, UndefinedUnitError +from ...errors import ( + DimensionalityError, + OffsetUnitCalculusError, + RedefinitionError, + UndefinedUnitError, +) from ...pint_eval import build_eval_tree from ...util import ( ParserHelper, @@ -667,6 +672,11 @@ def get_name(self, name_or_alias: str, case_sensitive: bool | None = None) -> st ) if prefix: + if not self._units[unit_name].is_multiplicative: + raise OffsetUnitCalculusError( + "Prefixing a unit requires multiplying the unit." + ) + name = prefix + unit_name symbol = self.get_symbol(name, case_sensitive) prefix_def = self._prefixes[prefix] diff --git a/pint/testsuite/test_unit.py b/pint/testsuite/test_unit.py index 2156bbafd..1cca93cec 100644 --- a/pint/testsuite/test_unit.py +++ b/pint/testsuite/test_unit.py @@ -1043,3 +1043,8 @@ def test_alias(self): # Define against unknown name with pytest.raises(KeyError): ureg.define("@alias notexist = something") + + def test_prefix_offset_units(self): + ureg = UnitRegistry() + with pytest.raises(errors.OffsetUnitCalculusError): + ureg.parse_units("kilodegree_Celsius") From 67303b8e20f1d4023bc5e0e7cb68f0c08855ba2c Mon Sep 17 00:00:00 2001 From: andrewgsavage Date: Sun, 28 Jul 2024 01:14:45 +0100 Subject: [PATCH 10/18] build: typing_extensions version closes #1996 --- CHANGES | 2 ++ requirements.txt | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 15d479972..6c3c827ae 100644 --- a/CHANGES +++ b/CHANGES @@ -32,6 +32,8 @@ Pint Changelog - Add `dim_sort` function to _formatter_helpers. - Add `dim_order` and `default_sort_func` properties to FullFormatter. (PR #1926, fixes Issue #1841) +- Minimum version requirement added for typing_extensions>=4.0.0. + (PR #1996) - Documented packages using pint. (PR #1960) - Fixed bug causing operations between arrays of quantity scalars and quantity holding diff --git a/requirements.txt b/requirements.txt index 0bc99005a..dc7cf4651 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ appdirs>=1.4.4 -typing_extensions +typing_extensions>=4.0.0 flexcache>=0.3 flexparser>=0.3 From 0b0ae61cebe6c470dcc2edbb84fe717c664fc223 Mon Sep 17 00:00:00 2001 From: Steve Kowalik Date: Mon, 29 Jul 2024 02:13:26 +1000 Subject: [PATCH 11/18] build: switch from appdirs to platformdirs appdirs has been officially deprecated upstream, the replacement module with more features is platformdirs. Closes #2028 --- CHANGES | 1 + docs/advanced/performance.rst | 4 ++-- pint/facets/plain/registry.py | 5 ++--- requirements.txt | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/CHANGES b/CHANGES index 6c3c827ae..4b4884d54 100644 --- a/CHANGES +++ b/CHANGES @@ -8,6 +8,7 @@ Pint Changelog - Added mu and mc as alternatives for SI micro prefix - Added ℓ as alternative for liter - Support permille units and `‰` symbol (PR #2033, Issue #1963) +- Switch from appdirs to platformdirs. 0.24.1 (2024-06-24) diff --git a/docs/advanced/performance.rst b/docs/advanced/performance.rst index d7b8a0cd5..998cac681 100644 --- a/docs/advanced/performance.rst +++ b/docs/advanced/performance.rst @@ -120,7 +120,7 @@ If you want to use the default cache folder provided by the OS, use **:auto:** >>> import pint >>> ureg = pint.UnitRegistry(cache_folder=":auto:") # doctest: +SKIP -Pint use an included version of appdirs_ to obtain the correct folder, +Pint use an external dependency of platformdirs_ to obtain the correct folder, for example in macOS is `/Users//Library/Caches/pint` In any case, you can check the location of the cache folder. @@ -146,5 +146,5 @@ In any case, you can check the location of the cache folder. .. _`brentq method`: http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.brentq.html -.. _appdirs: https://pypi.org/project/appdirs/ +.. _platformdirs: https://pypi.org/project/platformdirs .. _flexcache: https://github.com/hgrecco/flexcache/ diff --git a/pint/facets/plain/registry.py b/pint/facets/plain/registry.py index 325f2c315..c8ce3f2f0 100644 --- a/pint/facets/plain/registry.py +++ b/pint/facets/plain/registry.py @@ -49,7 +49,7 @@ # from ..._typing import Quantity, Unit -import appdirs +import platformdirs from ... import pint_eval from ..._typing import ( @@ -238,8 +238,7 @@ def __init__( self._init_dynamic_classes() if cache_folder == ":auto:": - cache_folder = appdirs.user_cache_dir(appname="pint", appauthor=False) - cache_folder = pathlib.Path(cache_folder) + cache_folder = platformdirs.user_cache_path(appname="pint", appauthor=False) from ... import delegates # TODO: change thiss diff --git a/requirements.txt b/requirements.txt index dc7cf4651..c62365819 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ -appdirs>=1.4.4 +platformdirs>=2.1.0 typing_extensions>=4.0.0 flexcache>=0.3 flexparser>=0.3 From 8f12bb923adb69cf2a772c4f2cb10ee3ef9dd11a Mon Sep 17 00:00:00 2001 From: Bogdan Reznychenko <100156521+theodotk@users.noreply.github.com> Date: Mon, 19 Aug 2024 13:51:19 -0700 Subject: [PATCH 12/18] fix GenericPlainRegistry getattr type (#2045) --- CHANGES | 1 + pint/facets/plain/registry.py | 2 +- pint/testsuite/test_quantity.py | 8 ++++++++ 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 4b4884d54..9d7de4298 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,7 @@ Pint Changelog - Added ℓ as alternative for liter - Support permille units and `‰` symbol (PR #2033, Issue #1963) - Switch from appdirs to platformdirs. +- Fixes issues related to GenericPlainRegistry.__getattr__ type (PR #2038, Issues #1946 and #1804) 0.24.1 (2024-06-24) diff --git a/pint/facets/plain/registry.py b/pint/facets/plain/registry.py index c8ce3f2f0..be70a2ca8 100644 --- a/pint/facets/plain/registry.py +++ b/pint/facets/plain/registry.py @@ -367,7 +367,7 @@ def __deepcopy__(self: Self, memo) -> type[Self]: new._init_dynamic_classes() return new - def __getattr__(self, item: str) -> QuantityT: + def __getattr__(self, item: str) -> UnitT: getattr_maybe_raise(self, item) # self.Unit will call parse_units diff --git a/pint/testsuite/test_quantity.py b/pint/testsuite/test_quantity.py index 8c6f15c49..26a5ee05d 100644 --- a/pint/testsuite/test_quantity.py +++ b/pint/testsuite/test_quantity.py @@ -2014,3 +2014,11 @@ def test_offset_autoconvert_gt_zero(self): assert q2 > 0 with pytest.raises(DimensionalityError): q1.__gt__(ureg.Quantity(0, "")) + + def test_types(self): + quantity = self.Q_(1.0, "m") + assert isinstance(quantity, self.Q_) + assert isinstance(quantity.units, self.ureg.Unit) + assert isinstance(quantity.m, float) + + assert isinstance(self.ureg.m, self.ureg.Unit) From 2839f6e23f48dd393c375c44581574afec04ff43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mar=C3=A7al=20Gabald=C3=A0?= Date: Fri, 4 Oct 2024 21:05:33 +0200 Subject: [PATCH 13/18] Replace references to the deprecated `UnitRegistry.default_format` (#2058) --- CHANGES | 1 + docs/getting/tutorial.rst | 4 ++-- docs/user/nonmult.rst | 2 +- pint/testsuite/test_babel.py | 2 +- pint/testsuite/test_unit.py | 16 ++++++++-------- 5 files changed, 13 insertions(+), 12 deletions(-) diff --git a/CHANGES b/CHANGES index 9d7de4298..de1c3bccb 100644 --- a/CHANGES +++ b/CHANGES @@ -10,6 +10,7 @@ Pint Changelog - Support permille units and `‰` symbol (PR #2033, Issue #1963) - Switch from appdirs to platformdirs. - Fixes issues related to GenericPlainRegistry.__getattr__ type (PR #2038, Issues #1946 and #1804) +- Removed deprecated references in documentation and tests (PR #2058, Issue #2057) 0.24.1 (2024-06-24) diff --git a/docs/getting/tutorial.rst b/docs/getting/tutorial.rst index d675860f2..a0836fe7e 100644 --- a/docs/getting/tutorial.rst +++ b/docs/getting/tutorial.rst @@ -415,7 +415,7 @@ Additionally, you can specify a default format specification: >>> accel = 1.3 * ureg.parse_units('meter/second**2') >>> 'The acceleration is {}'.format(accel) 'The acceleration is 1.3 meter / second ** 2' - >>> ureg.default_format = 'P' + >>> ureg.formatter.default_format = 'P' >>> 'The acceleration is {}'.format(accel) 'The acceleration is 1.3 meter/second²' @@ -446,7 +446,7 @@ and by doing that, string formatting is now localized: .. doctest:: - >>> ureg.default_format = 'P' + >>> ureg.formatter.default_format = 'P' >>> accel = 1.3 * ureg.parse_units('meter/second**2') >>> str(accel) '1,3 mètres par seconde²' diff --git a/docs/user/nonmult.rst b/docs/user/nonmult.rst index a649d2ad1..905dd0835 100644 --- a/docs/user/nonmult.rst +++ b/docs/user/nonmult.rst @@ -18,7 +18,7 @@ For example, to convert from celsius to fahrenheit: >>> from pint import UnitRegistry >>> ureg = UnitRegistry() - >>> ureg.default_format = '.3f' + >>> ureg.formatter.default_format = '.3f' >>> Q_ = ureg.Quantity >>> home = Q_(25.4, ureg.degC) >>> print(home.to('degF')) diff --git a/pint/testsuite/test_babel.py b/pint/testsuite/test_babel.py index 9adcb04a9..c68c641e7 100644 --- a/pint/testsuite/test_babel.py +++ b/pint/testsuite/test_babel.py @@ -66,7 +66,7 @@ def test_unit_format_babel(): volume = ureg.Unit("ml") assert volume.format_babel() == "millilitre" - ureg.default_format = "~" + ureg.formatter.default_format = "~" assert volume.format_babel() == "ml" dimensionless_unit = ureg.Unit("") diff --git a/pint/testsuite/test_unit.py b/pint/testsuite/test_unit.py index 1cca93cec..78d72e856 100644 --- a/pint/testsuite/test_unit.py +++ b/pint/testsuite/test_unit.py @@ -70,7 +70,7 @@ def test_latex_escaping(self, subtests): "Lx~": r"\si[]{\%}", }.items(): with subtests.test(spec): - ureg.default_format = spec + ureg.formatter.default_format = spec assert f"{x}" == result, f"Failed for {spec}, got {x} expected {result}" # no '#' here as it's a comment char when define()ing new units ureg.define(r"weirdunit = 1 = \~_^&%$_{}") @@ -83,7 +83,7 @@ def test_latex_escaping(self, subtests): # "Lx~": r"\si[]{\textbackslash \textasciitilde \_\textasciicircum \&\%\$\_\{\}}", }.items(): with subtests.test(spec): - ureg.default_format = spec + ureg.formatter.default_format = spec assert f"{x}" == result, f"Failed for {spec}, {result}" def test_unit_default_formatting(self, subtests): @@ -104,13 +104,13 @@ def test_unit_default_formatting(self, subtests): ("C~", "kg*m**2/s"), ): with subtests.test(spec): - ureg.default_format = spec + ureg.formatter.default_format = spec assert f"{x}" == result, f"Failed for {spec}, {result}" @pytest.mark.xfail(reason="Still not clear how default formatting will work.") def test_unit_formatting_defaults_warning(self): ureg = UnitRegistry() - ureg.default_format = "~P" + ureg.formatter.default_format = "~P" x = ureg.Unit("m / s ** 2") with pytest.warns(DeprecationWarning): @@ -136,7 +136,7 @@ def test_unit_formatting_snake_case(self, subtests): ("C~", "oil_bbl"), ): with subtests.test(spec): - ureg.default_format = spec + ureg.formatter.default_format = spec assert f"{x}" == result, f"Failed for {spec}, {result}" def test_unit_formatting_custom(self, monkeypatch): @@ -177,7 +177,7 @@ def pretty(cls, data): ) x._repr_pretty_(Pretty, False) assert "".join(alltext) == "kilogram·meter²/second" - ureg.default_format = "~" + ureg.formatter.default_format = "~" assert x._repr_html_() == "kg m2/s" assert ( x._repr_latex_() == r"$\frac{\mathrm{kg} \cdot \mathrm{m}^{2}}{\mathrm{s}}$" @@ -322,11 +322,11 @@ def test_default_format(self): q = ureg.meter s1 = f"{q}" s2 = f"{q:~}" - ureg.default_format = "~" + ureg.formatter.default_format = "~" s3 = f"{q}" assert s2 == s3 assert s1 != s3 - assert ureg.default_format == "~" + assert ureg.formatter.default_format == "~" def test_iterate(self): ureg = UnitRegistry() From d592aff209a0eeae9383042368906dfb5edc5f54 Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Wed, 6 Nov 2024 23:34:42 -0300 Subject: [PATCH 14/18] fix: upgrade to flexparser>=0.4, exceptions are no longer dataclasses --- pint/delegates/txt_defparser/common.py | 9 ++- pint/errors.py | 98 +++++++++++++++++--------- requirements.txt | 2 +- 3 files changed, 72 insertions(+), 37 deletions(-) diff --git a/pint/delegates/txt_defparser/common.py b/pint/delegates/txt_defparser/common.py index ebdabc062..def901d88 100644 --- a/pint/delegates/txt_defparser/common.py +++ b/pint/delegates/txt_defparser/common.py @@ -12,7 +12,7 @@ from __future__ import annotations -from dataclasses import dataclass, field +from dataclasses import dataclass import flexparser as fp @@ -20,7 +20,6 @@ from ..base_defparser import ParserConfig -@dataclass(frozen=True) class DefinitionSyntaxError(errors.DefinitionSyntaxError, fp.ParsingError): """A syntax error was found in a definition. Combines: @@ -30,7 +29,11 @@ class DefinitionSyntaxError(errors.DefinitionSyntaxError, fp.ParsingError): and an extra location attribute in which the filename or reseource is stored. """ - location: str = field(init=False, default="") + msg: str + + def __init__(self, msg: str, location: str = ""): + self.msg = msg + self.location = location def __str__(self) -> str: msg = ( diff --git a/pint/errors.py b/pint/errors.py index 59d3b4569..d1882dbdd 100644 --- a/pint/errors.py +++ b/pint/errors.py @@ -11,7 +11,6 @@ from __future__ import annotations import typing as ty -from dataclasses import dataclass, fields OFFSET_ERROR_DOCS_HTML = "https://pint.readthedocs.io/en/stable/user/nonmult.html" LOG_ERROR_DOCS_HTML = "https://pint.readthedocs.io/en/stable/user/log_units.html" @@ -81,12 +80,10 @@ def def_err(self, msg: str): return DefinitionError(self.name, self.__class__, msg) -@dataclass(frozen=False) class PintError(Exception): """Base exception for all Pint errors.""" -@dataclass(frozen=False) class DefinitionError(ValueError, PintError): """Raised when a definition is not properly constructed.""" @@ -94,69 +91,76 @@ class DefinitionError(ValueError, PintError): definition_type: type msg: str + def __init__(self, name: str, definition_type: type, msg: str): + self.name = name + self.definition_type = definition_type + self.msg = msg + def __str__(self): msg = f"Cannot define '{self.name}' ({self.definition_type}): {self.msg}" return msg def __reduce__(self): - return self.__class__, tuple(getattr(self, f.name) for f in fields(self)) + return self.__class__, (self.name, self.definition_type, self.msg) -@dataclass(frozen=False) class DefinitionSyntaxError(ValueError, PintError): """Raised when a textual definition has a syntax error.""" msg: str + def __init__(self, msg: str): + self.msg = msg + def __str__(self): return self.msg def __reduce__(self): - return self.__class__, tuple(getattr(self, f.name) for f in fields(self)) + return self.__class__, (self.msg,) -@dataclass(frozen=False) class RedefinitionError(ValueError, PintError): """Raised when a unit or prefix is redefined.""" name: str definition_type: type + def __init__(self, name: str, definition_type: type): + self.name = name + self.definition_type = definition_type + def __str__(self): msg = f"Cannot redefine '{self.name}' ({self.definition_type})" return msg def __reduce__(self): - return self.__class__, tuple(getattr(self, f.name) for f in fields(self)) + return self.__class__, (self.name, self.definition_type) -@dataclass(frozen=False) class UndefinedUnitError(AttributeError, PintError): """Raised when the units are not defined in the unit registry.""" - unit_names: str | tuple[str, ...] + unit_names: tuple[str, ...] + + def __init__(self, unit_names: str | ty.Iterable[str]): + if isinstance(unit_names, str): + self.unit_names = (unit_names,) + else: + self.unit_names = tuple(unit_names) def __str__(self): - if isinstance(self.unit_names, str): - return f"'{self.unit_names}' is not defined in the unit registry" - if ( - isinstance(self.unit_names, (tuple, list, set)) - and len(self.unit_names) == 1 - ): + if len(self.unit_names) == 1: return f"'{tuple(self.unit_names)[0]}' is not defined in the unit registry" return f"{tuple(self.unit_names)} are not defined in the unit registry" def __reduce__(self): - return self.__class__, tuple(getattr(self, f.name) for f in fields(self)) + return self.__class__, (self.unit_names,) -@dataclass(frozen=False) class PintTypeError(TypeError, PintError): - def __reduce__(self): - return self.__class__, tuple(getattr(self, f.name) for f in fields(self)) + pass -@dataclass(frozen=False) class DimensionalityError(PintTypeError): """Raised when trying to convert between incompatible units.""" @@ -166,6 +170,20 @@ class DimensionalityError(PintTypeError): dim2: str = "" extra_msg: str = "" + def __init__( + self, + units1: ty.Any, + units2: ty.Any, + dim1: str = "", + dim2: str = "", + extra_msg: str = "", + ) -> None: + self.units1 = units1 + self.units2 = units2 + self.dim1 = dim1 + self.dim2 = dim2 + self.extra_msg = extra_msg + def __str__(self): if self.dim1 or self.dim2: dim1 = f" ({self.dim1})" @@ -180,16 +198,25 @@ def __str__(self): ) def __reduce__(self): - return self.__class__, tuple(getattr(self, f.name) for f in fields(self)) + return self.__class__, ( + self.units1, + self.units2, + self.dim1, + self.dim2, + self.extra_msg, + ) -@dataclass(frozen=False) class OffsetUnitCalculusError(PintTypeError): """Raised on ambiguous operations with offset units.""" units1: ty.Any units2: ty.Optional[ty.Any] = None + def __init__(self, units1: ty.Any, units2: ty.Optional[ty.Any] = None) -> None: + self.units1 = units1 + self.units2 = units2 + def yield_units(self): yield self.units1 if self.units2: @@ -205,16 +232,19 @@ def __str__(self): ) def __reduce__(self): - return self.__class__, tuple(getattr(self, f.name) for f in fields(self)) + return self.__class__, (self.units1, self.units2) -@dataclass(frozen=False) class LogarithmicUnitCalculusError(PintTypeError): """Raised on inappropriate operations with logarithmic units.""" units1: ty.Any units2: ty.Optional[ty.Any] = None + def __init__(self, units1: ty.Any, units2: ty.Optional[ty.Any] = None) -> None: + self.units1 = units1 + self.units2 = units2 + def yield_units(self): yield self.units1 if self.units2: @@ -230,26 +260,28 @@ def __str__(self): ) def __reduce__(self): - return self.__class__, tuple(getattr(self, f.name) for f in fields(self)) + return self.__class__, (self.units1, self.units2) -@dataclass(frozen=False) class UnitStrippedWarning(UserWarning, PintError): msg: str + def __init__(self, msg: str): + self.msg = msg + def __reduce__(self): - return self.__class__, tuple(getattr(self, f.name) for f in fields(self)) + return self.__class__, (self.msg,) -@dataclass(frozen=False) class UnexpectedScaleInContainer(Exception): - def __reduce__(self): - return self.__class__, tuple(getattr(self, f.name) for f in fields(self)) + pass -@dataclass(frozen=False) class UndefinedBehavior(UserWarning, PintError): msg: str + def __init__(self, msg: str): + self.msg = msg + def __reduce__(self): - return self.__class__, tuple(getattr(self, f.name) for f in fields(self)) + return self.__class__, (self.msg,) diff --git a/requirements.txt b/requirements.txt index c62365819..b63f8da99 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,4 @@ platformdirs>=2.1.0 typing_extensions>=4.0.0 flexcache>=0.3 -flexparser>=0.3 +flexparser>=0.4 From a8bcb6ee1d0d61278bf17e332bc1aa473672e273 Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Wed, 6 Nov 2024 23:35:48 -0300 Subject: [PATCH 15/18] ci: add Python 3.13 to github ci --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 981f49e0c..dfebe5bdc 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,7 +7,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.9", "3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12", "3.13"] numpy: [null, "numpy>=1.23,<2.0.0", "numpy>=2.0.0rc1"] uncertainties: [null, "uncertainties==3.1.6", "uncertainties>=3.1.6,<4.0.0"] extras: [null] From 82801b3aa39528c62d20dbb834b51de42df9e03d Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Thu, 7 Nov 2024 13:21:53 -0300 Subject: [PATCH 16/18] Preparing for release 0.24.3 --- CHANGES | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index de1c3bccb..11c5e4372 100644 --- a/CHANGES +++ b/CHANGES @@ -1,8 +1,20 @@ Pint Changelog ============== -0.25 (unreleased) ------------------ +0.24.3 (2024-07-28) +------------------- + +- add error for prefixed non multi units (#1998) +- build: typing_extensions version +- build: switch from appdirs to platformdirs +- fix GenericPlainRegistry getattr type (#2045) +- Replace references to the deprecated `UnitRegistry.default_format` (#2058) +- fix: upgrade to flexparser>=0.4, exceptions are no longer dataclasses. + (required for Python 3.13) + + +0.24.2 (2024-07-28) +------------------- - Fix the default behaviour for pint-convert (cli) for importing uncertainties package (PR #2032, Issue #2016) - Added mu and mc as alternatives for SI micro prefix From b6a6f68faf55bc4635c1cc1bcd567858ce8c418d Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Thu, 7 Nov 2024 13:25:04 -0300 Subject: [PATCH 17/18] Preparing for release 0.24.4 --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 11c5e4372..d4baea170 100644 --- a/CHANGES +++ b/CHANGES @@ -1,7 +1,7 @@ Pint Changelog ============== -0.24.3 (2024-07-28) +0.24.4 (2024-11-07) ------------------- - add error for prefixed non multi units (#1998) From 861953eaa9d301e25c8135a61be37e01a9b00fad Mon Sep 17 00:00:00 2001 From: Hernan Grecco Date: Thu, 7 Nov 2024 13:26:43 -0300 Subject: [PATCH 18/18] Back to development: 0.25 --- CHANGES | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES b/CHANGES index d4baea170..8b2fe9ec8 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,12 @@ Pint Changelog ============== +0.25.0 (unreleased) +------------------- + +- Nothing changed yet + + 0.24.4 (2024-11-07) -------------------