mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
parent
5cac74c4ac
commit
c07e9946e5
82 changed files with 16910 additions and 9 deletions
188
datasette/vendored/pint/delegates/formatter/html.py
Normal file
188
datasette/vendored/pint/delegates/formatter/html.py
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
"""
|
||||
pint.delegates.formatter.html
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Implements:
|
||||
- HTML: suitable for web/jupyter notebook outputs.
|
||||
|
||||
:copyright: 2022 by Pint Authors, see AUTHORS for more details.
|
||||
:license: BSD, see LICENSE for more details.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import re
|
||||
from typing import TYPE_CHECKING, Any, Iterable
|
||||
|
||||
from ..._typing import Magnitude
|
||||
from ...compat import Unpack, ndarray, np
|
||||
from ...util import iterable
|
||||
from ._compound_unit_helpers import (
|
||||
BabelKwds,
|
||||
SortFunc,
|
||||
localize_per,
|
||||
prepare_compount_unit,
|
||||
)
|
||||
from ._format_helpers import (
|
||||
formatter,
|
||||
join_mu,
|
||||
join_unc,
|
||||
override_locale,
|
||||
)
|
||||
from ._spec_helpers import (
|
||||
remove_custom_flags,
|
||||
split_format,
|
||||
)
|
||||
from .plain import BaseFormatter
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ...facets.measurement import Measurement
|
||||
from ...facets.plain import MagnitudeT, PlainQuantity, PlainUnit
|
||||
|
||||
_EXP_PATTERN = re.compile(r"([0-9]\.?[0-9]*)e(-?)\+?0*([0-9]+)")
|
||||
|
||||
|
||||
class HTMLFormatter(BaseFormatter):
|
||||
"""HTML localizable text formatter."""
|
||||
|
||||
def format_magnitude(
|
||||
self, magnitude: Magnitude, mspec: str = "", **babel_kwds: Unpack[BabelKwds]
|
||||
) -> str:
|
||||
with override_locale(mspec, babel_kwds.get("locale", None)) as format_number:
|
||||
if hasattr(magnitude, "_repr_html_"):
|
||||
# If magnitude has an HTML repr, nest it within Pint's
|
||||
mstr = magnitude._repr_html_() # type: ignore
|
||||
assert isinstance(mstr, str)
|
||||
else:
|
||||
if isinstance(magnitude, ndarray):
|
||||
# Need to override for scalars, which are detected as iterable,
|
||||
# and don't respond to printoptions.
|
||||
if magnitude.ndim == 0:
|
||||
mstr = format_number(magnitude)
|
||||
else:
|
||||
with np.printoptions(formatter={"float_kind": format_number}):
|
||||
mstr = (
|
||||
"<pre>" + format(magnitude).replace("\n", "") + "</pre>"
|
||||
)
|
||||
elif not iterable(magnitude):
|
||||
# Use plain text for scalars
|
||||
mstr = format_number(magnitude)
|
||||
else:
|
||||
# Use monospace font for other array-likes
|
||||
mstr = (
|
||||
"<pre>"
|
||||
+ format_number(magnitude).replace("\n", "<br>")
|
||||
+ "</pre>"
|
||||
)
|
||||
|
||||
m = _EXP_PATTERN.match(mstr)
|
||||
_exp_formatter = lambda s: f"<sup>{s}</sup>"
|
||||
|
||||
if m:
|
||||
exp = int(m.group(2) + m.group(3))
|
||||
mstr = _EXP_PATTERN.sub(r"\1×10" + _exp_formatter(exp), mstr)
|
||||
|
||||
return mstr
|
||||
|
||||
def format_unit(
|
||||
self,
|
||||
unit: PlainUnit | Iterable[tuple[str, Any]],
|
||||
uspec: str = "",
|
||||
sort_func: SortFunc | None = None,
|
||||
**babel_kwds: Unpack[BabelKwds],
|
||||
) -> str:
|
||||
numerator, denominator = prepare_compount_unit(
|
||||
unit,
|
||||
uspec,
|
||||
sort_func=sort_func,
|
||||
**babel_kwds,
|
||||
registry=self._registry,
|
||||
)
|
||||
|
||||
if babel_kwds.get("locale", None):
|
||||
length = babel_kwds.get("length") or ("short" if "~" in uspec else "long")
|
||||
division_fmt = localize_per(length, babel_kwds.get("locale"), "{}/{}")
|
||||
else:
|
||||
division_fmt = "{}/{}"
|
||||
|
||||
return formatter(
|
||||
numerator,
|
||||
denominator,
|
||||
as_ratio=True,
|
||||
single_denominator=True,
|
||||
product_fmt=r" ",
|
||||
division_fmt=division_fmt,
|
||||
power_fmt=r"{}<sup>{}</sup>",
|
||||
parentheses_fmt=r"({})",
|
||||
)
|
||||
|
||||
def format_quantity(
|
||||
self,
|
||||
quantity: PlainQuantity[MagnitudeT],
|
||||
qspec: str = "",
|
||||
sort_func: SortFunc | None = None,
|
||||
**babel_kwds: Unpack[BabelKwds],
|
||||
) -> str:
|
||||
registry = self._registry
|
||||
|
||||
mspec, uspec = split_format(
|
||||
qspec, registry.formatter.default_format, registry.separate_format_defaults
|
||||
)
|
||||
|
||||
if iterable(quantity.magnitude):
|
||||
# Use HTML table instead of plain text template for array-likes
|
||||
joint_fstring = (
|
||||
"<table><tbody>"
|
||||
"<tr><th>Magnitude</th>"
|
||||
"<td style='text-align:left;'>{}</td></tr>"
|
||||
"<tr><th>Units</th><td style='text-align:left;'>{}</td></tr>"
|
||||
"</tbody></table>"
|
||||
)
|
||||
else:
|
||||
joint_fstring = "{} {}"
|
||||
|
||||
return join_mu(
|
||||
joint_fstring,
|
||||
self.format_magnitude(quantity.magnitude, mspec, **babel_kwds),
|
||||
self.format_unit(quantity.unit_items(), uspec, sort_func, **babel_kwds),
|
||||
)
|
||||
|
||||
def format_uncertainty(
|
||||
self,
|
||||
uncertainty,
|
||||
unc_spec: str = "",
|
||||
sort_func: SortFunc | None = None,
|
||||
**babel_kwds: Unpack[BabelKwds],
|
||||
) -> str:
|
||||
unc_str = format(uncertainty, unc_spec).replace("+/-", " ± ")
|
||||
|
||||
unc_str = re.sub(r"\)e\+0?(\d+)", r")×10<sup>\1</sup>", unc_str)
|
||||
unc_str = re.sub(r"\)e-0?(\d+)", r")×10<sup>-\1</sup>", unc_str)
|
||||
return unc_str
|
||||
|
||||
def format_measurement(
|
||||
self,
|
||||
measurement: Measurement,
|
||||
meas_spec: str = "",
|
||||
sort_func: SortFunc | None = None,
|
||||
**babel_kwds: Unpack[BabelKwds],
|
||||
) -> str:
|
||||
registry = self._registry
|
||||
|
||||
mspec, uspec = split_format(
|
||||
meas_spec,
|
||||
registry.formatter.default_format,
|
||||
registry.separate_format_defaults,
|
||||
)
|
||||
|
||||
unc_spec = remove_custom_flags(meas_spec)
|
||||
|
||||
joint_fstring = "{} {}"
|
||||
|
||||
return join_unc(
|
||||
joint_fstring,
|
||||
"(",
|
||||
")",
|
||||
self.format_uncertainty(measurement.magnitude, unc_spec, **babel_kwds),
|
||||
self.format_unit(measurement.units, uspec, sort_func, **babel_kwds),
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue