shabbyrobe / grpc-stubs

gRPC typing stubs for Python
MIT License
36 stars 21 forks source link

`CallIterator` is missing `__next__` method #50

Open bkeryan opened 1 year ago

bkeryan commented 1 year ago

Description of issue

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.

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) ```