The type hints for grpc.CallIterator define __iter__ but not __next__. Based on Iterator Types I think this makes grpc.CallIterator an iterable, not an iterator.
The result is that passing a grpc.CallIterator to the next() function works at runtime but causes mypy to emit this error:
main.py:16: error: No overload variant of "next" matches argument type "CallIterator[T]" [call-overload]
main.py:16: note: Possible overload variants:
main.py:16: note: def [_T] next(SupportsNext[_T], /) -> _T
main.py:16: note: def [_T, _VT] next(SupportsNext[_T], _VT, /) -> Union[_T, _VT]
The docs for grpc.UnaryStreamMultiCallable say the returned object is an iterator for response values, which suggests it implements the Iterator protocol, not only the Iterable protocol.
main.py
```py
from __future__ import annotations
import grpc
import typing
T = typing.TypeVar("T")
if typing.TYPE_CHECKING:
# grpc.CallIterator is only defined when type checking
class CallIteratorPlusNext(grpc.CallIterator[T]):
def __next__(self) -> T:
raise NotImplementedError()
# This generates mypy errors because grpc.CallIterator does not have a
# __next__() method.
def call_next(call_iterator: grpc.CallIterator[T]) -> T:
return next(call_iterator)
# This does not generate mypy errors because the derived class adds a
# __next__() method.
def call_next_plus(call_iterator: CallIteratorPlusNext[T]) -> T:
return next(call_iterator)
```
run.sh
```sh
#!/usr/bin/env bash
set -o errexit -o nounset -o pipefail
python -m venv venv
source ./venv/bin/activate
pip install grpcio grpc-stubs mypy
mypy main.py
```
Full output
```
Requirement already satisfied: grpcio in ./venv/lib/python3.9/site-packages (1.57.0)
Requirement already satisfied: grpc-stubs in ./venv/lib/python3.9/site-packages (1.53.0.2)
Requirement already satisfied: mypy in ./venv/lib/python3.9/site-packages (1.5.0)
Requirement already satisfied: tomli>=1.1.0 in ./venv/lib/python3.9/site-packages (from mypy) (2.0.1)
Requirement already satisfied: mypy-extensions>=1.0.0 in ./venv/lib/python3.9/site-packages (from mypy) (1.0.0)
Requirement already satisfied: typing-extensions>=4.1.0 in ./venv/lib/python3.9/site-packages (from mypy) (4.7.1)
WARNING: You are using pip version 22.0.4; however, version 23.2.1 is available.
You should consider upgrading via the '/tmp/grpc_itr/venv/bin/python -m pip install --upgrade pip' command.
main.py:16: error: No overload variant of "next" matches argument type "CallIterator[T]" [call-overload]
main.py:16: note: Possible overload variants:
main.py:16: note: def [_T] next(SupportsNext[_T], /) -> _T
main.py:16: note: def [_T, _VT] next(SupportsNext[_T], _VT, /) -> Union[_T, _VT]
Found 1 error in 1 file (checked 1 source file)
```
Description of issue
The type hints for
grpc.CallIterator
define__iter__
but not__next__
. Based on Iterator Types I think this makesgrpc.CallIterator
an iterable, not an iterator.The result is that passing a
grpc.CallIterator
to thenext()
function works at runtime but causes mypy to emit this error:The docs for grpc.UnaryStreamMultiCallable say the returned object is an iterator for response values, which suggests it implements the
Iterator
protocol, not only theIterable
protocol.The implementation in the grpc._channel._Rendezvous class supports
__next__
.Minimum Reproducible Example
main.py
```py from __future__ import annotations import grpc import typing T = typing.TypeVar("T") if typing.TYPE_CHECKING: # grpc.CallIterator is only defined when type checking class CallIteratorPlusNext(grpc.CallIterator[T]): def __next__(self) -> T: raise NotImplementedError() # This generates mypy errors because grpc.CallIterator does not have a # __next__() method. def call_next(call_iterator: grpc.CallIterator[T]) -> T: return next(call_iterator) # This does not generate mypy errors because the derived class adds a # __next__() method. def call_next_plus(call_iterator: CallIteratorPlusNext[T]) -> T: return next(call_iterator) ```run.sh
```sh #!/usr/bin/env bash set -o errexit -o nounset -o pipefail python -m venv venv source ./venv/bin/activate pip install grpcio grpc-stubs mypy mypy main.py ```Full output
``` Requirement already satisfied: grpcio in ./venv/lib/python3.9/site-packages (1.57.0) Requirement already satisfied: grpc-stubs in ./venv/lib/python3.9/site-packages (1.53.0.2) Requirement already satisfied: mypy in ./venv/lib/python3.9/site-packages (1.5.0) Requirement already satisfied: tomli>=1.1.0 in ./venv/lib/python3.9/site-packages (from mypy) (2.0.1) Requirement already satisfied: mypy-extensions>=1.0.0 in ./venv/lib/python3.9/site-packages (from mypy) (1.0.0) Requirement already satisfied: typing-extensions>=4.1.0 in ./venv/lib/python3.9/site-packages (from mypy) (4.7.1) WARNING: You are using pip version 22.0.4; however, version 23.2.1 is available. You should consider upgrading via the '/tmp/grpc_itr/venv/bin/python -m pip install --upgrade pip' command. main.py:16: error: No overload variant of "next" matches argument type "CallIterator[T]" [call-overload] main.py:16: note: Possible overload variants: main.py:16: note: def [_T] next(SupportsNext[_T], /) -> _T main.py:16: note: def [_T, _VT] next(SupportsNext[_T], _VT, /) -> Union[_T, _VT] Found 1 error in 1 file (checked 1 source file) ```