diff options
Diffstat (limited to 'venv/lib/python3.11/site-packages/litestar/dto/data_structures.py')
-rw-r--r-- | venv/lib/python3.11/site-packages/litestar/dto/data_structures.py | 116 |
1 files changed, 116 insertions, 0 deletions
diff --git a/venv/lib/python3.11/site-packages/litestar/dto/data_structures.py b/venv/lib/python3.11/site-packages/litestar/dto/data_structures.py new file mode 100644 index 0000000..a5c3386 --- /dev/null +++ b/venv/lib/python3.11/site-packages/litestar/dto/data_structures.py @@ -0,0 +1,116 @@ +from __future__ import annotations + +from dataclasses import dataclass +from typing import TYPE_CHECKING, Generic, TypeVar + +from litestar.typing import FieldDefinition + +if TYPE_CHECKING: + from typing import Any, Callable + + from litestar.dto import DTOField + from litestar.dto._backend import DTOBackend + +T = TypeVar("T") + + +class DTOData(Generic[T]): + """DTO validated data and utility methods.""" + + __slots__ = ("_backend", "_data_as_builtins") + + def __init__(self, backend: DTOBackend, data_as_builtins: Any) -> None: + self._backend = backend + self._data_as_builtins = data_as_builtins + + def create_instance(self, **kwargs: Any) -> T: + """Create an instance of the DTO validated data. + + Args: + **kwargs: Additional data to create the instance with. Takes precedence over DTO validated data. + """ + data = dict(self._data_as_builtins) + for k, v in kwargs.items(): + _set_nested_dict_value(data, k.split("__"), v) + return self._backend.transfer_data_from_builtins(data) # type: ignore[no-any-return] + + def update_instance(self, instance: T, **kwargs: Any) -> T: + """Update an instance with the DTO validated data. + + Args: + instance: The instance to update. + **kwargs: Additional data to update the instance with. Takes precedence over DTO validated data. + """ + data = {**self._data_as_builtins, **kwargs} + for k, v in data.items(): + setattr(instance, k, v) + return instance + + def as_builtins(self) -> Any: + """Return the DTO validated data as builtins.""" + return self._data_as_builtins + + +def _set_nested_dict_value(d: dict[str, Any], keys: list[str], value: Any) -> None: + if len(keys) == 1: + d[keys[0]] = value + else: + key = keys[0] + d.setdefault(key, {}) + _set_nested_dict_value(d[key], keys[1:], value) + + +@dataclass(frozen=True) +class DTOFieldDefinition(FieldDefinition): + """A model field representation for purposes of generating a DTO backend model type.""" + + __slots__ = ( + "default_factory", + "dto_field", + "model_name", + ) + + model_name: str + """The name of the model for which the field is generated.""" + default_factory: Callable[[], Any] | None + """Default factory of the field.""" + dto_field: DTOField + """DTO field configuration.""" + + @classmethod + def from_field_definition( + cls, + field_definition: FieldDefinition, + model_name: str, + default_factory: Callable[[], Any] | None, + dto_field: DTOField, + ) -> DTOFieldDefinition: + """Create a :class:`FieldDefinition` from a :class:`FieldDefinition`. + + Args: + field_definition: A :class:`FieldDefinition` to create a :class:`FieldDefinition` from. + model_name: The name of the model. + default_factory: Default factory function, if any. + dto_field: DTOField instance. + + Returns: + A :class:`FieldDefinition` instance. + """ + return DTOFieldDefinition( + annotation=field_definition.annotation, + args=field_definition.args, + default=field_definition.default, + default_factory=default_factory, + dto_field=dto_field, + extra=field_definition.extra, + inner_types=field_definition.inner_types, + instantiable_origin=field_definition.instantiable_origin, + kwarg_definition=field_definition.kwarg_definition, + metadata=field_definition.metadata, + model_name=model_name, + name=field_definition.name, + origin=field_definition.origin, + raw=field_definition.raw, + safe_generic_origin=field_definition.safe_generic_origin, + type_wrappers=field_definition.type_wrappers, + ) |