Coverage for pydantic/_internal/_fields.py: 98.80%

265 statements  

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

1"""Private logic related to fields (the `Field()` function and `FieldInfo` class), and arguments to `Annotated`.""" 

2 

3from __future__ import annotations as _annotations 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

4 

5import dataclasses 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

6import warnings 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

7from collections.abc import Mapping 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

8from copy import copy 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

9from functools import cache 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

10from inspect import Parameter, ismethoddescriptor, signature 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

11from re import Pattern 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

12from typing import TYPE_CHECKING, Any, Callable, TypeVar 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

13 

14from pydantic_core import PydanticUndefined 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

15from typing_extensions import TypeIs, get_origin 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

16from typing_inspection import typing_objects 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

17from typing_inspection.introspection import AnnotationSource 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

18 

19from pydantic import PydanticDeprecatedSince211 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

20from pydantic.errors import PydanticUserError 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

21 

22from ..aliases import AliasGenerator 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

23from . import _generics, _typing_extra 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

24from ._config import ConfigWrapper 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

25from ._docs_extraction import extract_docstrings_from_cls 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

26from ._import_utils import import_cached_base_model, import_cached_field_info 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

27from ._namespace_utils import NsResolver 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

28from ._repr import Representation 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

29from ._utils import can_be_positional, get_first_not_none 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

30 

31if TYPE_CHECKING: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

32 from annotated_types import BaseMetadata 

33 

34 from ..fields import FieldInfo 

35 from ..main import BaseModel 

36 from ._dataclasses import PydanticDataclass, StandardDataclass 

37 from ._decorators import DecoratorInfos 

38 

39 

40class PydanticMetadata(Representation): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

41 """Base class for annotation markers like `Strict`.""" 

42 

43 __slots__ = () 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

44 

45 

46def pydantic_general_metadata(**metadata: Any) -> BaseMetadata: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

47 """Create a new `_PydanticGeneralMetadata` class with the given metadata. 

48 

49 Args: 

50 **metadata: The metadata to add. 

51 

52 Returns: 

53 The new `_PydanticGeneralMetadata` class. 

54 """ 

55 return _general_metadata_cls()(metadata) # type: ignore 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

56 

57 

58@cache 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

59def _general_metadata_cls() -> type[BaseMetadata]: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

60 """Do it this way to avoid importing `annotated_types` at import time.""" 

61 from annotated_types import BaseMetadata 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

62 

63 class _PydanticGeneralMetadata(PydanticMetadata, BaseMetadata): 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

64 """Pydantic general metadata like `max_digits`.""" 

65 

66 def __init__(self, metadata: Any): 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

67 self.__dict__ = metadata 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

68 

69 return _PydanticGeneralMetadata # type: ignore 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

70 

71 

72def _check_protected_namespaces( 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

73 protected_namespaces: tuple[str | Pattern[str], ...], 

74 ann_name: str, 

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

76 cls_name: str, 

77) -> None: 

78 BaseModel = import_cached_base_model() 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

79 

80 for protected_namespace in protected_namespaces: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

81 ns_violation = False 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

82 if isinstance(protected_namespace, Pattern): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

83 ns_violation = protected_namespace.match(ann_name) is not None 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

84 elif isinstance(protected_namespace, str): 84 ↛ 87line 84 didn't jump to line 87 because the condition on line 84 was always true1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

85 ns_violation = ann_name.startswith(protected_namespace) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

86 

87 if ns_violation: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

88 for b in bases: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

89 if hasattr(b, ann_name): 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

90 if not (issubclass(b, BaseModel) and ann_name in getattr(b, '__pydantic_fields__', {})): 90 ↛ 88line 90 didn't jump to line 88 because the condition on line 90 was always true1abcghidefjkl

91 raise ValueError( 1abcghidefjkl

92 f'Field {ann_name!r} conflicts with member {getattr(b, ann_name)}' 

93 f' of protected namespace {protected_namespace!r}.' 

94 ) 

95 else: 

96 valid_namespaces: list[str] = [] 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

97 for pn in protected_namespaces: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

98 if isinstance(pn, Pattern): 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

99 if not pn.match(ann_name): 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

100 valid_namespaces.append(f're.compile({pn.pattern!r})') 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

101 else: 

