Source code for todays_paper_web.widgets.params

"""Shared Pydantic field types, used across both the ``View`` and
``DataSource`` ``Params`` hierarchies (see `todays_paper_web.widgets.view` and
`todays_paper_web.widgets.datasource` for those - a widget and a data source
are different enough that they don't share a base *model*, only these value
types).
"""
from __future__ import annotations

import webcolors


[docs] class Color: """A CSS color name or ``#hex`` code, parsed into a ``webcolors.IntegerRGB``. Same name-then-hex parsing as the pre-migration, now-removed ``View.decodeColor`` had, but with no separate "default on failure" behavior: an unrecognized color raises a validation error rather than silently falling back. Give the field itself the right default via ``Field(default_factory=...)``. """ @classmethod def __get_validators__(cls): yield cls.validate
[docs] @classmethod def validate(cls, value) -> webcolors.IntegerRGB: if isinstance(value, webcolors.IntegerRGB): return value try: return webcolors.name_to_rgb(value) except ValueError: pass try: return webcolors.hex_to_rgb(value) except ValueError: pass raise ValueError(f"Unknown color {value!r}: expected a CSS color name or a #hex code")
[docs] class Number: """An int or float, kept as whichever type it already was. For a `DataSource`'s YAML `params:` (unlike a widget's XML attributes, already native Python types, not strings), a plain ``float`` field would silently coerce a whole-number int like ``17`` to ``17.0`` - harmless on its own, but a naive ``Union[int, float]`` is actively unsafe in Pydantic v1: it tries ``int`` first and *truncates* a real float's fractional part (e.g. ``55.64277`` silently becomes ``55``) rather than falling through to ``float``. This preserves whatever numeric type was given, without either problem. """ @classmethod def __get_validators__(cls): yield cls.validate
[docs] @classmethod def validate(cls, value): if isinstance(value, bool) or not isinstance(value, (int, float)): raise TypeError(f"expected a number, got {type(value).__name__}") return value