MCPcopy
hub / github.com/pydantic/pydantic / collect_fields_and_class_vars

Method collect_fields_and_class_vars

pydantic/mypy.py:627–693  ·  view source on GitHub ↗

Collects the fields for the model, accounting for parent classes.

(
        self, model_config: ModelConfigData, is_root_model: bool
    )

Source from the content-addressed store, hash-verified

625 return config
626
627 def collect_fields_and_class_vars(
628 self, model_config: ModelConfigData, is_root_model: bool
629 ) -> tuple[list[PydanticModelField] | None, list[PydanticModelClassVar] | None]:
630 """Collects the fields for the model, accounting for parent classes."""
631 cls = self._cls
632
633 # First, collect fields and ClassVars belonging to any class in the MRO, ignoring duplicates.
634 #
635 # We iterate through the MRO in reverse because attrs defined in the parent must appear
636 # earlier in the attributes list than attrs defined in the child. See:
637 # https://docs.python.org/3/library/dataclasses.html#inheritance
638 #
639 # However, we also want fields defined in the subtype to override ones defined
640 # in the parent. We can implement this via a dict without disrupting the attr order
641 # because dicts preserve insertion order in Python 3.7+.
642 found_fields: dict[str, PydanticModelField] = {}
643 found_class_vars: dict[str, PydanticModelClassVar] = {}
644 for info in reversed(cls.info.mro[1:-1]): # 0 is the current class, -2 is BaseModel, -1 is object
645 # if BASEMODEL_METADATA_TAG_KEY in info.metadata and BASEMODEL_METADATA_KEY not in info.metadata:
646 # # We haven't processed the base class yet. Need another pass.
647 # return None, None
648 if METADATA_KEY not in info.metadata:
649 continue
650
651 # Each class depends on the set of attributes in its dataclass ancestors.
652 self._api.add_plugin_dependency(make_wildcard_trigger(info.fullname))
653
654 for name, data in info.metadata[METADATA_KEY]['fields'].items():
655 field = PydanticModelField.deserialize(info, data, self._api)
656 # (The following comment comes directly from the dataclasses plugin)
657 # TODO: We shouldn't be performing type operations during the main
658 # semantic analysis pass, since some TypeInfo attributes might
659 # still be in flux. This should be performed in a later phase.
660 field.expand_typevar_from_subtype(cls.info, self._api)
661 found_fields[name] = field
662
663 sym_node = cls.info.names.get(name)
664 if sym_node and sym_node.node and not isinstance(sym_node.node, (Var, PlaceholderNode)):
665 self._api.fail(
666 'BaseModel field may only be overridden by another field',
667 sym_node.node,
668 )
669 # Collect ClassVars
670 for name, data in info.metadata[METADATA_KEY]['class_vars'].items():
671 found_class_vars[name] = PydanticModelClassVar.deserialize(data)
672
673 # Second, collect fields and ClassVars belonging to the current class.
674 current_field_names: set[str] = set()
675 current_class_vars_names: set[str] = set()
676 for stmt in self._get_assignment_statements_from_block(cls.defs):
677 maybe_field = self.collect_field_or_class_var_from_stmt(stmt, model_config, found_class_vars)
678 if maybe_field is None:
679 continue
680
681 lhs = stmt.lvalues[0]
682 assert isinstance(lhs, NameExpr) # collect_field_or_class_var_from_stmt guarantees this
683 if isinstance(maybe_field, PydanticModelField):
684 if is_root_model and lhs.name != 'root':

Callers 1

transformMethod · 0.95

Calls 9

failMethod · 0.80
valuesMethod · 0.80
itemsMethod · 0.45
deserializeMethod · 0.45
getMethod · 0.45

Tested by

no test coverage detected