102 if not ann_name.startswith(pn): 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

103 valid_namespaces.append(f"'{pn}'") 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

104 

105 valid_namespaces_str = f'({", ".join(valid_namespaces)}{",)" if len(valid_namespaces) == 1 else ")"}' 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

106 

107 warnings.warn( 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

108 f'Field {ann_name!r} in {cls_name!r} conflicts with protected namespace {protected_namespace!r}.\n\n' 

109 f"You may be able to solve this by setting the 'protected_namespaces' configuration to {valid_namespaces_str}.", 

110 UserWarning, 

111 stacklevel=5, 

112 ) 

113 

114 

115def _update_fields_from_docstrings(cls: type[Any], fields: dict[str, FieldInfo], use_inspect: bool = False) -> None: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

116 fields_docs = extract_docstrings_from_cls(cls, use_inspect=use_inspect) 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

117 for ann_name, field_info in fields.items(): 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

118 if field_info.description is None and ann_name in fields_docs: 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

119 field_info.description = fields_docs[ann_name] 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

120 

121 

122def _apply_field_title_generator_to_field_info( 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

123 title_generator: Callable[[str, FieldInfo], str], 

124 field_name: str, 

125 field_info: FieldInfo, 

126): 

127 if field_info.title is None: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

128 title = title_generator(field_name, field_info) 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

129 if not isinstance(title, str): 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

130 raise TypeError(f'field_title_generator {title_generator} must return str, not {title.__class__}') 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

131 

132 field_info.title = title 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

133 

134 

135def _apply_alias_generator_to_field_info( 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

136 alias_generator: Callable[[str], str] | AliasGenerator, field_name: str, field_info: FieldInfo 

137): 

138 """Apply an alias generator to aliases on a `FieldInfo` instance if appropriate. 

139 

140 Args: 

141 alias_generator: A callable that takes a string and returns a string, or an `AliasGenerator` instance. 

142 field_name: The name of the field from which to generate the alias. 

143 field_info: The `FieldInfo` instance to which the alias generator is (maybe) applied. 

144 """ 

145 # Apply an alias_generator if 

146 # 1. An alias is not specified 

147 # 2. An alias is specified, but the priority is <= 1 

148 if ( 1amLBpqdv

149 field_info.alias_priority is None 

150 or field_info.alias_priority <= 1 

151 or field_info.alias is None 

152 or field_info.validation_alias is None 

153 or field_info.serialization_alias is None 

154 ): 

155 alias, validation_alias, serialization_alias = None, None, None 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

156 

157 if isinstance(alias_generator, AliasGenerator): 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

158 alias, validation_alias, serialization_alias = alias_generator.generate_aliases(field_name) 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

159 elif callable(alias_generator): 159 ↛ 167line 159 didn't jump to line 167 because the condition on line 159 was always true1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

160 alias = alias_generator(field_name) 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

161 if not isinstance(alias, str): 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

162 raise TypeError(f'alias_generator {alias_generator} must return str, not {alias.__class__}') 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

163 

164 # if priority is not set, we set to 1 

165 # which supports the case where the alias_generator from a child class is used 

166 # to generate an alias for a field in a parent class 

167 if field_info.alias_priority is None or field_info.alias_priority <= 1: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

168 field_info.alias_priority = 1 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

169 

170 # if the priority is 1, then we set the aliases to the generated alias 

171 if field_info.alias_priority == 1: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

172 field_info.serialization_alias = get_first_not_none(serialization_alias, alias) 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

173 field_info.validation_alias = get_first_not_none(validation_alias, alias) 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

174 field_info.alias = alias 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

175 

176 # if any of the aliases are not set, then we set them to the corresponding generated alias 

177 if field_info.alias is None: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

178 field_info.alias = alias 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

179 if field_info.serialization_alias is None: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

180 field_info.serialization_alias = get_first_not_none(serialization_alias, alias) 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

181 if field_info.validation_alias is None: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

182 field_info.validation_alias = get_first_not_none(validation_alias, alias) 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

183 

184 

185def update_field_from_config(config_wrapper: ConfigWrapper, field_name: str, field_info: FieldInfo) -> None: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

186 """Update the `FieldInfo` instance from the configuration set on the model it belongs to. 

187 

188 This will apply the title and alias generators from the configuration. 

189 

190 Args: 

191 config_wrapper: The configuration from the model. 

192 field_name: The field name the `FieldInfo` instance is attached to. 

193 field_info: The `FieldInfo` instance to update. 

194 """ 

195 field_title_generator = field_info.field_title_generator or config_wrapper.field_title_generator 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

196 if field_title_generator is not None: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

197 _apply_field_title_generator_to_field_info(field_title_generator, field_name, field_info) 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

198 if config_wrapper.alias_generator is not None: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

199 _apply_alias_generator_to_field_info(config_wrapper.alias_generator, field_name, field_info) 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

200 

201 

202_deprecated_method_names = {'dict', 'json', 'copy', '_iter', '_copy_and_set_values', '_calculate_keys'} 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

203 

204_deprecated_classmethod_names = { 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

205 'parse_obj', 

206 'parse_raw', 

207 'parse_file', 

208 'from_orm', 

209 'construct', 

210 'schema', 

211 'schema_json', 

212 'validate', 

213 'update_forward_refs', 

214 '_get_value', 

215} 

216 

217 

218def collect_model_fields( # noqa: C901 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

219 cls: type[BaseModel], 

220 config_wrapper: ConfigWrapper, 

221 ns_resolver: NsResolver | None, 

222 *, 

223 typevars_map: Mapping[TypeVar, Any] | None = None, 

224) -> tuple[dict[str, FieldInfo], set[str]]: 

225 """Collect the fields and class variables names of a nascent Pydantic model. 

226 

227 The fields collection process is *lenient*, meaning it won't error if string annotations 

228 fail to evaluate. If this happens, the original annotation (and assigned value, if any) 

229 is stored on the created `FieldInfo` instance. 

230 

231 The `rebuild_model_fields()` should be called at a later point (e.g. when rebuilding the model), 

232 and will make use of these stored attributes. 

233 

234 Args: 

235 cls: BaseModel or dataclass. 

236 config_wrapper: The config wrapper instance. 

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

238 typevars_map: A dictionary mapping type variables to their concrete types. 

239 

240 Returns: 

241 A two-tuple containing model fields and class variables names. 

242 

243 Raises: 

244 NameError: 

245 - If there is a conflict between a field name and protected namespaces. 

246 - If there is a field other than `root` in `RootModel`. 

247 - If a field shadows an attribute in the parent model. 

248 """ 

249 FieldInfo_ = import_cached_field_info() 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

250 BaseModel_ = import_cached_base_model() 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

251 

252 bases = cls.__bases__ 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

253 parent_fields_lookup: dict[str, FieldInfo] = {} 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

254 for base in reversed(bases): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

255 if model_fields := getattr(base, '__pydantic_fields__', None): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

256 parent_fields_lookup.update(model_fields) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

257 

258 type_hints = _typing_extra.get_model_type_hints(cls, ns_resolver=ns_resolver) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

259 

260 # https://docs.python.org/3/howto/annotations.html#accessing-the-annotations-dict-of-an-object-in-python-3-9-and-older 

261 # annotations is only used for finding fields in parent classes 

262 annotations = _typing_extra.safe_get_annotations(cls) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

263 

264 fields: dict[str, FieldInfo] = {} 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

265 

266 class_vars: set[str] = set() 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

267 for ann_name, (ann_type, evaluated) in type_hints.items(): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

268 if ann_name == 'model_config': 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

269 # We never want to treat `model_config` as a field 

270 # Note: we may need to change this logic if/when we introduce a `BareModel` class with no 

271 # protected namespaces (where `model_config` might be allowed as a field name) 

272 continue 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

273 

274 _check_protected_namespaces( 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

275 protected_namespaces=config_wrapper.protected_namespaces, 

276 ann_name=ann_name, 

277 bases=bases, 

278 cls_name=cls.__name__, 

279 ) 

280 

281 if _typing_extra.is_classvar_annotation(ann_type): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

282 class_vars.add(ann_name) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

283 continue 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

284 

285 assigned_value = getattr(cls, ann_name, PydanticUndefined) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

