diff --git a/mypy/plugins/attrs.py b/mypy/plugins/attrs.py index afd9423d6820..4a1b93e6bcde 100644 --- a/mypy/plugins/attrs.py +++ b/mypy/plugins/attrs.py @@ -875,6 +875,10 @@ def _add_attrs_magic_attribute( if isinstance(proper_type, Instance): var.info = proper_type.type ti.names[name] = SymbolTableNode(MDEF, var, plugin_generated=True) + + # We fix up the `__iter__` name so these tuples are iterable as attr.Attributes + ti.names["__iter__"] = fallback_type.type.names["__iter__"] + attributes_type = Instance(ti, []) # We need to stash the type of the magic attribute so it can be diff --git a/test-data/unit/check-plugin-attrs.test b/test-data/unit/check-plugin-attrs.test index 9aa31c1ed10b..0b5b27b7ebb6 100644 --- a/test-data/unit/check-plugin-attrs.test +++ b/test-data/unit/check-plugin-attrs.test @@ -1569,6 +1569,20 @@ f(A).x # E: "____main___A_AttrsAttributes__" has no attribute "x" [builtins fixtures/plugin_attrs.pyi] +[case testAttrsFieldsIteration] +import attr +from attrs import fields as f # Common usage. + +@attr.define +class A: + b: int + c: str + +for a in f(A): + reveal_type(a) # N: Revealed type is "attr.Attribute[Any]" + +[builtins fixtures/tuple.pyi] + [case testAttrsGenericFields] from typing import TypeVar