Skip to content

Commit 750e695

Browse files
committed
Fix PyPy tests
1 parent 496add1 commit 750e695

9 files changed

+95
-21
lines changed

gql/transport/common/base.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,8 @@ async def subscribe(
317317
if listener.send_stop:
318318
await self._stop_listener(query_id)
319319
listener.send_stop = False
320+
if isinstance(e, GeneratorExit):
321+
raise e
320322

321323
finally:
322324
log.debug(f"In subscribe finally for query_id {query_id}")
@@ -345,6 +347,11 @@ async def execute(
345347
first_result = result
346348
break
347349

350+
# Apparently, on pypy the GeneratorExit exception is not raised after a break
351+
# --> the clean_close has to time out
352+
# We still need to manually close the async generator
353+
await generator.aclose()
354+
348355
if first_result is None:
349356
raise TransportQueryError(
350357
"Query completed without any answer received from the server"
@@ -445,7 +452,6 @@ async def _clean_close(self, e: Exception) -> None:
445452

446453
# Send 'stop' message for all current queries
447454
for query_id, listener in self.listeners.items():
448-
449455
if listener.send_stop:
450456
await self._stop_listener(query_id)
451457
listener.send_stop = False
@@ -556,7 +562,7 @@ async def wait_closed(self) -> None:
556562
try:
557563
await asyncio.wait_for(self._wait_closed.wait(), self.close_timeout)
558564
except asyncio.TimeoutError:
559-
log.debug("Timer close_timeout fired in wait_closed")
565+
log.warning("Timer close_timeout fired in wait_closed")
560566

561567
log.debug("wait_close: done")
562568

tests/conftest.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import logging
44
import os
55
import pathlib
6+
import platform
67
import re
78
import ssl
89
import sys
@@ -19,6 +20,9 @@
1920
all_transport_dependencies = ["aiohttp", "requests", "httpx", "websockets", "botocore"]
2021

2122

23+
PyPy = platform.python_implementation() == "PyPy"
24+
25+
2226
def pytest_addoption(parser):
2327
parser.addoption(
2428
"--run-online",

tests/test_aiohttp_websocket_graphqlws_subscription.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from gql import Client, gql
1111
from gql.transport.exceptions import TransportConnectionClosed, TransportServerError
1212

13-
from .conftest import MS, WebSocketServerHelper
13+
from .conftest import MS, PyPy, WebSocketServerHelper
1414

1515
# Marking all tests in this file with the aiohttp AND websockets marker
1616
pytestmark = [pytest.mark.aiohttp, pytest.mark.websockets]
@@ -260,7 +260,8 @@ async def test_aiohttp_websocket_graphqlws_subscription_break(
260260
count = 10
261261
subscription = gql(subscription_str.format(count=count))
262262

263-
async for result in session.subscribe(subscription):
263+
generator = session.subscribe(subscription)
264+
async for result in generator:
264265

265266
number = result["number"]
266267
print(f"Number received: {number}")
@@ -274,6 +275,9 @@ async def test_aiohttp_websocket_graphqlws_subscription_break(
274275

275276
assert count == 5
276277

278+
# Using aclose here to make it stop cleanly on pypy
279+
await generator.aclose()
280+
277281

278282
@pytest.mark.asyncio
279283
@pytest.mark.parametrize("graphqlws_server", [server_countdown], indirect=True)
@@ -847,30 +851,42 @@ async def test_aiohttp_websocket_graphqlws_subscription_reconnecting_session(
847851
# Then with the same session handle, we make a subscription or an execute
848852
# which will detect that the transport is closed so that the client could
849853
# try to reconnect
854+
generator = None
850855
try:
851856
if execute_instead_of_subscribe:
852857
print("\nEXECUTION_2\n")
853858
await session.execute(subscription)
854859
else:
855860
print("\nSUBSCRIPTION_2\n")
856-
async for result in session.subscribe(subscription):
861+
generator = session.subscribe(subscription)
862+
async for result in generator:
857863
pass
858-
except TransportClosed:
864+
except (TransportClosed, TransportConnectionClosed):
865+
if generator:
866+
await generator.aclose()
859867
pass
860868

861-
await asyncio.sleep(50 * MS)
869+
timeout = 50
870+
871+
if PyPy:
872+
timeout = 500
873+
874+
await asyncio.sleep(timeout * MS)
862875

863876
# And finally with the same session handle, we make a subscription
864877
# which works correctly
865878
print("\nSUBSCRIPTION_3\n")
866-
async for result in session.subscribe(subscription):
879+
generator = session.subscribe(subscription)
880+
async for result in generator:
867881

868882
number = result["number"]
869883
print(f"Number received: {number}")
870884

871885
assert number == count
872886
count -= 1
873887

888+
await generator.aclose()
889+
874890
assert count == -1
875891

876892
await client.close_async()

tests/test_aiohttp_websocket_subscription.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,8 @@ async def test_aiohttp_websocket_subscription_break(
250250
count = 10
251251
subscription = gql(subscription_str.format(count=count))
252252

253-
async for result in session.subscribe(subscription):
253+
generator = session.subscribe(subscription)
254+
async for result in generator:
254255

255256
number = result["number"]
256257
print(f"Number received: {number}")
@@ -264,6 +265,9 @@ async def test_aiohttp_websocket_subscription_break(
264265

265266
assert count == 5
266267

268+
# Using aclose here to make it stop cleanly on pypy
269+
await generator.aclose()
270+
267271

268272
@pytest.mark.asyncio
269273
@pytest.mark.parametrize("server", [server_countdown], indirect=True)

tests/test_client.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,3 +280,7 @@ async def test_async_transport_close_on_schema_retrieval_failure():
280280
pass
281281

282282
assert client.transport.session is None
283+
284+
import asyncio
285+
286+
await asyncio.sleep(1)

tests/test_graphqlws_subscription.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
from gql import Client, gql
1111
from gql.transport.exceptions import TransportConnectionClosed, TransportServerError
1212

13-
from .conftest import MS, WebSocketServerHelper
13+
from .conftest import MS, PyPy, WebSocketServerHelper
1414

1515
# Marking all tests in this file with the websockets marker
1616
pytestmark = pytest.mark.websockets
@@ -260,7 +260,8 @@ async def test_graphqlws_subscription_break(
260260
count = 10
261261
subscription = gql(subscription_str.format(count=count))
262262

263-
async for result in session.subscribe(subscription):
263+
generator = session.subscribe(subscription)
264+
async for result in generator:
264265

265266
number = result["number"]
266267
print(f"Number received: {number}")
@@ -274,6 +275,9 @@ async def test_graphqlws_subscription_break(
274275

275276
assert count == 5
276277

278+
# Using aclose here to make it stop cleanly on pypy
279+
await generator.aclose()
280+
277281

278282
@pytest.mark.asyncio
279283
@pytest.mark.parametrize("graphqlws_server", [server_countdown], indirect=True)
@@ -843,30 +847,42 @@ async def test_graphqlws_subscription_reconnecting_session(
843847
# Then with the same session handle, we make a subscription or an execute
844848
# which will detect that the transport is closed so that the client could
845849
# try to reconnect
850+
generator = None
846851
try:
847852
if execute_instead_of_subscribe:
848853
print("\nEXECUTION_2\n")
849854
await session.execute(subscription)
850855
else:
851856
print("\nSUBSCRIPTION_2\n")
852-
async for result in session.subscribe(subscription):
857+
generator = session.subscribe(subscription)
858+
async for result in generator:
853859
pass
854-
except TransportClosed:
860+
except (TransportClosed, TransportConnectionClosed):
861+
if generator:
862+
await generator.aclose()
855863
pass
856864

857-
await asyncio.sleep(50 * MS)
865+
timeout = 50
866+
867+
if PyPy:
868+
timeout = 500
869+
870+
await asyncio.sleep(timeout * MS)
858871

859872
# And finally with the same session handle, we make a subscription
860873
# which works correctly
861874
print("\nSUBSCRIPTION_3\n")
862-
async for result in session.subscribe(subscription):
875+
generator = session.subscribe(subscription)
876+
async for result in generator:
863877

864878
number = result["number"]
865879
print(f"Number received: {number}")
866880

867881
assert number == count
868882
count -= 1
869883

884+
await generator.aclose()
885+
870886
assert count == -1
871887

872888
await client.close_async()

tests/test_phoenix_channel_query.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,8 +216,12 @@ async def test_phoenix_channel_subscription(event_loop, server, query_str):
216216
first_result = None
217217
query = gql(query_str)
218218
async with Client(transport=transport) as session:
219-
async for result in session.subscribe(query):
219+
generator = session.subscribe(query)
220+
async for result in generator:
220221
first_result = result
221222
break
222223

224+
# Using aclose here to make it stop cleanly on pypy
225+
await generator.aclose()
226+
223227
print("Client received:", first_result)

tests/test_phoenix_channel_subscription.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,9 @@ async def test_phoenix_channel_subscription(
201201
subscription = gql(subscription_str.format(count=count))
202202

203203
async with Client(transport=sample_transport) as session:
204-
async for result in session.subscribe(subscription):
204+
205+
generator = session.subscribe(subscription)
206+
async for result in generator:
205207
number = result["countdown"]["number"]
206208
print(f"Number received: {number}")
207209

@@ -212,6 +214,9 @@ async def test_phoenix_channel_subscription(
212214

213215
count -= 1
214216

217+
# Using aclose here to make it stop cleanly on pypy
218+
await generator.aclose()
219+
215220
assert count == end_count
216221

217222

@@ -378,7 +383,8 @@ async def test_phoenix_channel_heartbeat(event_loop, server, subscription_str):
378383
subscription = gql(heartbeat_subscription_str)
379384
async with Client(transport=sample_transport) as session:
380385
i = 0
381-
async for result in session.subscribe(subscription):
386+
generator = session.subscribe(subscription)
387+
async for result in generator:
382388
heartbeat_count = result["heartbeat"]["heartbeat_count"]
383389
print(f"Heartbeat count received: {heartbeat_count}")
384390

@@ -387,3 +393,6 @@ async def test_phoenix_channel_heartbeat(event_loop, server, subscription_str):
387393
break
388394

389395
i += 1
396+
397+
# Using aclose here to make it stop cleanly on pypy
398+
await generator.aclose()

tests/test_websocket_subscription.py

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from gql import Client, gql
1212
from gql.transport.exceptions import TransportConnectionClosed, TransportServerError
1313

14-
from .conftest import MS, WebSocketServerHelper
14+
from .conftest import MS, PyPy, WebSocketServerHelper
1515

1616
# Marking all tests in this file with the websockets marker
1717
pytestmark = pytest.mark.websockets
@@ -181,7 +181,8 @@ async def test_websocket_subscription_break(
181181
count = 10
182182
subscription = gql(subscription_str.format(count=count))
183183

184-
async for result in session.subscribe(subscription):
184+
generator = session.subscribe(subscription)
185+
async for result in generator:
185186

186187
number = result["number"]
187188
print(f"Number received: {number}")
@@ -195,6 +196,9 @@ async def test_websocket_subscription_break(
195196

196197
assert count == 5
197198

199+
# Using aclose here to make it stop cleanly on pypy
200+
await generator.aclose()
201+
198202

199203
@pytest.mark.asyncio
200204
@pytest.mark.parametrize("server", [server_countdown], indirect=True)
@@ -413,7 +417,14 @@ async def test_websocket_subscription_with_keepalive_with_timeout_ok(
413417

414418
path = "/graphql"
415419
url = f"ws://{server.hostname}:{server.port}{path}"
416-
sample_transport = WebsocketsTransport(url=url, keep_alive_timeout=(20 * MS))
420+
421+
keep_alive_timeout = 20 * MS
422+
if PyPy:
423+
keep_alive_timeout = 200 * MS
424+
425+
sample_transport = WebsocketsTransport(
426+
url=url, keep_alive_timeout=keep_alive_timeout
427+
)
417428

418429
client = Client(transport=sample_transport)
419430

0 commit comments

Comments
 (0)