Coverage for pydantic/_internal/_model_construction.py: 98.93%

334 statements  

« prev     ^ index     » next       coverage.py v7.8.1, created at 2025-05-22 20:36 +0000

1"""Private logic for creating models.""" 

2 

3from __future__ import annotations as _annotations 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

4 

5import builtins 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

6import operator 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

7import sys 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

8import typing 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

9import warnings 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

10import weakref 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

11from abc import ABCMeta 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

12from functools import cache, partial, wraps 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

13from types import FunctionType 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

14from typing import Any, Callable, Generic, Literal, NoReturn, cast 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

15 

16from pydantic_core import PydanticUndefined, SchemaSerializer 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

17from typing_extensions import TypeAliasType, dataclass_transform, deprecated, get_args, get_origin 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

18from typing_inspection import typing_objects 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

19 

20from ..errors import PydanticUndefinedAnnotation, PydanticUserError 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

21from ..plugin._schema_validator import create_schema_validator 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

22from ..warnings import GenericBeforeBaseModelWarning, PydanticDeprecatedSince20 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

23from ._config import ConfigWrapper 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

24from ._decorators import DecoratorInfos, PydanticDescriptorProxy, get_attribute_from_bases, unwrap_wrapped_function 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

25from ._fields import collect_model_fields, is_valid_field_name, is_valid_privateattr_name 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

26from ._generate_schema import GenerateSchema, InvalidSchemaError 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

27from ._generics import PydanticGenericMetadata, get_model_typevars_map 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

28from ._import_utils import import_cached_base_model, import_cached_field_info 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

29from ._mock_val_ser import set_model_mocks 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

30from ._namespace_utils import NsResolver 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

31from ._signature import generate_pydantic_signature 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

32from ._typing_extra import ( 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

33 _make_forward_ref, 

34 eval_type_backport, 

35 is_classvar_annotation, 

36 parent_frame_namespace, 

37) 

38from ._utils import LazyClassAttribute, SafeGetItemProxy 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

39 

40if typing.TYPE_CHECKING: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

41 from ..fields import Field as PydanticModelField 

42 from ..fields import FieldInfo, ModelPrivateAttr 

43 from ..fields import PrivateAttr as PydanticModelPrivateAttr 

44 from ..main import BaseModel 

45else: 

46 # See PyCharm issues https://youtrack.jetbrains.com/issue/PY-21915 

47 # and https://youtrack.jetbrains.com/issue/PY-51428 

48 DeprecationWarning = PydanticDeprecatedSince20 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

49 PydanticModelField = object() 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

50 PydanticModelPrivateAttr = object() 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

51 

52object_setattr = object.__setattr__ 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

53 

54 

55class _ModelNamespaceDict(dict): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

56 """A dictionary subclass that intercepts attribute setting on model classes and 

57 warns about overriding of decorators. 

58 """ 

59 

60 def __setitem__(self, k: str, v: object) -> None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

61 existing: Any = self.get(k, None) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

62 if existing and v is not existing and isinstance(existing, PydanticDescriptorProxy): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

63 warnings.warn(f'`{k}` overrides an existing Pydantic `{existing.decorator_info.decorator_repr}` decorator') 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

64 

65 return super().__setitem__(k, v) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

66 

67 

68def NoInitField( 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

69 *, 

70 init: Literal[False] = False, 

71) -> Any: 

72 """Only for typing purposes. Used as default value of `__pydantic_fields_set__`, 

73 `__pydantic_extra__`, `__pydantic_private__`, so they could be ignored when 

74 synthesizing the `__init__` signature. 

75 """ 

76 

77 

78@dataclass_transform(kw_only_default=True, field_specifiers=(PydanticModelField, PydanticModelPrivateAttr, NoInitField)) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

79class ModelMetaclass(ABCMeta): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

80 def __new__( 1adeofpqArBCbijsktuDvEFJKLMNOPclmwnxyGzHI

81 mcs, 

82 cls_name: str, 

83 bases: tuple[type[Any], ...], 

84 namespace: dict[str, Any], 

85 __pydantic_generic_metadata__: PydanticGenericMetadata | None = None, 

86 __pydantic_reset_parent_namespace__: bool = True, 

87 _create_model_module: str | None = None, 

88 **kwargs: Any, 

89 ) -> type: 

