Open
Description
See last line (Playground):
from collections.abc import Iterator, Generator
from typing import Any, Iterable, TypeVar, overload
from typing_extensions import assert_type
T = TypeVar("T")
IterableT = TypeVar("IterableT", bound=Iterable)
@overload
def read_iterator(iterable: Iterator[T]) -> list[T]: ...
@overload
def read_iterator(iterable: IterableT) -> IterableT: ...
def read_iterator(iterable: Iterable) -> Iterable:
if isinstance(iterable, Iterator):
return list(iterable)
else:
return iterable
def _create_generator() -> Generator[int, Any, None]:
for i in range(3):
yield i
def test_read_iterator() -> None:
an_iterator = iter(range(3))
assert_type(read_iterator(an_iterator), list[int])
a_range, a_list, a_tuple, a_set, a_dict = range(3), [1, 2, 3], (1, 2, 3), {1, 2, 3}, {"a": 1}
assert_type(read_iterator(a_range), range)
assert_type(read_iterator(a_list), list[int])
assert_type(read_iterator(a_tuple), tuple[int, int, int])
assert_type(read_iterator(a_set), set[int])
assert_type(read_iterator(a_dict), dict[str, int])
a_generator = _create_generator()
assert_type(a_generator, Generator[int, Any, None])
assert_type(read_iterator(a_generator), list[int]) # error: Expression is of type "Any", not "list[int]" [assert-type]
Mypy doesn't like this code:
error: Expression is of type "Any", not "list[int]" [assert-type]
Please remember that Generator is a subtype of Iterator:
>>> isinstance(a_generator, Iterator)
True
I think this is a bug in Mypy. The Generator
should match the signature of def read_iterator(iterable: Iterator[T]) -> list[T]
Versions:
> python -V
Python 3.11.1
> mypy --version
mypy 1.11.2 (compiled: yes)
❯ system_profiler SPSoftwareDataType
Software:
System Software Overview:
System Version: macOS 13.6.7 (22G720)
Kernel Version: Darwin 22.6.0
Related: python/typing#253