286 if assigned_value is not PydanticUndefined and ( 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

287 # One of the deprecated instance methods was used as a field name (e.g. `dict()`): 

288 any(getattr(BaseModel_, depr_name, None) is assigned_value for depr_name in _deprecated_method_names) 

289 # One of the deprecated class methods was used as a field name (e.g. `schema()`): 

290 or ( 

291 hasattr(assigned_value, '__func__') 

292 and any( 

293 getattr(getattr(BaseModel_, depr_name, None), '__func__', None) is assigned_value.__func__ # pyright: ignore[reportAttributeAccessIssue] 

294 for depr_name in _deprecated_classmethod_names 

295 ) 

296 ) 

297 ): 

298 # Then `assigned_value` would be the method, even though no default was specified: 

299 assigned_value = PydanticUndefined 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

300 

301 if not is_valid_field_name(ann_name): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

302 continue 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

303 if cls.__pydantic_root_model__ and ann_name != 'root': 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

304 raise NameError( 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

305 f"Unexpected field with name {ann_name!r}; only 'root' is allowed as a field of a `RootModel`" 

306 ) 

307 

308 # when building a generic model with `MyModel[int]`, the generic_origin check makes sure we don't get 

309 # "... shadows an attribute" warnings 

310 generic_origin = getattr(cls, '__pydantic_generic_metadata__', {}).get('origin') 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

311 for base in bases: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

312 dataclass_fields = { 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

313 field.name for field in (dataclasses.fields(base) if dataclasses.is_dataclass(base) else ()) 

314 } 

315 if hasattr(base, ann_name): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

316 if base is generic_origin: 316 ↛ 318line 316 didn't jump to line 318 because the condition on line 316 was never true1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

317 # Don't warn when "shadowing" of attributes in parametrized generics 

318 continue 

319 

320 if ann_name in dataclass_fields: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

321 # Don't warn when inheriting stdlib dataclasses whose fields are "shadowed" by defaults being set 

322 # on the class instance. 

323 continue 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

324 

325 if ann_name not in annotations: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

326 # Don't warn when a field exists in a parent class but has not been defined in the current class 

327 continue 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

328 

329 warnings.warn( 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

330 f'Field name "{ann_name}" in "{cls.__qualname__}" shadows an attribute in parent ' 

331 f'"{base.__qualname__}"', 

332 UserWarning, 

333 ) 

334 

335 if assigned_value is PydanticUndefined: # no assignment, just a plain annotation 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

336 if ann_name in annotations or ann_name not in parent_fields_lookup: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

337 # field is either: 

338 # - present in the current model's annotations (and *not* from parent classes) 

339 # - not found on any base classes; this seems to be caused by fields bot getting 

340 # generated due to models not being fully defined while initializing recursive models. 

341 # Nothing stops us from just creating a `FieldInfo` for this type hint, so we do this. 

342 field_info = FieldInfo_.from_annotation(ann_type, _source=AnnotationSource.CLASS) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

343 if not evaluated: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

344 field_info._complete = False 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

345 # Store the original annotation that should be used to rebuild 

346 # the field info later: 

347 field_info._original_annotation = ann_type 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

348 else: 

349 # The field was present on one of the (possibly multiple) base classes 

350 # copy the field to make sure typevar substitutions don't cause issues with the base classes 

351 field_info = copy(parent_fields_lookup[ann_name]) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

352 

353 else: # An assigned value is present (either the default value, or a `Field()` function) 

354 _warn_on_nested_alias_in_annotation(ann_type, ann_name) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

355 if isinstance(assigned_value, FieldInfo_) and ismethoddescriptor(assigned_value.default): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

356 # `assigned_value` was fetched using `getattr`, which triggers a call to `__get__` 

357 # for descriptors, so we do the same if the `= field(default=...)` form is used. 

358 # Note that we only do this for method descriptors for now, we might want to 

359 # extend this to any descriptor in the future (by simply checking for 

360 # `hasattr(assigned_value.default, '__get__')`). 

361 default = assigned_value.default.__get__(None, cls) 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

362 assigned_value.default = default 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

363 assigned_value._attributes_set['default'] = default 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

364 

365 field_info = FieldInfo_.from_annotated_attribute(ann_type, assigned_value, _source=AnnotationSource.CLASS) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

366 # Store the original annotation and assignment value that should be used to rebuild the field info later. 

367 # Note that the assignment is always stored as the annotation might contain a type var that is later 

368 # parameterized with an unknown forward reference (and we'll need it to rebuild the field info): 

