Source code for fsh_lib.transformers
"""Body→kwargs transformer helpers shared by generated builders.
Generated update builders one-line through :func:`build_patch_kwargs`
to read ``body.model_fields_set`` and emit a column-kwargs dict the
SQL ``update(...).values(**...)`` consumes. The same one-shot
extraction would otherwise be repeated per resource as a chain of
``if "<field>" in body.model_fields_set: out["<field>"] = ...`` lines
in every transformer module.
"""
from __future__ import annotations
from typing import TYPE_CHECKING, Any
if TYPE_CHECKING:
from collections.abc import Iterable
from pydantic import BaseModel
[docs]
def build_patch_kwargs(
body: BaseModel,
fields: Iterable[str],
) -> dict[str, Any]:
"""Project the explicitly-set subset of *fields* off *body* into a dict.
PATCH semantics: a field that the client *did not* send must
not appear in the returned dict, so the SQL ``UPDATE`` only
touches columns the client meant to change. ``body.model_fields_set``
is pydantic's record of which attributes were populated from
input (vs. left at their default), so iterating it is the
correct gate -- a ``None`` *value* the client explicitly sent
still passes through.
Args:
body: The parsed pydantic request model.
fields: Field names the caller wants to consider. Names
absent from *body*'s declared fields are ignored.
Returns:
A ``dict`` mapping each set field to its value on *body*.
The caller typically annotates the receiving variable with
the per-resource ``{Resource}UpdateKwargs`` ``TypedDict``
(``total=False``) so type-checkers see the result as the
expected partial shape.
"""
set_fields = body.model_fields_set
return {name: getattr(body, name) for name in fields if name in set_fields}
__all__ = ["build_patch_kwargs"]