MCPcopy
hub / github.com/pydantic/pydantic / collect_model_fields

Function collect_model_fields

pydantic/_internal/_fields.py:224–433  ·  view source on GitHub ↗

Collect the fields and class variables names of a nascent Pydantic model. The fields collection process is *lenient*, meaning it won't error if string annotations fail to evaluate. If this happens, the original annotation (and assigned value, if any) is stored on the created `FieldInfo`

(  # noqa: C901
    cls: type[BaseModel],
    config_wrapper: ConfigWrapper,
    ns_resolver: NsResolver,
    *,
    typevars_map: Mapping[TypeVar, Any] | None = None,
)

Source from the content-addressed store, hash-verified

222
223
224def collect_model_fields( # noqa: C901
225 cls: type[BaseModel],
226 config_wrapper: ConfigWrapper,
227 ns_resolver: NsResolver,
228 *,
229 typevars_map: Mapping[TypeVar, Any] | None = None,
230) -> tuple[dict[str, FieldInfo], PydanticExtraInfo | None, set[str]]:
231 """Collect the fields and class variables names of a nascent Pydantic model.
232
233 The fields collection process is *lenient*, meaning it won't error if string annotations
234 fail to evaluate. If this happens, the original annotation (and assigned value, if any)
235 is stored on the created `FieldInfo` instance.
236
237 The `rebuild_model_fields()` should be called at a later point (e.g. when rebuilding the model),
238 and will make use of these stored attributes.
239
240 Args:
241 cls: BaseModel or dataclass.
242 config_wrapper: The config wrapper instance.
243 ns_resolver: Namespace resolver to use when getting model annotations.
244 typevars_map: A dictionary mapping type variables to their concrete types.
245
246 Returns:
247 A three-tuple containing the model fields, the `PydanticExtraInfo` instance if the `__pydantic_extra__` annotation is set,
248 and class variables names.
249
250 Raises:
251 NameError:
252 - If there is a conflict between a field name and protected namespaces.
253 - If there is a field other than `root` in `RootModel`.
254 - If a field shadows an attribute in the parent model.
255 """
256 FieldInfo_ = import_cached_field_info()
257 BaseModel_ = import_cached_base_model()
258
259 bases = cls.__bases__
260 parent_fields_lookup: dict[str, FieldInfo] = {}
261 for base in reversed(bases):
262 if model_fields := getattr(base, '__pydantic_fields__', None):
263 parent_fields_lookup.update(model_fields)
264
265 type_hints = _typing_extra.get_model_type_hints(cls, ns_resolver=ns_resolver)
266
267 # `cls_annotations` is only used to determine if an annotation comes from a parent class
268 cls_annotations = _typing_extra.safe_get_annotations(cls)
269
270 fields: dict[str, FieldInfo] = {}
271
272 class_vars: set[str] = set()
273 for ann_name, (ann_type, evaluated) in type_hints.items():
274 if ann_name == 'model_config':
275 # We never want to treat `model_config` as a field
276 # Note: we may need to change this logic if/when we introduce a `BareModel` class with no
277 # protected namespaces (where `model_config` might be allowed as a field name)
278 continue
279
280 _check_protected_namespaces(
281 protected_namespaces=config_wrapper.protected_namespaces,

Callers 1

set_model_fieldsFunction · 0.85

Calls 15

import_cached_field_infoFunction · 0.85
import_cached_base_modelFunction · 0.85
is_valid_field_nameFunction · 0.85
_recreate_field_infoFunction · 0.85
update_field_from_configFunction · 0.85
PydanticExtraInfoClass · 0.85
from_annotationMethod · 0.80
_copyMethod · 0.80
is_requiredMethod · 0.80

Tested by

no test coverage detected