_model_construction.py 38 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868
  1. """Private logic for creating models."""
  2. from __future__ import annotations as _annotations
  3. import operator
  4. import sys
  5. import typing
  6. import warnings
  7. import weakref
  8. from abc import ABCMeta
  9. from functools import cache, partial, wraps
  10. from types import FunctionType
  11. from typing import TYPE_CHECKING, Any, Callable, Generic, Literal, NoReturn, TypeVar, cast
  12. from pydantic_core import PydanticUndefined, SchemaSerializer
  13. from typing_extensions import TypeAliasType, dataclass_transform, deprecated, get_args, get_origin
  14. from typing_inspection import typing_objects
  15. from ..errors import PydanticUndefinedAnnotation, PydanticUserError
  16. from ..plugin._schema_validator import create_schema_validator
  17. from ..warnings import GenericBeforeBaseModelWarning, PydanticDeprecatedSince20
  18. from ._config import ConfigWrapper
  19. from ._decorators import DecoratorInfos, PydanticDescriptorProxy, get_attribute_from_bases, unwrap_wrapped_function
  20. from ._fields import collect_model_fields, is_valid_field_name, is_valid_privateattr_name, rebuild_model_fields
  21. from ._generate_schema import GenerateSchema, InvalidSchemaError
  22. from ._generics import PydanticGenericMetadata, get_model_typevars_map
  23. from ._import_utils import import_cached_base_model, import_cached_field_info
  24. from ._mock_val_ser import set_model_mocks
  25. from ._namespace_utils import NsResolver
  26. from ._signature import generate_pydantic_signature
  27. from ._typing_extra import (
  28. _make_forward_ref,
  29. eval_type_backport,
  30. is_classvar_annotation,
  31. parent_frame_namespace,
  32. )
  33. from ._utils import LazyClassAttribute, SafeGetItemProxy
  34. if TYPE_CHECKING:
  35. from ..fields import Field as PydanticModelField
  36. from ..fields import FieldInfo, ModelPrivateAttr
  37. from ..fields import PrivateAttr as PydanticModelPrivateAttr
  38. from ..main import BaseModel
  39. from ._fields import PydanticExtraInfo
  40. else:
  41. PydanticModelField = object()
  42. PydanticModelPrivateAttr = object()
  43. object_setattr = object.__setattr__
  44. class _ModelNamespaceDict(dict):
  45. """A dictionary subclass that intercepts attribute setting on model classes and
  46. warns about overriding of decorators.
  47. """
  48. def __setitem__(self, k: str, v: object) -> None:
  49. existing: Any = self.get(k, None)
  50. if existing and v is not existing and isinstance(existing, PydanticDescriptorProxy):
  51. warnings.warn(
  52. f'`{k}` overrides an existing Pydantic `{existing.decorator_info.decorator_repr}` decorator',
  53. stacklevel=2,
  54. )
  55. return super().__setitem__(k, v)
  56. def NoInitField(
  57. *,
  58. init: Literal[False] = False,
  59. ) -> Any:
  60. """Only for typing purposes. Used as default value of `__pydantic_fields_set__`,
  61. `__pydantic_extra__`, `__pydantic_private__`, so they could be ignored when
  62. synthesizing the `__init__` signature.
  63. """
  64. # For ModelMetaclass.register():
  65. _T = TypeVar('_T')
  66. @dataclass_transform(kw_only_default=True, field_specifiers=(PydanticModelField, PydanticModelPrivateAttr, NoInitField))
  67. class ModelMetaclass(ABCMeta):
  68. def __new__(
  69. mcs,
  70. cls_name: str,
  71. bases: tuple[type[Any], ...],
  72. namespace: dict[str, Any],
  73. __pydantic_generic_metadata__: PydanticGenericMetadata | None = None,
  74. __pydantic_reset_parent_namespace__: bool = True,
  75. _create_model_module: str | None = None,
  76. **kwargs: Any,
  77. ) -> type:
  78. """Metaclass for creating Pydantic models.
  79. Args:
  80. cls_name: The name of the class to be created.
  81. bases: The base classes of the class to be created.
  82. namespace: The attribute dictionary of the class to be created.
  83. __pydantic_generic_metadata__: Metadata for generic models.
  84. __pydantic_reset_parent_namespace__: Reset parent namespace.
  85. _create_model_module: The module of the class to be created, if created by `create_model`.
  86. **kwargs: Catch-all for any other keyword arguments.
  87. Returns:
  88. The new class created by the metaclass.
  89. """
  90. # Note `ModelMetaclass` refers to `BaseModel`, but is also used to *create* `BaseModel`, so we rely on the fact
  91. # that `BaseModel` itself won't have any bases, but any subclass of it will, to determine whether the `__new__`
  92. # call we're in the middle of is for the `BaseModel` class.
  93. if bases:
  94. raw_annotations: dict[str, Any]
  95. if sys.version_info >= (3, 14):
  96. if (
  97. '__annotations__' in namespace
  98. ): # `from __future__ import annotations` was used in the model's module
  99. raw_annotations = namespace['__annotations__']
  100. else:
  101. # See https://docs.python.org/3.14/library/annotationlib.html#using-annotations-in-a-metaclass:
  102. from annotationlib import Format, call_annotate_function, get_annotate_from_class_namespace
  103. if annotate := get_annotate_from_class_namespace(namespace):
  104. raw_annotations = call_annotate_function(annotate, format=Format.FORWARDREF)
  105. else:
  106. raw_annotations = {}
  107. else:
  108. raw_annotations = namespace.get('__annotations__', {})
  109. base_field_names, class_vars, base_private_attributes = mcs._collect_bases_data(bases)
  110. config_wrapper = ConfigWrapper.for_model(bases, namespace, raw_annotations, kwargs)
  111. namespace['model_config'] = config_wrapper.config_dict
  112. private_attributes = inspect_namespace(
  113. namespace, raw_annotations, config_wrapper.ignored_types, class_vars, base_field_names
  114. )
  115. if private_attributes or base_private_attributes:
  116. original_model_post_init = get_model_post_init(namespace, bases)
  117. if original_model_post_init is not None:
  118. # if there are private attributes and a model_post_init function, we handle both
  119. @wraps(original_model_post_init)
  120. def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None:
  121. """We need to both initialize private attributes and call the user-defined model_post_init
  122. method.
  123. """
  124. init_private_attributes(self, context)
  125. original_model_post_init(self, context)
  126. namespace['model_post_init'] = wrapped_model_post_init
  127. else:
  128. namespace['model_post_init'] = init_private_attributes
  129. namespace['__class_vars__'] = class_vars
  130. namespace['__private_attributes__'] = {**base_private_attributes, **private_attributes}
  131. cls = cast('type[BaseModel]', super().__new__(mcs, cls_name, bases, namespace, **kwargs))
  132. BaseModel_ = import_cached_base_model()
  133. mro = cls.__mro__
  134. if Generic in mro and mro.index(Generic) < mro.index(BaseModel_):
  135. warnings.warn(
  136. GenericBeforeBaseModelWarning(
  137. 'Classes should inherit from `BaseModel` before generic classes (e.g. `typing.Generic[T]`) '
  138. 'for pydantic generics to work properly.'
  139. ),
  140. stacklevel=2,
  141. )
  142. cls.__pydantic_custom_init__ = not getattr(cls.__init__, '__pydantic_base_init__', False)
  143. cls.__pydantic_post_init__ = (
  144. None if cls.model_post_init is BaseModel_.model_post_init else 'model_post_init'
  145. )
  146. cls.__pydantic_setattr_handlers__ = {}
  147. cls.__pydantic_decorators__ = DecoratorInfos.build(cls, replace_wrapped_methods=True)
  148. cls.__pydantic_decorators__.update_from_config(config_wrapper)
  149. # Use the getattr below to grab the __parameters__ from the `typing.Generic` parent class
  150. if __pydantic_generic_metadata__:
  151. cls.__pydantic_generic_metadata__ = __pydantic_generic_metadata__
  152. else:
  153. parent_parameters = getattr(cls, '__pydantic_generic_metadata__', {}).get('parameters', ())
  154. parameters = getattr(cls, '__parameters__', None) or parent_parameters
  155. if parameters and parent_parameters and not all(x in parameters for x in parent_parameters):
  156. from ..root_model import RootModelRootType
  157. missing_parameters = tuple(x for x in parameters if x not in parent_parameters)
  158. if RootModelRootType in parent_parameters and RootModelRootType not in parameters:
  159. # This is a special case where the user has subclassed RootModel, but has not parameterized
  160. # RootModel with the generic type identifiers being used. Ex:
  161. # class MyModel(RootModel, Generic[T]):
  162. # root: T
  163. # Should instead just be:
  164. # class MyModel(RootModel[T]):
  165. # root: T
  166. parameters_str = ', '.join([x.__name__ for x in missing_parameters])
  167. error_message = (
  168. f'{cls.__name__} is a subclass of `RootModel`, but does not include the generic type identifier(s) '
  169. f'{parameters_str} in its parameters. '
  170. f'You should parametrize RootModel directly, e.g., `class {cls.__name__}(RootModel[{parameters_str}]): ...`.'
  171. )
  172. else:
  173. combined_parameters = parent_parameters + missing_parameters
  174. parameters_str = ', '.join([str(x) for x in combined_parameters])
  175. generic_type_label = f'typing.Generic[{parameters_str}]'
  176. error_message = (
  177. f'All parameters must be present on typing.Generic;'
  178. f' you should inherit from {generic_type_label}.'
  179. )
  180. if Generic not in bases: # pragma: no cover
  181. # We raise an error here not because it is desirable, but because some cases are mishandled.
  182. # It would be nice to remove this error and still have things behave as expected, it's just
  183. # challenging because we are using a custom `__class_getitem__` to parametrize generic models,
  184. # and not returning a typing._GenericAlias from it.
  185. bases_str = ', '.join([x.__name__ for x in bases] + [generic_type_label])
  186. error_message += (
  187. f' Note: `typing.Generic` must go last: `class {cls.__name__}({bases_str}): ...`)'
  188. )
  189. raise TypeError(error_message)
  190. cls.__pydantic_generic_metadata__ = {
  191. 'origin': None,
  192. 'args': (),
  193. 'parameters': parameters,
  194. }
  195. cls.__pydantic_complete__ = False # Ensure this specific class gets completed
  196. # preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487
  197. # for attributes not in `new_namespace` (e.g. private attributes)
  198. for name, obj in private_attributes.items():
  199. obj.__set_name__(cls, name)
  200. if __pydantic_reset_parent_namespace__:
  201. cls.__pydantic_parent_namespace__ = build_lenient_weakvaluedict(parent_frame_namespace())
  202. parent_namespace: dict[str, Any] | None = getattr(cls, '__pydantic_parent_namespace__', None)
  203. if isinstance(parent_namespace, dict):
  204. parent_namespace = unpack_lenient_weakvaluedict(parent_namespace)
  205. ns_resolver = NsResolver(parent_namespace=parent_namespace)
  206. set_model_fields(cls, config_wrapper=config_wrapper, ns_resolver=ns_resolver)
  207. # This is also set in `complete_model_class()`, after schema gen because they are recreated.
  208. # We set them here as well for backwards compatibility:
  209. cls.__pydantic_computed_fields__ = {
  210. k: v.info for k, v in cls.__pydantic_decorators__.computed_fields.items()
  211. }
  212. if config_wrapper.defer_build:
  213. set_model_mocks(cls)
  214. else:
  215. # Any operation that requires accessing the field infos instances should be put inside
  216. # `complete_model_class()`:
  217. complete_model_class(
  218. cls,
  219. config_wrapper,
  220. ns_resolver,
  221. raise_errors=False,
  222. create_model_module=_create_model_module,
  223. )
  224. if config_wrapper.frozen and '__hash__' not in namespace:
  225. set_default_hash_func(cls, bases)
  226. # using super(cls, cls) on the next line ensures we only call the parent class's __pydantic_init_subclass__
  227. # I believe the `type: ignore` is only necessary because mypy doesn't realize that this code branch is
  228. # only hit for _proper_ subclasses of BaseModel
  229. super(cls, cls).__pydantic_init_subclass__(**kwargs) # type: ignore[misc]
  230. return cls
  231. else:
  232. # These are instance variables, but have been assigned to `NoInitField` to trick the type checker.
  233. for instance_slot in '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__':
  234. namespace.pop(
  235. instance_slot,
  236. None, # In case the metaclass is used with a class other than `BaseModel`.
  237. )
  238. namespace.get('__annotations__', {}).clear()
  239. return super().__new__(mcs, cls_name, bases, namespace, **kwargs)
  240. if not TYPE_CHECKING: # pragma: no branch
  241. # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access
  242. def __getattr__(self, item: str) -> Any:
  243. """This is necessary to keep attribute access working for class attribute access."""
  244. private_attributes = self.__dict__.get('__private_attributes__')
  245. if private_attributes and item in private_attributes:
  246. return private_attributes[item]
  247. raise AttributeError(item)
  248. @classmethod
  249. def __prepare__(cls, *args: Any, **kwargs: Any) -> dict[str, object]:
  250. return _ModelNamespaceDict()
  251. # Due to performance and memory issues, in the ABCMeta.__subclasscheck__ implementation, we don't support
  252. # registered virtual subclasses. See https://github.com/python/cpython/issues/92810#issuecomment-2762454345.
  253. # This may change once CPython is fixed (possibly in 3.15), in which case we should conditionally
  254. # define `register()`.
  255. def register(self, subclass: type[_T]) -> type[_T]:
  256. warnings.warn(
  257. f"For performance reasons, virtual subclasses registered using '{self.__qualname__}.register()' "
  258. "are not supported in 'isinstance()' and 'issubclass()' checks.",
  259. stacklevel=2,
  260. )
  261. return super().register(subclass)
  262. __instancecheck__ = type.__instancecheck__ # pyright: ignore[reportAssignmentType]
  263. __subclasscheck__ = type.__subclasscheck__ # pyright: ignore[reportAssignmentType]
  264. @staticmethod
  265. def _collect_bases_data(bases: tuple[type[Any], ...]) -> tuple[set[str], set[str], dict[str, ModelPrivateAttr]]:
  266. BaseModel = import_cached_base_model()
  267. field_names: set[str] = set()
  268. class_vars: set[str] = set()
  269. private_attributes: dict[str, ModelPrivateAttr] = {}
  270. for base in bases:
  271. if issubclass(base, BaseModel) and base is not BaseModel:
  272. # model_fields might not be defined yet in the case of generics, so we use getattr here:
  273. field_names.update(getattr(base, '__pydantic_fields__', {}).keys())
  274. class_vars.update(base.__class_vars__)
  275. private_attributes.update(base.__private_attributes__)
  276. return field_names, class_vars, private_attributes
  277. @property
  278. @deprecated(
  279. 'The `__fields__` attribute is deprecated, use the `model_fields` class property instead.', category=None
  280. )
  281. def __fields__(self) -> dict[str, FieldInfo]:
  282. warnings.warn(
  283. 'The `__fields__` attribute is deprecated, use the `model_fields` class property instead.',
  284. PydanticDeprecatedSince20,
  285. stacklevel=2,
  286. )
  287. return getattr(self, '__pydantic_fields__', {})
  288. @property
  289. def __pydantic_fields_complete__(self) -> bool:
  290. """Whether the fields were successfully collected (i.e. type hints were successfully resolved).
  291. This is a private attribute, not meant to be used outside Pydantic.
  292. """
  293. if '__pydantic_fields__' not in self.__dict__:
  294. return False
  295. field_infos = cast('dict[str, FieldInfo]', self.__pydantic_fields__) # pyright: ignore[reportAttributeAccessIssue]
  296. pydantic_extra_info = cast('PydanticExtraInfo | None', self.__pydantic_extra_info__) # pyright: ignore[reportAttributeAccessIssue]
  297. if pydantic_extra_info is not None:
  298. extra_complete = pydantic_extra_info.complete
  299. else:
  300. extra_complete = True
  301. return all(field_info._complete for field_info in field_infos.values()) and extra_complete
  302. def __dir__(self) -> list[str]:
  303. attributes = list(super().__dir__())
  304. if '__fields__' in attributes:
  305. attributes.remove('__fields__')
  306. return attributes
  307. def init_private_attributes(self: BaseModel, context: Any, /) -> None:
  308. """This function is meant to behave like a BaseModel method to initialize private attributes.
  309. It takes context as an argument since that's what pydantic-core passes when calling it.
  310. Args:
  311. self: The BaseModel instance.
  312. context: The context.
  313. """
  314. if getattr(self, '__pydantic_private__', None) is None:
  315. pydantic_private = {}
  316. for name, private_attr in self.__private_attributes__.items():
  317. # Avoid needlessly creating a new dict for the validated data:
  318. if private_attr.default_factory_takes_validated_data:
  319. default = private_attr.get_default(
  320. call_default_factory=True, validated_data={**self.__dict__, **pydantic_private}
  321. )
  322. else:
  323. default = private_attr.get_default(call_default_factory=True)
  324. if default is not PydanticUndefined:
  325. pydantic_private[name] = default
  326. object_setattr(self, '__pydantic_private__', pydantic_private)
  327. def get_model_post_init(namespace: dict[str, Any], bases: tuple[type[Any], ...]) -> Callable[..., Any] | None:
  328. """Get the `model_post_init` method from the namespace or the class bases, or `None` if not defined."""
  329. if 'model_post_init' in namespace:
  330. return namespace['model_post_init']
  331. BaseModel = import_cached_base_model()
  332. model_post_init = get_attribute_from_bases(bases, 'model_post_init')
  333. if model_post_init is not BaseModel.model_post_init:
  334. return model_post_init
  335. def inspect_namespace( # noqa C901
  336. namespace: dict[str, Any],
  337. raw_annotations: dict[str, Any],
  338. ignored_types: tuple[type[Any], ...],
  339. base_class_vars: set[str],
  340. base_class_fields: set[str],
  341. ) -> dict[str, ModelPrivateAttr]:
  342. """Iterate over the namespace and:
  343. * gather private attributes
  344. * check for items which look like fields but are not (e.g. have no annotation) and warn.
  345. Args:
  346. namespace: The attribute dictionary of the class to be created.
  347. raw_annotations: The (non-evaluated) annotations of the model.
  348. ignored_types: A tuple of ignore types.
  349. base_class_vars: A set of base class class variables.
  350. base_class_fields: A set of base class fields.
  351. Returns:
  352. A dict containing private attributes info.
  353. Raises:
  354. TypeError: If there is a `__root__` field in model.
  355. NameError: If private attribute name is invalid.
  356. PydanticUserError:
  357. - If a field does not have a type annotation.
  358. - If a field on base class was overridden by a non-annotated attribute.
  359. """
  360. from ..fields import ModelPrivateAttr, PrivateAttr
  361. FieldInfo = import_cached_field_info()
  362. all_ignored_types = ignored_types + default_ignored_types()
  363. private_attributes: dict[str, ModelPrivateAttr] = {}
  364. if '__root__' in raw_annotations or '__root__' in namespace:
  365. raise TypeError("To define root models, use `pydantic.RootModel` rather than a field called '__root__'")
  366. ignored_names: set[str] = set()
  367. for var_name, value in list(namespace.items()):
  368. if var_name == 'model_config' or var_name == '__pydantic_extra__':
  369. continue
  370. elif (
  371. isinstance(value, type)
  372. and value.__module__ == namespace['__module__']
  373. and '__qualname__' in namespace
  374. and value.__qualname__.startswith(f'{namespace["__qualname__"]}.')
  375. ):
  376. # `value` is a nested type defined in this namespace; don't error
  377. continue
  378. elif isinstance(value, all_ignored_types) or value.__class__.__module__ == 'functools':
  379. ignored_names.add(var_name)
  380. continue
  381. elif isinstance(value, ModelPrivateAttr):
  382. if var_name.startswith('__'):
  383. raise NameError(
  384. 'Private attributes must not use dunder names;'
  385. f' use a single underscore prefix instead of {var_name!r}.'
  386. )
  387. elif is_valid_field_name(var_name):
  388. raise NameError(
  389. 'Private attributes must not use valid field names;'
  390. f' use sunder names, e.g. {"_" + var_name!r} instead of {var_name!r}.'
  391. )
  392. private_attributes[var_name] = value
  393. del namespace[var_name]
  394. elif isinstance(value, FieldInfo) and not is_valid_field_name(var_name):
  395. suggested_name = var_name.lstrip('_') or 'my_field' # don't suggest '' for all-underscore name
  396. raise NameError(
  397. f'Fields must not use names with leading underscores;'
  398. f' e.g., use {suggested_name!r} instead of {var_name!r}.'
  399. )
  400. elif var_name.startswith('__'):
  401. continue
  402. elif is_valid_privateattr_name(var_name):
  403. if var_name not in raw_annotations or not is_classvar_annotation(raw_annotations[var_name]):
  404. private_attributes[var_name] = cast(ModelPrivateAttr, PrivateAttr(default=value))
  405. del namespace[var_name]
  406. elif var_name in base_class_vars:
  407. continue
  408. elif var_name not in raw_annotations:
  409. if var_name in base_class_fields:
  410. raise PydanticUserError(
  411. f'Field {var_name!r} defined on a base class was overridden by a non-annotated attribute. '
  412. f'All field definitions, including overrides, require a type annotation.',
  413. code='model-field-overridden',
  414. )
  415. elif isinstance(value, FieldInfo):
  416. raise PydanticUserError(
  417. f'Field {var_name!r} requires a type annotation', code='model-field-missing-annotation'
  418. )
  419. else:
  420. raise PydanticUserError(
  421. f'A non-annotated attribute was detected: `{var_name} = {value!r}`. All model fields require a '
  422. f'type annotation; if `{var_name}` is not meant to be a field, you may be able to resolve this '
  423. f"error by annotating it as a `ClassVar` or updating `model_config['ignored_types']`.",
  424. code='model-field-missing-annotation',
  425. )
  426. for ann_name, ann_type in raw_annotations.items():
  427. if (
  428. is_valid_privateattr_name(ann_name)
  429. and ann_name not in private_attributes
  430. and ann_name not in ignored_names
  431. # This condition can be a false negative when `ann_type` is stringified,
  432. # but it is handled in most cases in `set_model_fields`:
  433. and not is_classvar_annotation(ann_type)
  434. and ann_type not in all_ignored_types
  435. and getattr(ann_type, '__module__', None) != 'functools'
  436. ):
  437. if isinstance(ann_type, str):
  438. # Walking up the frames to get the module namespace where the model is defined
  439. # (as the model class wasn't created yet, we unfortunately can't use `cls.__module__`):
  440. frame = sys._getframe(2)
  441. if frame is not None:
  442. try:
  443. ann_type = eval_type_backport(
  444. _make_forward_ref(ann_type, is_argument=False, is_class=True),
  445. globalns=frame.f_globals,
  446. localns=frame.f_locals,
  447. )
  448. except (NameError, TypeError):
  449. pass
  450. if typing_objects.is_annotated(get_origin(ann_type)):
  451. _, *metadata = get_args(ann_type)
  452. private_attr = next((v for v in metadata if isinstance(v, ModelPrivateAttr)), None)
  453. if private_attr is not None:
  454. private_attributes[ann_name] = private_attr
  455. continue
  456. private_attributes[ann_name] = PrivateAttr()
  457. return private_attributes
  458. def set_default_hash_func(cls: type[BaseModel], bases: tuple[type[Any], ...]) -> None:
  459. base_hash_func = get_attribute_from_bases(bases, '__hash__')
  460. new_hash_func = make_hash_func(cls)
  461. if base_hash_func in {None, object.__hash__} or getattr(base_hash_func, '__code__', None) == new_hash_func.__code__:
  462. # If `__hash__` is some default, we generate a hash function.
  463. # It will be `None` if not overridden from BaseModel.
  464. # It may be `object.__hash__` if there is another
  465. # parent class earlier in the bases which doesn't override `__hash__` (e.g. `typing.Generic`).
  466. # It may be a value set by `set_default_hash_func` if `cls` is a subclass of another frozen model.
  467. # In the last case we still need a new hash function to account for new `model_fields`.
  468. cls.__hash__ = new_hash_func
  469. def make_hash_func(cls: type[BaseModel]) -> Any:
  470. getter = operator.itemgetter(*cls.__pydantic_fields__.keys()) if cls.__pydantic_fields__ else lambda _: 0
  471. def hash_func(self: Any) -> int:
  472. try:
  473. return hash(getter(self.__dict__))
  474. except KeyError:
  475. # In rare cases (such as when using the deprecated copy method), the __dict__ may not contain
  476. # all model fields, which is how we can get here.
  477. # getter(self.__dict__) is much faster than any 'safe' method that accounts for missing keys,
  478. # and wrapping it in a `try` doesn't slow things down much in the common case.
  479. return hash(getter(SafeGetItemProxy(self.__dict__)))
  480. return hash_func
  481. def set_model_fields(
  482. cls: type[BaseModel],
  483. config_wrapper: ConfigWrapper,
  484. ns_resolver: NsResolver,
  485. ) -> None:
  486. """Collect and set `cls.__pydantic_fields__` and `cls.__class_vars__`.
  487. Args:
  488. cls: BaseModel or dataclass.
  489. config_wrapper: The config wrapper instance.
  490. ns_resolver: Namespace resolver to use when getting model annotations.
  491. """
  492. typevars_map = get_model_typevars_map(cls)
  493. fields, pydantic_extra_info, class_vars = collect_model_fields(
  494. cls, config_wrapper, ns_resolver, typevars_map=typevars_map
  495. )
  496. cls.__pydantic_fields__ = fields
  497. cls.__pydantic_extra_info__ = pydantic_extra_info
  498. cls.__class_vars__.update(class_vars)
  499. for k in class_vars:
  500. # Class vars should not be private attributes
  501. # We remove them _here_ and not earlier because we rely on inspecting the class to determine its classvars,
  502. # but private attributes are determined by inspecting the namespace _prior_ to class creation.
  503. # In the case that a classvar with a leading-'_' is defined via a ForwardRef (e.g., when using
  504. # `__future__.annotations`), we want to remove the private attribute which was detected _before_ we knew it
  505. # evaluated to a classvar
  506. value = cls.__private_attributes__.pop(k, None)
  507. if value is not None and value.default is not PydanticUndefined:
  508. setattr(cls, k, value.default)
  509. def complete_model_class(
  510. cls: type[BaseModel],
  511. config_wrapper: ConfigWrapper,
  512. ns_resolver: NsResolver,
  513. *,
  514. raise_errors: bool = True,
  515. call_on_complete_hook: bool = True,
  516. create_model_module: str | None = None,
  517. is_force_rebuild: bool = False,
  518. ) -> bool:
  519. """Finish building a model class.
  520. This logic must be called after class has been created since validation functions must be bound
  521. and `get_type_hints` requires a class object.
  522. Args:
  523. cls: BaseModel or dataclass.
  524. config_wrapper: The config wrapper instance.
  525. ns_resolver: The namespace resolver instance to use during schema building.
  526. raise_errors: Whether to raise errors.
  527. call_on_complete_hook: Whether to call the `__pydantic_on_complete__` hook.
  528. create_model_module: The module of the class to be created, if created by `create_model`.
  529. is_force_rebuild: Whether the model is being force-rebuilt (if True, pre-built serializers and
  530. validators are not used, to avoid stale references).
  531. Returns:
  532. `True` if the model is successfully completed, else `False`.
  533. Raises:
  534. PydanticUndefinedAnnotation: If PydanticUndefinedAnnotation occurs in __get_pydantic_core_schema__
  535. and `raise_errors=True`.
  536. """
  537. typevars_map = get_model_typevars_map(cls)
  538. if not cls.__pydantic_fields_complete__:
  539. # Note: when coming from `ModelMetaclass.__new__()`, this results in fields being built twice.
  540. # We do so a second time here so that we can get the ``NameError`` for the specific undefined annotation.
  541. # Alternatively, we could let `GenerateSchema()` raise the error, but there are cases where incomplete
  542. # fields are inherited in `collect_model_fields()` and can actually have their annotation resolved in the
  543. # generate schema process. As we want to avoid having `__pydantic_fields_complete__` set to `False`
  544. # when `__pydantic_complete__` is `True`, we rebuild here:
  545. try:
  546. cls.__pydantic_fields__, cls.__pydantic_extra_info__ = rebuild_model_fields(
  547. cls,
  548. config_wrapper=config_wrapper,
  549. ns_resolver=ns_resolver,
  550. typevars_map=typevars_map,
  551. )
  552. except NameError as e:
  553. exc = PydanticUndefinedAnnotation.from_name_error(e)
  554. set_model_mocks(cls, f'`{exc.name}`')
  555. if raise_errors:
  556. raise exc from e
  557. if not raise_errors and not cls.__pydantic_fields_complete__:
  558. # No need to continue with schema gen, it is guaranteed to fail
  559. return False
  560. assert cls.__pydantic_fields_complete__
  561. gen_schema = GenerateSchema(
  562. config_wrapper,
  563. ns_resolver,
  564. typevars_map,
  565. )
  566. try:
  567. schema = gen_schema.generate_schema(cls)
  568. except PydanticUndefinedAnnotation as e:
  569. if raise_errors:
  570. raise
  571. set_model_mocks(cls, f'`{e.name}`')
  572. return False
  573. core_config = config_wrapper.core_config(title=cls.__name__)
  574. try:
  575. schema = gen_schema.clean_schema(schema)
  576. except InvalidSchemaError:
  577. set_model_mocks(cls)
  578. return False
  579. # This needs to happen *after* model schema generation, as the return types
  580. # of the properties are evaluated and the `ComputedFieldInfo` are recreated:
  581. cls.__pydantic_computed_fields__ = {k: v.info for k, v in cls.__pydantic_decorators__.computed_fields.items()}
  582. set_deprecated_descriptors(cls)
  583. cls.__pydantic_core_schema__ = schema
  584. cls.__pydantic_validator__ = create_schema_validator(
  585. schema,
  586. cls,
  587. create_model_module or cls.__module__,
  588. cls.__qualname__,
  589. 'create_model' if create_model_module else 'BaseModel',
  590. core_config,
  591. config_wrapper.plugin_settings,
  592. _use_prebuilt=not is_force_rebuild,
  593. )
  594. cls.__pydantic_serializer__ = SchemaSerializer(schema, core_config, _use_prebuilt=not is_force_rebuild)
  595. # set __signature__ attr only for model class, but not for its instances
  596. # (because instances can define `__call__`, and `inspect.signature` shouldn't
  597. # use the `__signature__` attribute and instead generate from `__call__`).
  598. cls.__signature__ = LazyClassAttribute(
  599. '__signature__',
  600. partial(
  601. generate_pydantic_signature,
  602. init=cls.__init__,
  603. fields=cls.__pydantic_fields__,
  604. validate_by_name=config_wrapper.validate_by_name,
  605. extra=config_wrapper.extra,
  606. ),
  607. )
  608. cls.__pydantic_complete__ = True
  609. if call_on_complete_hook:
  610. cls.__pydantic_on_complete__()
  611. return True
  612. def set_deprecated_descriptors(cls: type[BaseModel]) -> None:
  613. """Set data descriptors on the class for deprecated fields."""
  614. for field, field_info in cls.__pydantic_fields__.items():
  615. if (msg := field_info.deprecation_message) is not None:
  616. desc = _DeprecatedFieldDescriptor(msg)
  617. desc.__set_name__(cls, field)
  618. setattr(cls, field, desc)
  619. for field, computed_field_info in cls.__pydantic_computed_fields__.items():
  620. if (
  621. (msg := computed_field_info.deprecation_message) is not None
  622. # Avoid having two warnings emitted:
  623. and not hasattr(unwrap_wrapped_function(computed_field_info.wrapped_property), '__deprecated__')
  624. ):
  625. desc = _DeprecatedFieldDescriptor(msg, computed_field_info.wrapped_property)
  626. desc.__set_name__(cls, field)
  627. setattr(cls, field, desc)
  628. class _DeprecatedFieldDescriptor:
  629. """Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
  630. Attributes:
  631. msg: The deprecation message to be emitted.
  632. wrapped_property: The property instance if the deprecated field is a computed field, or `None`.
  633. field_name: The name of the field being deprecated.
  634. """
  635. field_name: str
  636. def __init__(self, msg: str, wrapped_property: property | None = None) -> None:
  637. self.msg = msg
  638. self.wrapped_property = wrapped_property
  639. def __set_name__(self, cls: type[BaseModel], name: str) -> None:
  640. self.field_name = name
  641. def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any:
  642. if obj is None:
  643. if self.wrapped_property is not None:
  644. return self.wrapped_property.__get__(None, obj_type)
  645. raise AttributeError(self.field_name)
  646. warnings.warn(self.msg, DeprecationWarning, stacklevel=2)
  647. if self.wrapped_property is not None:
  648. return self.wrapped_property.__get__(obj, obj_type)
  649. return obj.__dict__[self.field_name]
  650. # Defined to make it a data descriptor and take precedence over the instance's dictionary.
  651. # Note that it will not be called when setting a value on a model instance
  652. # as `BaseModel.__setattr__` is defined and takes priority.
  653. def __set__(self, obj: Any, value: Any) -> NoReturn:
  654. raise AttributeError(self.field_name)
  655. class _PydanticWeakRef:
  656. """Wrapper for `weakref.ref` that enables `pickle` serialization.
  657. Cloudpickle fails to serialize weakref.ref objects due to an arcane error related to
  658. to abstract base classes (`abc.ABC`). This class works around the issue by wrapping
  659. `weakref.ref` instead of subclassing it.
  660. See https://github.com/pydantic/pydantic/issues/6763 for context.
  661. Semantics:
  662. - If not pickled, behaves the same as a `weakref.ref`.
  663. - If pickled along with the referenced object, the same `weakref.ref` behavior
  664. will be maintained between them after unpickling.
  665. - If pickled without the referenced object, after unpickling the underlying
  666. reference will be cleared (`__call__` will always return `None`).
  667. """
  668. def __init__(self, obj: Any):
  669. if obj is None:
  670. # The object will be `None` upon deserialization if the serialized weakref
  671. # had lost its underlying object.
  672. self._wr = None
  673. else:
  674. self._wr = weakref.ref(obj)
  675. def __call__(self) -> Any:
  676. if self._wr is None:
  677. return None
  678. else:
  679. return self._wr()
  680. def __reduce__(self) -> tuple[Callable, tuple[weakref.ReferenceType | None]]:
  681. return _PydanticWeakRef, (self(),)
  682. def build_lenient_weakvaluedict(d: dict[str, Any] | None) -> dict[str, Any] | None:
  683. """Takes an input dictionary, and produces a new value that (invertibly) replaces the values with weakrefs.
  684. We can't just use a WeakValueDictionary because many types (including int, str, etc.) can't be stored as values
  685. in a WeakValueDictionary.
  686. The `unpack_lenient_weakvaluedict` function can be used to reverse this operation.
  687. """
  688. if d is None:
  689. return None
  690. result = {}
  691. for k, v in d.items():
  692. try:
  693. proxy = _PydanticWeakRef(v)
  694. except TypeError:
  695. proxy = v
  696. result[k] = proxy
  697. return result
  698. def unpack_lenient_weakvaluedict(d: dict[str, Any] | None) -> dict[str, Any] | None:
  699. """Inverts the transform performed by `build_lenient_weakvaluedict`."""
  700. if d is None:
  701. return None
  702. result = {}
  703. for k, v in d.items():
  704. if isinstance(v, _PydanticWeakRef):
  705. v = v()
  706. if v is not None:
  707. result[k] = v
  708. else:
  709. result[k] = v
  710. return result
  711. @cache
  712. def default_ignored_types() -> tuple[type[Any], ...]:
  713. from ..fields import ComputedFieldInfo
  714. ignored_types = [
  715. FunctionType,
  716. property,
  717. classmethod,
  718. staticmethod,
  719. PydanticDescriptorProxy,
  720. ComputedFieldInfo,
  721. TypeAliasType, # from `typing_extensions`
  722. ]
  723. if sys.version_info >= (3, 12):
  724. ignored_types.append(typing.TypeAliasType)
  725. return tuple(ignored_types)