90 """Metaclass for creating Pydantic models. 

91 

92 Args: 

93 cls_name: The name of the class to be created. 

94 bases: The base classes of the class to be created. 

95 namespace: The attribute dictionary of the class to be created. 

96 __pydantic_generic_metadata__: Metadata for generic models. 

97 __pydantic_reset_parent_namespace__: Reset parent namespace. 

98 _create_model_module: The module of the class to be created, if created by `create_model`. 

99 **kwargs: Catch-all for any other keyword arguments. 

100 

101 Returns: 

102 The new class created by the metaclass. 

103 """ 

104 # Note `ModelMetaclass` refers to `BaseModel`, but is also used to *create* `BaseModel`, so we rely on the fact 

105 # that `BaseModel` itself won't have any bases, but any subclass of it will, to determine whether the `__new__` 

106 # call we're in the middle of is for the `BaseModel` class. 

107 if bases: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

108 base_field_names, class_vars, base_private_attributes = mcs._collect_bases_data(bases) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

109 

110 config_wrapper = ConfigWrapper.for_model(bases, namespace, kwargs) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

111 namespace['model_config'] = config_wrapper.config_dict 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

112 private_attributes = inspect_namespace( 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

113 namespace, config_wrapper.ignored_types, class_vars, base_field_names 

114 ) 

115 if private_attributes or base_private_attributes: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

116 original_model_post_init = get_model_post_init(namespace, bases) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

117 if original_model_post_init is not None: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

118 # if there are private_attributes and a model_post_init function, we handle both 

119 

120 @wraps(original_model_post_init) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

121 def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

122 """We need to both initialize private attributes and call the user-defined model_post_init 

123 method. 

124 """ 

125 init_private_attributes(self, context) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

126 original_model_post_init(self, context) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

127 

128 namespace['model_post_init'] = wrapped_model_post_init 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

129 else: 

130 namespace['model_post_init'] = init_private_attributes 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

131 

132 namespace['__class_vars__'] = class_vars 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

133 namespace['__private_attributes__'] = {**base_private_attributes, **private_attributes} 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

134 

135 cls = cast('type[BaseModel]', super().__new__(mcs, cls_name, bases, namespace, **kwargs)) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

136 BaseModel_ = import_cached_base_model() 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

137 

138 mro = cls.__mro__ 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

139 if Generic in mro and mro.index(Generic) < mro.index(BaseModel_): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

140 warnings.warn( 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

141 GenericBeforeBaseModelWarning( 

142 'Classes should inherit from `BaseModel` before generic classes (e.g. `typing.Generic[T]`) ' 

143 'for pydantic generics to work properly.' 

144 ), 

145 stacklevel=2, 

146 ) 

147 

148 cls.__pydantic_custom_init__ = not getattr(cls.__init__, '__pydantic_base_init__', False) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

149 cls.__pydantic_post_init__ = ( 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

150 None if cls.model_post_init is BaseModel_.model_post_init else 'model_post_init' 

151 ) 

152 

153 cls.__pydantic_setattr_handlers__ = {} 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

154 

155 cls.__pydantic_decorators__ = DecoratorInfos.build(cls) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

156 

157 # Use the getattr below to grab the __parameters__ from the `typing.Generic` parent class 

158 if __pydantic_generic_metadata__: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

159 cls.__pydantic_generic_metadata__ = __pydantic_generic_metadata__ 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

160 else: 

161 parent_parameters = getattr(cls, '__pydantic_generic_metadata__', {}).get('parameters', ()) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

162 parameters = getattr(cls, '__parameters__', None) or parent_parameters 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

163 if parameters and parent_parameters and not all(x in parameters for x in parent_parameters): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

164 from ..root_model import RootModelRootType 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

165 

166 missing_parameters = tuple(x for x in parameters if x not in parent_parameters) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

167 if RootModelRootType in parent_parameters and RootModelRootType not in parameters: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

168 # This is a special case where the user has subclassed `RootModel`, but has not parametrized 

169 # RootModel with the generic type identifiers being used. Ex: 

170 # class MyModel(RootModel, Generic[T]): 

171 # root: T 

172 # Should instead just be: 

173 # class MyModel(RootModel[T]): 

174 # root: T 

175 parameters_str = ', '.join([x.__name__ for x in missing_parameters]) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

176 error_message = ( 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

177 f'{cls.__name__} is a subclass of `RootModel`, but does not include the generic type identifier(s) ' 

178 f'{parameters_str} in its parameters. ' 

179 f'You should parametrize RootModel directly, e.g., `class {cls.__name__}(RootModel[{parameters_str}]): ...`.' 

180 ) 

181 else: 

182 combined_parameters = parent_parameters + missing_parameters 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

183 parameters_str = ', '.join([str(x) for x in combined_parameters]) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

184 generic_type_label = f'typing.Generic[{parameters_str}]' 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

