Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/pydantic/root_model.py: 50%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""RootModel class and type definitions."""
3from __future__ import annotations as _annotations
5from collections.abc import Callable
6from copy import copy, deepcopy
7from typing import TYPE_CHECKING, Any, Generic, Literal, TypeVar
9from pydantic_core import PydanticUndefined
10from typing_extensions import Self, dataclass_transform
12from . import PydanticUserError
13from ._internal import _model_construction, _repr
14from .main import BaseModel, _object_setattr
16if TYPE_CHECKING:
17 from .fields import Field as PydanticModelField
18 from .fields import PrivateAttr as PydanticModelPrivateAttr
19 from .main import IncEx
21 # dataclass_transform could be applied to RootModel directly, but `ModelMetaclass`'s dataclass_transform
22 # takes priority (at least with pyright). We trick type checkers into thinking we apply dataclass_transform
23 # on a new metaclass.
24 @dataclass_transform(kw_only_default=False, field_specifiers=(PydanticModelField, PydanticModelPrivateAttr))
25 class _RootModelMetaclass(_model_construction.ModelMetaclass): ...
26else:
27 _RootModelMetaclass = _model_construction.ModelMetaclass
29__all__ = ('RootModel',)
31RootModelRootType = TypeVar('RootModelRootType')
34class RootModel(BaseModel, Generic[RootModelRootType], metaclass=_RootModelMetaclass):
35 """!!! abstract "Usage Documentation"
36 [`RootModel` and Custom Root Types](../concepts/models.md#rootmodel-and-custom-root-types)
38 A Pydantic `BaseModel` for the root object of the model.
40 Attributes:
41 root: The root object of the model.
42 __pydantic_root_model__: Whether the model is a RootModel.
43 __pydantic_private__: Private fields in the model.
44 __pydantic_extra__: Extra fields in the model.
46 """
48 __pydantic_root_model__ = True
49 __pydantic_private__ = None
50 __pydantic_extra__ = None
52 root: RootModelRootType
54 def __init_subclass__(cls, **kwargs):
55 extra = cls.model_config.get('extra')
56 if extra is not None:
57 raise PydanticUserError(
58 "`RootModel` does not support setting `model_config['extra']`", code='root-model-extra'
59 )
60 super().__init_subclass__(**kwargs)
62 def __init__(self, /, root: RootModelRootType = PydanticUndefined, **data) -> None: # type: ignore
63 __tracebackhide__ = True
64 if data:
65 if root is not PydanticUndefined:
66 raise ValueError(
67 '"RootModel.__init__" accepts either a single positional argument or arbitrary keyword arguments'
68 )
69 root = data # type: ignore
70 self.__pydantic_validator__.validate_python(root, self_instance=self)
72 __init__.__pydantic_base_init__ = True # pyright: ignore[reportFunctionMemberAccess]
74 @classmethod
75 def model_construct(cls, root: RootModelRootType, _fields_set: set[str] | None = None) -> Self: # type: ignore
76 """Create a new model using the provided root object and update fields set.
78 Args:
79 root: The root object of the model.
80 _fields_set: The set of fields to be updated.
82 Returns:
83 The new model.
85 Raises:
86 NotImplemented: If the model is not a subclass of `RootModel`.
87 """
88 return super().model_construct(root=root, _fields_set=_fields_set)
90 def __getstate__(self) -> dict[Any, Any]:
91 return {
92 '__dict__': self.__dict__,
93 '__pydantic_fields_set__': self.__pydantic_fields_set__,
94 }
96 def __setstate__(self, state: dict[Any, Any]) -> None:
97 _object_setattr(self, '__pydantic_fields_set__', state['__pydantic_fields_set__'])
98 _object_setattr(self, '__dict__', state['__dict__'])
100 def __copy__(self) -> Self:
101 """Returns a shallow copy of the model."""
102 cls = type(self)
103 m = cls.__new__(cls)
104 new_dict = copy(self.__dict__)
105 new_dict['root'] = copy(self.__dict__['root']) # pyright: ignore[reportIndexIssue] (https://github.com/microsoft/pyright/issues/11548)
106 _object_setattr(m, '__dict__', new_dict)
107 _object_setattr(m, '__pydantic_fields_set__', copy(self.__pydantic_fields_set__))
108 return m
110 def __deepcopy__(self, memo: dict[int, Any] | None = None) -> Self:
111 """Returns a deep copy of the model."""
112 cls = type(self)
113 m = cls.__new__(cls)
114 _object_setattr(m, '__dict__', deepcopy(self.__dict__, memo=memo))
115 # This next line doesn't need a deepcopy because __pydantic_fields_set__ is a set[str],
116 # and attempting a deepcopy would be marginally slower.
117 _object_setattr(m, '__pydantic_fields_set__', copy(self.__pydantic_fields_set__))
118 return m
120 if TYPE_CHECKING:
121 # This `model_dump()` definition is only provided to get a more accurate return type for type checkers
122 # (no override is actually necessary at runtime). Generally, the return type will be `RootModelRootType`,
123 # assuming that `RootModelRootType` is not a `BaseModel` subclass. If `RootModelRootType` is a `BaseModel`
124 # subclass, then the return type will likely be `dict[str, Any]`, as `model_dump()` calls are recursive.
125 # The return type could even be something different, in the case of a custom serializer. Thus, `Any` is
126 # used here to catch all of these cases.
128 def model_dump( # type: ignore
129 self,
130 *,
131 mode: Literal['json', 'python'] | str = 'python',
132 include: IncEx | None = None,
133 exclude: IncEx | None = None,
134 context: Any | None = None,
135 by_alias: bool | None = None,
136 exclude_unset: bool = False,
137 exclude_defaults: bool = False,
138 exclude_none: bool = False,
139 exclude_computed_fields: bool = False,
140 round_trip: bool = False,
141 warnings: bool | Literal['none', 'warn', 'error'] = True,
142 fallback: Callable[[Any], Any] | None = None,
143 serialize_as_any: bool = False,
144 polymorphic_serialization: bool | None = None,
145 ) -> Any:
146 """!!! abstract "Usage Documentation"
147 [`model_dump`](../concepts/serialization.md#python-mode)
149 Generate a dictionary representation of the model, optionally specifying which fields to include or exclude.
151 Args:
152 mode: The mode in which `to_python` should run.
153 If mode is 'json', the output will only contain JSON serializable types.
154 If mode is 'python', the output may contain non-JSON-serializable Python objects.
155 include: A set of fields to include in the output.
156 exclude: A set of fields to exclude from the output.
157 context: Additional context to pass to the serializer.
158 by_alias: Whether to use the field's alias in the dictionary key if defined.
159 exclude_unset: Whether to exclude fields that have not been explicitly set.
160 exclude_defaults: Whether to exclude fields that are set to their default value.
161 exclude_none: Whether to exclude fields that have a value of `None`.
162 exclude_computed_fields: Whether to exclude computed fields.
163 While this can be useful for round-tripping, it is usually recommended to use the dedicated
164 `round_trip` parameter instead.
165 round_trip: If True, dumped values should be valid as input for non-idempotent types such as Json[T].
166 warnings: How to handle serialization errors. False/"none" ignores them, True/"warn" logs errors,
167 "error" raises a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError].
168 fallback: A function to call when an unknown value is encountered. If not provided,
169 a [`PydanticSerializationError`][pydantic_core.PydanticSerializationError] error is raised.
170 serialize_as_any: Whether to serialize fields with duck-typing serialization behavior.
171 polymorphic_serialization: Whether to use model and dataclass polymorphic serialization for this call.
173 Returns:
174 A dictionary representation of the model.
175 """
176 ...
178 def __eq__(self, other: Any) -> bool:
179 if not isinstance(other, RootModel):
180 return NotImplemented
181 return self.__pydantic_fields__['root'].annotation == other.__pydantic_fields__[
182 'root'
183 ].annotation and super().__eq__(other)
185 def __repr_args__(self) -> _repr.ReprArgs:
186 yield 'root', self.root