369 field_info._original_assignment = assigned_value 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

370 if not evaluated: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

371 field_info._complete = False 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

372 field_info._original_annotation = ann_type 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

373 elif 'final' in field_info._qualifiers and not field_info.is_required(): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

374 warnings.warn( 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

375 f'Annotation {ann_name!r} is marked as final and has a default value. Pydantic treats {ann_name!r} as a ' 

376 'class variable, but it will be considered as a normal field in V3 to be aligned with dataclasses. If you ' 

377 f'still want {ann_name!r} to be considered as a class variable, annotate it as: `ClassVar[<type>] = <default>.`', 

378 category=PydanticDeprecatedSince211, 

379 # Incorrect when `create_model` is used, but the chance that final with a default is used is low in that case: 

380 stacklevel=4, 

381 ) 

382 class_vars.add(ann_name) 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

383 continue 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

384 

385 # attributes which are fields are removed from the class namespace: 

386 # 1. To match the behaviour of annotation-only fields 

387 # 2. To avoid false positives in the NameError check above 

388 try: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

389 delattr(cls, ann_name) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

390 except AttributeError: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

391 pass # indicates the attribute was on a parent class 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

392 

393 # Use cls.__dict__['__pydantic_decorators__'] instead of cls.__pydantic_decorators__ 

394 # to make sure the decorators have already been built for this exact class 

395 decorators: DecoratorInfos = cls.__dict__['__pydantic_decorators__'] 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

396 if ann_name in decorators.computed_fields: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

397 raise TypeError( 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

398 f'Field {ann_name!r} of class {cls.__name__!r} overrides symbol of same name in a parent class. ' 

399 'This override with a computed_field is incompatible.' 

400 ) 

401 fields[ann_name] = field_info 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

402 

403 if field_info._complete: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

404 # If not complete, this will be called in `rebuild_model_fields()`: 

405 update_field_from_config(config_wrapper, ann_name, field_info) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

406 

407 if typevars_map: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

408 for field in fields.values(): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

409 if field._complete: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

410 field.apply_typevars_map(typevars_map) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

411 

412 if config_wrapper.use_attribute_docstrings: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

413 _update_fields_from_docstrings(cls, fields) 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

414 return fields, class_vars 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

415 

416 

417def _warn_on_nested_alias_in_annotation(ann_type: type[Any], ann_name: str) -> None: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

418 FieldInfo = import_cached_field_info() 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

419 

420 args = getattr(ann_type, '__args__', None) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

421 if args: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

422 for anno_arg in args: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

423 if typing_objects.is_annotated(get_origin(anno_arg)): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

424 for anno_type_arg in _typing_extra.get_args(anno_arg): 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

425 if isinstance(anno_type_arg, FieldInfo) and anno_type_arg.alias is not None: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

426 warnings.warn( 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

427 f'`alias` specification on field "{ann_name}" must be set on outermost annotation to take effect.', 

428 UserWarning, 

429 ) 

430 return 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

431 

432 

433def rebuild_model_fields( 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

434 cls: type[BaseModel], 

435 *, 

436 config_wrapper: ConfigWrapper, 

437 ns_resolver: NsResolver, 

438 typevars_map: Mapping[TypeVar, Any], 

439) -> dict[str, FieldInfo]: 

440 """Rebuild the (already present) model fields by trying to reevaluate annotations. 

441 

442 This function should be called whenever a model with incomplete fields is encountered. 

443 

444 Raises: 

445 NameError: If one of the annotations failed to evaluate. 

446 

447 Note: 

448 This function *doesn't* mutate the model fields in place, as it can be called during 

449 schema generation, where you don't want to mutate other model's fields. 

450 """ 

451 FieldInfo_ = import_cached_field_info() 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

452 

453 rebuilt_fields: dict[str, FieldInfo] = {} 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

454 with ns_resolver.push(cls): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

455 for f_name, field_info in cls.__pydantic_fields__.items(): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

456 if field_info._complete: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

457 rebuilt_fields[f_name] = field_info 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

458 else: 

459 existing_desc = field_info.description 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

460 ann = _typing_extra.eval_type( 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

461 field_info._original_annotation, 

462 *ns_resolver.types_namespace, 

463 ) 

464 ann = _generics.replace_types(ann, typevars_map) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

