Skip to content

Commit aa6d559

Browse files
authored
Merge pull request #298 from rsocket/coveralls_upgrade
requirements upgrade
2 parents 6d681b3 + aa6a73d commit aa6d559

File tree

7 files changed

+141
-19
lines changed

7 files changed

+141
-19
lines changed

requirements.txt

+31-12
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
Rx==3.2.0
2-
aiohttp==3.10.2
2+
3+
aiohttp==3.11.12; python_version > "3.8"
4+
aiohttp==3.10.11; python_version == "3.8"
5+
36
aioquic==1.2.0
4-
asyncstdlib==3.12.5
5-
asyncclick==8.1.7.2
7+
asyncstdlib==3.13.0
8+
9+
asyncclick==8.1.8; python_version > "3.8"
10+
asyncclick==8.1.7.2; python_version == "3.8"
11+
612
coverage==6.5.0
713
coveralls==3.3.1
814
decoy==2.1.1
9-
flake8==7.1.1
15+
flake8==7.1.2
1016

1117
pytest-asyncio==0.25.3; python_version > "3.8"
1218
pytest-asyncio==0.23.4; python_version == "3.8"
@@ -16,21 +22,34 @@ pytest-cov==4.1.0
1622
pytest-profiling==1.8.1; python_version > "3.8"
1723
pytest-profiling==1.7.0; python_version == "3.8"
1824

19-
pytest-rerunfailures==13.0
25+
pytest-rerunfailures==15.0; python_version > "3.8"
26+
pytest-rerunfailures==14.0; python_version == "3.8"
27+
2028
pytest-timeout==2.3.1
2129
pytest-xdist==3.6.1
2230

2331
pytest==8.3.4; python_version > "3.8"
2432
pytest==7.4.4; python_version == "3.8"
2533

26-
quart==0.19.9
34+
quart==0.20.0; python_version > "3.8"
35+
quart==0.19.9; python_version == "3.8"
36+
2737
reactivex==4.0.4
28-
starlette==0.40.0
38+
39+
starlette==0.45.3; python_version > "3.8"
40+
starlette==0.44.0; python_version == "3.8"
41+
2942
cbitstruct==1.1.0; python_version <= "3.12"
3043
cloudevents==1.11.0
31-
pydantic==1.10.18
32-
Werkzeug==3.0.4
33-
graphql-core==3.2.5
34-
gql==3.5.0
35-
websockets==13.1
44+
pydantic==1.10.21
45+
46+
Werkzeug==3.1.3; python_version > "3.8"
47+
Werkzeug==3.0.6; python_version == "3.8"
48+
49+
graphql-core==3.2.3
50+
gql==3.5.1
51+
52+
websockets==15.0; python_version > "3.8"
53+
websockets==13.1; python_version == "3.8"
54+
3655
asyncwebsockets==0.9.4

rsocket/graphql/rsocket_transport.py

+23-6
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from reactivestreams.subscriber import DefaultSubscriber
1010
from rsocket.extensions.helpers import composite, route
1111
from rsocket.frame_helpers import str_to_bytes
12+
from rsocket.logger import logger
1213
from rsocket.payload import Payload
1314
from rsocket.rsocket_client import RSocketClient
1415

@@ -104,6 +105,14 @@ def on_complete(self):
104105
def on_error(self, exception: Exception):
105106
self._received_queue.put_nowait(exception)
106107

108+
def cancel(self):
109+
if self.subscription is not None:
110+
self.subscription.cancel()
111+
112+
def request(self, n: int):
113+
if self.subscription is not None:
114+
self.subscription.request(n)
115+
107116
rsocket_payload = self._create_rsocket_payload(document, variable_values, operation_name)
108117

109118
received_queue = Queue()
@@ -112,12 +121,20 @@ def on_error(self, exception: Exception):
112121
self._rsocket_client.request_stream(rsocket_payload).subscribe(subscriber)
113122

114123
while True:
115-
response = await received_queue.get()
124+
try:
125+
response = await received_queue.get()
126+
127+
if isinstance(response, Exception):
128+
raise response
129+
130+
if response is complete_object:
131+
break
116132

117-
if isinstance(response, Exception):
118-
raise response
133+
execution_result = self._response_to_execution_result(response)
119134

120-
if response is complete_object:
121-
break
135+
yield execution_result
136+
except GeneratorExit:
137+
logger().debug('Generator exited')
138+
subscriber.cancel()
139+
return
122140

123-
yield self._response_to_execution_result(response)

rsocket/transports/aioquic_transport.py

+5
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,8 @@ async def send_frame(self, frame: Frame):
102102

103103
async def incoming_data_listener(self):
104104
try:
105+
logger().debug('Quic - Listener started')
106+
105107
await self._quic_protocol.wait_connected()
106108

107109
while True:
@@ -118,8 +120,11 @@ async def incoming_data_listener(self):
118120
logger().debug('Asyncio task canceled: incoming_data_listener')
119121
except Exception:
120122
self._incoming_frame_queue.put_nowait(RSocketTransportError())
123+
finally:
124+
logger().debug('Quic - Listener stopped')
121125

122126
async def close(self):
127+
logger().debug('Quic - Closing transport')
123128
await cancel_if_task_exists(self._listener)
124129
self._quic_protocol.close()
125130

tests/rsocket/test_concurrency.py

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import asyncio
2+
import logging
23
from typing import Tuple, Optional
34

