python-betterproto icon indicating copy to clipboard operation
python-betterproto copied to clipboard

`_stream_unary` doesn't work with empty iterables

Open spietras opened this issue 1 year ago • 2 comments

Methods that use _stream_unary work correctly when I use any iterable that is not empty. However, I noticed that when I try to pass any empty iterable (an empty list for example: []) then I always get this exception:

grpclib.exceptions.ProtocolError: Request was not sent

I started digging into the source code, and the source of this error is here:

https://github.com/vmagamedov/grpclib/blob/e964bbb2cc2429294e9685d75ac5e2f1c2b13971/grpclib/client.py#L264-L275

The end method is invoked here, after sending all messages:

https://github.com/danielgtaylor/python-betterproto/blob/bfc0fac7544bbdf4e0e2beabd45482a4958af514/src/betterproto/grpc/grpclib_client.py#L168-L176

If we now look at _stream_unary:

https://github.com/danielgtaylor/python-betterproto/blob/bfc0fac7544bbdf4e0e2beabd45482a4958af514/src/betterproto/grpc/grpclib_client.py#L111-L131

it goes straight into sending messages with _send_messages.

Compare that to _stream_stream:

https://github.com/danielgtaylor/python-betterproto/blob/bfc0fac7544bbdf4e0e2beabd45482a4958af514/src/betterproto/grpc/grpclib_client.py#L135-L166

which first calls send_request before calling _send_messages.

It seems that when any messages are present, the request will be sent before the first message if not sent already, but if there are no messages then the request will not be sent and end will fail. Unless I misunderstand something, it seems that the fix is to simply add await stream.send_request() in _stream_unary.

spietras avatar Sep 22 '22 00:09 spietras

Would you be willing to create a PR for this with a test to prevent a regression like this again?

Gobot1234 avatar Sep 22 '22 13:09 Gobot1234

Sure: #422

spietras avatar Sep 22 '22 19:09 spietras