Skip to content

Commit 49ebd62

Browse files
committed
test: fix some tests
1 parent df6adf1 commit 49ebd62

File tree

7 files changed

+42
-32
lines changed

7 files changed

+42
-32
lines changed

.travis.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ stages:
1010
if: tag IS present AND type != pull_request
1111
env:
1212
# We run pypy tests first because they run the slowest
13-
- PYTHON_IMAGE="pypy:3 PURERPC_BACKEND="asyncio"
13+
- PYTHON_IMAGE="pypy:3" PURERPC_BACKEND="asyncio"
1414
- PYTHON_IMAGE="pypy:3" PURERPC_BACKEND="curio"
1515
- PYTHON_IMAGE="pypy:3" PURERPC_BACKEND="trio"
1616
- PYTHON_IMAGE="standy/pypy:3.6-6.1.0" PURERPC_BACKEND="asyncio"

README.md

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
# purerpc
22

33
[![Build Status](https://travis-ci.org/standy66/purerpc.png?branch=master)](https://travis-ci.org/standy66/purerpc)
4+
[![Downloads](https://pepy.tech/badge/purerpc/month)](https://pepy.tech/project/purerpc)
45

56
Asynchronous pure Python gRPC client and server implementation supporting
67
[asyncio](https://docs.python.org/3/library/asyncio.html),
@@ -47,7 +48,7 @@ python -m grpc_tools.protoc --purerpc_out=. --python_out=. -I. greeter.proto
4748

4849
NOTE: `greeter_grpc` module is generated by purerpc's `protoc-gen-purerpc` plugin.
4950

50-
Below is the examples for Python 3.6 and above which introduced asynchronous generators as a language concept.
51+
Below are the examples for Python 3.6 and above which introduced asynchronous generators as a language concept.
5152
For Python 3.5, where native asynchronous generators are not supported, you can use [async_generator](https://github.com/python-trio/async_generator) library for this purpose.
5253
Just mark yielding coroutines with `@async_generator` decorator and use `await yield_(value)` and `await yield_from_(async_iterable)` instead of `yield`.
5354

@@ -98,7 +99,7 @@ async def main():
9899

99100

100101
if __name__ == "__main__":
101-
curio.run(main) # Or trio.run(main)
102+
curio.run(main) # Or trio.run(main), or run in asyncio event loop
102103
```
103104

104105
You can mix server and client code, for example make a server that requests something using purerpc from another gRPC server, etc.

setup.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
import os
33
from setuptools import setup, find_packages
44

5+
exec(open("src/purerpc/_version.py", encoding="utf-8").read())
6+
57

68
def read(*names, **kwargs):
79
with open(os.path.join(os.path.dirname(__file__), *names), "r") as fin:
@@ -12,7 +14,7 @@ def main():
1214
console_scripts = ['protoc-gen-purerpc=purerpc.protoc_plugin.plugin:main']
1315
setup(
1416
name="purerpc",
15-
version="0.1.6",
17+
version=__version__,
1618
license="Apache License Version 2.0",
1719
description="Asynchronous pure python gRPC server and client implementation using curio "
1820
"and hyper-h2.",

src/purerpc/_version.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# This file is imported from __init__.py and exec'd from setup.py
2+
3+
__version__ = "0.2.0"

src/purerpc/client.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,12 @@ def __init__(self, host, port):
1616
self._host = host
1717
self._port = port
1818
self._grpc_socket = None
19-
self._task_group = None
2019

2120
async def __aenter__(self):
2221
await super().__aenter__() # Does nothing
2322

2423
background_task_group = await self.enter_async_context(anyio.create_task_group())
2524
self.push_async_callback(background_task_group.cancel_scope.cancel)
26-
self._task_group = await self.enter_async_context(anyio.create_task_group())
2725

2826
socket = await anyio.connect_tcp(self._host, self._port, autostart_tls=False, tls_standard_compatible=False)
2927
config = GRPCConfiguration(client_side=True)
@@ -57,10 +55,10 @@ def get_method_stub(self, method_name: str, signature: RPCSignature):
5755
stream_fn = functools.partial(self.rpc, method_name, signature.request_type,
5856
signature.response_type)
5957
if signature.cardinality == Cardinality.STREAM_STREAM:
60-
return ClientStubStreamStream(stream_fn, self.channel._task_group)
58+
return ClientStubStreamStream(stream_fn)
6159
elif signature.cardinality == Cardinality.UNARY_STREAM:
62-
return ClientStubUnaryStream(stream_fn, self.channel._task_group)
60+
return ClientStubUnaryStream(stream_fn)
6361
elif signature.cardinality == Cardinality.STREAM_UNARY:
64-
return ClientStubStreamUnary(stream_fn, self.channel._task_group)
62+
return ClientStubStreamUnary(stream_fn)
6563
else:
66-
return ClientStubUnaryUnary(stream_fn, self.channel._task_group)
64+
return ClientStubUnaryUnary(stream_fn)

src/purerpc/wrappers.py

Lines changed: 21 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
from async_generator import aclosing, async_generator, yield_, yield_from_
1+
import functools
2+
3+
import anyio
4+
from async_generator import aclosing, async_generator, asynccontextmanager, yield_, yield_from_
5+
26
from .grpclib.exceptions import ProtocolError, raise_status
37
from .grpclib.status import Status, StatusCode
48
from purerpc.grpc_proto import GRPCProtoStream
@@ -29,9 +33,9 @@ async def stream_to_async_iterator(stream: GRPCProtoStream):
2933
await yield_(msg)
3034

3135

32-
async def send_multiple_messages_server(stream, agen):
33-
async with aclosing(agen) as tmp:
34-
async for message in tmp:
36+
async def send_multiple_messages_server(stream, aiter):
37+
async with aclosing(aiter) as aiter:
38+
async for message in aiter:
3539
await stream.send_message(message)
3640
await stream.close(Status(StatusCode.OK))
3741

@@ -41,18 +45,20 @@ async def send_single_message_server(stream, message):
4145
await stream.close(Status(StatusCode.OK))
4246

4347

44-
async def send_multiple_messages_client(stream, agen):
48+
async def send_multiple_messages_client(stream, aiter):
4549
try:
46-
async with aclosing(agen) as tmp:
47-
async for message in tmp:
50+
async with aclosing(aiter) as aiter:
51+
async for message in aiter:
4852
await stream.send_message(message)
4953
finally:
5054
await stream.close()
5155

5256

5357
async def send_single_message_client(stream, message):
54-
await stream.send_message(message)
55-
await stream.close()
58+
try:
59+
await stream.send_message(message)
60+
finally:
61+
await stream.close()
5662

5763

5864
async def call_server_unary_unary(func, stream):
@@ -76,9 +82,8 @@ async def call_server_stream_stream(func, stream):
7682

7783

7884
class ClientStub:
79-
def __init__(self, stream_fn, parent_task_group):
85+
def __init__(self, stream_fn):
8086
self._stream_fn = stream_fn
81-
self._parent_task_group = parent_task_group
8287

8388

8489
class ClientStubUnaryUnary(ClientStub):
@@ -99,16 +104,17 @@ async def __call__(self, message, *, metadata=None):
99104
class ClientStubStreamUnary(ClientStub):
100105
async def __call__(self, message_aiter, *, metadata=None):
101106
stream = await self._stream_fn(metadata=metadata)
102-
await self._parent_task_group.spawn(send_multiple_messages_client, stream, message_aiter)
103-
return await extract_message_from_singleton_stream(stream)
107+
async with anyio.create_task_group() as task_group:
108+
await task_group.spawn(send_multiple_messages_client, stream, message_aiter)
109+
return await extract_message_from_singleton_stream(stream)
104110

105111

106112
class ClientStubStreamStream(ClientStub):
107113
@async_generator
108114
async def call_aiter(self, message_aiter, metadata):
109115
stream = await self._stream_fn(metadata=metadata)
110-
if message_aiter is not None:
111-
await self._parent_task_group.spawn(send_multiple_messages_client, stream, message_aiter)
116+
async with anyio.create_task_group() as task_group:
117+
await task_group.spawn(send_multiple_messages_client, stream, message_aiter)
112118
await yield_from_(stream_to_async_iterator(stream))
113119

114120
async def call_stream(self, metadata):

tests/test_client_server_errors.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import typing
55
import time
66

7-
from async_generator import async_generator, yield_
7+
from async_generator import async_generator, aclosing, yield_
88

99
from .greeter_pb2 import HelloReply, HelloRequest
1010
from .greeter_pb2_grpc import GreeterStub, GreeterServicer, add_GreeterServicer_to_server
@@ -60,7 +60,7 @@ def SayHelloToMany(self, messages, context):
6060

6161
@async_generator
6262
async def generator():
63-
for _ in range(10):
63+
for _ in range(7):
6464
await yield_(HelloRequest())
6565

6666
GreeterStub = grpc_module.GreeterStub
@@ -69,11 +69,11 @@ async def worker(channel):
6969
with self.assertRaisesRegex(purerpc.RpcFailedError, r"oops my bad"):
7070
await stub.SayHello(HelloRequest(name="World"))
7171

72-
aiter = stub.SayHelloToMany(generator())
73-
for _ in range(7):
74-
await aiter.__anext__()
75-
with self.assertRaisesRegex(purerpc.RpcFailedError, r"Lucky 7"):
76-
await aiter.__anext__()
72+
async with aclosing(stub.SayHelloToMany(generator())) as aiter:
73+
for _ in range(7):
74+
await aiter.__anext__()
75+
with self.assertRaisesRegex(purerpc.RpcFailedError, r"Lucky 7"):
76+
await aiter.__anext__()
7777

7878
async def main():
7979
async with purerpc.insecure_channel("localhost", port) as channel:

0 commit comments

Comments
 (0)