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

355 statements  

« prev     ^ index     » next       coverage.py v7.9.2, created at 2025-07-20 16:49 +0000

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

2 

3from __future__ import annotations as _annotations 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

4 

5import builtins 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

6import operator 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

7import sys 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

8import typing 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

9import warnings 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

10import weakref 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

11from abc import ABCMeta 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

12from functools import cache, partial, wraps 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

13from types import FunctionType 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

15 

16from pydantic_core import PydanticUndefined, SchemaSerializer 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

18from typing_inspection import typing_objects 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

19 

20from ..errors import PydanticUndefinedAnnotation, PydanticUserError 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

21from ..plugin._schema_validator import create_schema_validator 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

22from ..warnings import GenericBeforeBaseModelWarning, PydanticDeprecatedSince20 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

23from ._config import ConfigWrapper 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

25from ._fields import collect_model_fields, is_valid_field_name, is_valid_privateattr_name, rebuild_model_fields 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

26from ._generate_schema import GenerateSchema, InvalidSchemaError 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

27from ._generics import PydanticGenericMetadata, get_model_typevars_map 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

28from ._import_utils import import_cached_base_model, import_cached_field_info 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

29from ._mock_val_ser import set_model_mocks 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

30from ._namespace_utils import NsResolver 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

31from ._signature import generate_pydantic_signature 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

32from ._typing_extra import ( 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

33 _make_forward_ref, 

34 eval_type_backport, 

35 is_classvar_annotation, 

36 parent_frame_namespace, 

37) 

38from ._utils import LazyClassAttribute, SafeGetItemProxy 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

39 

40if typing.TYPE_CHECKING: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

49 PydanticModelField = object() 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

50 PydanticModelPrivateAttr = object() 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

51 

52object_setattr = object.__setattr__ 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

53 

54 

55class _ModelNamespaceDict(dict): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

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

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

64 

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

66 

67 

68def NoInitField( 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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)) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

79class ModelMetaclass(ABCMeta): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