185 error_message = ( 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

186 f'All parameters must be present on typing.Generic;' 

187 f' you should inherit from {generic_type_label}.' 

188 ) 

189 if Generic not in bases: # pragma: no cover 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

190 # We raise an error here not because it is desirable, but because some cases are mishandled. 

191 # It would be nice to remove this error and still have things behave as expected, it's just 

192 # challenging because we are using a custom `__class_getitem__` to parametrize generic models, 

193 # and not returning a typing._GenericAlias from it. 

194 bases_str = ', '.join([x.__name__ for x in bases] + [generic_type_label]) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

195 error_message += ( 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

196 f' Note: `typing.Generic` must go last: `class {cls.__name__}({bases_str}): ...`)' 

197 ) 

198 raise TypeError(error_message) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

199 

200 cls.__pydantic_generic_metadata__ = { 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

201 'origin': None, 

202 'args': (), 

203 'parameters': parameters, 

204 } 

205 

206 cls.__pydantic_complete__ = False # Ensure this specific class gets completed 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

207 

208 # preserve `__set_name__` protocol defined in https://peps.python.org/pep-0487 

209 # for attributes not in `new_namespace` (e.g. private attributes) 

210 for name, obj in private_attributes.items(): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

211 obj.__set_name__(cls, name) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

212 

213 if __pydantic_reset_parent_namespace__: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

214 cls.__pydantic_parent_namespace__ = build_lenient_weakvaluedict(parent_frame_namespace()) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

215 parent_namespace: dict[str, Any] | None = getattr(cls, '__pydantic_parent_namespace__', None) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

216 if isinstance(parent_namespace, dict): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

217 parent_namespace = unpack_lenient_weakvaluedict(parent_namespace) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

218 

219 ns_resolver = NsResolver(parent_namespace=parent_namespace) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

220 

221 set_model_fields(cls, config_wrapper=config_wrapper, ns_resolver=ns_resolver) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

222 

223 # This is also set in `complete_model_class()`, after schema gen because they are recreated. 

224 # We set them here as well for backwards compatibility: 

225 cls.__pydantic_computed_fields__ = { 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

226 k: v.info for k, v in cls.__pydantic_decorators__.computed_fields.items() 

227 } 

228 

229 if config_wrapper.defer_build: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

230 # TODO we can also stop there if `__pydantic_fields_complete__` is False. 

231 # However, `set_model_fields()` is currently lenient and we don't have access to the `NameError`. 

232 # (which is useful as we can provide the name in the error message: `set_model_mock(cls, e.name)`) 

233 set_model_mocks(cls) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

234 else: 

235 # Any operation that requires accessing the field infos instances should be put inside 

236 # `complete_model_class()`: 

237 complete_model_class( 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

238 cls, 

239 config_wrapper, 

240 raise_errors=False, 

241 ns_resolver=ns_resolver, 

242 create_model_module=_create_model_module, 

243 ) 

244 

245 if config_wrapper.frozen and '__hash__' not in namespace: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

246 set_default_hash_func(cls, bases) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

247 

248 # using super(cls, cls) on the next line ensures we only call the parent class's __pydantic_init_subclass__ 

249 # I believe the `type: ignore` is only necessary because mypy doesn't realize that this code branch is 

250 # only hit for _proper_ subclasses of BaseModel 

251 super(cls, cls).__pydantic_init_subclass__(**kwargs) # type: ignore[misc] 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

252 return cls 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

253 else: 

254 # These are instance variables, but have been assigned to `NoInitField` to trick the type checker. 

255 for instance_slot in '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__': 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

256 namespace.pop( 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

257 instance_slot, 

258 None, # In case the metaclass is used with a class other than `BaseModel`. 

259 ) 

260 namespace.get('__annotations__', {}).clear() 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

261 return super().__new__(mcs, cls_name, bases, namespace, **kwargs) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

262 

263 if not typing.TYPE_CHECKING: # pragma: no branch 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

264 # We put `__getattr__` in a non-TYPE_CHECKING block because otherwise, mypy allows arbitrary attribute access 

265 

266 def __getattr__(self, item: str) -> Any: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

267 """This is necessary to keep attribute access working for class attribute access.""" 

268 private_attributes = self.__dict__.get('__private_attributes__') 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

269 if private_attributes and item in private_attributes: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

270 return private_attributes[item] 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

271 raise AttributeError(item) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

272 

273 @classmethod 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

274 def __prepare__(cls, *args: Any, **kwargs: Any) -> dict[str, object]: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

275 return _ModelNamespaceDict() 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

276 

