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

159 statements  

« prev     ^ index     » next       coverage.py v7.5.4, created at 2024-07-03 19:29 +0000

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

2 

3from __future__ import annotations as _annotations 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

4 

5import dataclasses 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

6import sys 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

7import warnings 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

8from copy import copy 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

9from functools import lru_cache 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

10from typing import TYPE_CHECKING, Any 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

11 

12from pydantic_core import PydanticUndefined 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

13 

14from pydantic.errors import PydanticUserError 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

15 

16from . import _typing_extra 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

17from ._config import ConfigWrapper 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

18from ._docs_extraction import extract_docstrings_from_cls 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

19from ._repr import Representation 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

20from ._typing_extra import get_cls_type_hints_lenient, get_type_hints, is_classvar, is_finalvar 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

21 

22if TYPE_CHECKING: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

23 from annotated_types import BaseMetadata 

24 

25 from ..fields import FieldInfo 

26 from ..main import BaseModel 

27 from ._dataclasses import StandardDataclass 

28 from ._decorators import DecoratorInfos 

29 

30 

31def get_type_hints_infer_globalns( 1mnopabcdqrstvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

32 obj: Any, 

33 localns: dict[str, Any] | None = None, 

34 include_extras: bool = False, 

35) -> dict[str, Any]: 

36 """Gets type hints for an object by inferring the global namespace. 

37 

38 It uses the `typing.get_type_hints`, The only thing that we do here is fetching 

39 global namespace from `obj.__module__` if it is not `None`. 

40 

41 Args: 

42 obj: The object to get its type hints. 

43 localns: The local namespaces. 

44 include_extras: Whether to recursively include annotation metadata. 

45 

46 Returns: 

47 The object type hints. 

48 """ 

49 module_name = getattr(obj, '__module__', None) 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

50 globalns: dict[str, Any] | None = None 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

51 if module_name: 51 ↛ 57line 51 didn't jump to line 57 because the condition on line 51 was always true1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

52 try: 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

53 globalns = sys.modules[module_name].__dict__ 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

54 except KeyError: 

55 # happens occasionally, see https://github.com/pydantic/pydantic/issues/2363 

56 pass 

57 return get_type_hints(obj, globalns=globalns, localns=localns, include_extras=include_extras) 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

58 

59 

60class PydanticMetadata(Representation): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

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

62 

63 __slots__ = () 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

64 

65 

66def pydantic_general_metadata(**metadata: Any) -> BaseMetadata: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

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

68 

69 Args: 

70 **metadata: The metadata to add. 

71 

72 Returns: 

73 The new `_PydanticGeneralMetadata` class. 

74 """ 

75 return _general_metadata_cls()(metadata) # type: ignore 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

76 

77 

78@lru_cache(maxsize=None) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

79def _general_metadata_cls() -> type[BaseMetadata]: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

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

81 from annotated_types import BaseMetadata 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

82 

83 class _PydanticGeneralMetadata(PydanticMetadata, BaseMetadata): 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

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

85 

86 def __init__(self, metadata: Any): 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

87 self.__dict__ = metadata 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

88 

89 return _PydanticGeneralMetadata # type: ignore 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

90 

91 

92def _update_fields_from_docstrings(cls: type[Any], fields: dict[str, FieldInfo], config_wrapper: ConfigWrapper) -> None: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

93 if config_wrapper.use_attribute_docstrings: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

94 fields_docs = extract_docstrings_from_cls(cls) 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

95 for ann_name, field_info in fields.items(): 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

96 if field_info.description is None and ann_name in fields_docs: 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

97 field_info.description = fields_docs[ann_name] 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

98 

99 

100def collect_model_fields( # noqa: C901 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

101 cls: type[BaseModel], 

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

103 config_wrapper: ConfigWrapper, 

104 types_namespace: dict[str, Any] | None, 

105 *, 

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

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

108 """Collect the fields of a nascent pydantic model. 

109 

110 Also collect the names of any ClassVars present in the type hints. 

111 

112 The returned value is a tuple of two items: the fields dict, and the set of ClassVar names. 

113 

114 Args: 

115 cls: BaseModel or dataclass. 

116 bases: Parents of the class, generally `cls.__bases__`. 

117 config_wrapper: The config wrapper instance. 

118 types_namespace: Optional extra namespace to look for types in. 

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

120 

121 Returns: 

122 A tuple contains fields and class variables. 

123 

124 Raises: 

