Source code for pint.delegates.formatter.sorting
"""
pint.delegates.formatter.sorting
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Sort functions used to order the units within a compound unit's string
representation, and the signature they must implement to be assigned to
``UnitRegistry.formatter.default_sort_func``.
:copyright: 2022 by Pint Authors, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
from __future__ import annotations
from collections.abc import Callable, Iterable
from typing import TYPE_CHECKING, Any
from ...compat import TypeAlias
if TYPE_CHECKING:
from ...compat import Number
from ...registry import UnitRegistry
#: Signature required by ``UnitRegistry.formatter.default_sort_func``.
#:
#: A sort function takes:
#:
#: - ``items``: an iterable of ``(display_name, exponent, unit_name)`` triplets,
#: one per unit in the compound unit.
#: - ``registry``: the :class:`~pint.UnitRegistry` in use, or ``None``.
#:
#: and returns an iterable of the same triplets, in the desired display order.
SortFunc: TypeAlias = Callable[
[Iterable[tuple[str, Any, str]], Any], Iterable[tuple[str, Any, str]]
]
[docs]
def sort_by_unit_name(
items: Iterable[tuple[str, Number, str]], _registry: UnitRegistry | None
) -> Iterable[tuple[str, Number, str]]:
"""Sort a list of units alphabetically by (canonical) unit name.
This is the default ``default_sort_func``.
"""
return sorted(items, key=lambda el: el[2])
[docs]
def sort_by_display_name(
items: Iterable[tuple[str, Number, str]], _registry: UnitRegistry | None
) -> Iterable[tuple[str, Number, str]]:
"""Sort a list of units alphabetically by display name."""
return sorted(items)
[docs]
def sort_by_dimensionality(
items: Iterable[tuple[str, Number, str]], registry: UnitRegistry | None
) -> Iterable[tuple[str, Number, str]]:
"""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 | None
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
dim_order = registry.formatter.dim_order
def sort_key(item: tuple[str, Number, str]):
_display_name, _unit_exponent, unit_name = item
cname = registry.get_name(unit_name)
cname_dims = registry.get_dimensionality(cname) or {"[]": None}
for cname_dim in cname_dims:
if cname_dim in dim_order:
return dim_order.index(cname_dim), cname
raise KeyError(f"Unit {unit_name} (aka {cname}) has no recognized dimensions")
return sorted(items, key=sort_key)