277 def __instancecheck__(self, instance: Any) -> bool: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

278 """Avoid calling ABC _abc_instancecheck unless we're pretty sure. 

279 

280 See #3829 and python/cpython#92810 

281 """ 

282 return hasattr(instance, '__pydantic_decorators__') and super().__instancecheck__(instance) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

283 

284 def __subclasscheck__(self, subclass: type[Any]) -> bool: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

285 """Avoid calling ABC _abc_subclasscheck unless we're pretty sure. 

286 

287 See #3829 and python/cpython#92810 

288 """ 

289 return hasattr(subclass, '__pydantic_decorators__') and super().__subclasscheck__(subclass) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

290 

291 @staticmethod 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

292 def _collect_bases_data(bases: tuple[type[Any], ...]) -> tuple[set[str], set[str], dict[str, ModelPrivateAttr]]: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

293 BaseModel = import_cached_base_model() 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

294 

295 field_names: set[str] = set() 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

296 class_vars: set[str] = set() 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

297 private_attributes: dict[str, ModelPrivateAttr] = {} 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

298 for base in bases: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

299 if issubclass(base, BaseModel) and base is not BaseModel: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

300 # model_fields might not be defined yet in the case of generics, so we use getattr here: 

301 field_names.update(getattr(base, '__pydantic_fields__', {}).keys()) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

302 class_vars.update(base.__class_vars__) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

303 private_attributes.update(base.__private_attributes__) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

304 return field_names, class_vars, private_attributes 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

305 

306 @property 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

307 @deprecated('The `__fields__` attribute is deprecated, use `model_fields` instead.', category=None) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

308 def __fields__(self) -> dict[str, FieldInfo]: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

309 warnings.warn( 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

310 'The `__fields__` attribute is deprecated, use `model_fields` instead.', 

311 PydanticDeprecatedSince20, 

312 stacklevel=2, 

313 ) 

314 return getattr(self, '__pydantic_fields__', {}) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

315 

316 @property 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

317 def __pydantic_fields_complete__(self) -> bool: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

318 """Whether the fields where successfully collected (i.e. type hints were successfully resolves). 

319 

320 This is a private attribute, not meant to be used outside Pydantic. 

321 """ 

322 if not hasattr(self, '__pydantic_fields__'): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

323 return False 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

324 

325 field_infos = cast('dict[str, FieldInfo]', self.__pydantic_fields__) # pyright: ignore[reportAttributeAccessIssue] 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

326 

327 return all(field_info._complete for field_info in field_infos.values()) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

328 

329 def __dir__(self) -> list[str]: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

330 attributes = list(super().__dir__()) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

331 if '__fields__' in attributes: 331 ↛ 333line 331 didn't jump to line 333 because the condition on line 331 was always true1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

332 attributes.remove('__fields__') 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

333 return attributes 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

334 

335 

336def init_private_attributes(self: BaseModel, context: Any, /) -> None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

337 """This function is meant to behave like a BaseModel method to initialise private attributes. 

338 

339 It takes context as an argument since that's what pydantic-core passes when calling it. 

340 

341 Args: 

342 self: The BaseModel instance. 

343 context: The context. 

344 """ 

345 if getattr(self, '__pydantic_private__', None) is None: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

346 pydantic_private = {} 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

347 for name, private_attr in self.__private_attributes__.items(): 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

348 default = private_attr.get_default() 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

349 if default is not PydanticUndefined: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

350 pydantic_private[name] = default 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

351 object_setattr(self, '__pydantic_private__', pydantic_private) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

352 

353 

354def get_model_post_init(namespace: dict[str, Any], bases: tuple[type[Any], ...]) -> Callable[..., Any] | None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

355 """Get the `model_post_init` method from the namespace or the class bases, or `None` if not defined.""" 

356 if 'model_post_init' in namespace: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

357 return namespace['model_post_init'] 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

358 

359 BaseModel = import_cached_base_model() 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

360 

361 model_post_init = get_attribute_from_bases(bases, 'model_post_init') 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

362 if model_post_init is not BaseModel.model_post_init: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

363 return model_post_init 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

364 

365 

366def inspect_namespace( # noqa C901 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

367 namespace: dict[str, Any], 

368 ignored_types: tuple[type[Any], ...], 

369 base_class_vars: set[str], 

370 base_class_fields: set[str], 

371) -> dict[str, ModelPrivateAttr]: 