125 NameError: 

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

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

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

129 """ 

130 from ..fields import FieldInfo 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

131 

132 type_hints = get_cls_type_hints_lenient(cls, types_namespace) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

133 

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

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

136 annotations = cls.__dict__.get('__annotations__', {}) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

137 fields: dict[str, FieldInfo] = {} 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

138 

139 class_vars: set[str] = set() 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

140 for ann_name, ann_type in type_hints.items(): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

141 if ann_name == 'model_config': 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

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

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

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

145 continue 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

146 for protected_namespace in config_wrapper.protected_namespaces: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

147 if ann_name.startswith(protected_namespace): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

148 for b in bases: 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

149 if hasattr(b, ann_name): 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

150 from ..main import BaseModel 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

151 

152 if not (issubclass(b, BaseModel) and ann_name in b.model_fields): 152 ↛ 148line 152 didn't jump to line 148 because the condition on line 152 was always true1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

153 raise NameError( 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

154 f'Field "{ann_name}" conflicts with member {getattr(b, ann_name)}' 

155 f' of protected namespace "{protected_namespace}".' 

156 ) 

157 else: 

158 valid_namespaces = tuple( 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

159 x for x in config_wrapper.protected_namespaces if not ann_name.startswith(x) 

160 ) 

161 warnings.warn( 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

162 f'Field "{ann_name}" has conflict with protected namespace "{protected_namespace}".' 

163 '\n\nYou may be able to resolve this warning by setting' 

164 f" `model_config['protected_namespaces'] = {valid_namespaces}`.", 

165 UserWarning, 

166 ) 

167 if is_classvar(ann_type): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

168 class_vars.add(ann_name) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

169 continue 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

170 if _is_finalvar_with_default_val(ann_type, getattr(cls, ann_name, PydanticUndefined)): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

171 class_vars.add(ann_name) 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

172 continue 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

173 if not is_valid_field_name(ann_name): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

174 continue 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

175 if cls.__pydantic_root_model__ and ann_name != 'root': 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

176 raise NameError( 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

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

178 ) 

179 

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

181 # "... shadows an attribute" warnings 

182 generic_origin = getattr(cls, '__pydantic_generic_metadata__', {}).get('origin') 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

183 for base in bases: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

184 dataclass_fields = { 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

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

186 } 

187 if hasattr(base, ann_name): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

188 if base is generic_origin: 188 ↛ 190line 188 didn't jump to line 190 because the condition on line 188 was never true1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

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

190 continue 

191 

192 if ann_name in dataclass_fields: 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

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

194 # on the class instance. 

195 continue 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

196 

197 if ann_name not in annotations: 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

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

199 continue 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

200 

201 warnings.warn( 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

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

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

204 UserWarning, 

205 ) 

206 

207 try: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

208 default = getattr(cls, ann_name, PydanticUndefined) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

209 if default is PydanticUndefined: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

210 raise AttributeError 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

211 except AttributeError: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

212 if ann_name in annotations: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

213 field_info = FieldInfo.from_annotation(ann_type) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

214 else: 

215 # if field has no default value and is not in __annotations__ this means that it is 

216 # defined in a base class and we can take it from there 

217 model_fields_lookup: dict[str, FieldInfo] = {} 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

218 for x in cls.__bases__[::-1]: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

219 model_fields_lookup.update(getattr(x, 'model_fields', {})) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

220 if ann_name in model_fields_lookup: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

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

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

223 field_info = copy(model_fields_lookup[ann_name]) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

224 else: 

225 # The field was not found on any base classes; this seems to be caused by fields not getting 

226 # generated thanks to models not being fully defined while initializing recursive models. 

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

228 field_info = FieldInfo.from_annotation(ann_type) 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

229 else: 

230 _warn_on_nested_alias_in_annotation(ann_type, ann_name) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

231 field_info = FieldInfo.from_annotated_attribute(ann_type, default) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

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

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

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

235 try: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

236 delattr(cls, ann_name) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

237 except AttributeError: 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

238 pass # indicates the attribute was on a parent class 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

239 

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

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

242 decorators: DecoratorInfos = cls.__dict__['__pydantic_decorators__'] 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

243 if ann_name in decorators.computed_fields: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

244 raise ValueError("you can't override a field with a computed field") 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

245 fields[ann_name] = field_info 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

246 

247 if typevars_map: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

248 for field in fields.values(): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

249 field.apply_typevars_map(typevars_map, types_namespace) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

250 

251 _update_fields_from_docstrings(cls, fields, config_wrapper) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

252 

253 return fields, class_vars 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

254 

255 

256def _warn_on_nested_alias_in_annotation(ann_type: type[Any], ann_name: str): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

257 from ..fields import FieldInfo 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

258 

259 if hasattr(ann_type, '__args__'): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

260 for anno_arg in ann_type.__args__: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

261 if _typing_extra.is_annotated(anno_arg): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

262 for anno_type_arg in _typing_extra.get_args(anno_arg): 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

263 if isinstance(anno_type_arg, FieldInfo) and anno_type_arg.alias is not None: 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

264 warnings.warn( 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

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

266 UserWarning, 

267 ) 

268 break 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

269 

270 

271def _is_finalvar_with_default_val(type_: type[Any], val: Any) -> bool: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

272 from ..fields import FieldInfo 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

273 

274 if not is_finalvar(type_): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

275 return False 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

276 elif val is PydanticUndefined: 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

277 return False 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

278 elif isinstance(val, FieldInfo) and (val.default is PydanticUndefined and val.default_factory is None): 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

279 return False 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

280 else: 

281 return True 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

282 

283 

284def collect_dataclass_fields( 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

285 cls: type[StandardDataclass], 

286 types_namespace: dict[str, Any] | None, 

287 *, 

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

289 config_wrapper: ConfigWrapper | None = None, 

290) -> dict[str, FieldInfo]: 

291 """Collect the fields of a dataclass. 