80 def __new__( 1gjkulvwGxHadMhopyqzAIBJbeNPirsCtDEKFLcfO

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: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

108 raw_annotations: dict[str, Any] 

109 if sys.version_info >= (3, 14): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

110 if ( 

111 '__annotations__' in namespace 

112 ): # `from __future__ import annotations` was used in the model's module 

113 raw_annotations = namespace['__annotations__'] 1adMbeNcfO

114 else: 

115 # See https://docs.python.org/3.14/library/annotationlib.html#using-annotations-in-a-metaclass: 

116 from annotationlib import Format, call_annotate_function, get_annotate_from_class_namespace 1adMbeNcfO

117 

118 if annotate := get_annotate_from_class_namespace(namespace): 1adMbeNcfO

119 raw_annotations = call_annotate_function(annotate, format=Format.FORWARDREF) 1adMbeNcfO

120 else: 

121 raw_annotations = {} 1adMbeNcfO

122 else: 

123 raw_annotations = namespace.get('__annotations__', {}) 1gjkulvwGxHmnhopyqzAIBJPirsCtDEKFL

124 

125 base_field_names, class_vars, base_private_attributes = mcs._collect_bases_data(bases) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

126 

127 config_wrapper = ConfigWrapper.for_model(bases, namespace, raw_annotations, kwargs) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

128 namespace['model_config'] = config_wrapper.config_dict 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

129 private_attributes = inspect_namespace( 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

130 namespace, raw_annotations, config_wrapper.ignored_types, class_vars, base_field_names 

131 ) 

132 if private_attributes or base_private_attributes: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

133 original_model_post_init = get_model_post_init(namespace, bases) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

134 if original_model_post_init is not None: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

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

136 

137 @wraps(original_model_post_init) 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

138 def wrapped_model_post_init(self: BaseModel, context: Any, /) -> None: 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

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

140 method. 

141 """ 

142 init_private_attributes(self, context) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

143 original_model_post_init(self, context) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

144 

145 namespace['model_post_init'] = wrapped_model_post_init 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

146 else: 

147 namespace['model_post_init'] = init_private_attributes 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

148 

149 namespace['__class_vars__'] = class_vars 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

150 namespace['__private_attributes__'] = {**base_private_attributes, **private_attributes} 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

151 

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

153 BaseModel_ = import_cached_base_model() 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

154 

155 mro = cls.__mro__ 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

156 if Generic in mro and mro.index(Generic) < mro.index(BaseModel_): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

157 warnings.warn( 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

158 GenericBeforeBaseModelWarning( 

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

160 'for pydantic generics to work properly.' 

161 ), 

162 stacklevel=2, 

163 ) 

164 

165 cls.__pydantic_custom_init__ = not getattr(cls.__init__, '__pydantic_base_init__', False) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

166 cls.__pydantic_post_init__ = ( 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

168 ) 

169 

170 cls.__pydantic_setattr_handlers__ = {} 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

171 

172 cls.__pydantic_decorators__ = DecoratorInfos.build(cls) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

173 cls.__pydantic_decorators__.update_from_config(config_wrapper) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

174 

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

176 if __pydantic_generic_metadata__: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

177 cls.__pydantic_generic_metadata__ = __pydantic_generic_metadata__ 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

178 else: 

179 parent_parameters = getattr(cls, '__pydantic_generic_metadata__', {}).get('parameters', ()) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

180 parameters = getattr(cls, '__parameters__', None) or parent_parameters 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

181 if parameters and parent_parameters and not all(x in parameters for x in parent_parameters): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

182 from ..root_model import RootModelRootType 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

183 

184 missing_parameters = tuple(x for x in parameters if x not in parent_parameters) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

185 if RootModelRootType in parent_parameters and RootModelRootType not in parameters: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

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

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

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

189 # root: T 

190 # Should instead just be: 

191 # class MyModel(RootModel[T]): 

192 # root: T 

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

194 error_message = ( 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

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

196 f'{parameters_str} in its parameters. ' 

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

198 ) 

199 else: 

200 combined_parameters = parent_parameters + missing_parameters 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

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

202 generic_type_label = f'typing.Generic[{parameters_str}]' 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

203 error_message = ( 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

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

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

206 ) 

207 if Generic not in bases: # pragma: no cover 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

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

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

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

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

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

213 error_message += ( 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

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

215 ) 

216 raise TypeError(error_message) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

217 

218 cls.__pydantic_generic_metadata__ = { 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

219 'origin': None, 

220 'args': (), 

221 'parameters': parameters, 

222 } 

223 

224 cls.__pydantic_complete__ = False # Ensure this specific class gets completed 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

225 

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

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

228 for name, obj in private_attributes.items(): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

229 obj.__set_name__(cls, name) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

230 

231 if __pydantic_reset_parent_namespace__: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

232 cls.__pydantic_parent_namespace__ = build_lenient_weakvaluedict(parent_frame_namespace()) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

234 if isinstance(parent_namespace, dict): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

235 parent_namespace = unpack_lenient_weakvaluedict(parent_namespace) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

236 

237 ns_resolver = NsResolver(parent_namespace=parent_namespace) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

238 

239 set_model_fields(cls, config_wrapper=config_wrapper, ns_resolver=ns_resolver) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

240 

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

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

243 cls.__pydantic_computed_fields__ = { 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

245 } 

246 

247 if config_wrapper.defer_build: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

248 set_model_mocks(cls) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

249 else: 

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

251 # `complete_model_class()`: 

252 complete_model_class( 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

253 cls, 

254 config_wrapper, 

255 ns_resolver, 

256 raise_errors=False, 

257 create_model_module=_create_model_module, 

258 ) 

259 

260 if config_wrapper.frozen and '__hash__' not in namespace: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

261 set_default_hash_func(cls, bases) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

262 

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

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

265 # only hit for _proper_ subclasses of BaseModel 

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

267 return cls 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

268 else: 

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

270 for instance_slot in '__pydantic_fields_set__', '__pydantic_extra__', '__pydantic_private__': 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

271 namespace.pop( 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

272 instance_slot, 

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

274 ) 

275 namespace.get('__annotations__', {}).clear() 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

276 return super().__new__(mcs, cls_name, bases, namespace, **kwargs) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

277 

278 if not typing.TYPE_CHECKING: # pragma: no branch 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

280 

281 def __getattr__(self, item: str) -> Any: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

283 private_attributes = self.__dict__.get('__private_attributes__') 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

284 if private_attributes and item in private_attributes: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

285 return private_attributes[item] 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

286 raise AttributeError(item) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

287 

288 @classmethod 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

290 return _ModelNamespaceDict() 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

291 

292 def __instancecheck__(self, instance: Any) -> bool: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

294 

295 See #3829 and python/cpython#92810 

296 """ 

297 return hasattr(instance, '__pydantic_decorators__') and super().__instancecheck__(instance) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

298 

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

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

301 

302 See #3829 and python/cpython#92810 

303 """ 

304 return hasattr(subclass, '__pydantic_decorators__') and super().__subclasscheck__(subclass) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

305 

306 @staticmethod 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

308 BaseModel = import_cached_base_model() 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

309 

310 field_names: set[str] = set() 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

311 class_vars: set[str] = set() 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

312 private_attributes: dict[str, ModelPrivateAttr] = {} 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

313 for base in bases: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

314 if issubclass(base, BaseModel) and base is not BaseModel: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

316 field_names.update(getattr(base, '__pydantic_fields__', {}).keys()) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

317 class_vars.update(base.__class_vars__) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

318 private_attributes.update(base.__private_attributes__) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

319 return field_names, class_vars, private_attributes 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

320 

321 @property 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

323 def __fields__(self) -> dict[str, FieldInfo]: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

324 warnings.warn( 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

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

326 PydanticDeprecatedSince20, 

327 stacklevel=2, 

328 ) 

329 return getattr(self, '__pydantic_fields__', {}) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

330 

331 @property 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

332 def __pydantic_fields_complete__(self) -> bool: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

334 

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

336 """ 

337 if not hasattr(self, '__pydantic_fields__'): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

338 return False 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

339 

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

341 

342 return all(field_info._complete for field_info in field_infos.values()) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

343 

344 def __dir__(self) -> list[str]: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

345 attributes = list(super().__dir__()) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

346 if '__fields__' in attributes: 346 ↛ 348line 346 didn't jump to line 348 because the condition on line 346 was always true1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

347 attributes.remove('__fields__') 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

348 return attributes 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

349 

350 

351def init_private_attributes(self: BaseModel, context: Any, /) -> None: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

353 

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

355 

356 Args: 

357 self: The BaseModel instance. 

358 context: The context. 

359 """ 

360 if getattr(self, '__pydantic_private__', None) is None: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

361 pydantic_private = {} 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

362 for name, private_attr in self.__private_attributes__.items(): 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

363 default = private_attr.get_default() 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

364 if default is not PydanticUndefined: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

365 pydantic_private[name] = default 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

366 object_setattr(self, '__pydantic_private__', pydantic_private) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

367 

368 

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

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

371 if 'model_post_init' in namespace: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

372 return namespace['model_post_init'] 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

373 

374 BaseModel = import_cached_base_model() 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

375 

376 model_post_init = get_attribute_from_bases(bases, 'model_post_init') 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

377 if model_post_init is not BaseModel.model_post_init: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

378 return model_post_init 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

379 

380 

381def inspect_namespace( # noqa C901 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

382 namespace: dict[str, Any], 

383 raw_annotations: dict[str, Any], 

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

385 base_class_vars: set[str], 

386 base_class_fields: set[str], 

387) -> dict[str, ModelPrivateAttr]: 

388 """Iterate over the namespace and: 

389 * gather private attributes 

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

391 

392 Args: 

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

394 raw_annotations: The (non-evaluated) annotations of the model. 

395 ignored_types: A tuple of ignore types. 

396 base_class_vars: A set of base class class variables. 

397 base_class_fields: A set of base class fields. 

398 

399 Returns: 

400 A dict contains private attributes info. 

401 

402 Raises: 

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

404 NameError: If private attribute name is invalid. 

405 PydanticUserError: 

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

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

408 """ 

409 from ..fields import ModelPrivateAttr, PrivateAttr 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

410 

411 FieldInfo = import_cached_field_info() 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

412 

413 all_ignored_types = ignored_types + default_ignored_types() 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

414 

415 private_attributes: dict[str, ModelPrivateAttr] = {} 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

416 

417 if '__root__' in raw_annotations or '__root__' in namespace: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

419 

420 ignored_names: set[str] = set() 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

421 for var_name, value in list(namespace.items()): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

422 if var_name == 'model_config' or var_name == '__pydantic_extra__': 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

423 continue 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

424 elif ( 1gjkulvmnhopyqzirsCtD

425 isinstance(value, type) 

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

427 and '__qualname__' in namespace 

428 and value.__qualname__.startswith(f'{namespace["__qualname__"]}.') 

429 ): 

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

431 continue 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

433 ignored_names.add(var_name) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

434 continue 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

435 elif isinstance(value, ModelPrivateAttr): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

436 if var_name.startswith('__'): 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

437 raise NameError( 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

438 'Private attributes must not use dunder names;' 

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

440 ) 

441 elif is_valid_field_name(var_name): 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

442 raise NameError( 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

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

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

445 ) 

446 private_attributes[var_name] = value 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

447 del namespace[var_name] 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

448 elif isinstance(value, FieldInfo) and not is_valid_field_name(var_name): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

450 raise NameError( 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

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

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

453 ) 

454 

455 elif var_name.startswith('__'): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

456 continue 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

457 elif is_valid_privateattr_name(var_name): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

458 if var_name not in raw_annotations or not is_classvar_annotation(raw_annotations[var_name]): 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

459 private_attributes[var_name] = cast(ModelPrivateAttr, PrivateAttr(default=value)) 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

460 del namespace[var_name] 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

461 elif var_name in base_class_vars: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

462 continue 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

463 elif var_name not in raw_annotations: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

464 if var_name in base_class_fields: 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

465 raise PydanticUserError( 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

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

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

468 code='model-field-overridden', 

469 ) 

470 elif isinstance(value, FieldInfo): 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

471 raise PydanticUserError( 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

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

473 ) 

474 else: 

475 raise PydanticUserError( 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

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

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

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

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

480 ) 

481 

482 for ann_name, ann_type in raw_annotations.items(): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

483 if ( 1gjkulvmnhopyqzirsCtD

484 is_valid_privateattr_name(ann_name) 

485 and ann_name not in private_attributes 

486 and ann_name not in ignored_names 

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

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

489 and not is_classvar_annotation(ann_type) 

490 and ann_type not in all_ignored_types 

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

492 ): 

493 if isinstance(ann_type, str): 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

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

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

496 frame = sys._getframe(2) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

497 if frame is not None: 497 ↛ 507line 497 didn't jump to line 507 because the condition on line 497 was always true1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

498 try: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

499 ann_type = eval_type_backport( 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

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

501 globalns=frame.f_globals, 

502 localns=frame.f_locals, 

503 ) 

504 except (NameError, TypeError): 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

505 pass 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

506 

507 if typing_objects.is_annotated(get_origin(ann_type)): 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

508 _, *metadata = get_args(ann_type) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

509 private_attr = next((v for v in metadata if isinstance(v, ModelPrivateAttr)), None) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

510 if private_attr is not None: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

511 private_attributes[ann_name] = private_attr 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

512 continue 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

513 private_attributes[ann_name] = PrivateAttr() 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

514 

515 return private_attributes 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

516 

517 

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

519 base_hash_func = get_attribute_from_bases(bases, '__hash__') 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

520 new_hash_func = make_hash_func(cls) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

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

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

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

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

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

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

528 cls.__hash__ = new_hash_func 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

529 

530 

531def make_hash_func(cls: type[BaseModel]) -> Any: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

533 

534 def hash_func(self: Any) -> int: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

535 try: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

536 return hash(getter(self.__dict__)) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

537 except KeyError: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

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

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

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

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

542 return hash(getter(SafeGetItemProxy(self.__dict__))) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

543 

544 return hash_func 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

545 

546 

547def set_model_fields( 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

548 cls: type[BaseModel], 

549 config_wrapper: ConfigWrapper, 

550 ns_resolver: NsResolver | None, 

551) -> None: 

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

553 

554 Args: 

555 cls: BaseModel or dataclass. 

556 config_wrapper: The config wrapper instance. 

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

558 """ 

559 typevars_map = get_model_typevars_map(cls) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

560 fields, class_vars = collect_model_fields(cls, config_wrapper, ns_resolver, typevars_map=typevars_map) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

561 

562 cls.__pydantic_fields__ = fields 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

563 cls.__class_vars__.update(class_vars) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

564 

565 for k in class_vars: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

566 # Class vars should not be private attributes 

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

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

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

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

571 # evaluated to a classvar 

572 

573 value = cls.__private_attributes__.pop(k, None) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

574 if value is not None and value.default is not PydanticUndefined: 574 ↛ 575line 574 didn't jump to line 575 because the condition on line 574 was never true1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

575 setattr(cls, k, value.default) 

576 

577 

578def complete_model_class( 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

579 cls: type[BaseModel], 

580 config_wrapper: ConfigWrapper, 

581 ns_resolver: NsResolver, 

582 *, 

583 raise_errors: bool = True, 

584 call_on_complete_hook: bool = True, 

585 create_model_module: str | None = None, 

586) -> bool: 

587 """Finish building a model class. 

588 

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

590 and `get_type_hints` requires a class object. 

591 

592 Args: 

593 cls: BaseModel or dataclass. 

594 config_wrapper: The config wrapper instance. 

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

596 raise_errors: Whether to raise errors. 

597 call_on_complete_hook: Whether to call the `__pydantic_on_complete__` hook. 

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

599 

600 Returns: 

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

602 

603 Raises: 

604 PydanticUndefinedAnnotation: If `PydanticUndefinedAnnotation` occurs in`__get_pydantic_core_schema__` 

605 and `raise_errors=True`. 

606 """ 

607 typevars_map = get_model_typevars_map(cls) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

608 

609 if not cls.__pydantic_fields_complete__: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

610 # Note: when coming from `ModelMetaclass.__new__()`, this results in fields being built twice. 

611 # We do so a second time here so that we can get the `NameError` for the specific undefined annotation. 

612 # Alternatively, we could let `GenerateSchema()` raise the error, but there are cases where incomplete 

613 # fields are inherited in `collect_model_fields()` and can actually have their annotation resolved in the 

614 # generate schema process. As we want to avoid having `__pydantic_fields_complete__` set to `False` 

615 # when `__pydantic_complete__` is `True`, we rebuild here: 

616 try: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

617 cls.__pydantic_fields__ = rebuild_model_fields( 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

618 cls, 

619 config_wrapper=config_wrapper, 

620 ns_resolver=ns_resolver, 

621 typevars_map=typevars_map, 

622 ) 

623 except NameError as e: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

624 exc = PydanticUndefinedAnnotation.from_name_error(e) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

625 set_model_mocks(cls, f'`{exc.name}`') 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

626 if raise_errors: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

627 raise exc from e 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

628 

629 if not raise_errors and not cls.__pydantic_fields_complete__: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

630 # No need to continue with schema gen, it is guaranteed to fail 

631 return False 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

632 

633 assert cls.__pydantic_fields_complete__ 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

634 

635 gen_schema = GenerateSchema( 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

636 config_wrapper, 

637 ns_resolver, 

638 typevars_map, 

639 ) 

640 

641 try: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

642 schema = gen_schema.generate_schema(cls) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

643 except PydanticUndefinedAnnotation as e: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

644 if raise_errors: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

645 raise 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

646 set_model_mocks(cls, f'`{e.name}`') 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

647 return False 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

648 

649 core_config = config_wrapper.core_config(title=cls.__name__) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

650 

651 try: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

652 schema = gen_schema.clean_schema(schema) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

653 except InvalidSchemaError: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

654 set_model_mocks(cls) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

655 return False 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

656 

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

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

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

660 

661 set_deprecated_descriptors(cls) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

662 

663 cls.__pydantic_core_schema__ = schema 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

664 

665 cls.__pydantic_validator__ = create_schema_validator( 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

666 schema, 

667 cls, 

668 create_model_module or cls.__module__, 

669 cls.__qualname__, 

670 'create_model' if create_model_module else 'BaseModel', 

671 core_config, 

672 config_wrapper.plugin_settings, 

673 ) 

674 cls.__pydantic_serializer__ = SchemaSerializer(schema, core_config) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

675 

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

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

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

679 cls.__signature__ = LazyClassAttribute( 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

680 '__signature__', 

681 partial( 

682 generate_pydantic_signature, 

683 init=cls.__init__, 

684 fields=cls.__pydantic_fields__, 

685 validate_by_name=config_wrapper.validate_by_name, 

686 extra=config_wrapper.extra, 

687 ), 

688 ) 

689 

690 cls.__pydantic_complete__ = True 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

691 

692 if call_on_complete_hook: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

693 cls.__pydantic_on_complete__() 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

694 

695 return True 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

696 

697 

698def set_deprecated_descriptors(cls: type[BaseModel]) -> None: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

700 for field, field_info in cls.__pydantic_fields__.items(): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

701 if (msg := field_info.deprecation_message) is not None: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

702 desc = _DeprecatedFieldDescriptor(msg) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

703 desc.__set_name__(cls, field) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

704 setattr(cls, field, desc) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

705 

706 for field, computed_field_info in cls.__pydantic_computed_fields__.items(): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

707 if ( 1gjmnhoir

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

709 # Avoid having two warnings emitted: 

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

711 ): 

712 desc = _DeprecatedFieldDescriptor(msg, computed_field_info.wrapped_property) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

713 desc.__set_name__(cls, field) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

714 setattr(cls, field, desc) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

715 

716 

717class _DeprecatedFieldDescriptor: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

719 

720 Attributes: 

721 msg: The deprecation message to be emitted. 

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

723 field_name: The name of the field being deprecated. 

724 """ 

725 

726 field_name: str 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

727 

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

729 self.msg = msg 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

730 self.wrapped_property = wrapped_property 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

731 

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

733 self.field_name = name 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

734 

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

736 if obj is None: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

737 if self.wrapped_property is not None: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

738 return self.wrapped_property.__get__(None, obj_type) 1gjkulvwGxHadmnhopyqzAIBJbeirsCtDEKFLcf

739 raise AttributeError(self.field_name) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

740 

741 warnings.warn(self.msg, builtins.DeprecationWarning, stacklevel=2) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

742 

743 if self.wrapped_property is not None: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

744 return self.wrapped_property.__get__(obj, obj_type) 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

745 return obj.__dict__[self.field_name] 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

746 

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

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

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

750 def __set__(self, obj: Any, value: Any) -> NoReturn: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

751 raise AttributeError(self.field_name) 

752 

753 

754class _PydanticWeakRef: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

756 

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

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

759 `weakref.ref` instead of subclassing it. 

760 

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

762 

763 Semantics: 

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

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

766 will be maintained between them after unpickling. 

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

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

769 """ 

770 

771 def __init__(self, obj: Any): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

772 if obj is None: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

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

774 # had lost its underlying object. 

775 self._wr = None 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

776 else: 

777 self._wr = weakref.ref(obj) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

778 

779 def __call__(self) -> Any: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

780 if self._wr is None: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

781 return None 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

782 else: 

783 return self._wr() 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

784 

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

786 return _PydanticWeakRef, (self(),) 1gklwxamnhpqABbistEFc

787 

788 

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

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

791 

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

793 in a WeakValueDictionary. 

794 

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

796 """ 

797 if d is None: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

798 return None 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

799 result = {} 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

800 for k, v in d.items(): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

801 try: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

802 proxy = _PydanticWeakRef(v) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

803 except TypeError: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

804 proxy = v 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

805 result[k] = proxy 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

806 return result 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

807 

808 

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

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

811 if d is None: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

812 return None 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

813 

814 result = {} 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

815 for k, v in d.items(): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

816 if isinstance(v, _PydanticWeakRef): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

817 v = v() 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

818 if v is not None: 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

819 result[k] = v 1gjkulvwGxHadMmnhopyqzAIBJbeNirsCtDEKFLcfO

820 else: 

821 result[k] = v 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

822 return result 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

823 

824 

825@cache 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

826def default_ignored_types() -> tuple[type[Any], ...]: 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

827 from ..fields import ComputedFieldInfo 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

828 

829 ignored_types = [ 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

830 FunctionType, 

831 property, 

832 classmethod, 

833 staticmethod, 

834 PydanticDescriptorProxy, 

835 ComputedFieldInfo, 

836 TypeAliasType, # from `typing_extensions` 

837 ] 

838 

839 if sys.version_info >= (3, 12): 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO

840 ignored_types.append(typing.TypeAliasType) 1wGxHadMAIBJbeNPEKFLcfO

841 

842 return tuple(ignored_types) 1gjkulvwGxHadMmnhopyqzAIBJbeNPirsCtDEKFLcfO