372 """Iterate over the namespace and: 

373 * gather private attributes 

374 * check for items which look like fields but are not (e.g. have no annotation) and warn. 

375 

376 Args: 

377 namespace: The attribute dictionary of the class to be created. 

378 ignored_types: A tuple of ignore types. 

379 base_class_vars: A set of base class class variables. 

380 base_class_fields: A set of base class fields. 

381 

382 Returns: 

383 A dict contains private attributes info. 

384 

385 Raises: 

386 TypeError: If there is a `__root__` field in model. 

387 NameError: If private attribute name is invalid. 

388 PydanticUserError: 

389 - If a field does not have a type annotation. 

390 - If a field on base class was overridden by a non-annotated attribute. 

391 """ 

392 from ..fields import ModelPrivateAttr, PrivateAttr 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

393 

394 FieldInfo = import_cached_field_info() 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

395 

396 all_ignored_types = ignored_types + default_ignored_types() 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

397 

398 private_attributes: dict[str, ModelPrivateAttr] = {} 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

399 raw_annotations = namespace.get('__annotations__', {}) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

400 

401 if '__root__' in raw_annotations or '__root__' in namespace: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

402 raise TypeError("To define root models, use `pydantic.RootModel` rather than a field called '__root__'") 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

403 

404 ignored_names: set[str] = set() 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

405 for var_name, value in list(namespace.items()): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

406 if var_name == 'model_config' or var_name == '__pydantic_extra__': 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

407 continue 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

408 elif ( 1adeofpghbijsktJKLclmwnx

409 isinstance(value, type) 

410 and value.__module__ == namespace['__module__'] 

411 and '__qualname__' in namespace 

412 and value.__qualname__.startswith(namespace['__qualname__']) 

413 ): 

414 # `value` is a nested type defined in this namespace; don't error 

415 continue 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

416 elif isinstance(value, all_ignored_types) or value.__class__.__module__ == 'functools': 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

417 ignored_names.add(var_name) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

418 continue 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

419 elif isinstance(value, ModelPrivateAttr): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

420 if var_name.startswith('__'): 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

421 raise NameError( 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

422 'Private attributes must not use dunder names;' 

423 f' use a single underscore prefix instead of {var_name!r}.' 

424 ) 

425 elif is_valid_field_name(var_name): 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

426 raise NameError( 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

427 'Private attributes must not use valid field names;' 

428 f' use sunder names, e.g. {"_" + var_name!r} instead of {var_name!r}.' 

429 ) 

430 private_attributes[var_name] = value 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

431 del namespace[var_name] 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

432 elif isinstance(value, FieldInfo) and not is_valid_field_name(var_name): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

433 suggested_name = var_name.lstrip('_') or 'my_field' # don't suggest '' for all-underscore name 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

434 raise NameError( 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

435 f'Fields must not use names with leading underscores;' 

436 f' e.g., use {suggested_name!r} instead of {var_name!r}.' 

437 ) 

438 

439 elif var_name.startswith('__'): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

440 continue 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

441 elif is_valid_privateattr_name(var_name): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

442 if var_name not in raw_annotations or not is_classvar_annotation(raw_annotations[var_name]): 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

443 private_attributes[var_name] = cast(ModelPrivateAttr, PrivateAttr(default=value)) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

444 del namespace[var_name] 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

445 elif var_name in base_class_vars: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

446 continue 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

447 elif var_name not in raw_annotations: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

448 if var_name in base_class_fields: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

449 raise PydanticUserError( 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

450 f'Field {var_name!r} defined on a base class was overridden by a non-annotated attribute. ' 

451 f'All field definitions, including overrides, require a type annotation.', 

452 code='model-field-overridden', 

453 ) 

454 elif isinstance(value, FieldInfo): 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

455 raise PydanticUserError( 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

456 f'Field {var_name!r} requires a type annotation', code='model-field-missing-annotation' 

457 ) 

458 else: 

459 raise PydanticUserError( 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

460 f'A non-annotated attribute was detected: `{var_name} = {value!r}`. All model fields require a ' 

461 f'type annotation; if `{var_name}` is not meant to be a field, you may be able to resolve this ' 

462 f"error by annotating it as a `ClassVar` or updating `model_config['ignored_types']`.", 

463 code='model-field-missing-annotation', 

464 ) 

465 

466 for ann_name, ann_type in raw_annotations.items(): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

467 if ( 1adeofpghbijsktJKLclmwnx

468 is_valid_privateattr_name(ann_name) 

469 and ann_name not in private_attributes 

470 and ann_name not in ignored_names 

471 # This condition can be a false negative when `ann_type` is stringified, 

472 # but it is handled in most cases in `set_model_fields`: 

473 and not is_classvar_annotation(ann_type) 

474 and ann_type not in all_ignored_types 

475 and getattr(ann_type, '__module__', None) != 'functools' 

476 ): 

