Coverage for pydantic/_internal/_model_construction.py: 99.11%
306 statements
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-03 19:29 +0000
« prev ^ index » next coverage.py v7.5.4, created at 2024-07-03 19:29 +0000
1"""Private logic for creating models."""
3from __future__ import annotations as _annotations 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
5import builtins 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
6import operator 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
7import typing 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
8import warnings 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
9import weakref 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
10from abc import ABCMeta 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
11from functools import partial 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
12from types import FunctionType 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
13from typing import Any, Callable, Generic, NoReturn 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
15import typing_extensions 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
16from pydantic_core import PydanticUndefined, SchemaSerializer 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
17from typing_extensions import dataclass_transform, deprecated 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
19from ..errors import PydanticUndefinedAnnotation, PydanticUserError 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
20from ..plugin._schema_validator import create_schema_validator 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
21from ..warnings import GenericBeforeBaseModelWarning, PydanticDeprecatedSince20 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
22from ._config import ConfigWrapper 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
23from ._decorators import DecoratorInfos, PydanticDescriptorProxy, get_attribute_from_bases, unwrap_wrapped_function 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
24from ._fields import collect_model_fields, is_valid_field_name, is_valid_privateattr_name 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
25from ._generate_schema import GenerateSchema 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
26from ._generics import PydanticGenericMetadata, get_model_typevars_map 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
27from ._mock_val_ser import set_model_mocks 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
28from ._schema_generation_shared import CallbackGetCoreSchemaHandler 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
29from ._signature import generate_pydantic_signature 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
30from ._typing_extra import get_cls_types_namespace, is_annotated, is_classvar, parent_frame_namespace 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
31from ._utils import ClassAttribute, SafeGetItemProxy 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
32from ._validate_call import ValidateCallWrapper 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
34if typing.TYPE_CHECKING: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
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
39else:
40 # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915
41 # and https://youtrack.jetbrains.com/issue/PY-51428
42 DeprecationWarning = PydanticDeprecatedSince20 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
43 PydanticModelField = object() 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
44 PydanticModelPrivateAttr = object() 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
46object_setattr = object.__setattr__ 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
49class _ModelNamespaceDict(dict): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
50 """A dictionary subclass that intercepts attribute setting on model classes and
51 warns about overriding of decorators.
52 """
54 def __setitem__(self, k: str, v: object) -> None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
55 existing: Any = self.get(k, None) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
56 if existing and v is not existing and isinstance(existing, PydanticDescriptorProxy): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
57 warnings.warn(f'`{k}` overrides an existing Pydantic `{existing.decorator_info.decorator_repr}` decorator') 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
59 return super().__setitem__(k, v) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
62@dataclass_transform(kw_only_default=True, field_specifiers=(PydanticModelField, PydanticModelPrivateAttr)) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
63class ModelMetaclass(ABCMeta): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
64 def __new__( 1abcdmnopABCDefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
65 mcs,
66 cls_name: str,
67 bases: tuple[type[Any], ...],
68 namespace: dict[str, Any],
69 __pydantic_generic_metadata__: PydanticGenericMetadata | None = None,
70 __pydantic_reset_parent_namespace__: bool = True,
71 _create_model_module: str | None = None,
72 **kwargs: Any,
73 ) -> type:
74 """Metaclass for creating Pydantic models.
76 Args:
77 cls_name: The name of the class to be created.
78 bases: The base classes of the class to be created.
79 namespace: The attribute dictionary of the class to be created.
80 __pydantic_generic_metadata__: Metadata for generic models.
81 __pydantic_reset_parent_namespace__: Reset parent namespace.
82 _create_model_module: The module of the class to be created, if created by `create_model`.
83 **kwargs: Catch-all for any other keyword arguments.
85 Returns:
86 The new class created by the metaclass.
87 """
88 # Note `ModelMetaclass` refers to `BaseModel`, but is also used to *create* `BaseModel`, so we rely on the fact
89 # that `BaseModel` itself won't have any bases, but any subclass of it will, to determine whether the `__new__`
90 # call we're in the middle of is for the `BaseModel` class.
91 if bases: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
92 base_field_names, class_vars, base_private_attributes = mcs._collect_bases_data(bases) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
94 config_wrapper = ConfigWrapper.for_model(bases, namespace, kwargs) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
95 namespace['model_config'] = config_wrapper.config_dict 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
96 private_attributes = inspect_namespace( 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
97 namespace, config_wrapper.ignored_types, class_vars, base_field_names
98 )
99 if private_attributes or base_private_attributes: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
100 original_model_post_init = get_model_post_init(namespace, bases) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
101 if original_model_post_init is not None: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
102 # if there are private_attributes and a model_post_init function, we handle both
104 def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
105 """We need to both initialize private attributes and call the user-defined model_post_init
106 method.
107 """
108 init_private_attributes(self, context) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
109 original_model_post_init(self, context) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
111 namespace['model_post_init'] = wrapped_model_post_init 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
112 else:
113 namespace['model_post_init'] = init_private_attributes 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
115 namespace['__class_vars__'] = class_vars 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
116 namespace['__private_attributes__'] = {**base_private_attributes, **private_attributes} 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
118 cls: type[BaseModel] = super().__new__(mcs, cls_name, bases, namespace, **kwargs) # type: ignore 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
120 from ..main import BaseModel 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
122 mro = cls.__mro__ 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
123 if Generic in mro and mro.index(Generic) < mro.index(BaseModel): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
124 warnings.warn( 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
125 GenericBeforeBaseModelWarning(
126 'Classes should inherit from `BaseModel` before generic classes (e.g. `typing.Generic[T]`) '
127 'for pydantic generics to work properly.'
128 ),
129 stacklevel=2,
130 )
132 cls.__pydantic_custom_init__ = not getattr(cls.__init__, '__pydantic_base_init__', False) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
133 cls.__pydantic_post_init__ = None if cls.model_post_init is BaseModel.model_post_init else 'model_post_init' 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
135 cls.__pydantic_decorators__ = DecoratorInfos.build(cls) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
137 # Use the getattr below to grab the __parameters__ from the `typing.Generic` parent class
138 if __pydantic_generic_metadata__: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
139 cls.__pydantic_generic_metadata__ = __pydantic_generic_metadata__ 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
140 else:
141 parent_parameters = getattr(cls, '__pydantic_generic_metadata__', {}).get('parameters', ()) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
142 parameters = getattr(cls, '__parameters__', None) or parent_parameters 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
143 if parameters and parent_parameters and not all(x in parameters for x in parent_parameters): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
144 from ..root_model import RootModelRootType 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
146 missing_parameters = tuple(x for x in parameters if x not in parent_parameters) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
147 if RootModelRootType in parent_parameters and RootModelRootType not in parameters: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
148 # This is a special case where the user has subclassed `RootModel`, but has not parametrized
149 # RootModel with the generic type identifiers being used. Ex:
150 # class MyModel(RootModel, Generic[T]):
151 # root: T
152 # Should instead just be:
153 # class MyModel(RootModel[T]):
154 # root: T
155 parameters_str = ', '.join([x.__name__ for x in missing_parameters]) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
156 error_message = ( 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
157 f'{cls.__name__} is a subclass of `RootModel`, but does not include the generic type identifier(s) '
158 f'{parameters_str} in its parameters. '
159 f'You should parametrize RootModel directly, e.g., `class {cls.__name__}(RootModel[{parameters_str}]): ...`.'
160 )
161 else:
162 combined_parameters = parent_parameters + missing_parameters 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
163 parameters_str = ', '.join([str(x) for x in combined_parameters]) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
164 generic_type_label = f'typing.Generic[{parameters_str}]' 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
165 error_message = ( 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
166 f'All parameters must be present on typing.Generic;'
167 f' you should inherit from {generic_type_label}.'
168 )
169 if Generic not in bases: # pragma: no cover 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
170 # We raise an error here not because it is desirable, but because some cases are mishandled.
171 # It would be nice to remove this error and still have things behave as expected, it's just
172 # challenging because we are using a custom `__class_getitem__` to parametrize generic models,
173 # and not returning a typing._GenericAlias from it.
174 bases_str = ', '.join([x.__name__ for x in bases] + [generic_type_label]) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
175 error_message += ( 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
176 f' Note: `typing.Generic` must go last: `class {cls.__name__}({bases_str}): ...`)'
177 )
178 raise TypeError(error_message) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
180 cls.__pydantic_generic_metadata__ = { 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
181 'origin': None,
182 'args': (),
183 'parameters': parameters,
184 }
186 cls.__pydantic_complete__ = False # Ensure this specific class gets completed 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
188 # preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487
189 # for attributes not in `new_namespace` (e.g. private attributes)
190 for name, obj in private_attributes.items(): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
191 obj.__set_name__(cls, name) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
193 if __pydantic_reset_parent_namespace__: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
194 cls.__pydantic_parent_namespace__ = build_lenient_weakvaluedict(parent_frame_namespace()) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
195 parent_namespace = getattr(cls, '__pydantic_parent_namespace__', None) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
196 if isinstance(parent_namespace, dict): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
197 parent_namespace = unpack_lenient_weakvaluedict(parent_namespace) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
199 types_namespace = get_cls_types_namespace(cls, parent_namespace) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
200 set_model_fields(cls, bases, config_wrapper, types_namespace) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
202 if config_wrapper.frozen and '__hash__' not in namespace: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
203 set_default_hash_func(cls, bases) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
205 complete_model_class( 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
206 cls,
207 cls_name,
208 config_wrapper,
209 raise_errors=False,
210 types_namespace=types_namespace,
211 create_model_module=_create_model_module,
212 )
214 # If this is placed before the complete_model_class call above,
215 # the generic computed fields return type is set to PydanticUndefined
216 cls.model_computed_fields = {k: v.info for k, v in cls.__pydantic_decorators__.computed_fields.items()} 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
218 set_deprecated_descriptors(cls) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
220 # using super(cls, cls) on the next line ensures we only call the parent class's __pydantic_init_subclass__
221 # I believe the `type: ignore` is only necessary because mypy doesn't realize that this code branch is
222 # only hit for _proper_ subclasses of BaseModel
223 super(cls, cls).__pydantic_init_subclass__(**kwargs) # type: ignore[misc] 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
224 return cls 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
225 else:
226 # this is the BaseModel class itself being created, no logic required
227 return super().__new__(mcs, cls_name, bases, namespace, **kwargs) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
229 if not typing.TYPE_CHECKING: # pragma: no branch 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
230 # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access
232 def __getattr__(self, item: str) -> Any: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
233 """This is necessary to keep attribute access working for class attribute access."""
234 private_attributes = self.__dict__.get('__private_attributes__') 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
235 if private_attributes and item in private_attributes: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
236 return private_attributes[item] 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
237 raise AttributeError(item) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
239 @classmethod 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
240 def __prepare__(cls, *args: Any, **kwargs: Any) -> dict[str, object]: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
241 return _ModelNamespaceDict() 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
243 def __instancecheck__(self, instance: Any) -> bool: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
244 """Avoid calling ABC _abc_subclasscheck unless we're pretty sure.
246 See #3829 and python/cpython#92810
247 """
248 return hasattr(instance, '__pydantic_validator__') and super().__instancecheck__(instance) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
250 @staticmethod 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
251 def _collect_bases_data(bases: tuple[type[Any], ...]) -> tuple[set[str], set[str], dict[str, ModelPrivateAttr]]: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
252 from ..main import BaseModel 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
254 field_names: set[str] = set() 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
255 class_vars: set[str] = set() 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
256 private_attributes: dict[str, ModelPrivateAttr] = {} 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
257 for base in bases: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
258 if issubclass(base, BaseModel) and base is not BaseModel: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
259 # model_fields might not be defined yet in the case of generics, so we use getattr here:
260 field_names.update(getattr(base, 'model_fields', {}).keys()) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
261 class_vars.update(base.__class_vars__) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
262 private_attributes.update(base.__private_attributes__) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
263 return field_names, class_vars, private_attributes 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
265 @property 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
266 @deprecated('The `__fields__` attribute is deprecated, use `model_fields` instead.', category=None) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
267 def __fields__(self) -> dict[str, FieldInfo]: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
268 warnings.warn( 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
269 'The `__fields__` attribute is deprecated, use `model_fields` instead.', PydanticDeprecatedSince20
270 )
271 return self.model_fields # type: ignore 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
273 def __dir__(self) -> list[str]: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
274 attributes = list(super().__dir__()) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
275 if '__fields__' in attributes: 275 ↛ 277line 275 didn't jump to line 277 because the condition on line 275 was always true1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
276 attributes.remove('__fields__') 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
277 return attributes 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
280def init_private_attributes(self: BaseModel, context: Any, /) -> None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
281 """This function is meant to behave like a BaseModel method to initialise private attributes.
283 It takes context as an argument since that's what pydantic-core passes when calling it.
285 Args:
286 self: The BaseModel instance.
287 context: The context.
288 """
289 if getattr(self, '__pydantic_private__', None) is None: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
290 pydantic_private = {} 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
291 for name, private_attr in self.__private_attributes__.items(): 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
292 default = private_attr.get_default() 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
293 if default is not PydanticUndefined: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
294 pydantic_private[name] = default 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
295 object_setattr(self, '__pydantic_private__', pydantic_private) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
298def get_model_post_init(namespace: dict[str, Any], bases: tuple[type[Any], ...]) -> Callable[..., Any] | None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
299 """Get the `model_post_init` method from the namespace or the class bases, or `None` if not defined."""
300 if 'model_post_init' in namespace: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
301 return namespace['model_post_init'] 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
303 from ..main import BaseModel 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
305 model_post_init = get_attribute_from_bases(bases, 'model_post_init') 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
306 if model_post_init is not BaseModel.model_post_init: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
307 return model_post_init 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
310def inspect_namespace( # noqa C901 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
311 namespace: dict[str, Any],
312 ignored_types: tuple[type[Any], ...],
313 base_class_vars: set[str],
314 base_class_fields: set[str],
315) -> dict[str, ModelPrivateAttr]:
316 """Iterate over the namespace and:
317 * gather private attributes
318 * check for items which look like fields but are not (e.g. have no annotation) and warn.
320 Args:
321 namespace: The attribute dictionary of the class to be created.
322 ignored_types: A tuple of ignore types.
323 base_class_vars: A set of base class class variables.
324 base_class_fields: A set of base class fields.
326 Returns:
327 A dict contains private attributes info.
329 Raises:
330 TypeError: If there is a `__root__` field in model.
331 NameError: If private attribute name is invalid.
332 PydanticUserError:
333 - If a field does not have a type annotation.
334 - If a field on base class was overridden by a non-annotated attribute.
335 """
336 from ..fields import FieldInfo, ModelPrivateAttr, PrivateAttr 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
338 all_ignored_types = ignored_types + default_ignored_types() 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
340 private_attributes: dict[str, ModelPrivateAttr] = {} 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
341 raw_annotations = namespace.get('__annotations__', {}) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
343 if '__root__' in raw_annotations or '__root__' in namespace: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
344 raise TypeError("To define root models, use `pydantic.RootModel` rather than a field called '__root__'") 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
346 ignored_names: set[str] = set() 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
347 for var_name, value in list(namespace.items()): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
348 if var_name == 'model_config' or var_name == '__pydantic_extra__': 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
349 continue 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
350 elif ( 1abcdmnopqrefghstuvMNOPQRSTijklwxyz
351 isinstance(value, type)
352 and value.__module__ == namespace['__module__']
353 and '__qualname__' in namespace
354 and value.__qualname__.startswith(namespace['__qualname__'])
355 ):
356 # `value` is a nested type defined in this namespace; don't error
357 continue 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
358 elif isinstance(value, all_ignored_types) or value.__class__.__module__ == 'functools': 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
359 ignored_names.add(var_name) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
360 continue 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
361 elif isinstance(value, ModelPrivateAttr): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
362 if var_name.startswith('__'): 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
363 raise NameError( 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
364 'Private attributes must not use dunder names;'
365 f' use a single underscore prefix instead of {var_name!r}.'
366 )
367 elif is_valid_field_name(var_name): 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
368 raise NameError( 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
369 'Private attributes must not use valid field names;'
370 f' use sunder names, e.g. {"_" + var_name!r} instead of {var_name!r}.'
371 )
372 private_attributes[var_name] = value 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
373 del namespace[var_name] 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
374 elif isinstance(value, FieldInfo) and not is_valid_field_name(var_name): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
375 suggested_name = var_name.lstrip('_') or 'my_field' # don't suggest '' for all-underscore name 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
376 raise NameError( 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
377 f'Fields must not use names with leading underscores;'
378 f' e.g., use {suggested_name!r} instead of {var_name!r}.'
379 )
381 elif var_name.startswith('__'): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
382 continue 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
383 elif is_valid_privateattr_name(var_name): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
384 if var_name not in raw_annotations or not is_classvar(raw_annotations[var_name]): 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
385 private_attributes[var_name] = PrivateAttr(default=value) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
386 del namespace[var_name] 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
387 elif var_name in base_class_vars: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
388 continue 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
389 elif var_name not in raw_annotations: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
390 if var_name in base_class_fields: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
391 raise PydanticUserError( 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
392 f'Field {var_name!r} defined on a base class was overridden by a non-annotated attribute. '
393 f'All field definitions, including overrides, require a type annotation.',
394 code='model-field-overridden',
395 )
396 elif isinstance(value, FieldInfo): 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
397 raise PydanticUserError( 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
398 f'Field {var_name!r} requires a type annotation', code='model-field-missing-annotation'
399 )
400 else:
401 raise PydanticUserError( 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
402 f'A non-annotated attribute was detected: `{var_name} = {value!r}`. All model fields require a '
403 f'type annotation; if `{var_name}` is not meant to be a field, you may be able to resolve this '
404 f"error by annotating it as a `ClassVar` or updating `model_config['ignored_types']`.",
405 code='model-field-missing-annotation',
406 )
408 for ann_name, ann_type in raw_annotations.items(): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
409 if ( 1abcdmnopqrefghstuvMNOPQRSTijklwxyz
410 is_valid_privateattr_name(ann_name)
411 and ann_name not in private_attributes
412 and ann_name not in ignored_names
413 and not is_classvar(ann_type)
414 and ann_type not in all_ignored_types
415 and getattr(ann_type, '__module__', None) != 'functools'
416 ):
417 if is_annotated(ann_type): 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
418 _, *metadata = typing_extensions.get_args(ann_type) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
419 private_attr = next((v for v in metadata if isinstance(v, ModelPrivateAttr)), None) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
420 if private_attr is not None: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
421 private_attributes[ann_name] = private_attr 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
422 continue 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
423 private_attributes[ann_name] = PrivateAttr() 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
425 return private_attributes 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
428def set_default_hash_func(cls: type[BaseModel], bases: tuple[type[Any], ...]) -> None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
429 base_hash_func = get_attribute_from_bases(bases, '__hash__') 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
430 new_hash_func = make_hash_func(cls) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
431 if base_hash_func in {None, object.__hash__} or getattr(base_hash_func, '__code__', None) == new_hash_func.__code__: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
432 # If `__hash__` is some default, we generate a hash function.
433 # It will be `None` if not overridden from BaseModel.
434 # It may be `object.__hash__` if there is another
435 # parent class earlier in the bases which doesn't override `__hash__` (e.g. `typing.Generic`).
436 # It may be a value set by `set_default_hash_func` if `cls` is a subclass of another frozen model.
437 # In the last case we still need a new hash function to account for new `model_fields`.
438 cls.__hash__ = new_hash_func 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
441def make_hash_func(cls: type[BaseModel]) -> Any: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
442 getter = operator.itemgetter(*cls.model_fields.keys()) if cls.model_fields else lambda _: 0 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
444 def hash_func(self: Any) -> int: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
445 try: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
446 return hash(getter(self.__dict__)) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
447 except KeyError: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
448 # In rare cases (such as when using the deprecated copy method), the __dict__ may not contain
449 # all model fields, which is how we can get here.
450 # getter(self.__dict__) is much faster than any 'safe' method that accounts for missing keys,
451 # and wrapping it in a `try` doesn't slow things down much in the common case.
452 return hash(getter(SafeGetItemProxy(self.__dict__))) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
454 return hash_func 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
457def set_model_fields( 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
458 cls: type[BaseModel], bases: tuple[type[Any], ...], config_wrapper: ConfigWrapper, types_namespace: dict[str, Any]
459) -> None:
460 """Collect and set `cls.model_fields` and `cls.__class_vars__`.
462 Args:
463 cls: BaseModel or dataclass.
464 bases: Parents of the class, generally `cls.__bases__`.
465 config_wrapper: The config wrapper instance.
466 types_namespace: Optional extra namespace to look for types in.
467 """
468 typevars_map = get_model_typevars_map(cls) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
469 fields, class_vars = collect_model_fields(cls, bases, config_wrapper, types_namespace, typevars_map=typevars_map) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
471 cls.model_fields = fields 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
472 cls.__class_vars__.update(class_vars) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
474 for k in class_vars: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
475 # Class vars should not be private attributes
476 # We remove them _here_ and not earlier because we rely on inspecting the class to determine its classvars,
477 # but private attributes are determined by inspecting the namespace _prior_ to class creation.
478 # In the case that a classvar with a leading-'_' is defined via a ForwardRef (e.g., when using
479 # `__future__.annotations`), we want to remove the private attribute which was detected _before_ we knew it
480 # evaluated to a classvar
482 value = cls.__private_attributes__.pop(k, None) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
483 if value is not None and value.default is not PydanticUndefined: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
484 setattr(cls, k, value.default) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
487def complete_model_class( 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
488 cls: type[BaseModel],
489 cls_name: str,
490 config_wrapper: ConfigWrapper,
491 *,
492 raise_errors: bool = True,
493 types_namespace: dict[str, Any] | None,
494 create_model_module: str | None = None,
495) -> bool:
496 """Finish building a model class.
498 This logic must be called after class has been created since validation functions must be bound
499 and `get_type_hints` requires a class object.
501 Args:
502 cls: BaseModel or dataclass.
503 cls_name: The model or dataclass name.
504 config_wrapper: The config wrapper instance.
505 raise_errors: Whether to raise errors.
506 types_namespace: Optional extra namespace to look for types in.
507 create_model_module: The module of the class to be created, if created by `create_model`.
509 Returns:
510 `True` if the model is successfully completed, else `False`.
512 Raises:
513 PydanticUndefinedAnnotation: If `PydanticUndefinedAnnotation` occurs in`__get_pydantic_core_schema__`
514 and `raise_errors=True`.
515 """
516 typevars_map = get_model_typevars_map(cls) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
517 gen_schema = GenerateSchema( 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
518 config_wrapper,
519 types_namespace,
520 typevars_map,
521 )
523 handler = CallbackGetCoreSchemaHandler( 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
524 partial(gen_schema.generate_schema, from_dunder_get_core_schema=False),
525 gen_schema,
526 ref_mode='unpack',
527 )
529 if config_wrapper.defer_build and 'model' in config_wrapper.experimental_defer_build_mode: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
530 set_model_mocks(cls, cls_name) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
531 return False 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
533 try: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
534 schema = cls.__get_pydantic_core_schema__(cls, handler) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
535 except PydanticUndefinedAnnotation as e: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
536 if raise_errors: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
537 raise 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
538 set_model_mocks(cls, cls_name, f'`{e.name}`') 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
539 return False 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
541 core_config = config_wrapper.core_config(cls) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
543 try: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
544 schema = gen_schema.clean_schema(schema) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
545 except gen_schema.CollectedInvalid: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
546 set_model_mocks(cls, cls_name) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
547 return False 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
549 # debug(schema)
550 cls.__pydantic_core_schema__ = schema 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
552 cls.__pydantic_validator__ = create_schema_validator( 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
553 schema,
554 cls,
555 create_model_module or cls.__module__,
556 cls.__qualname__,
557 'create_model' if create_model_module else 'BaseModel',
558 core_config,
559 config_wrapper.plugin_settings,
560 )
561 cls.__pydantic_serializer__ = SchemaSerializer(schema, core_config) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
562 cls.__pydantic_complete__ = True 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
564 # set __signature__ attr only for model class, but not for its instances
565 cls.__signature__ = ClassAttribute( 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
566 '__signature__',
567 generate_pydantic_signature(init=cls.__init__, fields=cls.model_fields, config_wrapper=config_wrapper),
568 )
569 return True 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
572def set_deprecated_descriptors(cls: type[BaseModel]) -> None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
573 """Set data descriptors on the class for deprecated fields."""
574 for field, field_info in cls.model_fields.items(): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
575 if (msg := field_info.deprecation_message) is not None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
576 desc = _DeprecatedFieldDescriptor(msg) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
577 desc.__set_name__(cls, field) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
578 setattr(cls, field, desc) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
580 for field, computed_field_info in cls.model_computed_fields.items(): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
581 if ( 1abcdqrefghijkl
582 (msg := computed_field_info.deprecation_message) is not None
583 # Avoid having two warnings emitted:
584 and not hasattr(unwrap_wrapped_function(computed_field_info.wrapped_property), '__deprecated__')
585 ):
586 desc = _DeprecatedFieldDescriptor(msg, computed_field_info.wrapped_property) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
587 desc.__set_name__(cls, field) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
588 setattr(cls, field, desc) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
591class _DeprecatedFieldDescriptor: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
592 """Data descriptor used to emit a runtime deprecation warning before accessing a deprecated field.
594 Attributes:
595 msg: The deprecation message to be emitted.
596 wrapped_property: The property instance if the deprecated field is a computed field, or `None`.
597 field_name: The name of the field being deprecated.
598 """
600 field_name: str 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
602 def __init__(self, msg: str, wrapped_property: property | None = None) -> None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
603 self.msg = msg 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
604 self.wrapped_property = wrapped_property 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
606 def __set_name__(self, cls: type[BaseModel], name: str) -> None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
607 self.field_name = name 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
609 def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
610 if obj is None: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
611 raise AttributeError(self.field_name) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
613 warnings.warn(self.msg, builtins.DeprecationWarning, stacklevel=2) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
615 if self.wrapped_property is not None: 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
616 return self.wrapped_property.__get__(obj, obj_type) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
617 return obj.__dict__[self.field_name] 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
619 # Defined to take precedence over the instance's dictionary
620 # Note that it will not be called when setting a value on a model instance
621 # as `BaseModel.__setattr__` is defined and takes priority.
622 def __set__(self, obj: Any, value: Any) -> NoReturn: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
623 raise AttributeError(self.field_name)
626class _PydanticWeakRef: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
627 """Wrapper for `weakref.ref` that enables `pickle` serialization.
629 Cloudpickle fails to serialize `weakref.ref` objects due to an arcane error related
630 to abstract base classes (`abc.ABC`). This class works around the issue by wrapping
631 `weakref.ref` instead of subclassing it.
633 See https://github.com/pydantic/pydantic/issues/6763 for context.
635 Semantics:
636 - If not pickled, behaves the same as a `weakref.ref`.
637 - If pickled along with the referenced object, the same `weakref.ref` behavior
638 will be maintained between them after unpickling.
639 - If pickled without the referenced object, after unpickling the underlying
640 reference will be cleared (`__call__` will always return `None`).
641 """
643 def __init__(self, obj: Any): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
644 if obj is None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
645 # The object will be `None` upon deserialization if the serialized weakref
646 # had lost its underlying object.
647 self._wr = None 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
648 else:
649 self._wr = weakref.ref(obj) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
651 def __call__(self) -> Any: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
652 if self._wr is None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
653 return None 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
654 else:
655 return self._wr() 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
657 def __reduce__(self) -> tuple[Callable, tuple[weakref.ReferenceType | None]]: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
658 return _PydanticWeakRef, (self(),) 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
661def build_lenient_weakvaluedict(d: dict[str, Any] | None) -> dict[str, Any] | None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
662 """Takes an input dictionary, and produces a new value that (invertibly) replaces the values with weakrefs.
664 We can't just use a WeakValueDictionary because many types (including int, str, etc.) can't be stored as values
665 in a WeakValueDictionary.
667 The `unpack_lenient_weakvaluedict` function can be used to reverse this operation.
668 """
669 if d is None: 669 ↛ 670line 669 didn't jump to line 670 because the condition on line 669 was never true1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
670 return None
671 result = {} 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
672 for k, v in d.items(): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
673 try: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
674 proxy = _PydanticWeakRef(v) 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
675 except TypeError: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
676 proxy = v 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
677 result[k] = proxy 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
678 return result 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
681def unpack_lenient_weakvaluedict(d: dict[str, Any] | None) -> dict[str, Any] | None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
682 """Inverts the transform performed by `build_lenient_weakvaluedict`."""
683 if d is None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
684 return None 1abcdmnopABCDqrefghstuvEFGHijklwxyzIJKL
686 result = {} 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
687 for k, v in d.items(): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
688 if isinstance(v, _PydanticWeakRef): 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
689 v = v() 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
690 if v is not None: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
691 result[k] = v 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
692 else:
693 result[k] = v 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
694 return result 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
697def default_ignored_types() -> tuple[type[Any], ...]: 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
698 from ..fields import ComputedFieldInfo 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
700 return ( 1abcdmnopABCDqrefghstuvEFGHMNOPQRSTUVijklwxyzIJKL
701 FunctionType,
702 property,
703 classmethod,
704 staticmethod,
705 PydanticDescriptorProxy,
706 ComputedFieldInfo,
707 ValidateCallWrapper,
708 )