diff --git a/pint/delegates/formatter/html.py b/pint/delegates/formatter/html.py index 263a01155..531f2933f 100644 --- a/pint/delegates/formatter/html.py +++ b/pint/delegates/formatter/html.py @@ -10,16 +10,18 @@ from typing import TYPE_CHECKING import re +from functools import partial from ...util import iterable from ...compat import ndarray, np, Unpack from ._helpers import ( split_format, formatter, + join_mu, ) from ..._typing import Magnitude from ._unit_handlers import BabelKwds, format_compound_unit -from .plain import DEFAULT_NUM_FMT +from .plain import format_number if TYPE_CHECKING: from ...facets.plain import PlainQuantity, PlainUnit, MagnitudeT @@ -38,25 +40,23 @@ def format_magnitude( assert isinstance(mstr, str) else: if isinstance(magnitude, ndarray): - # Use custom ndarray text formatting with monospace font - formatter = f"{{:{mspec or DEFAULT_NUM_FMT}}}" # Need to override for scalars, which are detected as iterable, # and don't respond to printoptions. if magnitude.ndim == 0: - mstr = formatter.format(magnitude) + mstr = format_number(magnitude, mspec) else: - with np.printoptions(formatter={"float_kind": formatter.format}): - mstr = ( - "
" + format(magnitude).replace("\n", "
") + "
" - ) + with np.printoptions( + formatter={"float_kind": partial(format_number, spec=mspec)} + ): + mstr = "
" + format(magnitude).replace("\n", "") + "
" elif not iterable(magnitude): # Use plain text for scalars - mstr = format(magnitude, mspec or DEFAULT_NUM_FMT) + mstr = format_number(magnitude, mspec) else: # Use monospace font for other array-likes mstr = ( "
"
-                    + format(magnitude, mspec or DEFAULT_NUM_FMT).replace("\n", "
") + + format_number(magnitude, mspec).replace("\n", "
") + "
" ) @@ -108,7 +108,8 @@ def format_quantity( else: joint_fstring = "{} {}" - return joint_fstring.format( + return join_mu( + joint_fstring, self.format_magnitude(quantity.magnitude, mspec, **babel_kwds), self.format_unit(quantity.units, uspec, **babel_kwds), ) diff --git a/pint/delegates/formatter/latex.py b/pint/delegates/formatter/latex.py index 3c3db69cd..fb199cbd6 100644 --- a/pint/delegates/formatter/latex.py +++ b/pint/delegates/formatter/latex.py @@ -17,7 +17,8 @@ from ..._typing import Magnitude from ...compat import ndarray, Unpack, Number from ._unit_handlers import BabelKwds, override_locale, format_compound_unit -from .plain import DEFAULT_NUM_FMT +from ._helpers import join_mu +from .plain import format_number if TYPE_CHECKING: from ...facets.plain import PlainQuantity, PlainUnit, MagnitudeT @@ -142,9 +143,9 @@ def format_magnitude( ) -> str: with override_locale(babel_kwds.get("locale", None)): if isinstance(magnitude, ndarray): - mstr = ndarray_to_latex(magnitude, mspec or DEFAULT_NUM_FMT) + mstr = ndarray_to_latex(magnitude, mspec) else: - mstr = format(magnitude, mspec or DEFAULT_NUM_FMT).replace("\n", "") + mstr = format_number(magnitude, mspec) mstr = _EXP_PATTERN.sub(r"\1\\times 10^{\2\3}", mstr) @@ -181,7 +182,8 @@ def format_quantity( joint_fstring = r"{}\ {}" - return joint_fstring.format( + return join_mu( + joint_fstring, self.format_magnitude(quantity.magnitude, mspec, **babel_kwds), self.format_unit(quantity.units, uspec, **babel_kwds), ) @@ -193,11 +195,12 @@ def format_magnitude( ) -> str: with override_locale(babel_kwds.get("locale", None)): if isinstance(magnitude, ndarray): - mstr = ndarray_to_latex(magnitude, mspec or DEFAULT_NUM_FMT) + mstr = ndarray_to_latex(magnitude, mspec) else: - mstr = format(magnitude, mspec or DEFAULT_NUM_FMT).replace("\n", "") + mstr = format_number(magnitude, mspec) - mstr = _EXP_PATTERN.sub(r"\1\\times 10^{\2\3}", mstr) + # TODO: Why this is not needed in siunitx? + # mstr = _EXP_PATTERN.sub(r"\1\\times 10^{\2\3}", mstr) return mstr @@ -215,10 +218,14 @@ def format_unit( # TODO: not sure if I should call format_compound_unit here. # siunitx_format_unit requires certain specific names? + # should unit names be translated? + # should unit names be shortened? + # units = format_compound_unit(unit, uspec, **babel_kwds) - units = format_compound_unit(unit, uspec, **babel_kwds) + formatted = siunitx_format_unit(unit._units.items(), registry) - formatted = siunitx_format_unit(units, registry) + # TODO: is this the right behaviour? Should we return the \si[] when only + # the units are returned? return rf"\si[]{{{formatted}}}" def format_quantity( @@ -233,9 +240,8 @@ def format_quantity( qspec, registry.default_format, registry.separate_format_defaults ) - joint_fstring = r"{}\ {}" + joint_fstring = "{}{}" - return joint_fstring.format( - self.format_magnitude(quantity.magnitude, mspec, **babel_kwds), - self.format_unit(quantity.units, uspec, **babel_kwds), - ) + mstr = self.format_magnitude(quantity.magnitude, mspec, **babel_kwds) + ustr = self.format_unit(quantity.units, uspec, **babel_kwds)[len(r"\si[]") :] + return r"\SI[]" + join_mu(joint_fstring, "{%s}" % mstr, ustr) diff --git a/pint/delegates/formatter/plain.py b/pint/delegates/formatter/plain.py index 4e1dd9a6b..a6dab74ef 100644 --- a/pint/delegates/formatter/plain.py +++ b/pint/delegates/formatter/plain.py @@ -7,14 +7,16 @@ """ from __future__ import annotations +from functools import partial -from typing import TYPE_CHECKING +from typing import TYPE_CHECKING, Any import re from ...compat import ndarray, np, Unpack from ._helpers import ( _pretty_fmt_exponent, split_format, formatter, + join_mu, ) from ..._typing import Magnitude @@ -25,7 +27,21 @@ from ...facets.plain import PlainQuantity, PlainUnit, MagnitudeT -DEFAULT_NUM_FMT = ".16n" +def format_number(value: Any, spec: str = "") -> str: + if isinstance(value, float): + return format(value, spec or ".16n") + + elif isinstance(value, int): + return format(value, spec or "n") + + elif isinstance(value, ndarray) and value.ndim == 0: + if issubclass(value.dtype.type, np.integer): + return format(value, spec or "n") + else: + return format(value, spec or ".16n") + else: + return str(value) + _EXP_PATTERN = re.compile(r"([0-9]\.?[0-9]*)e(-?)\+?0*([0-9]+)") @@ -56,8 +72,8 @@ def format_quantity( ) joint_fstring = "{} {}" - print(repr(mspec), repr(uspec)) - return joint_fstring.format( + return join_mu( + joint_fstring, self.format_magnitude(quantity.magnitude, mspec, **babel_kwds), self.format_unit(quantity.units, uspec, **babel_kwds), ) @@ -71,11 +87,12 @@ def format_magnitude( if isinstance(magnitude, ndarray) and magnitude.ndim > 0: # Use custom ndarray text formatting--need to handle scalars differently # since they don't respond to printoptions - formatter = f"{{:{mspec or DEFAULT_NUM_FMT}}}" - with np.printoptions(formatter={"float_kind": formatter.format}): + with np.printoptions( + formatter={"float_kind": partial(format_number, spec=mspec)} + ): mstr = format(magnitude).replace("\n", "") else: - mstr = format(magnitude, mspec or DEFAULT_NUM_FMT) + mstr = format_number(magnitude, mspec) return mstr @@ -107,8 +124,8 @@ def format_quantity( ) joint_fstring = "{} {}" - print(repr(mspec), repr(uspec)) - return joint_fstring.format( + return join_mu( + joint_fstring, self.format_magnitude(quantity.magnitude, mspec, **babel_kwds), self.format_unit(quantity.units, uspec, **babel_kwds), ) @@ -122,11 +139,12 @@ def format_magnitude( if isinstance(magnitude, ndarray) and magnitude.ndim > 0: # Use custom ndarray text formatting--need to handle scalars differently # since they don't respond to printoptions - formatter = f"{{:{mspec or DEFAULT_NUM_FMT}}}" - with np.printoptions(formatter={"float_kind": formatter.format}): + with np.printoptions( + formatter={"float_kind": partial(format_number, spec=mspec)} + ): mstr = format(magnitude).replace("\n", "") else: - mstr = format(magnitude, mspec or DEFAULT_NUM_FMT) + mstr = format_number(magnitude, mspec) return mstr @@ -159,7 +177,8 @@ def format_quantity( joint_fstring = "{} {}" - return joint_fstring.format( + return join_mu( + joint_fstring, self.format_magnitude(quantity.magnitude, mspec, **babel_kwds), self.format_unit(quantity.units, uspec, **babel_kwds), ) @@ -173,11 +192,12 @@ def format_magnitude( if isinstance(magnitude, ndarray) and magnitude.ndim > 0: # Use custom ndarray text formatting--need to handle scalars differently # since they don't respond to printoptions - formatter = f"{{:{mspec or DEFAULT_NUM_FMT}}}" - with np.printoptions(formatter={"float_kind": formatter.format}): + with np.printoptions( + formatter={"float_kind": partial(format_number, spec=mspec)} + ): mstr = format(magnitude).replace("\n", "") else: - mstr = format(magnitude, mspec or DEFAULT_NUM_FMT) + mstr = format_number(magnitude, mspec) m = _EXP_PATTERN.match(mstr) @@ -217,7 +237,8 @@ def format_quantity( joint_fstring = "{} {}" - return joint_fstring.format( + return join_mu( + joint_fstring, self.format_magnitude(quantity.magnitude, mspec, **babel_kwds), self.format_unit(quantity.units, uspec, **babel_kwds), )