Skip to content

Commit ecc00ef

Browse files
committed
Fix inference for attrs.fields
Fixes #15393
1 parent 235a3bb commit ecc00ef

File tree

3 files changed

+20
-2
lines changed

3 files changed

+20
-2
lines changed

mypy/checker.py

+8
Original file line numberDiff line numberDiff line change
@@ -4594,6 +4594,14 @@ def analyze_iterable_item_type(self, expr: Expression) -> tuple[Type, Type]:
45944594

45954595
if isinstance(iterable, TupleType):
45964596
joined: Type = UninhabitedType()
4597+
if iterable.partial_fallback.type.fullname != "builtins.tuple":
4598+
# If we're some fancier tuple variant, join with the fallback type
4599+
proper_iterator = get_proper_type(iterator)
4600+
if isinstance(proper_iterator, Instance) and not isinstance(
4601+
get_proper_type(proper_iterator.args[0]), AnyType
4602+
):
4603+
joined = proper_iterator.args[0]
4604+
45974605
for item in iterable.items:
45984606
joined = join_types(joined, item)
45994607
return iterator, joined

test-data/unit/check-plugin-attrs.test

+3
Original file line numberDiff line numberDiff line change
@@ -1570,6 +1570,9 @@ reveal_type(f(A)[0]) # N: Revealed type is "attr.Attribute[builtins.int]"
15701570
reveal_type(f(A).b) # N: Revealed type is "attr.Attribute[builtins.int]"
15711571
f(A).x # E: "____main___A_AttrsAttributes__" has no attribute "x"
15721572

1573+
for ff in f(A):
1574+
reveal_type(ff) # N: Revealed type is "attr.Attribute[Any]"
1575+
15731576
[builtins fixtures/plugin_attrs.pyi]
15741577

15751578
[case testAttrsGenericFields]

test-data/unit/fixtures/plugin_attrs.pyi

+9-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# Builtins stub used to support attrs plugin tests.
2-
from typing import Union, overload
2+
from typing import Union, overload, Generic, Sequence, TypeVar, Type, Iterable, Iterator
33

44
class object:
55
def __init__(self) -> None: pass
@@ -24,6 +24,13 @@ class complex:
2424

2525
class str: pass
2626
class ellipsis: pass
27-
class tuple: pass
2827
class list: pass
2928
class dict: pass
29+
30+
T = TypeVar("T")
31+
Tco = TypeVar('Tco', covariant=True)
32+
class tuple(Sequence[Tco], Generic[Tco]):
33+
def __new__(cls: Type[T], iterable: Iterable[Tco] = ...) -> T: ...
34+
def __iter__(self) -> Iterator[Tco]: pass
35+
def __contains__(self, item: object) -> bool: pass
36+
def __getitem__(self, x: int) -> Tco: pass

0 commit comments

Comments
 (0)