465 

466 if (assign := field_info._original_assignment) is PydanticUndefined: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

467 new_field = FieldInfo_.from_annotation(ann, _source=AnnotationSource.CLASS) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

468 else: 

469 new_field = FieldInfo_.from_annotated_attribute(ann, assign, _source=AnnotationSource.CLASS) 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

470 # The description might come from the docstring if `use_attribute_docstrings` was `True`: 

471 new_field.description = new_field.description if new_field.description is not None else existing_desc 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

472 update_field_from_config(config_wrapper, f_name, new_field) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

473 rebuilt_fields[f_name] = new_field 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

474 

475 return rebuilt_fields 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

476 

477 

478def collect_dataclass_fields( 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

479 cls: type[StandardDataclass], 

480 *, 

481 config_wrapper: ConfigWrapper, 

482 ns_resolver: NsResolver | None = None, 

483 typevars_map: dict[Any, Any] | None = None, 

484) -> dict[str, FieldInfo]: 

485 """Collect the fields of a dataclass. 

486 

487 Args: 

488 cls: dataclass. 

489 config_wrapper: The config wrapper instance. 

490 ns_resolver: Namespace resolver to use when getting dataclass annotations. 

491 Defaults to an empty instance. 

492 typevars_map: A dictionary mapping type variables to their concrete types. 

493 

494 Returns: 

495 The dataclass fields. 

496 """ 

497 FieldInfo_ = import_cached_field_info() 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

498 

499 fields: dict[str, FieldInfo] = {} 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

500 ns_resolver = ns_resolver or NsResolver() 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

501 dataclass_fields = cls.__dataclass_fields__ 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

502 

503 # The logic here is similar to `_typing_extra.get_cls_type_hints`, 

504 # although we do it manually as stdlib dataclasses already have annotations 

505 # collected in each class: 

506 for base in reversed(cls.__mro__): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

507 if not dataclasses.is_dataclass(base): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

508 continue 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

509 

510 with ns_resolver.push(base): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

511 for ann_name, dataclass_field in dataclass_fields.items(): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

512 base_anns = _typing_extra.safe_get_annotations(base) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

513 

514 if ann_name not in base_anns: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

515 # `__dataclass_fields__`contains every field, even the ones from base classes. 

516 # Only collect the ones defined on `base`. 

517 continue 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

518 

519 globalns, localns = ns_resolver.types_namespace 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

520 ann_type, evaluated = _typing_extra.try_eval_type(dataclass_field.type, globalns, localns) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

521 

522 if _typing_extra.is_classvar_annotation(ann_type): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

523 continue 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

524 

525 if ( 1ambncoLBpqrstudvewfx

526 not dataclass_field.init 

527 and dataclass_field.default is dataclasses.MISSING 

528 and dataclass_field.default_factory is dataclasses.MISSING 

529 ): 

530 # TODO: We should probably do something with this so that validate_assignment behaves properly 

531 # Issue: https://github.com/pydantic/pydantic/issues/5470 

532 continue 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

533 

534 if isinstance(dataclass_field.default, FieldInfo_): 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

535 if dataclass_field.default.init_var: 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

536 if dataclass_field.default.init is False: 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

537 raise PydanticUserError( 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

538 f'Dataclass field {ann_name} has init=False and init_var=True, but these are mutually exclusive.', 

539 code='clashing-init-and-init-var', 

540 ) 

541 

542 # TODO: same note as above re validate_assignment 

543 continue 1bncogyhziABrstuCDEFGHewfxjIkJlK

544 field_info = FieldInfo_.from_annotated_attribute( 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

545 ann_type, dataclass_field.default, _source=AnnotationSource.DATACLASS 

546 ) 

547 field_info._original_assignment = dataclass_field.default 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

548 else: 

549 field_info = FieldInfo_.from_annotated_attribute( 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

550 ann_type, dataclass_field, _source=AnnotationSource.DATACLASS 

551 ) 

552 field_info._original_assignment = dataclass_field 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

553 

554 if not evaluated: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

555 field_info._complete = False 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

556 field_info._original_annotation = ann_type 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

557 

558 fields[ann_name] = field_info 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

559 update_field_from_config(config_wrapper, ann_name, field_info) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

560 