292 

293 Args: 

294 cls: dataclass. 

295 types_namespace: Optional extra namespace to look for types in. 

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

297 config_wrapper: The config wrapper instance. 

298 

299 Returns: 

300 The dataclass fields. 

301 """ 

302 from ..fields import FieldInfo 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

303 

304 fields: dict[str, FieldInfo] = {} 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

305 dataclass_fields: dict[str, dataclasses.Field] = cls.__dataclass_fields__ 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

306 cls_localns = dict(vars(cls)) # this matches get_cls_type_hints_lenient, but all tests pass with `= None` instead 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

307 

308 source_module = sys.modules.get(cls.__module__) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

309 if source_module is not None: 309 ↛ 312line 309 didn't jump to line 312 because the condition on line 309 was always true1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

310 types_namespace = {**source_module.__dict__, **(types_namespace or {})} 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

311 

312 for ann_name, dataclass_field in dataclass_fields.items(): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

313 ann_type = _typing_extra.eval_type_lenient(dataclass_field.type, types_namespace, cls_localns) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

314 if is_classvar(ann_type): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

315 continue 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

316 

317 if ( 1mnopabcdLuvwxyefghMNOPQRSTDEFGijkl

318 not dataclass_field.init 

319 and dataclass_field.default == dataclasses.MISSING 

320 and dataclass_field.default_factory == dataclasses.MISSING 

321 ): 

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

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

324 continue 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

325 

326 if isinstance(dataclass_field.default, FieldInfo): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

327 if dataclass_field.default.init_var: 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

328 if dataclass_field.default.init is False: 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

329 raise PydanticUserError( 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

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

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

332 ) 

333 

334 # TODO: same note as above re validate_assignment 

335 continue 1abcdqrstuefghzABCijklHIJK

336 field_info = FieldInfo.from_annotated_attribute(ann_type, dataclass_field.default) 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

337 else: 

338 field_info = FieldInfo.from_annotated_attribute(ann_type, dataclass_field) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

339 

340 fields[ann_name] = field_info 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

341 

342 if field_info.default is not PydanticUndefined and isinstance(getattr(cls, ann_name, field_info), FieldInfo): 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

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

344 setattr(cls, ann_name, field_info.default) 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

345 

346 if typevars_map: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

347 for field in fields.values(): 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

348 field.apply_typevars_map(typevars_map, types_namespace) 1mnopabcdqrstLuvwxyefghzABCDEFGijklHIJK

349 

350 if config_wrapper is not None: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

351 _update_fields_from_docstrings(cls, fields, config_wrapper) 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

352 

353 return fields 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

354 

355 

356def is_valid_field_name(name: str) -> bool: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

357 return not name.startswith('_') 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

358 

359 

360def is_valid_privateattr_name(name: str) -> bool: 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK

361 return name.startswith('_') and not name.startswith('__') 1mnopabcdqrstLuvwxyefghzABCMNOPQRSTUVDEFGijklHIJK