From 1f78c5e88c773052bf32322ff61c8aceb44a8674 Mon Sep 17 00:00:00 2001 From: andrewgsavage Date: Fri, 31 May 2024 19:54:31 +0100 Subject: [PATCH 01/12] changes (#2002) --- CHANGES | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGES b/CHANGES index 8243e3471..26a1dfb9b 100644 --- a/CHANGES +++ b/CHANGES @@ -9,6 +9,8 @@ Pint Changelog - NumPy 2.0 support (PR #1985, #1971) - Implement numpy roll (Related to issue #981) +- Implement numpy correlate + (PR #1990) - Add `dim_sort` function to _formatter_helpers. - Add `dim_order` and `default_sort_func` properties to FullFormatter. (PR #1926, fixes Issue #1841) @@ -18,6 +20,7 @@ Pint Changelog array resulting in incorrect units. (PR #1677) - Fix LaTeX siuntix formatting when using non_int_type=decimal.Decimal. + (PR #1977) - Added refractive index units. (PR #1816) - Fix converting to offset units of higher dimension e.g. gauge pressure From 858f59ce04cd84111a15c55f25c6f964da0fd72d Mon Sep 17 00:00:00 2001 From: andrewgsavage Date: Sat, 1 Jun 2024 18:19:05 +0100 Subject: [PATCH 02/12] fix readme duplicate target (#2004) --- README.rst | 1 - 1 file changed, 1 deletion(-) diff --git a/README.rst b/README.rst index a839fcdd7..3c16a4541 100644 --- a/README.rst +++ b/README.rst @@ -3,7 +3,6 @@ :alt: Latest Version .. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json - :target: https://github.com/python/black :target: https://github.com/astral-sh/ruff :alt: Ruff From 7b47d6b7b0f7655efca810a90f2781c0d1cc7fb9 Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 7 Jun 2024 20:01:57 +0100 Subject: [PATCH 03/12] Preparing for release 0.24 --- CHANGES | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGES b/CHANGES index 26a1dfb9b..e848fd127 100644 --- a/CHANGES +++ b/CHANGES @@ -1,7 +1,7 @@ Pint Changelog ============== -0.24 (unreleased) +0.24 (2024-06-07) ----------------- - Fix detection of invalid conversion between offset and delta units. (PR #1905) From a472c2634622622b51e96d174b811e5b86d2aa1a Mon Sep 17 00:00:00 2001 From: Andrew Date: Fri, 7 Jun 2024 20:02:57 +0100 Subject: [PATCH 04/12] Back to development: 0.25 --- CHANGES | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/CHANGES b/CHANGES index e848fd127..e3a1b7ad0 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,12 @@ Pint Changelog ============== +0.25 (unreleased) +----------------- + +Nothing added yet. + + 0.24 (2024-06-07) ----------------- From 5f6773330a10cf826a73cd7f1147234344191b62 Mon Sep 17 00:00:00 2001 From: Ben Elliston Date: Wed, 12 Jun 2024 06:29:33 +1000 Subject: [PATCH 05/12] docs/ecosystem.rst: Add NEMO. (#2010) --- docs/ecosystem.rst | 1 + 1 file changed, 1 insertion(+) diff --git a/docs/ecosystem.rst b/docs/ecosystem.rst index 751c49726..c83c52f49 100644 --- a/docs/ecosystem.rst +++ b/docs/ecosystem.rst @@ -21,3 +21,4 @@ Packages using pint: - `thermo `_ Thermodynamic equilibrium calculations - `Taurus `_ Control system UI creation - `InstrumentKit `_ Interacting with laboratory equipment over various buses. +- `NEMO `_ Electricity production cost model From 32ccd205095c42bf07182b73ea97eecdf1feba96 Mon Sep 17 00:00:00 2001 From: Pascal Bourgault Date: Thu, 13 Jun 2024 02:33:15 -0400 Subject: [PATCH 06/12] Fix custom formatters needing registry (#2011) * Fix custom formatters needing registry * add a doc note --- CHANGES | 2 +- docs/user/formatting.rst | 3 ++- pint/delegates/formatter/_to_register.py | 2 ++ pint/delegates/formatter/full.py | 12 +++++++++--- pint/testsuite/test_formatting.py | 2 ++ 5 files changed, 16 insertions(+), 5 deletions(-) diff --git a/CHANGES b/CHANGES index e3a1b7ad0..8e59b4803 100644 --- a/CHANGES +++ b/CHANGES @@ -4,7 +4,7 @@ Pint Changelog 0.25 (unreleased) ----------------- -Nothing added yet. +- Fix custom formatter needing the registry object. (PR #2011) 0.24 (2024-06-07) diff --git a/docs/user/formatting.rst b/docs/user/formatting.rst index d45fc1e13..fbf2fae42 100644 --- a/docs/user/formatting.rst +++ b/docs/user/formatting.rst @@ -98,7 +98,8 @@ formats: '2.3e-06 kilogram ** -1 * meter ** 3 * second ** -2' where ``unit`` is a :py:class:`dict` subclass containing the unit names and -their exponents. +their exponents, ``registry`` is the current instance of :py:class:``UnitRegistry`` and +``options`` is not yet implemented. You can choose to replace the complete formatter. Briefly, the formatter if an object with the following methods: `format_magnitude`, `format_unit`, `format_quantity`, `format_uncertainty`, diff --git a/pint/delegates/formatter/_to_register.py b/pint/delegates/formatter/_to_register.py index 0f8f46788..697973716 100644 --- a/pint/delegates/formatter/_to_register.py +++ b/pint/delegates/formatter/_to_register.py @@ -61,6 +61,8 @@ def wrapper(func: Callable[[PlainUnit, UnitRegistry], str]): raise ValueError(f"format {name!r} already exists") # or warn instead class NewFormatter(BaseFormatter): + spec = name + def format_magnitude( self, magnitude: Magnitude, diff --git a/pint/delegates/formatter/full.py b/pint/delegates/formatter/full.py index e6d0eee47..adc6f6c83 100644 --- a/pint/delegates/formatter/full.py +++ b/pint/delegates/formatter/full.py @@ -103,11 +103,17 @@ def get_formatter(self, spec: str): return v try: - return REGISTERED_FORMATTERS[spec] + orphan_fmt = REGISTERED_FORMATTERS[spec] except KeyError: - pass + return self._formatters["D"] - return self._formatters["D"] + try: + fmt = orphan_fmt.__class__(self._registry) + spec = getattr(fmt, "spec", spec) + self._formatters[spec] = fmt + return fmt + except Exception: + return orphan_fmt def format_magnitude( self, magnitude: Magnitude, mspec: str = "", **babel_kwds: Unpack[BabelKwds] diff --git a/pint/testsuite/test_formatting.py b/pint/testsuite/test_formatting.py index e74c09c50..d8f10715b 100644 --- a/pint/testsuite/test_formatting.py +++ b/pint/testsuite/test_formatting.py @@ -59,6 +59,8 @@ def test_split_format(format, default, flag, expected): def test_register_unit_format(func_registry): @fmt.register_unit_format("custom") def format_custom(unit, registry, **options): + # Ensure the registry is correct.. + registry.Unit(unit) return "" quantity = 1.0 * func_registry.meter From 4c25f321e09b05c311b70c5c8fbdc5f021d95d6a Mon Sep 17 00:00:00 2001 From: andrewgsavage Date: Fri, 21 Jun 2024 14:24:44 +0100 Subject: [PATCH 07/12] support 3.9 (#2019) changed matplotlib test to use a build that has a pypi wheel available for python3.10 changed TypeAlias import for 3.9 compat changed min versions --- .github/workflows/ci.yml | 8 ++++---- CHANGES | 4 ++-- docs/user/log_units.rst | 6 +++--- pint/compat.py | 6 +++++- pint/delegates/formatter/_compound_unit_helpers.py | 3 +-- pyproject.toml | 3 ++- 6 files changed, 17 insertions(+), 13 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 0797decb5..24f001b43 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -7,18 +7,18 @@ jobs: strategy: fail-fast: false matrix: - python-version: ["3.10", "3.11", "3.12"] + python-version: ["3.9", "3.10", "3.11", "3.12"] 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] include: - python-version: "3.10" # Minimal versions - numpy: "numpy" - extras: matplotlib==2.2.5 + numpy: "numpy>=1.23,<2.0.0" + extras: matplotlib==3.5.3 - python-version: "3.10" numpy: "numpy" uncertainties: "uncertainties" - extras: "sparse xarray netCDF4 dask[complete]==2023.4.0 graphviz babel==2.8 mip>=1.13" + extras: "sparse xarray netCDF4 dask[complete]==2024.5.1 graphviz babel==2.8 mip>=1.13" runs-on: ubuntu-latest env: diff --git a/CHANGES b/CHANGES index 8e59b4803..588e7f5b7 100644 --- a/CHANGES +++ b/CHANGES @@ -1,11 +1,11 @@ Pint Changelog ============== -0.25 (unreleased) +0.24.1 (unreleased) ----------------- - Fix custom formatter needing the registry object. (PR #2011) - +- Support python 3.9 following difficulties installing with NumPy 2. (PR #2019) 0.24 (2024-06-07) ----------------- diff --git a/docs/user/log_units.rst b/docs/user/log_units.rst index 03e007914..096397350 100644 --- a/docs/user/log_units.rst +++ b/docs/user/log_units.rst @@ -111,16 +111,16 @@ will not work: .. doctest:: >>> -161.0 * ureg('dBm/Hz') == (-161.0 * ureg.dBm / ureg.Hz) - False + np.False_ But this will: .. doctest:: >>> ureg('-161.0 dBm/Hz') == (-161.0 * ureg.dBm / ureg.Hz) - True + np.True_ >>> Q_(-161.0, 'dBm') / ureg.Hz == (-161.0 * ureg.dBm / ureg.Hz) - True + np.True_ To begin using this feature while avoiding problems, define logarithmic units as single-unit quantities and convert them to their base units as quickly as diff --git a/pint/compat.py b/pint/compat.py index 277662410..32ad04afb 100644 --- a/pint/compat.py +++ b/pint/compat.py @@ -19,9 +19,13 @@ from typing import ( Any, NoReturn, - TypeAlias, # noqa ) +if sys.version_info >= (3, 10): + from typing import TypeAlias # noqa +else: + from typing_extensions import TypeAlias # noqa + if sys.version_info >= (3, 11): from typing import Self # noqa else: diff --git a/pint/delegates/formatter/_compound_unit_helpers.py b/pint/delegates/formatter/_compound_unit_helpers.py index 89bda87a2..7631a94ef 100644 --- a/pint/delegates/formatter/_compound_unit_helpers.py +++ b/pint/delegates/formatter/_compound_unit_helpers.py @@ -20,12 +20,11 @@ TYPE_CHECKING, Any, Literal, - TypeAlias, TypedDict, TypeVar, ) -from ...compat import babel_parse +from ...compat import TypeAlias, babel_parse from ...util import UnitsContainer T = TypeVar("T") diff --git a/pyproject.toml b/pyproject.toml index a376bd6a4..9f29f8f92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,11 +22,12 @@ classifiers = [ "Programming Language :: Python", "Topic :: Scientific/Engineering", "Topic :: Software Development :: Libraries", + "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", "Programming Language :: Python :: 3.12", ] -requires-python = ">=3.10" +requires-python = ">=3.9" dynamic = ["version", "dependencies"] [tool.setuptools.package-data] From 2493241f0d26f3357bc3498a617297aafeb460e0 Mon Sep 17 00:00:00 2001 From: andrewgsavage Date: Fri, 21 Jun 2024 14:42:51 +0100 Subject: [PATCH 08/12] fix default format dimensionless (#2012) --- CHANGES | 1 + .../formatter/_compound_unit_helpers.py | 6 ++++++ pint/delegates/formatter/_format_helpers.py | 2 ++ pint/testsuite/test_issues.py | 18 ++++++++++++++++++ 4 files changed, 27 insertions(+) diff --git a/CHANGES b/CHANGES index 588e7f5b7..52bdf1a8a 100644 --- a/CHANGES +++ b/CHANGES @@ -6,6 +6,7 @@ Pint Changelog - Fix custom formatter needing the registry object. (PR #2011) - Support python 3.9 following difficulties installing with NumPy 2. (PR #2019) +- Fix default formatting of dimensionless unit issue. (PR #2012) 0.24 (2024-06-07) ----------------- diff --git a/pint/delegates/formatter/_compound_unit_helpers.py b/pint/delegates/formatter/_compound_unit_helpers.py index 7631a94ef..5757b46fa 100644 --- a/pint/delegates/formatter/_compound_unit_helpers.py +++ b/pint/delegates/formatter/_compound_unit_helpers.py @@ -256,6 +256,12 @@ def prepare_compount_unit( # out: unit_name, unit_exponent + if len(out) == 0: + if "~" in spec: + return ([], []) + else: + return ([("dimensionless", 1)], []) + if "~" in spec: if registry is None: raise ValueError( diff --git a/pint/delegates/formatter/_format_helpers.py b/pint/delegates/formatter/_format_helpers.py index 995159e65..8a2f37a59 100644 --- a/pint/delegates/formatter/_format_helpers.py +++ b/pint/delegates/formatter/_format_helpers.py @@ -131,6 +131,8 @@ def join_mu(joint_fstring: str, mstr: str, ustr: str) -> str: This avoids that `3 and `1 / m` becomes `3 1 / m` """ + if ustr == "": + return mstr if ustr.startswith("1 / "): return joint_fstring.format(mstr, ustr[2:]) return joint_fstring.format(mstr, ustr) diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py index 2a0b7edf6..2fcc1f22c 100644 --- a/pint/testsuite/test_issues.py +++ b/pint/testsuite/test_issues.py @@ -1255,3 +1255,21 @@ def test_issue1949(registry_empty): def test_issue1772(given, expected): ureg = UnitRegistry(non_int_type=decimal.Decimal) assert f"{ureg(given):Lx}" == expected + + +def test_issue2007(): + ureg = UnitRegistry() + q = ureg.Quantity(1, "") + assert f"{q:P}" == "1 dimensionless" + assert f"{q:C}" == "1 dimensionless" + assert f"{q:D}" == "1 dimensionless" + assert f"{q:H}" == "1 dimensionless" + + assert f"{q:L}" == "1\\ \\mathrm{dimensionless}" + # L returned '1\\ dimensionless' in pint 0.23 + + assert f"{q:Lx}" == "\\SI[]{1}{}" + assert f"{q:~P}" == "1" + assert f"{q:~C}" == "1" + assert f"{q:~D}" == "1" + assert f"{q:~H}" == "1" From 5f75bdcab61af9f680f0c8a76b9c76ac6bbd4558 Mon Sep 17 00:00:00 2001 From: andrewgsavage Date: Fri, 21 Jun 2024 16:35:29 +0100 Subject: [PATCH 09/12] fix Custom formatters not working with modifiers (#2021) --- CHANGES | 1 + pint/delegates/formatter/full.py | 8 +++++--- pint/testsuite/test_issues.py | 32 +++++++++++++++++++++++++++++++- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/CHANGES b/CHANGES index 52bdf1a8a..11df3542b 100644 --- a/CHANGES +++ b/CHANGES @@ -7,6 +7,7 @@ Pint Changelog - Fix custom formatter needing the registry object. (PR #2011) - Support python 3.9 following difficulties installing with NumPy 2. (PR #2019) - Fix default formatting of dimensionless unit issue. (PR #2012) +- Fix bug preventing custom formatters with modifiers working. (PR #2021) 0.24 (2024-06-07) ----------------- diff --git a/pint/delegates/formatter/full.py b/pint/delegates/formatter/full.py index adc6f6c83..d5de43326 100644 --- a/pint/delegates/formatter/full.py +++ b/pint/delegates/formatter/full.py @@ -102,9 +102,11 @@ def get_formatter(self, spec: str): if k in spec: return v - try: - orphan_fmt = REGISTERED_FORMATTERS[spec] - except KeyError: + for k, v in REGISTERED_FORMATTERS.items(): + if k in spec: + orphan_fmt = REGISTERED_FORMATTERS[k] + break + else: return self._formatters["D"] try: diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py index 2fcc1f22c..3f3d69e67 100644 --- a/pint/testsuite/test_issues.py +++ b/pint/testsuite/test_issues.py @@ -7,7 +7,12 @@ import pytest -from pint import Context, DimensionalityError, UnitRegistry, get_application_registry +from pint import ( + Context, + DimensionalityError, + UnitRegistry, + get_application_registry, +) from pint.compat import np from pint.delegates.formatter._compound_unit_helpers import sort_by_dimensionality from pint.facets.plain.unit import UnitsContainer @@ -1257,6 +1262,31 @@ def test_issue1772(given, expected): assert f"{ureg(given):Lx}" == expected +def test_issue2017(): + ureg = UnitRegistry() + + from pint import formatting as fmt + + @fmt.register_unit_format("test") + def _test_format(unit, registry, **options): + print("format called") + proc = {u.replace("µ", "u"): e for u, e in unit.items()} + return fmt.formatter( + proc.items(), + as_ratio=True, + single_denominator=False, + product_fmt="*", + division_fmt="/", + power_fmt="{}{}", + parentheses_fmt="({})", + **options, + ) + + base_unit = ureg.microsecond + assert f"{base_unit:~test}" == "us" + assert f"{base_unit:test}" == "microsecond" + + def test_issue2007(): ureg = UnitRegistry() q = ureg.Quantity(1, "") From 88e2e8014c2e0331768e14d584a7e038599a9c50 Mon Sep 17 00:00:00 2001 From: andrewgsavage Date: Fri, 21 Jun 2024 20:00:42 +0100 Subject: [PATCH 10/12] fix babel tests issue (#2020) --- .github/workflows/ci.yml | 4 ++++ pint/delegates/formatter/_compound_unit_helpers.py | 10 +++++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 24f001b43..981f49e0c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -19,6 +19,10 @@ jobs: numpy: "numpy" uncertainties: "uncertainties" extras: "sparse xarray netCDF4 dask[complete]==2024.5.1 graphviz babel==2.8 mip>=1.13" + - python-version: "3.10" + numpy: "numpy==1.26.1" + uncertainties: null + extras: "babel==2.15 matplotlib==3.9.0" runs-on: ubuntu-latest env: diff --git a/pint/delegates/formatter/_compound_unit_helpers.py b/pint/delegates/formatter/_compound_unit_helpers.py index 5757b46fa..06a8ac2d3 100644 --- a/pint/delegates/formatter/_compound_unit_helpers.py +++ b/pint/delegates/formatter/_compound_unit_helpers.py @@ -82,11 +82,19 @@ def localize_per( locale = babel_parse(locale) patterns = locale._data["compound_unit_patterns"].get("per", None) + if patterns is None: + return default or "{}/{}" + patterns = patterns.get(length, None) if patterns is None: return default or "{}/{}" - return patterns.get(length, default or "{}/{}") + # babel 2.8 + if isinstance(patterns, str): + return patterns + + # babe; 2.15 + return patterns.get("compound", default or "{}/{}") @functools.lru_cache From 9014d140cb77146accff4613904d90f5a5644826 Mon Sep 17 00:00:00 2001 From: andrewgsavage Date: Sat, 22 Jun 2024 00:09:43 +0100 Subject: [PATCH 11/12] skip babel tests if locales aren't installed (#2022) --- pint/testsuite/helpers.py | 23 ++++++++++++++++++++--- pint/testsuite/test_babel.py | 8 ++++---- pint/testsuite/test_issues.py | 2 +- 3 files changed, 25 insertions(+), 8 deletions(-) diff --git a/pint/testsuite/helpers.py b/pint/testsuite/helpers.py index c9106b75a..d317e0755 100644 --- a/pint/testsuite/helpers.py +++ b/pint/testsuite/helpers.py @@ -128,9 +128,26 @@ def requires_numpy_at_least(version): ) -requires_babel = pytest.mark.skipif( - not HAS_BABEL, reason="Requires Babel with units support" -) +def requires_babel(tested_locales=[]): + if not HAS_BABEL: + return pytest.mark.skip("Requires Babel with units support") + + import locale + + default_locale = locale.getlocale(locale.LC_NUMERIC) + locales_unavailable = False + try: + for loc in tested_locales: + locale.setlocale(locale.LC_NUMERIC, loc) + except locale.Error: + locales_unavailable = True + locale.setlocale(locale.LC_NUMERIC, default_locale) + + return pytest.mark.skipif( + locales_unavailable, reason="Tested locales not available." + ) + + requires_not_babel = pytest.mark.skipif( HAS_BABEL, reason="Requires Babel not to be installed" ) diff --git a/pint/testsuite/test_babel.py b/pint/testsuite/test_babel.py index 2dd66d58d..9adcb04a9 100644 --- a/pint/testsuite/test_babel.py +++ b/pint/testsuite/test_babel.py @@ -16,7 +16,7 @@ def test_no_babel(func_registry): distance.format_babel(locale="fr_FR", length="long") -@helpers.requires_babel() +@helpers.requires_babel(["fr_FR", "ro_RO"]) def test_format(func_registry): ureg = func_registry dirname = os.path.dirname(__file__) @@ -36,7 +36,7 @@ def test_format(func_registry): assert mks.format_babel(locale="fr_FR") == "métrique" -@helpers.requires_babel() +@helpers.requires_babel(["fr_FR", "ro_RO"]) def test_registry_locale(): ureg = UnitRegistry(fmt_locale="fr_FR") dirname = os.path.dirname(__file__) @@ -60,7 +60,7 @@ def test_registry_locale(): assert mks.format_babel(locale="fr_FR") == "métrique" -@helpers.requires_babel() +@helpers.requires_babel(["fr_FR"]) def test_unit_format_babel(): ureg = UnitRegistry(fmt_locale="fr_FR") volume = ureg.Unit("ml") @@ -85,7 +85,7 @@ def test_no_registry_locale(func_registry): distance.format_babel() -@helpers.requires_babel() +@helpers.requires_babel(["fr_FR"]) def test_str(func_registry): ureg = func_registry d = 24.1 * ureg.meter diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py index 3f3d69e67..97eca3cde 100644 --- a/pint/testsuite/test_issues.py +++ b/pint/testsuite/test_issues.py @@ -913,7 +913,7 @@ def test_issue1674(self, module_registry): arr_of_q * q_arr, np.array([Q_(2, "m^2"), Q_(8, "m s")], dtype="object") ) - @helpers.requires_babel() + @helpers.requires_babel(["es_ES"]) def test_issue_1400(self, sess_registry): q1 = 3.1 * sess_registry.W q2 = 3.1 * sess_registry.W / sess_registry.cm From 62046f0518befbf870836fe3620bf0398d75999d Mon Sep 17 00:00:00 2001 From: andrewgsavage Date: Sat, 22 Jun 2024 10:45:18 +0100 Subject: [PATCH 12/12] add note on symbols to currency docs (#2023) --- docs/advanced/currencies.rst | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/docs/advanced/currencies.rst b/docs/advanced/currencies.rst index 26b66b531..addc94785 100644 --- a/docs/advanced/currencies.rst +++ b/docs/advanced/currencies.rst @@ -84,3 +84,16 @@ currency on its own dimension, and then implement transformations:: More sophisticated formulas, e.g. dealing with flat fees and thresholds, can be implemented with arbitrary python code by programmatically defining a context (see :ref:`contexts`). + +Currency Symbols +---------------- + +Many common currency symbols are not supported by the pint parser. A preprocessor can be used as a workaround: + +.. doctest:: + + >>> import pint + >>> ureg = pint.UnitRegistry(preprocessors = [lambda s: s.replace("€", "EUR")]) + >>> ureg.define("euro = [currency] = € = EUR") + >>> print(ureg.Quantity("1 €")) + 1 euro