477 if isinstance(ann_type, str): 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

478 # Walking up the frames to get the module namespace where the model is defined 

479 # (as the model class wasn't created yet, we unfortunately can't use `cls.__module__`): 

480 frame = sys._getframe(2) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

481 if frame is not None: 481 ↛ 491line 481 didn't jump to line 491 because the condition on line 481 was always true1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

482 try: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

483 ann_type = eval_type_backport( 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

484 _make_forward_ref(ann_type, is_argument=False, is_class=True), 

485 globalns=frame.f_globals, 

486 localns=frame.f_locals, 

487 ) 

488 except (NameError, TypeError): 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

489 pass 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

490 

491 if typing_objects.is_annotated(get_origin(ann_type)): 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

492 _, *metadata = get_args(ann_type) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

493 private_attr = next((v for v in metadata if isinstance(v, ModelPrivateAttr)), None) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

494 if private_attr is not None: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

495 private_attributes[ann_name] = private_attr 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

496 continue 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

497 private_attributes[ann_name] = PrivateAttr() 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

498 

499 return private_attributes 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

500 

501 

502def set_default_hash_func(cls: type[BaseModel], bases: tuple[type[Any], ...]) -> None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

503 base_hash_func = get_attribute_from_bases(bases, '__hash__') 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

504 new_hash_func = make_hash_func(cls) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

505 if base_hash_func in {None, object.__hash__} or getattr(base_hash_func, '__code__', None) == new_hash_func.__code__: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

506 # If `__hash__` is some default, we generate a hash function. 

507 # It will be `None` if not overridden from BaseModel. 

508 # It may be `object.__hash__` if there is another 

509 # parent class earlier in the bases which doesn't override `__hash__` (e.g. `typing.Generic`). 

510 # It may be a value set by `set_default_hash_func` if `cls` is a subclass of another frozen model. 

511 # In the last case we still need a new hash function to account for new `model_fields`. 

512 cls.__hash__ = new_hash_func 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

513 

514 

515def make_hash_func(cls: type[BaseModel]) -> Any: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

516 getter = operator.itemgetter(*cls.__pydantic_fields__.keys()) if cls.__pydantic_fields__ else lambda _: 0 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

517 

518 def hash_func(self: Any) -> int: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

519 try: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

520 return hash(getter(self.__dict__)) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

521 except KeyError: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

522 # In rare cases (such as when using the deprecated copy method), the __dict__ may not contain 

523 # all model fields, which is how we can get here. 

524 # getter(self.__dict__) is much faster than any 'safe' method that accounts for missing keys, 

525 # and wrapping it in a `try` doesn't slow things down much in the common case. 

526 return hash(getter(SafeGetItemProxy(self.__dict__))) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

527 

528 return hash_func 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

529 

530 

531def set_model_fields( 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

532 cls: type[BaseModel], 

533 config_wrapper: ConfigWrapper, 

534 ns_resolver: NsResolver | None, 

535) -> None: 

536 """Collect and set `cls.__pydantic_fields__` and `cls.__class_vars__`. 

537 

538 Args: 

539 cls: BaseModel or dataclass. 

540 config_wrapper: The config wrapper instance. 

541 ns_resolver: Namespace resolver to use when getting model annotations. 

542 """ 

543 typevars_map = get_model_typevars_map(cls) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

544 fields, class_vars = collect_model_fields(cls, config_wrapper, ns_resolver, typevars_map=typevars_map) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

545 

546 cls.__pydantic_fields__ = fields 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

547 cls.__class_vars__.update(class_vars) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

548 

549 for k in class_vars: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

550 # Class vars should not be private attributes 

551 # We remove them _here_ and not earlier because we rely on inspecting the class to determine its classvars, 

552 # but private attributes are determined by inspecting the namespace _prior_ to class creation. 

553 # In the case that a classvar with a leading-'_' is defined via a ForwardRef (e.g., when using 

554 # `__future__.annotations`), we want to remove the private attribute which was detected _before_ we knew it 

555 # evaluated to a classvar 

556 

557 value = cls.__private_attributes__.pop(k, None) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

558 if value is not None and value.default is not PydanticUndefined: 558 ↛ 559line 558 didn't jump to line 559 because the condition on line 558 was never true1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

559 setattr(cls, k, value.default) 

560 

561 

562def complete_model_class( 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

563 cls: type[BaseModel], 

564 config_wrapper: ConfigWrapper, 

565 *, 

566 raise_errors: bool = True, 

567 ns_resolver: NsResolver | None = None, 

568 create_model_module: str | None = None, 

569) -> bool: 

