From b1b941b3195ac49849ccb461b61a0395431be2c2 Mon Sep 17 00:00:00 2001
From: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
Date: Tue, 23 Jan 2024 17:17:30 +1300
Subject: [PATCH 1/7] Reimplementation of sorting units by dimensions
Adapt PR#1841 to the new Pint formatter.
Signed-off-by: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
---
pint/delegates/formatter/_format_helpers.py | 61 ++++++++++++++++++++-
pint/delegates/formatter/full.py | 16 +++++-
pint/delegates/formatter/html.py | 1 +
pint/delegates/formatter/latex.py | 4 ++
pint/delegates/formatter/plain.py | 1 +
pint/testsuite/test_issues.py | 49 +++++++++++++++++
6 files changed, 128 insertions(+), 4 deletions(-)
diff --git a/pint/delegates/formatter/_format_helpers.py b/pint/delegates/formatter/_format_helpers.py
index 2ed4ba985..868663b99 100644
--- a/pint/delegates/formatter/_format_helpers.py
+++ b/pint/delegates/formatter/_format_helpers.py
@@ -268,6 +268,61 @@ def format_compound_unit(
return out
+def dim_sort(items: Iterable[tuple[str, Number]], registry: UnitRegistry):
+ """Sort a list of units by dimensional order (from `registry.formatter.dim_order`).
+
+ Parameters
+ ----------
+ items : tuple
+ a list of tuples containing (unit names, exponent values).
+ registry : UnitRegistry
+ the registry to use for looking up the dimensions of each unit.
+
+ Returns
+ -------
+ list
+ the list of units sorted by most significant dimension first.
+
+ Raises
+ ------
+ KeyError
+ If unit cannot be found in the registry.
+ """
+
+ if registry is None:
+ return items
+ ret_dict = dict()
+ dim_order = registry.formatter.dim_order
+ for unit_name, unit_exponent in items:
+ cname = registry.get_name(unit_name)
+ if not cname:
+ continue
+ cname_dims = registry.get_dimensionality(cname)
+ if len(cname_dims) == 0:
+ cname_dims = {"[]": None}
+ dim_types = iter(dim_order)
+ while True:
+ try:
+ dim = next(dim_types)
+ if dim in cname_dims:
+ if dim not in ret_dict:
+ ret_dict[dim] = list()
+ ret_dict[dim].append(
+ (
+ unit_name,
+ unit_exponent,
+ )
+ )
+ break
+ except StopIteration:
+ raise KeyError(
+ f"Unit {unit_name} (aka {cname}) has no recognized dimensions"
+ )
+
+ ret = sum([ret_dict[dim] for dim in dim_order if dim in ret_dict], [])
+ return ret
+
+
def formatter(
items: Iterable[tuple[str, Number]],
as_ratio: bool = True,
@@ -309,6 +364,8 @@ def formatter(
(Default value = lambda x: f"{x:n}")
sort : bool, optional
True to sort the formatted units alphabetically (Default value = True)
+ sort_func : callable
+ If not None, `sort_func` returns its sorting of the formatted units
Returns
-------
@@ -320,14 +377,14 @@ def formatter(
if sort is False:
warn(
"The boolean `sort` argument is deprecated. "
- "Use `sort_fun` to specify the sorting function (default=sorted) "
+ "Use `sort_func` to specify the sorting function (default=sorted) "
"or None to keep units in the original order."
)
sort_func = None
elif sort is True:
warn(
"The boolean `sort` argument is deprecated. "
- "Use `sort_fun` to specify the sorting function (default=sorted) "
+ "Use `sort_func` to specify the sorting function (default=sorted) "
"or None to keep units in the original order."
)
sort_func = sorted
diff --git a/pint/delegates/formatter/full.py b/pint/delegates/formatter/full.py
index fae26d524..a8dc1ec56 100644
--- a/pint/delegates/formatter/full.py
+++ b/pint/delegates/formatter/full.py
@@ -11,9 +11,9 @@
from __future__ import annotations
-from typing import TYPE_CHECKING, Literal, Optional, Any
+from typing import TYPE_CHECKING, Callable, Literal, Optional, Any
import locale
-from ...compat import babel_parse, Unpack
+from ...compat import babel_parse, Number, Unpack
from ...util import iterable
from ..._typing import Magnitude
@@ -38,6 +38,18 @@ class FullFormatter:
_formatters: dict[str, Any] = {}
default_format: str = ""
+ # TODO: This can be over-riden by the registry definitions file
+ dim_order = (
+ "[substance]",
+ "[mass]",
+ "[current]",
+ "[luminosity]",
+ "[length]",
+ "[]",
+ "[time]",
+ "[temperature]",
+ )
+ default_sort_func: Optional[Callable[Iterable[tuple[str, Number]]], Iterable[tuple[str, Number]]] = None
locale: Optional[Locale] = None
babel_length: Literal["short", "long", "narrow"] = "long"
diff --git a/pint/delegates/formatter/html.py b/pint/delegates/formatter/html.py
index 3dc14330c..ea88fb13b 100644
--- a/pint/delegates/formatter/html.py
+++ b/pint/delegates/formatter/html.py
@@ -87,6 +87,7 @@ def format_unit(
division_fmt=r"{}/{}",
power_fmt=r"{}{}",
parentheses_fmt=r"({})",
+ sort_func=lambda x: unit._REGISTRY.formatter.default_sort_func(x, unit._REGISTRY),
)
def format_quantity(
diff --git a/pint/delegates/formatter/latex.py b/pint/delegates/formatter/latex.py
index aacf8cdf5..cf2b57848 100644
--- a/pint/delegates/formatter/latex.py
+++ b/pint/delegates/formatter/latex.py
@@ -173,6 +173,9 @@ def format_unit(
self, unit: PlainUnit, uspec: str = "", **babel_kwds: Unpack[BabelKwds]
) -> str:
units = format_compound_unit(unit, uspec, **babel_kwds)
+ if unit._REGISTRY.formatter.default_sort_func:
+ # Lift the sorting by dimensions b/c the preprocessed units are unrecognizeable
+ units = unit._REGISTRY.formatter.default_sort_func(units, unit._REGISTRY)
preprocessed = {rf"\mathrm{{{latex_escape(u)}}}": p for u, p in units}
formatted = formatter(
@@ -183,6 +186,7 @@ def format_unit(
division_fmt=r"\frac[{}][{}]",
power_fmt="{}^[{}]",
parentheses_fmt=r"\left({}\right)",
+ sort_func=None,
)
return formatted.replace("[", "{").replace("]", "}")
diff --git a/pint/delegates/formatter/plain.py b/pint/delegates/formatter/plain.py
index 4b9616631..01c352bf9 100644
--- a/pint/delegates/formatter/plain.py
+++ b/pint/delegates/formatter/plain.py
@@ -269,6 +269,7 @@ def format_unit(
power_fmt="{}{}",
parentheses_fmt="({})",
exp_call=pretty_fmt_exponent,
+ sort_func=lambda x: unit._REGISTRY.formatter.default_sort_func(x, unit._REGISTRY),
)
def format_quantity(
diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py
index 3db01fb4e..167d6bb4d 100644
--- a/pint/testsuite/test_issues.py
+++ b/pint/testsuite/test_issues.py
@@ -1155,3 +1155,52 @@ def test_issues_1505():
assert isinstance(
ur.Quantity("m/s").magnitude, decimal.Decimal
) # unexpected fail (magnitude should be a decimal)
+
+
+def test_issues_1841(subtests):
+ import pint
+ from pint.delegates.formatter._format_helpers import dim_sort
+
+ ur = UnitRegistry()
+ ur.formatter.default_sort_func = dim_sort
+
+ for x, spec, result in (
+ (ur.Unit(UnitsContainer(hour=1,watt=1)), "P~", "W·h"),
+ (ur.Unit(UnitsContainer(ampere=1,volt=1)), "P~", "V·A"),
+ (ur.Unit(UnitsContainer(meter=1,newton=1)), "P~", "N·m"),
+ ):
+ with subtests.test(spec):
+ ur.default_format = spec
+ breakpoint()
+ assert f"{x}" == result, f"Failed for {spec}, {result}"
+
+
+@pytest.mark.xfail
+def test_issues_1841_xfail():
+ import pint
+ from pint import formatting as fmt
+ import pint.delegates.formatter._format_helpers
+ from pint.delegates.formatter._format_helpers import dim_sort
+
+ # sets compact display mode by default
+ ur = UnitRegistry()
+ ur.default_format = "~P"
+ ur.formatter.default_sort_func = dim_sort
+
+ q = ur.Quantity("2*pi radian * hour")
+
+ # Note that `radian` (and `bit` and `count`) are treated as dimensionless.
+ # And note that dimensionless quantities are stripped by this process,
+ # leading to errorneous output. Suggestions?
+ breakpoint()
+ assert (
+ fmt.format_unit(q.u._units, spec="", registry=ur, sort_dims=True)
+ == "radian * hour"
+ )
+ assert (
+ fmt.format_unit(q.u._units, spec="", registry=ur, sort_dims=False)
+ == "hour * radian"
+ )
+
+ # this prints "2*pi hour * radian", not "2*pi radian * hour" unless sort_dims is True
+ # print(q)
From f6fbcc0fb428cf479f24aa5e9b010b05bf8eb3e8 Mon Sep 17 00:00:00 2001
From: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
Date: Tue, 23 Jan 2024 17:25:06 +1300
Subject: [PATCH 2/7] Fix up pre-commit formatting
Signed-off-by: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
---
CHANGES | 4 +++-
pint/delegates/formatter/_format_helpers.py | 2 +-
pint/delegates/formatter/full.py | 6 ++++--
pint/delegates/formatter/html.py | 4 +++-
pint/delegates/formatter/plain.py | 4 +++-
pint/testsuite/test_issues.py | 9 +++------
6 files changed, 17 insertions(+), 12 deletions(-)
diff --git a/CHANGES b/CHANGES
index 6b1d0484e..c65d1f1d0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -4,7 +4,9 @@ Pint Changelog
0.24 (unreleased)
-----------------
-- Nothing changed yet.
+- Add `dim_sort` function to _formatter_helpers.
+- Add `dim_order` and `default_sort_func` properties to FullFormatter.
+ (PR #????, fixes Issue #1841)
0.23 (2023-12-08)
diff --git a/pint/delegates/formatter/_format_helpers.py b/pint/delegates/formatter/_format_helpers.py
index 868663b99..a736c8d5f 100644
--- a/pint/delegates/formatter/_format_helpers.py
+++ b/pint/delegates/formatter/_format_helpers.py
@@ -288,7 +288,7 @@ def dim_sort(items: Iterable[tuple[str, Number]], registry: UnitRegistry):
KeyError
If unit cannot be found in the registry.
"""
-
+
if registry is None:
return items
ret_dict = dict()
diff --git a/pint/delegates/formatter/full.py b/pint/delegates/formatter/full.py
index a8dc1ec56..5864809b3 100644
--- a/pint/delegates/formatter/full.py
+++ b/pint/delegates/formatter/full.py
@@ -11,7 +11,7 @@
from __future__ import annotations
-from typing import TYPE_CHECKING, Callable, Literal, Optional, Any
+from typing import TYPE_CHECKING, Callable, Iterable, Literal, Optional, Any
import locale
from ...compat import babel_parse, Number, Unpack
from ...util import iterable
@@ -49,7 +49,9 @@ class FullFormatter:
"[time]",
"[temperature]",
)
- default_sort_func: Optional[Callable[Iterable[tuple[str, Number]]], Iterable[tuple[str, Number]]] = None
+ default_sort_func: Optional[
+ Callable[Iterable[tuple[str, Number]]], Iterable[tuple[str, Number]]
+ ] = None
locale: Optional[Locale] = None
babel_length: Literal["short", "long", "narrow"] = "long"
diff --git a/pint/delegates/formatter/html.py b/pint/delegates/formatter/html.py
index ea88fb13b..cc7d9ad07 100644
--- a/pint/delegates/formatter/html.py
+++ b/pint/delegates/formatter/html.py
@@ -87,7 +87,9 @@ def format_unit(
division_fmt=r"{}/{}",
power_fmt=r"{}{}",
parentheses_fmt=r"({})",
- sort_func=lambda x: unit._REGISTRY.formatter.default_sort_func(x, unit._REGISTRY),
+ sort_func=lambda x: unit._REGISTRY.formatter.default_sort_func(
+ x, unit._REGISTRY
+ ),
)
def format_quantity(
diff --git a/pint/delegates/formatter/plain.py b/pint/delegates/formatter/plain.py
index 01c352bf9..37150f9d2 100644
--- a/pint/delegates/formatter/plain.py
+++ b/pint/delegates/formatter/plain.py
@@ -269,7 +269,9 @@ def format_unit(
power_fmt="{}{}",
parentheses_fmt="({})",
exp_call=pretty_fmt_exponent,
- sort_func=lambda x: unit._REGISTRY.formatter.default_sort_func(x, unit._REGISTRY),
+ sort_func=lambda x: unit._REGISTRY.formatter.default_sort_func(
+ x, unit._REGISTRY
+ ),
)
def format_quantity(
diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py
index 167d6bb4d..7917b891a 100644
--- a/pint/testsuite/test_issues.py
+++ b/pint/testsuite/test_issues.py
@@ -1158,16 +1158,15 @@ def test_issues_1505():
def test_issues_1841(subtests):
- import pint
from pint.delegates.formatter._format_helpers import dim_sort
ur = UnitRegistry()
ur.formatter.default_sort_func = dim_sort
for x, spec, result in (
- (ur.Unit(UnitsContainer(hour=1,watt=1)), "P~", "W·h"),
- (ur.Unit(UnitsContainer(ampere=1,volt=1)), "P~", "V·A"),
- (ur.Unit(UnitsContainer(meter=1,newton=1)), "P~", "N·m"),
+ (ur.Unit(UnitsContainer(hour=1, watt=1)), "P~", "W·h"),
+ (ur.Unit(UnitsContainer(ampere=1, volt=1)), "P~", "V·A"),
+ (ur.Unit(UnitsContainer(meter=1, newton=1)), "P~", "N·m"),
):
with subtests.test(spec):
ur.default_format = spec
@@ -1177,9 +1176,7 @@ def test_issues_1841(subtests):
@pytest.mark.xfail
def test_issues_1841_xfail():
- import pint
from pint import formatting as fmt
- import pint.delegates.formatter._format_helpers
from pint.delegates.formatter._format_helpers import dim_sort
# sets compact display mode by default
From 65fd12c832654a32216deb0ac726e3854d2fa77d Mon Sep 17 00:00:00 2001
From: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
Date: Tue, 23 Jan 2024 17:25:58 +1300
Subject: [PATCH 3/7] Update CHANGES
Signed-off-by: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
---
CHANGES | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/CHANGES b/CHANGES
index c65d1f1d0..048765ec0 100644
--- a/CHANGES
+++ b/CHANGES
@@ -6,7 +6,7 @@ Pint Changelog
- Add `dim_sort` function to _formatter_helpers.
- Add `dim_order` and `default_sort_func` properties to FullFormatter.
- (PR #????, fixes Issue #1841)
+ (PR #1926, fixes Issue #1841)
0.23 (2023-12-08)
From 45515865cc446ea4c7107d9d9f3ef4b3f6ed99db Mon Sep 17 00:00:00 2001
From: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
Date: Tue, 23 Jan 2024 19:54:48 +1300
Subject: [PATCH 4/7] Update test_issues.py
Remove `breakpoint`s that should have been linted out by pre-commit.
Signed-off-by: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
---
pint/testsuite/test_issues.py | 2 --
1 file changed, 2 deletions(-)
diff --git a/pint/testsuite/test_issues.py b/pint/testsuite/test_issues.py
index 7917b891a..f23c1bb84 100644
--- a/pint/testsuite/test_issues.py
+++ b/pint/testsuite/test_issues.py
@@ -1170,7 +1170,6 @@ def test_issues_1841(subtests):
):
with subtests.test(spec):
ur.default_format = spec
- breakpoint()
assert f"{x}" == result, f"Failed for {spec}, {result}"
@@ -1189,7 +1188,6 @@ def test_issues_1841_xfail():
# Note that `radian` (and `bit` and `count`) are treated as dimensionless.
# And note that dimensionless quantities are stripped by this process,
# leading to errorneous output. Suggestions?
- breakpoint()
assert (
fmt.format_unit(q.u._units, spec="", registry=ur, sort_dims=True)
== "radian * hour"
From 7b9bc340b3db1ed49ea26d98fa89875efc3c8dde Mon Sep 17 00:00:00 2001
From: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
Date: Tue, 23 Jan 2024 21:02:23 +1300
Subject: [PATCH 5/7] Ensure called `default_sort_func` is not None
It would be easier to just default to `sorted` instead of `None`, but since `None` is an option, we have to test for it anyway.
Signed-off-by: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
---
pint/delegates/formatter/html.py | 10 +++++++---
pint/delegates/formatter/plain.py | 10 +++++++---
2 files changed, 14 insertions(+), 6 deletions(-)
diff --git a/pint/delegates/formatter/html.py b/pint/delegates/formatter/html.py
index cc7d9ad07..98329bcca 100644
--- a/pint/delegates/formatter/html.py
+++ b/pint/delegates/formatter/html.py
@@ -78,6 +78,12 @@ def format_unit(
self, unit: PlainUnit, uspec: str = "", **babel_kwds: Unpack[BabelKwds]
) -> str:
units = format_compound_unit(unit, uspec, **babel_kwds)
+ if unit._REGISTRY.formatter.default_sort_func is not None:
+ sort_func = lambda x: unit._REGISTRY.formatter.default_sort_func(
+ x, unit._REGISTRY
+ )
+ else:
+ sort_func = None
return formatter(
units,
@@ -87,9 +93,7 @@ def format_unit(
division_fmt=r"{}/{}",
power_fmt=r"{}{}",
parentheses_fmt=r"({})",
- sort_func=lambda x: unit._REGISTRY.formatter.default_sort_func(
- x, unit._REGISTRY
- ),
+ sort_func=sort_func,
)
def format_quantity(
diff --git a/pint/delegates/formatter/plain.py b/pint/delegates/formatter/plain.py
index 37150f9d2..850e2eab5 100644
--- a/pint/delegates/formatter/plain.py
+++ b/pint/delegates/formatter/plain.py
@@ -259,6 +259,12 @@ def format_unit(
self, unit: PlainUnit, uspec: str = "", **babel_kwds: Unpack[BabelKwds]
) -> str:
units = format_compound_unit(unit, uspec, **babel_kwds)
+ if unit._REGISTRY.formatter.default_sort_func is not None:
+ sort_func = lambda x: unit._REGISTRY.formatter.default_sort_func(
+ x, unit._REGISTRY
+ )
+ else:
+ sort_func = None
return formatter(
units,
@@ -269,9 +275,7 @@ def format_unit(
power_fmt="{}{}",
parentheses_fmt="({})",
exp_call=pretty_fmt_exponent,
- sort_func=lambda x: unit._REGISTRY.formatter.default_sort_func(
- x, unit._REGISTRY
- ),
+ sort_func=sort_func,
)
def format_quantity(
From a47b5e92d206ececae9e542b1c82a9fc061d3e83 Mon Sep 17 00:00:00 2001
From: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
Date: Tue, 23 Jan 2024 22:46:28 +1300
Subject: [PATCH 6/7] Fix default_sort_func
The default sort function needs to be able to handle a registry passed to it, so to make `sorted` the default behavior, we have to create a lambda that strips the registry parameter before calling `sorted`.
Signed-off-by: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
---
pint/delegates/formatter/full.py | 14 +++++++++++---
pint/delegates/formatter/html.py | 11 +++--------
pint/delegates/formatter/latex.py | 5 ++---
pint/delegates/formatter/plain.py | 11 +++--------
4 files changed, 19 insertions(+), 22 deletions(-)
diff --git a/pint/delegates/formatter/full.py b/pint/delegates/formatter/full.py
index 5864809b3..98f22fdb6 100644
--- a/pint/delegates/formatter/full.py
+++ b/pint/delegates/formatter/full.py
@@ -24,7 +24,12 @@
from ._to_register import REGISTERED_FORMATTERS
if TYPE_CHECKING:
- from ...facets.plain import PlainQuantity, PlainUnit, MagnitudeT
+ from ...facets.plain import (
+ GenericPlainRegistry,
+ PlainQuantity,
+ PlainUnit,
+ MagnitudeT,
+ )
from ...facets.measurement import Measurement
from ...compat import Locale
@@ -50,8 +55,11 @@ class FullFormatter:
"[temperature]",
)
default_sort_func: Optional[
- Callable[Iterable[tuple[str, Number]]], Iterable[tuple[str, Number]]
- ] = None
+ Callable[
+ [Iterable[tuple[str, Number]], GenericPlainRegistry],
+ Iterable[tuple[str, Number]],
+ ]
+ ] = lambda self, x, registry: sorted(x)
locale: Optional[Locale] = None
babel_length: Literal["short", "long", "narrow"] = "long"
diff --git a/pint/delegates/formatter/html.py b/pint/delegates/formatter/html.py
index 98329bcca..024a8c052 100644
--- a/pint/delegates/formatter/html.py
+++ b/pint/delegates/formatter/html.py
@@ -78,13 +78,6 @@ def format_unit(
self, unit: PlainUnit, uspec: str = "", **babel_kwds: Unpack[BabelKwds]
) -> str:
units = format_compound_unit(unit, uspec, **babel_kwds)
- if unit._REGISTRY.formatter.default_sort_func is not None:
- sort_func = lambda x: unit._REGISTRY.formatter.default_sort_func(
- x, unit._REGISTRY
- )
- else:
- sort_func = None
-
return formatter(
units,
as_ratio=True,
@@ -93,7 +86,9 @@ def format_unit(
division_fmt=r"{}/{}",
power_fmt=r"{}{}",
parentheses_fmt=r"({})",
- sort_func=sort_func,
+ sort_func=lambda x: unit._REGISTRY.formatter.default_sort_func(
+ x, unit._REGISTRY
+ ),
)
def format_quantity(
diff --git a/pint/delegates/formatter/latex.py b/pint/delegates/formatter/latex.py
index cf2b57848..fcf2494d3 100644
--- a/pint/delegates/formatter/latex.py
+++ b/pint/delegates/formatter/latex.py
@@ -173,9 +173,8 @@ def format_unit(
self, unit: PlainUnit, uspec: str = "", **babel_kwds: Unpack[BabelKwds]
) -> str:
units = format_compound_unit(unit, uspec, **babel_kwds)
- if unit._REGISTRY.formatter.default_sort_func:
- # Lift the sorting by dimensions b/c the preprocessed units are unrecognizeable
- units = unit._REGISTRY.formatter.default_sort_func(units, unit._REGISTRY)
+ # Lift the sorting by dimensions b/c the preprocessed units are unrecognizeable
+ units = unit._REGISTRY.formatter.default_sort_func(units, unit._REGISTRY)
preprocessed = {rf"\mathrm{{{latex_escape(u)}}}": p for u, p in units}
formatted = formatter(
diff --git a/pint/delegates/formatter/plain.py b/pint/delegates/formatter/plain.py
index 850e2eab5..b6ce3c372 100644
--- a/pint/delegates/formatter/plain.py
+++ b/pint/delegates/formatter/plain.py
@@ -259,13 +259,6 @@ def format_unit(
self, unit: PlainUnit, uspec: str = "", **babel_kwds: Unpack[BabelKwds]
) -> str:
units = format_compound_unit(unit, uspec, **babel_kwds)
- if unit._REGISTRY.formatter.default_sort_func is not None:
- sort_func = lambda x: unit._REGISTRY.formatter.default_sort_func(
- x, unit._REGISTRY
- )
- else:
- sort_func = None
-
return formatter(
units,
as_ratio=True,
@@ -275,7 +268,9 @@ def format_unit(
power_fmt="{}{}",
parentheses_fmt="({})",
exp_call=pretty_fmt_exponent,
- sort_func=sort_func,
+ sort_func=lambda x: unit._REGISTRY.formatter.default_sort_func(
+ x, unit._REGISTRY
+ ),
)
def format_quantity(
From 32f543dd3f884f82d86454781f342d7c52cff16f Mon Sep 17 00:00:00 2001
From: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
Date: Wed, 24 Jan 2024 09:36:45 +1300
Subject: [PATCH 7/7] Refactor sort_func into `format_compound_unit`
This is a much more logical place to put it. Note that the default formatters (plain, html, latex) all now call `formatter` with sort_func=None so that we don't accidentally use `sorted` as a default argument. But those who call `formatter` directly for their own purposes can call with a sort_func of their choosing that will do what they want it to do.
This also fixes a latent bug where we failed to call `sort_func` in one of the paths of `plain.py`.
Signed-off-by: Michael Tiemann <72577720+MichaelTiemannOSC@users.noreply.github.com>
---
pint/delegates/formatter/_format_helpers.py | 3 +++
pint/delegates/formatter/html.py | 4 +---
pint/delegates/formatter/latex.py | 2 --
pint/delegates/formatter/plain.py | 6 +++---
4 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/pint/delegates/formatter/_format_helpers.py b/pint/delegates/formatter/_format_helpers.py
index a736c8d5f..ca9e86a1b 100644
--- a/pint/delegates/formatter/_format_helpers.py
+++ b/pint/delegates/formatter/_format_helpers.py
@@ -265,6 +265,9 @@ def format_compound_unit(
if locale is not None:
out = localized_form(out, use_plural, length or "long", locale)
+ if registry:
+ out = registry.formatter.default_sort_func(out, registry)
+
return out
diff --git a/pint/delegates/formatter/html.py b/pint/delegates/formatter/html.py
index 024a8c052..773cd87ae 100644
--- a/pint/delegates/formatter/html.py
+++ b/pint/delegates/formatter/html.py
@@ -86,9 +86,7 @@ def format_unit(
division_fmt=r"{}/{}",
power_fmt=r"{}{}",
parentheses_fmt=r"({})",
- sort_func=lambda x: unit._REGISTRY.formatter.default_sort_func(
- x, unit._REGISTRY
- ),
+ sort_func=None,
)
def format_quantity(
diff --git a/pint/delegates/formatter/latex.py b/pint/delegates/formatter/latex.py
index fcf2494d3..a5df38ef3 100644
--- a/pint/delegates/formatter/latex.py
+++ b/pint/delegates/formatter/latex.py
@@ -173,8 +173,6 @@ def format_unit(
self, unit: PlainUnit, uspec: str = "", **babel_kwds: Unpack[BabelKwds]
) -> str:
units = format_compound_unit(unit, uspec, **babel_kwds)
- # Lift the sorting by dimensions b/c the preprocessed units are unrecognizeable
- units = unit._REGISTRY.formatter.default_sort_func(units, unit._REGISTRY)
preprocessed = {rf"\mathrm{{{latex_escape(u)}}}": p for u, p in units}
formatted = formatter(
diff --git a/pint/delegates/formatter/plain.py b/pint/delegates/formatter/plain.py
index b6ce3c372..31b47bd95 100644
--- a/pint/delegates/formatter/plain.py
+++ b/pint/delegates/formatter/plain.py
@@ -77,6 +77,7 @@ def format_unit(
division_fmt=" / ",
power_fmt="{} ** {}",
parentheses_fmt=r"({})",
+ sort_func=None,
)
def format_quantity(
@@ -175,6 +176,7 @@ def format_unit(
division_fmt="/",
power_fmt="{}**{}",
parentheses_fmt=r"({})",
+ sort_func=None,
)
def format_quantity(
@@ -268,9 +270,7 @@ def format_unit(
power_fmt="{}{}",
parentheses_fmt="({})",
exp_call=pretty_fmt_exponent,
- sort_func=lambda x: unit._REGISTRY.formatter.default_sort_func(
- x, unit._REGISTRY
- ),
+ sort_func=None,
)
def format_quantity(