561 if field_info.default is not PydanticUndefined and isinstance( 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

562 getattr(cls, ann_name, field_info), FieldInfo_ 

563 ): 

564 # We need this to fix the default when the "default" from __dataclass_fields__ is a pydantic.FieldInfo 

565 setattr(cls, ann_name, field_info.default) 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

566 

567 if typevars_map: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

568 for field in fields.values(): 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

569 # We don't pass any ns, as `field.annotation` 

570 # was already evaluated. TODO: is this method relevant? 

571 # Can't we juste use `_generics.replace_types`? 

572 field.apply_typevars_map(typevars_map) 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

573 

574 if config_wrapper.use_attribute_docstrings: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

575 _update_fields_from_docstrings( 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

576 cls, 

577 fields, 

578 # We can't rely on the (more reliable) frame inspection method 

579 # for stdlib dataclasses: 

580 use_inspect=not hasattr(cls, '__is_pydantic_dataclass__'), 

581 ) 

582 

583 return fields 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

584 

585 

586def rebuild_dataclass_fields( 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

587 cls: type[PydanticDataclass], 

588 *, 

589 config_wrapper: ConfigWrapper, 

590 ns_resolver: NsResolver, 

591 typevars_map: Mapping[TypeVar, Any], 

592) -> dict[str, FieldInfo]: 

593 """Rebuild the (already present) dataclass fields by trying to reevaluate annotations. 

594 

595 This function should be called whenever a dataclass with incomplete fields is encountered. 

596 

597 Raises: 

598 NameError: If one of the annotations failed to evaluate. 

599 

600 Note: 

601 This function *doesn't* mutate the dataclass fields in place, as it can be called during 

602 schema generation, where you don't want to mutate other dataclass's fields. 

603 """ 

604 FieldInfo_ = import_cached_field_info() 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

605 

606 rebuilt_fields: dict[str, FieldInfo] = {} 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

607 with ns_resolver.push(cls): 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

608 for f_name, field_info in cls.__pydantic_fields__.items(): 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

609 if field_info._complete: 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

610 rebuilt_fields[f_name] = field_info 1ambncogyhziALBpqrstuCDEFGHdvewfxjIkJlK

611 else: 

612 existing_desc = field_info.description 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

613 ann = _typing_extra.eval_type( 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

614 field_info._original_annotation, 

615 *ns_resolver.types_namespace, 

616 ) 

617 ann = _generics.replace_types(ann, typevars_map) 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

618 new_field = FieldInfo_.from_annotated_attribute( 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

619 ann, 

620 field_info._original_assignment, 

621 _source=AnnotationSource.DATACLASS, 

622 ) 

623 

624 # The description might come from the docstring if `use_attribute_docstrings` was `True`: 

625 new_field.description = new_field.description if new_field.description is not None else existing_desc 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

626 update_field_from_config(config_wrapper, f_name, new_field) 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

627 rebuilt_fields[f_name] = new_field 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

628 

629 return rebuilt_fields 1ambncogyhziAMLBpqrstuCDEFGHNdvewfxjIkJlKO

630 

631 

632def is_valid_field_name(name: str) -> bool: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

633 return not name.startswith('_') 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

634 

635 

636def is_valid_privateattr_name(name: str) -> bool: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

637 return name.startswith('_') and not name.startswith('__') 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

638 

639 

640def takes_validated_data_argument( 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

641 default_factory: Callable[[], Any] | Callable[[dict[str, Any]], Any], 

642) -> TypeIs[Callable[[dict[str, Any]], Any]]: 

643 """Whether the provided default factory callable has a validated data parameter.""" 

644 try: 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

645 sig = signature(default_factory) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

646 except (ValueError, TypeError): 1ambncogyhziAMpqrstuCDEFGHNdvewfxjIkJlKO

647 # `inspect.signature` might not be able to infer a signature, e.g. with C objects. 

648 # In this case, we assume no data argument is present: 

649 return False 1ambncogyhziAMpqrstuCDEFGHNdvewfxjIkJlKO

650 

651 parameters = list(sig.parameters.values()) 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO

652 

653 return len(parameters) == 1 and can_be_positional(parameters[0]) and parameters[0].default is Parameter.empty 1ambncogyhziAMLBpqrstuCDEFGHNPdvewfxjIkJlKO