570 """Finish building a model class. 

571 

572 This logic must be called after class has been created since validation functions must be bound 

573 and `get_type_hints` requires a class object. 

574 

575 Args: 

576 cls: BaseModel or dataclass. 

577 config_wrapper: The config wrapper instance. 

578 raise_errors: Whether to raise errors. 

579 ns_resolver: The namespace resolver instance to use during schema building. 

580 create_model_module: The module of the class to be created, if created by `create_model`. 

581 

582 Returns: 

583 `True` if the model is successfully completed, else `False`. 

584 

585 Raises: 

586 PydanticUndefinedAnnotation: If `PydanticUndefinedAnnotation` occurs in`__get_pydantic_core_schema__` 

587 and `raise_errors=True`. 

588 """ 

589 typevars_map = get_model_typevars_map(cls) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

590 gen_schema = GenerateSchema( 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

591 config_wrapper, 

592 ns_resolver, 

593 typevars_map, 

594 ) 

595 

596 try: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

597 schema = gen_schema.generate_schema(cls) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

598 except PydanticUndefinedAnnotation as e: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

599 if raise_errors: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

600 raise 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

601 set_model_mocks(cls, f'`{e.name}`') 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

602 return False 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

603 

604 core_config = config_wrapper.core_config(title=cls.__name__) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

605 

606 try: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

607 schema = gen_schema.clean_schema(schema) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

608 except InvalidSchemaError: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

609 set_model_mocks(cls) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

610 return False 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

611 

612 # This needs to happen *after* model schema generation, as the return type 

613 # of the properties are evaluated and the `ComputedFieldInfo` are recreated: 

614 cls.__pydantic_computed_fields__ = {k: v.info for k, v in cls.__pydantic_decorators__.computed_fields.items()} 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

615 

616 set_deprecated_descriptors(cls) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

617 

618 cls.__pydantic_core_schema__ = schema 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

619 

620 cls.__pydantic_validator__ = create_schema_validator( 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

621 schema, 

622 cls, 

623 create_model_module or cls.__module__, 

624 cls.__qualname__, 

625 'create_model' if create_model_module else 'BaseModel', 

626 core_config, 

627 config_wrapper.plugin_settings, 

628 ) 

629 cls.__pydantic_serializer__ = SchemaSerializer(schema, core_config) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

630 cls.__pydantic_complete__ = True 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

631 

632 # set __signature__ attr only for model class, but not for its instances 

633 # (because instances can define `__call__`, and `inspect.signature` shouldn't 

634 # use the `__signature__` attribute and instead generate from `__call__`). 

635 cls.__signature__ = LazyClassAttribute( 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

636 '__signature__', 

637 partial( 

638 generate_pydantic_signature, 

639 init=cls.__init__, 

640 fields=cls.__pydantic_fields__, 

641 validate_by_name=config_wrapper.validate_by_name, 

642 extra=config_wrapper.extra, 

643 ), 

644 ) 

645 return True 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

646 

647 

648def set_deprecated_descriptors(cls: type[BaseModel]) -> None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

649 """Set data descriptors on the class for deprecated fields.""" 

650 for field, field_info in cls.__pydantic_fields__.items(): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

651 if (msg := field_info.deprecation_message) is not None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

652 desc = _DeprecatedFieldDescriptor(msg) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

653 desc.__set_name__(cls, field) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

654 setattr(cls, field, desc) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

655 

656 for field, computed_field_info in cls.__pydantic_computed_fields__.items(): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

657 if ( 1adghbicl

658 (msg := computed_field_info.deprecation_message) is not None 

659 # Avoid having two warnings emitted: 

660 and not hasattr(unwrap_wrapped_function(computed_field_info.wrapped_property), '__deprecated__') 

661 ): 

662 desc = _DeprecatedFieldDescriptor(msg, computed_field_info.wrapped_property) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

663 desc.__set_name__(cls, field) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

664 setattr(cls, field, desc) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

665 

666 

667class _DeprecatedFieldDescriptor: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

668 """Read-only data descriptor used to emit a runtime deprecation warning before accessing a deprecated field. 

669 

670 Attributes: 

671 msg: The deprecation message to be emitted. 

672 wrapped_property: The property instance if the deprecated field is a computed field, or `None`. 

673 field_name: The name of the field being deprecated. 

674 """ 

675 

676 field_name: str 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

677 

678 def __init__(self, msg: str, wrapped_property: property | None = None) -> None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

