MCPcopy
hub / github.com/python/mypy / collect_attributes

Method collect_attributes

mypy/plugins/dataclasses.py:513–748  ·  view source on GitHub ↗

Collect all attributes declared in the dataclass and its parents. All assignments of the form a: SomeType b: SomeOtherType = ... are collected. Return None if some dataclass base class hasn't been processed yet and thus we'll need to ask for an

(self)

Source from the content-addressed store, hash-verified

511 yield from self._get_assignment_statements_from_if_statement(stmt)
512
513 def collect_attributes(self) -> list[DataclassAttribute] | None:
514 """Collect all attributes declared in the dataclass and its parents.
515
516 All assignments of the form
517
518 a: SomeType
519 b: SomeOtherType = ...
520
521 are collected.
522
523 Return None if some dataclass base class hasn't been processed
524 yet and thus we'll need to ask for another pass.
525 """
526 cls = self._cls
527
528 # First, collect attributes belonging to any class in the MRO, ignoring duplicates.
529 #
530 # We iterate through the MRO in reverse because attrs defined in the parent must appear
531 # earlier in the attributes list than attrs defined in the child. See:
532 # https://docs.python.org/3/library/dataclasses.html#inheritance
533 #
534 # However, we also want attributes defined in the subtype to override ones defined
535 # in the parent. We can implement this via a dict without disrupting the attr order
536 # because dicts preserve insertion order in Python 3.7+.
537 found_attrs: dict[str, DataclassAttribute] = {}
538 for info in reversed(cls.info.mro[1:-1]):
539 if "dataclass_tag" in info.metadata and "dataclass" not in info.metadata:
540 # We haven't processed the base class yet. Need another pass.
541 return None
542 if "dataclass" not in info.metadata:
543 continue
544
545 # Each class depends on the set of attributes in its dataclass ancestors.
546 self._api.add_plugin_dependency(make_wildcard_trigger(info.fullname))
547
548 for data in info.metadata["dataclass"]["attributes"]:
549 name: str = data["name"]
550
551 attr = DataclassAttribute.deserialize(info, data, self._api)
552 # TODO: We shouldn't be performing type operations during the main
553 # semantic analysis pass, since some TypeInfo attributes might
554 # still be in flux. This should be performed in a later phase.
555 attr.expand_typevar_from_subtype(cls.info)
556 found_attrs[name] = attr
557
558 sym_node = cls.info.names.get(name)
559 if sym_node and sym_node.node and not isinstance(sym_node.node, Var):
560 self._api.fail(
561 "Dataclass attribute may only be overridden by another attribute",
562 sym_node.node,
563 )
564
565 # Second, collect attributes belonging to the current class.
566 current_attr_names: set[str] = set()
567 kw_only = self._get_bool_arg("kw_only", self._spec.kw_only_default)
568 for stmt in self._get_assignment_statements_from_block(cls.defs):
569 # Any assignment that doesn't use the new type declaration
570 # syntax can be ignored out of hand.

Callers 1

transformMethod · 0.95

Calls 15

_get_bool_argMethod · 0.95
_is_kw_only_typeMethod · 0.95
_collect_field_argsMethod · 0.95
make_wildcard_triggerFunction · 0.90
get_proper_typeFunction · 0.90
AnyTypeClass · 0.90
ContextClass · 0.90
reversedFunction · 0.85
isinstanceFunction · 0.85

Tested by

no test coverage detected