MCPcopy
hub / github.com/pydantic/pydantic / patch_base_fields

Function patch_base_fields

pydantic/_internal/_dataclasses.py:230–315  ·  view source on GitHub ↗

Temporarily patch the stdlib dataclasses bases of `cls` if the Pydantic `Field()` function is used. When creating a Pydantic dataclass, it is possible to inherit from stdlib dataclasses, where the Pydantic `Field()` function is used. To create this Pydantic dataclass, we first apply the

(cls: type[Any])

Source from the content-addressed store, hash-verified

228
229@contextmanager
230def patch_base_fields(cls: type[Any]) -> Generator[None]:
231 """Temporarily patch the stdlib dataclasses bases of `cls` if the Pydantic `Field()` function is used.
232
233 When creating a Pydantic dataclass, it is possible to inherit from stdlib dataclasses, where
234 the Pydantic `Field()` function is used. To create this Pydantic dataclass, we first apply
235 the stdlib `@dataclass` decorator on it. During the construction of the stdlib dataclass,
236 the `kw_only` and `repr` field arguments need to be understood by the stdlib *during* the
237 dataclass construction. To do so, we temporarily patch the fields dictionary of the affected
238 bases.
239
240 For instance, with the following example:
241
242 ```python {test="skip" lint="skip"}
243 import dataclasses as stdlib_dc
244
245 import pydantic
246 import pydantic.dataclasses as pydantic_dc
247
248 @stdlib_dc.dataclass
249 class A:
250 a: int = pydantic.Field(repr=False)
251
252 # Notice that the `repr` attribute of the dataclass field is `True`:
253 A.__dataclass_fields__['a']
254 #> dataclass.Field(default=FieldInfo(repr=False), repr=True, ...)
255
256 @pydantic_dc.dataclass
257 class B(A):
258 b: int = pydantic.Field(repr=False)
259 ```
260
261 When passing `B` to the stdlib `@dataclass` decorator, it will look for fields in the parent classes
262 and reuse them directly. When this context manager is active, `A` will be temporarily patched to be
263 equivalent to:
264
265 ```python {test="skip" lint="skip"}
266 @stdlib_dc.dataclass
267 class A:
268 a: int = stdlib_dc.field(default=Field(repr=False), repr=False)
269 ```
270
271 !!! note
272 This is only applied to the bases of `cls`, and not `cls` itself. The reason is that the Pydantic
273 dataclass decorator "owns" `cls` (in the previous example, `B`). As such, we instead modify the fields
274 directly (in the previous example, we simply do `setattr(B, 'b', as_dataclass_field(pydantic_field))`).
275
276 !!! note
277 This approach is far from ideal, and can probably be the source of unwanted side effects/race conditions.
278 The previous implemented approach was mutating the `__annotations__` dict of `cls`, which is no longer a
279 safe operation in Python 3.14+, and resulted in unexpected behavior with field ordering anyway.
280 """
281 # A list of two-tuples, the first element being a reference to the
282 # dataclass fields dictionary, the second element being a mapping between
283 # the field names that were modified, and their original `Field`:
284 original_fields_list: list[tuple[DcFields, DcFields]] = []
285
286 for base in cls.__mro__[1:]:
287 dc_fields: dict[str, dataclasses.Field[Any]] = base.__dict__.get('__dataclass_fields__', {})

Callers

nothing calls this directly

Calls 3

getMethod · 0.45
itemsMethod · 0.45
copyMethod · 0.45

Tested by

no test coverage detected