679 self.msg = msg 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

680 self.wrapped_property = wrapped_property 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

681 

682 def __set_name__(self, cls: type[BaseModel], name: str) -> None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

683 self.field_name = name 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

684 

685 def __get__(self, obj: BaseModel | None, obj_type: type[BaseModel] | None = None) -> Any: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

686 if obj is None: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

687 if self.wrapped_property is not None: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

688 return self.wrapped_property.__get__(None, obj_type) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

689 raise AttributeError(self.field_name) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

690 

691 warnings.warn(self.msg, builtins.DeprecationWarning, stacklevel=2) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

692 

693 if self.wrapped_property is not None: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

694 return self.wrapped_property.__get__(obj, obj_type) 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

695 return obj.__dict__[self.field_name] 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

696 

697 # Defined to make it a data descriptor and take precedence over the instance's dictionary. 

698 # Note that it will not be called when setting a value on a model instance 

699 # as `BaseModel.__setattr__` is defined and takes priority. 

700 def __set__(self, obj: Any, value: Any) -> NoReturn: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

701 raise AttributeError(self.field_name) 

702 

703 

704class _PydanticWeakRef: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

705 """Wrapper for `weakref.ref` that enables `pickle` serialization. 

706 

707 Cloudpickle fails to serialize `weakref.ref` objects due to an arcane error related 

708 to abstract base classes (`abc.ABC`). This class works around the issue by wrapping 

709 `weakref.ref` instead of subclassing it. 

710 

711 See https://github.com/pydantic/pydantic/issues/6763 for context. 

712 

713 Semantics: 

714 - If not pickled, behaves the same as a `weakref.ref`. 

715 - If pickled along with the referenced object, the same `weakref.ref` behavior 

716 will be maintained between them after unpickling. 

717 - If pickled without the referenced object, after unpickling the underlying 

718 reference will be cleared (`__call__` will always return `None`). 

719 """ 

720 

721 def __init__(self, obj: Any): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

722 if obj is None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

723 # The object will be `None` upon deserialization if the serialized weakref 

724 # had lost its underlying object. 

725 self._wr = None 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

726 else: 

727 self._wr = weakref.ref(obj) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

728 

729 def __call__(self) -> Any: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

730 if self._wr is None: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

731 return None 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

732 else: 

733 return self._wr() 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

734 

735 def __reduce__(self) -> tuple[Callable, tuple[weakref.ReferenceType | None]]: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

736 return _PydanticWeakRef, (self(),) 1aefqrghbjkuvcmnyz

737 

738 

739def build_lenient_weakvaluedict(d: dict[str, Any] | None) -> dict[str, Any] | None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

740 """Takes an input dictionary, and produces a new value that (invertibly) replaces the values with weakrefs. 

741 

742 We can't just use a WeakValueDictionary because many types (including int, str, etc.) can't be stored as values 

743 in a WeakValueDictionary. 

744 

745 The `unpack_lenient_weakvaluedict` function can be used to reverse this operation. 

746 """ 

747 if d is None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

748 return None 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

749 result = {} 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

750 for k, v in d.items(): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

751 try: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

752 proxy = _PydanticWeakRef(v) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

753 except TypeError: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

754 proxy = v 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

755 result[k] = proxy 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

756 return result 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

757 

758 

759def unpack_lenient_weakvaluedict(d: dict[str, Any] | None) -> dict[str, Any] | None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

760 """Inverts the transform performed by `build_lenient_weakvaluedict`.""" 

761 if d is None: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

762 return None 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

763 

764 result = {} 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

765 for k, v in d.items(): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

766 if isinstance(v, _PydanticWeakRef): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

767 v = v() 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

768 if v is not None: 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

769 result[k] = v 1adeofpqArBCghbijsktuDvEFclmwnxyGzHI

770 else: 

771 result[k] = v 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

772 return result 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

773 

774 

775@cache 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

776def default_ignored_types() -> tuple[type[Any], ...]: 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

777 from ..fields import ComputedFieldInfo 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

778 

779 ignored_types = [ 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

780 FunctionType, 

781 property, 

782 classmethod, 

783 staticmethod, 

784 PydanticDescriptorProxy, 

785 ComputedFieldInfo, 

786 TypeAliasType, # from `typing_extensions` 

787 ] 

788 

789 if sys.version_info >= (3, 12): 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI

790 ignored_types.append(typing.TypeAliasType) 1qArBCuDvEFMNOPyGzHI

791 

792 return tuple(ignored_types) 1adeofpqArBCghbijsktuDvEFJKLMNOPclmwnxyGzHI