Coverage for pydantic/dataclasses.py: 98.25%
123 statements
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-10 09:28 +0000
« prev ^ index » next coverage.py v7.9.2, created at 2025-07-10 09:28 +0000
1"""Provide an enhanced dataclass that performs validation."""
3from __future__ import annotations as _annotations 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
5import dataclasses 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
6import functools 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
7import sys 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
8import types 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
9from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, NoReturn, TypeVar, overload 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
10from warnings import warn 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
12from typing_extensions import TypeGuard, dataclass_transform 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
14from ._internal import _config, _decorators, _namespace_utils, _typing_extra 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
15from ._internal import _dataclasses as _pydantic_dataclasses 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
16from ._migration import getattr_migration 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
17from .config import ConfigDict 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
18from .errors import PydanticUserError 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
19from .fields import Field, FieldInfo, PrivateAttr 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
21if TYPE_CHECKING: 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
22 from ._internal._dataclasses import PydanticDataclass
23 from ._internal._namespace_utils import MappingNamespace
25__all__ = 'dataclass', 'rebuild_dataclass' 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
27_T = TypeVar('_T') 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
29if sys.version_info >= (3, 10): 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
31 @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr)) 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
32 @overload 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
33 def dataclass( 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
34 *,
35 init: Literal[False] = False, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
36 repr: bool = True, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
37 eq: bool = True, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
38 order: bool = False, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
39 unsafe_hash: bool = False, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
40 frozen: bool = False, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
41 config: ConfigDict | type[object] | None = None, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
42 validate_on_init: bool | None = None, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
43 kw_only: bool = ..., 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
44 slots: bool = ..., 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
45 ) -> Callable[[type[_T]], type[PydanticDataclass]]: # type: ignore 1jkabcpqdePvwfg
46 ...
48 @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr)) 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
49 @overload 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
50 def dataclass( 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
51 _cls: type[_T], # type: ignore 1jkabcpqdePvwfg
52 *,
53 init: Literal[False] = False, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
54 repr: bool = True, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
55 eq: bool = True, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
56 order: bool = False, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
57 unsafe_hash: bool = False, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
58 frozen: bool | None = None, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
59 config: ConfigDict | type[object] | None = None, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
60 validate_on_init: bool | None = None, 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
61 kw_only: bool = ..., 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
62 slots: bool = ..., 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
63 ) -> type[PydanticDataclass]: ... 1jkabcpqdePvwfg
65else:
67 @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr)) 1GHFIJKL
68 @overload 1GHFIJKL
69 def dataclass( 1GHFIJKL
70 *,
71 init: Literal[False] = False, 1GHFIJKL
72 repr: bool = True, 1GHFIJKL
73 eq: bool = True, 1GHFIJKL
74 order: bool = False, 1GHFIJKL
75 unsafe_hash: bool = False, 1GHFIJKL
76 frozen: bool | None = None, 1GHFIJKL
77 config: ConfigDict | type[object] | None = None, 1GHFIJKL
78 validate_on_init: bool | None = None, 1GHFIJKL
79 ) -> Callable[[type[_T]], type[PydanticDataclass]]: # type: ignore 1F
80 ...
82 @dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr)) 1GHFIJKL
83 @overload 1GHFIJKL
84 def dataclass( 1GHFIJKL
85 _cls: type[_T], # type: ignore 1F
86 *,
87 init: Literal[False] = False, 1GHFIJKL
88 repr: bool = True, 1GHFIJKL
89 eq: bool = True, 1GHFIJKL
90 order: bool = False, 1GHFIJKL
91 unsafe_hash: bool = False, 1GHFIJKL
92 frozen: bool | None = None, 1GHFIJKL
93 config: ConfigDict | type[object] | None = None, 1GHFIJKL
94 validate_on_init: bool | None = None, 1GHFIJKL
95 ) -> type[PydanticDataclass]: ... 1F
98@dataclass_transform(field_specifiers=(dataclasses.field, Field, PrivateAttr)) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
99def dataclass( 1GHhizAjkablmMIJnoBCpqdersNPKLtuDEvwfgxyO
100 _cls: type[_T] | None = None,
101 *,
102 init: Literal[False] = False,
103 repr: bool = True,
104 eq: bool = True,
105 order: bool = False,
106 unsafe_hash: bool = False,
107 frozen: bool | None = None,
108 config: ConfigDict | type[object] | None = None,
109 validate_on_init: bool | None = None,
110 kw_only: bool = False,
111 slots: bool = False,
112) -> Callable[[type[_T]], type[PydanticDataclass]] | type[PydanticDataclass]:
113 """!!! abstract "Usage Documentation"
114 [`dataclasses`](../concepts/dataclasses.md)
116 A decorator used to create a Pydantic-enhanced dataclass, similar to the standard Python `dataclass`,
117 but with added validation.
119 This function should be used similarly to `dataclasses.dataclass`.
121 Args:
122 _cls: The target `dataclass`.
123 init: Included for signature compatibility with `dataclasses.dataclass`, and is passed through to
124 `dataclasses.dataclass` when appropriate. If specified, must be set to `False`, as pydantic inserts its
125 own `__init__` function.
126 repr: A boolean indicating whether to include the field in the `__repr__` output.
127 eq: Determines if a `__eq__` method should be generated for the class.
128 order: Determines if comparison magic methods should be generated, such as `__lt__`, but not `__eq__`.
129 unsafe_hash: Determines if a `__hash__` method should be included in the class, as in `dataclasses.dataclass`.
130 frozen: Determines if the generated class should be a 'frozen' `dataclass`, which does not allow its
131 attributes to be modified after it has been initialized. If not set, the value from the provided `config` argument will be used (and will default to `False` otherwise).
132 config: The Pydantic config to use for the `dataclass`.
133 validate_on_init: A deprecated parameter included for backwards compatibility; in V2, all Pydantic dataclasses
134 are validated on init.
135 kw_only: Determines if `__init__` method parameters must be specified by keyword only. Defaults to `False`.
136 slots: Determines if the generated class should be a 'slots' `dataclass`, which does not allow the addition of
137 new attributes after instantiation.
139 Returns:
140 A decorator that accepts a class as its argument and returns a Pydantic `dataclass`.
142 Raises:
143 AssertionError: Raised if `init` is not `False` or `validate_on_init` is `False`.
144 """
145 assert init is False, 'pydantic.dataclasses.dataclass only supports init=False' 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
146 assert validate_on_init is not False, 'validate_on_init=False is no longer supported' 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
148 if sys.version_info >= (3, 10): 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
149 kwargs = {'kw_only': kw_only, 'slots': slots} 1hizAjkablmMcnoBCpqdersNPtuDEvwfgxyO
150 else:
151 kwargs = {} 1GHFIJKL
153 def make_pydantic_fields_compatible(cls: type[Any]) -> None: 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
154 """Make sure that stdlib `dataclasses` understands `Field` kwargs like `kw_only`
155 To do that, we simply change
156 `x: int = pydantic.Field(..., kw_only=True)`
157 into
158 `x: int = dataclasses.field(default=pydantic.Field(..., kw_only=True), kw_only=True)`
159 """
160 for annotation_cls in cls.__mro__: 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
161 if sys.version_info >= (3, 14): 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
162 from annotationlib import Format, get_annotations 1lmMrsNxyO
164 annotations = get_annotations(annotation_cls, format=Format.FORWARDREF) 1lmMrsNxyO
165 else:
166 annotations: dict[str, Any] = getattr(annotation_cls, '__annotations__', {}) 1GHhizAjkabFcIJnoBCpqdePKLtuDEvwfg
167 for field_name in annotations: 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
168 field_value = getattr(cls, field_name, None) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
169 # Process only if this is an instance of `FieldInfo`.
170 if not isinstance(field_value, FieldInfo): 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
171 continue 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
173 # Initialize arguments for the standard `dataclasses.field`.
174 field_args: dict = {'default': field_value} 1GHhizAjkablmFcIJnoBCpqdersKLtuDEvwfgxy
176 # Handle `kw_only` for Python 3.10+
177 if sys.version_info >= (3, 10) and field_value.kw_only: 1GHhizAjkablmFcIJnoBCpqdersKLtuDEvwfgxy
178 field_args['kw_only'] = True 1hizAjkablmcnoBCpqderstuDEvwfgxy
180 # Set `repr` attribute if it's explicitly specified to be not `True`.
181 if field_value.repr is not True: 1GHhizAjkablmFcIJnoBCpqdersKLtuDEvwfgxy
182 field_args['repr'] = field_value.repr 1GHhizAjkablmFcIJnoBCpqdersKLtuDEvwfgxy
184 setattr(cls, field_name, dataclasses.field(**field_args)) 1GHhizAjkablmFcIJnoBCpqdersKLtuDEvwfgxy
185 if sys.version_info < (3, 10) and cls.__dict__.get('__annotations__') is None: 1GHhizAjkablmFcIJnoBCpqdersKLtuDEvwfgxy
186 # In Python 3.9, when a class doesn't have any annotations, accessing `__annotations__`
187 # raises an `AttributeError`.
188 cls.__annotations__ = {} 1GHFIJKL
189 cls.__annotations__[field_name] = annotations[field_name] 1GHhizAjkablmFcIJnoBCpqdersKLtuDEvwfgxy
191 def create_dataclass(cls: type[Any]) -> type[PydanticDataclass]: 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
192 """Create a Pydantic dataclass from a regular dataclass.
194 Args:
195 cls: The class to create the Pydantic dataclass from.
197 Returns:
198 A Pydantic dataclass.
199 """
200 from ._internal._utils import is_model_class 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
202 if is_model_class(cls): 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
203 raise PydanticUserError( 1GHhizAjkablmFcIJnoBCpqdersKLtuDEvwfgxy
204 f'Cannot create a Pydantic dataclass from {cls.__name__} as it is already a Pydantic model',
205 code='dataclass-on-model',
206 )
208 original_cls = cls 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
210 # we warn on conflicting config specifications, but only if the class doesn't have a dataclass base
211 # because a dataclass base might provide a __pydantic_config__ attribute that we don't want to warn about
212 has_dataclass_base = any(dataclasses.is_dataclass(base) for base in cls.__bases__) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
213 if not has_dataclass_base and config is not None and hasattr(cls, '__pydantic_config__'): 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
214 warn( 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
215 f'`config` is set via both the `dataclass` decorator and `__pydantic_config__` for dataclass {cls.__name__}. '
216 f'The `config` specification from `dataclass` decorator will take priority.',
217 category=UserWarning,
218 stacklevel=2,
219 )
221 # if config is not explicitly provided, try to read it from the type
222 config_dict = config if config is not None else getattr(cls, '__pydantic_config__', None) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
223 config_wrapper = _config.ConfigWrapper(config_dict) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
224 decorators = _decorators.DecoratorInfos.build(cls) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
225 decorators.update_from_config(config_wrapper) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
227 # Keep track of the original __doc__ so that we can restore it after applying the dataclasses decorator
228 # Otherwise, classes with no __doc__ will have their signature added into the JSON schema description,
229 # since dataclasses.dataclass will set this as the __doc__
230 original_doc = cls.__doc__ 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
232 if _pydantic_dataclasses.is_stdlib_dataclass(cls): 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
233 # Vanilla dataclasses include a default docstring (representing the class signature),
234 # which we don't want to preserve.
235 original_doc = None 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
237 # We don't want to add validation to the existing std lib dataclass, so we will subclass it
238 # If the class is generic, we need to make sure the subclass also inherits from Generic
239 # with all the same parameters.
240 bases = (cls,) 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
241 if issubclass(cls, Generic): 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
242 generic_base = Generic[cls.__parameters__] # type: ignore 1GHhizAjkablmFcIJnoBCpqdersKLtuDEvwfgxy
243 bases = bases + (generic_base,) 1GHhizAjkablmFcIJnoBCpqdersKLtuDEvwfgxy
244 cls = types.new_class(cls.__name__, bases) 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
246 make_pydantic_fields_compatible(cls) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
248 # Respect frozen setting from dataclass constructor and fallback to config setting if not provided
249 if frozen is not None: 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
250 frozen_ = frozen 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
251 if config_wrapper.frozen: 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
252 # It's not recommended to define both, as the setting from the dataclass decorator will take priority.
253 warn( 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
254 f'`frozen` is set via both the `dataclass` decorator and `config` for dataclass {cls.__name__!r}.'
255 'This is not recommended. The `frozen` specification on `dataclass` will take priority.',
256 category=UserWarning,
257 stacklevel=2,
258 )
259 else:
260 frozen_ = config_wrapper.frozen or False 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
262 cls = dataclasses.dataclass( # type: ignore[call-overload] 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
263 cls,
264 # the value of init here doesn't affect anything except that it makes it easier to generate a signature
265 init=True,
266 repr=repr,
267 eq=eq,
268 order=order,
269 unsafe_hash=unsafe_hash,
270 frozen=frozen_,
271 **kwargs,
272 )
274 if config_wrapper.validate_assignment: 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
276 @functools.wraps(cls.__setattr__) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
277 def validated_setattr(instance: Any, field: str, value: str, /) -> None: 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
278 type(instance).__pydantic_validator__.validate_assignment(instance, field, value) 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
280 cls.__setattr__ = validated_setattr.__get__(None, cls) # type: ignore 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
282 if slots and not hasattr(cls, '__setstate__'): 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
283 # If slots is set, `pickle` (relied on by `copy.copy()`) will use
284 # `__setattr__()` to reconstruct the dataclass. However, the custom
285 # `__setattr__()` set above relies on `validate_assignment()`, which
286 # in turn expects all the field values to be already present on the
287 # instance, resulting in attribute errors.
288 # As such, we make use of `object.__setattr__()` instead.
289 # Note that we do so only if `__setstate__()` isn't already set (this is the
290 # case if on top of `slots`, `frozen` is used).
292 # Taken from `dataclasses._dataclass_get/setstate()`:
293 def _dataclass_getstate(self: Any) -> list[Any]: 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
294 return [getattr(self, f.name) for f in dataclasses.fields(self)] 1hizAjkablmMcnoBCpqdersNtuDEvwfgxyO
296 def _dataclass_setstate(self: Any, state: list[Any]) -> None: 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
297 for field, value in zip(dataclasses.fields(self), state): 1hizAjkablmMcnoBCpqdersNtuDEvwfgxyO
298 object.__setattr__(self, field.name, value) 1hizAjkablmMcnoBCpqdersNtuDEvwfgxyO
300 cls.__getstate__ = _dataclass_getstate # pyright: ignore[reportAttributeAccessIssue] 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
301 cls.__setstate__ = _dataclass_setstate # pyright: ignore[reportAttributeAccessIssue] 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
303 # This is an undocumented attribute to distinguish stdlib/Pydantic dataclasses.
304 # It should be set as early as possible:
305 cls.__is_pydantic_dataclass__ = True 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
306 cls.__pydantic_decorators__ = decorators # type: ignore 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
307 cls.__doc__ = original_doc 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
308 # Can be non-existent for dynamically created classes:
309 firstlineno = getattr(original_cls, '__firstlineno__', None) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
310 cls.__module__ = original_cls.__module__ 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
311 if sys.version_info >= (3, 13) and firstlineno is not None: 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
312 # As per https://docs.python.org/3/reference/datamodel.html#type.__firstlineno__:
313 # Setting the `__module__` attribute removes the `__firstlineno__` item from the type’s dictionary.
314 original_cls.__firstlineno__ = firstlineno 1ablmMdersNPfgxyO
315 cls.__firstlineno__ = firstlineno 1ablmMdersNPfgxyO
316 cls.__qualname__ = original_cls.__qualname__ 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
317 cls.__pydantic_fields_complete__ = classmethod(_pydantic_fields_complete) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
318 cls.__pydantic_complete__ = False # `complete_dataclass` will set it to `True` if successful. 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
319 # TODO `parent_namespace` is currently None, but we could do the same thing as Pydantic models:
320 # fetch the parent ns using `parent_frame_namespace` (if the dataclass was defined in a function),
321 # and possibly cache it (see the `__pydantic_parent_namespace__` logic for models).
322 _pydantic_dataclasses.complete_dataclass(cls, config_wrapper, raise_errors=False) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
323 return cls 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
325 return create_dataclass if _cls is None else create_dataclass(_cls) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
328def _pydantic_fields_complete(cls: type[PydanticDataclass]) -> bool: 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
329 """Return whether the fields where successfully collected (i.e. type hints were successfully resolves).
331 This is a private property, not meant to be used outside Pydantic.
332 """
333 return all(field_info._complete for field_info in cls.__pydantic_fields__.values()) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
336__getattr__ = getattr_migration(__name__) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
338if sys.version_info < (3, 11): 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
339 # Monkeypatch dataclasses.InitVar so that typing doesn't error if it occurs as a type when evaluating type hints
340 # Starting in 3.11, typing.get_type_hints will not raise an error if the retrieved type hints are not callable.
342 def _call_initvar(*args: Any, **kwargs: Any) -> NoReturn: 1GHhiFcIJnoKLtu
343 """This function does nothing but raise an error that is as similar as possible to what you'd get
344 if you were to try calling `InitVar[int]()` without this monkeypatch. The whole purpose is just
345 to ensure typing._type_check does not error if the type hint evaluates to `InitVar[<parameter>]`.
346 """
347 raise TypeError("'InitVar' object is not callable") 1GHhiFcIJnoKLtu
349 dataclasses.InitVar.__call__ = _call_initvar 1GHhiFcIJnoKLtu
352def rebuild_dataclass( 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
353 cls: type[PydanticDataclass],
354 *,
355 force: bool = False,
356 raise_errors: bool = True,
357 _parent_namespace_depth: int = 2,
358 _types_namespace: MappingNamespace | None = None,
359) -> bool | None:
360 """Try to rebuild the pydantic-core schema for the dataclass.
362 This may be necessary when one of the annotations is a ForwardRef which could not be resolved during
363 the initial attempt to build the schema, and automatic rebuilding fails.
365 This is analogous to `BaseModel.model_rebuild`.
367 Args:
368 cls: The class to rebuild the pydantic-core schema for.
369 force: Whether to force the rebuilding of the schema, defaults to `False`.
370 raise_errors: Whether to raise errors, defaults to `True`.
371 _parent_namespace_depth: The depth level of the parent namespace, defaults to 2.
372 _types_namespace: The types namespace, defaults to `None`.
374 Returns:
375 Returns `None` if the schema is already "complete" and rebuilding was not required.
376 If rebuilding _was_ required, returns `True` if rebuilding was successful, otherwise `False`.
377 """
378 if not force and cls.__pydantic_complete__: 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
379 return None 1GHhizAjkablmFcIJnoBCpqdersKLtuDEvwfgxy
381 for attr in ('__pydantic_core_schema__', '__pydantic_validator__', '__pydantic_serializer__'): 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
382 if attr in cls.__dict__: 382 ↛ 381line 382 didn't jump to line 381 because the condition on line 382 was always true1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
383 # Deleting the validator/serializer is necessary as otherwise they can get reused in
384 # pydantic-core. Same applies for the core schema that can be reused in schema generation.
385 delattr(cls, attr) 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
387 cls.__pydantic_complete__ = False 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
389 if _types_namespace is not None: 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
390 rebuild_ns = _types_namespace 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
391 elif _parent_namespace_depth > 0: 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
392 rebuild_ns = _typing_extra.parent_frame_namespace(parent_depth=_parent_namespace_depth, force=True) or {} 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
393 else:
394 rebuild_ns = {} 1GHhizAjkablmFcIJnoBCpqdersKLtuDEvwfgxy
396 ns_resolver = _namespace_utils.NsResolver( 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
397 parent_namespace=rebuild_ns,
398 )
400 return _pydantic_dataclasses.complete_dataclass( 1GHhizAjkablmMFcIJnoBCpqdersNKLtuDEvwfgxyO
401 cls,
402 _config.ConfigWrapper(cls.__pydantic_config__, check=False),
403 raise_errors=raise_errors,
404 ns_resolver=ns_resolver,
405 # We could provide a different config instead (with `'defer_build'` set to `True`)
406 # of this explicit `_force_build` argument, but because config can come from the
407 # decorator parameter or the `__pydantic_config__` attribute, `complete_dataclass`
408 # will overwrite `__pydantic_config__` with the provided config above:
409 _force_build=True,
410 )
413def is_pydantic_dataclass(class_: type[Any], /) -> TypeGuard[type[PydanticDataclass]]: 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
414 """Whether a class is a pydantic dataclass.
416 Args:
417 class_: The class.
419 Returns:
420 `True` if the class is a pydantic dataclass, `False` otherwise.
421 """
422 try: 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
423 return '__is_pydantic_dataclass__' in class_.__dict__ and dataclasses.is_dataclass(class_) 1GHhizAjkablmMFcIJnoBCpqdersNPKLtuDEvwfgxyO
424 except AttributeError:
425 return False