Skip to content

Commit 6d4bb06

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

File tree

3 files changed

+19
-2
lines changed

3 files changed

+19
-2
lines changed

mypy/checker.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4592,8 +4592,15 @@ def analyze_iterable_item_type(self, expr: Expression) -> tuple[Type, Type]:
45924592
if int_type:
45934593
return iterator, int_type
45944594

4595+
45954596
if isinstance(iterable, TupleType):
45964597
joined: Type = UninhabitedType()
4598+
if iterable.partial_fallback.type.fullname != "builtins.tuple":
4599+
# If we're some fancier tuple variant, join with the item type
4600+
item_type = echk.check_method_call_by_name("__next__", iterator, [], [], expr)[0]
4601+
if not isinstance(get_proper_type(item_type), AnyType):
4602+
joined = item_type
4603+
45974604
for item in iterable.items:
45984605
joined = join_types(joined, item)
45994606
return iterator, joined

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

Lines changed: 3 additions & 0 deletions
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

Lines changed: 9 additions & 2 deletions
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)