45
import pytest
@@ -76,6 +77,8 @@ async def run():
7677
request_2 = asyncio.create_task(measure_time(client.request_response(Payload(b'10'))))
7778
return await request_1, await request_2
7879

80+
logging.debug("Starting concurrent requests")
81+
7982
measure_result = await measure_time(run())
8083

8184
results = measure_result.result

tests/rsocket/test_routing.py

+32
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55

66
from reactivestreams.subscriber import DefaultSubscriber
77
from rsocket.awaitable.awaitable_rsocket import AwaitableRSocket
8+
from rsocket.error_codes import ErrorCode
89
from rsocket.extensions.authentication import Authentication, AuthenticationSimple
910
from rsocket.extensions.composite_metadata import CompositeMetadata
1011
from rsocket.extensions.helpers import route, composite, authenticate_simple
1112
from rsocket.extensions.mimetypes import WellKnownMimeTypes
1213
from rsocket.helpers import create_response
1314
from rsocket.payload import Payload
15+
from rsocket.request_handler import BaseRequestHandler
1416
from rsocket.routing.request_router import RequestRouter
1517
from rsocket.routing.routing_request_handler import RoutingRequestHandler
1618
from rsocket.rx_support.rx_rsocket import RxRSocket
@@ -357,3 +359,33 @@ def handler_factory():
357359
'pass'))))
358360

359361
assert result.data == b'result'
362+
363+
364+
@pytest.mark.allow_error_log(regex_filter='(RSocket error REJECTED_SETUP|Setup error)')
365+
async def test_invalid_metadata_for_routing(lazy_pipe):
366+
router = RequestRouter()
367+
368+
async def authenticate(path: str, authentication: Authentication):
369+
if not isinstance(authentication, AuthenticationSimple) or authentication.password != b'pass':
370+
raise Exception('Invalid credentials')
371+
372+
error_wait = asyncio.Event()
373+
374+
def client_handler_factory():
375+
class ClientHandler(BaseRequestHandler):
376+
async def on_error(self, error_code: ErrorCode, payload: Payload):
377+
error_wait.set()
378+
379+
return ClientHandler()
380+
381+
@router.response('test.path')
382+
async def response():
383+
return create_response(b'result')
384+
385+
def handler_factory():
386+
return RoutingRequestHandler(router, authentication_verifier=authenticate)
387+
388+
async with lazy_pipe(
389+
client_arguments={'handler_factory': client_handler_factory},
390+
server_arguments={'handler_factory': handler_factory}) as (server, client):
391+
await error_wait.wait()

tests/test_integrations/test_graphql.py

+37-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import asyncio
2+
13
from gql import Client, gql
24

35
from rsocket.extensions.mimetypes import WellKnownMimeTypes
@@ -75,4 +77,38 @@ def handler_factory():
7577
gql("""{__schema { types { name } } }"""),
7678
get_execution_result=True)
7779

78-
assert response.data == expected_schema
80+
assert response.data == expected_schema
81+
82+
83+
async def test_graphql_break_loop(lazy_pipe, graphql_schema):
84+
def handler_factory():
85+
return RoutingRequestHandler(graphql_handler(graphql_schema, 'graphql'))
86+
87+
async with lazy_pipe(
88+
client_arguments={'metadata_encoding': WellKnownMimeTypes.MESSAGE_RSOCKET_COMPOSITE_METADATA},
89+
server_arguments={'handler_factory': handler_factory}) as (server, client):
90+
graphql = Client(
91+
schema=graphql_schema,
92+
transport=RSocketTransport(client),
93+
)
94+
95+
responses = []
96+
i = 0
97+
async for response in graphql.subscribe_async(
98+
document=gql("""
99+
subscription {
100+
greetings {message}
101+
}
102+
"""),
103+
get_execution_result=True):
104+
responses.append(response.data)
105+
i += 1
106+
if i > 4:
107+
break
108+
109+
assert len(responses) == 5
110+
assert responses[0] == {'greetings': {'message': 'Hello world 0'}}
111+
112+
await asyncio.sleep(1)
113+
114+
# assert responses[9] == {'greetings': {'message': 'Hello world 9'}}

tests/tools/fixtures_aioquic.py

+10
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import logging
12
from asyncio import Event
23
from contextlib import asynccontextmanager
34
from typing import Optional
@@ -34,12 +35,16 @@ def store_server(new_server):
3435
server = new_server
3536
wait_for_server.set()
3637

38+
logging.debug('test quic - starting server')
39+
3740
quic_server = await rsocket_serve(host='localhost',
3841
port=unused_tcp_port,
3942
configuration=server_configuration,
4043
on_server_create=store_server,
4144
**(server_arguments or {}))
4245

46+
logging.debug('test quic - server started')
47+
4348
try:
4449
# from datetime import timedelta
4550
# test_overrides = {'keep_alive_period': timedelta(minutes=20)}
@@ -49,7 +54,12 @@ def store_server(new_server):
4954
configuration=quic_client_configuration(certificate)) as transport:
5055
async with RSocketClient(single_transport_provider(transport),
5156
**client_arguments) as client:
57+
logging.debug('test quic - waiting for server to be ready')
58+
5259
await wait_for_server.wait()
60+
61+
logging.debug('test quic - server and client ready, starting test')
62+
5363
yield server, client
5464
finally:
5565
if server is not None:

0 commit comments

Comments
 (0)