Open bkeryan opened 1 year ago
Nice find! Thank you for the bug report, and thank you very much for the MRE. I've taken a run at a fix here, your MRE made verifying this and writing the test trivial. Does this look like it will solve your problem? https://github.com/shabbyrobe/grpc-stubs/pull/42
Thanks, I tried it out and left feedback on the PR.
Description of issue
The object returned from
grpc.UnaryStreamMultiCallable
andgrpc.StreamStreamMultiCallable
is aCall
, an iterator of response values, and aFuture
, but the grpc-stubs definition ofCallIterator[TResponse]
is only aCall
and an iterator of response values.Here's a link to the documentation for this return value: https://grpc.github.io/grpc/python/grpc.html#grpc.UnaryStreamMultiCallable
I attached an example
main.py
that calls aUnaryStreamMultiCallable
and usesFuture
methodsdone()
andexception()
to query its status. This works correctly at runtime (the exception is expected).However, it fails type checking with mypy:
Minimum Reproducible Example
main.py
```py from __future__ import annotations import grpc from hellostreamingworld_pb2 import HelloRequest, HelloReply from hellostreamingworld_pb2_grpc import MultiGreeterStub if __name__ == "__main__": channel = grpc.insecure_channel("localhost:1234") stub = MultiGreeterStub(channel) stream = stub.sayHello(HelloRequest(name="world", num_greetings="3")) stream.initial_metadata() if stream.done() and stream.exception() is not None: ex = stream.exception() print(f"Exception (expected): {ex}") ```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 grpcio-tools grpc-stubs mypy mypy-protobuf python -m grpc_tools.protoc -I. --python_out=. --grpc_python_out=. --pyi_out=. --mypy_grpc_out=. hellostreamingworld.proto python main.py python -m mypy main.py ```hellostreamingworld.proto
```sh // Copyright 2015 gRPC authors. // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. syntax = "proto3"; option java_package = "ex.grpc"; option objc_class_prefix = "HSW"; package hellostreamingworld; // The greeting service definition. service MultiGreeter { // Sends multiple greetings rpc sayHello (HelloRequest) returns (stream HelloReply) {} } // The request message containing the user's name and how many greetings // they want. message HelloRequest { string name = 1; string num_greetings = 2; } // A response message containing a greeting message HelloReply { string message = 1; } ```Full output
``` Requirement already satisfied: grpcio in ./venv/lib/python3.9/site-packages (1.55.0) Requirement already satisfied: grpcio-tools in ./venv/lib/python3.9/site-packages (1.55.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.3.0) Requirement already satisfied: mypy-protobuf in ./venv/lib/python3.9/site-packages (3.4.0) Requirement already satisfied: protobuf<5.0dev,>=4.21.6 in ./venv/lib/python3.9/site-packages (from grpcio-tools) (4.23.1) Requirement already satisfied: setuptools in ./venv/lib/python3.9/site-packages (from grpcio-tools) (58.1.0) 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>=3.10 in ./venv/lib/python3.9/site-packages (from mypy) (4.6.0) Requirement already satisfied: tomli>=1.1.0 in ./venv/lib/python3.9/site-packages (from mypy) (2.0.1) Requirement already satisfied: types-protobuf>=3.20.4 in ./venv/lib/python3.9/site-packages (from mypy-protobuf) (4.23.0.1) WARNING: You are using pip version 22.0.4; however, version 23.1.2 is available. You should consider upgrading via the '/tmp/unary_stream_call_future/venv/bin/python -m pip install --upgrade pip' command. Writing mypy to hellostreamingworld_pb2_grpc.pyi Exception (expected): <_MultiThreadedRendezvous of RPC that terminated with: status = StatusCode.UNAVAILABLE details = "failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:1234: Failed to connect to remote host: Connection refused" debug_error_string = "UNKNOWN:failed to connect to all addresses; last error: UNKNOWN: ipv4:127.0.0.1:1234: Failed to connect to remote host: Connection refused {created_time:"2023-05-22T19:47:20.563451309-05:00", grpc_status:14}" > main.py:12: error: "CallIterator[HelloReply]" has no attribute "done" [attr-defined] main.py:12: error: "CallIterator[HelloReply]" has no attribute "exception" [attr-defined] main.py:13: error: "CallIterator[HelloReply]" has no attribute "exception" [attr-defined] Found 3 errors in 1 file (checked 1 source file) ```