Skip to content

Commit 66174a6

Browse files
authored
Async generators always ensure that inner generator are closed properly (#230)
Should close a generator directly after a break if you don't keep any references of the generator
1 parent 4e08f09 commit 66174a6

File tree

2 files changed

+24
-18
lines changed

2 files changed

+24
-18
lines changed

gql/client.py

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -356,13 +356,11 @@ async def _subscribe(
356356
# before a break if python version is too old (pypy3 py 3.6.1)
357357
self._generator = inner_generator
358358

359-
async for result in inner_generator:
360-
if result.errors:
361-
# Note: we need to run generator.aclose() here or the finally block in
362-
# transport.subscribe will not be reached in pypy3 (py 3.6.1)
363-
await inner_generator.aclose()
364-
365-
yield result
359+
try:
360+
async for result in inner_generator:
361+
yield result
362+
finally:
363+
await inner_generator.aclose()
366364

367365
async def subscribe(
368366
self, document: DocumentNode, *args, **kwargs
@@ -372,17 +370,24 @@ async def subscribe(
372370
373371
The extra arguments are passed to the transport subscribe method."""
374372

375-
# Validate and subscribe on the transport
376-
async for result in self._subscribe(document, *args, **kwargs):
377-
378-
# Raise an error if an error is returned in the ExecutionResult object
379-
if result.errors:
380-
raise TransportQueryError(
381-
str(result.errors[0]), errors=result.errors, data=result.data
382-
)
373+
inner_generator: AsyncGenerator[ExecutionResult, None] = self._subscribe(
374+
document, *args, **kwargs
375+
)
383376

384-
elif result.data is not None:
385-
yield result.data
377+
try:
378+
# Validate and subscribe on the transport
379+
async for result in inner_generator:
380+
381+
# Raise an error if an error is returned in the ExecutionResult object
382+
if result.errors:
383+
raise TransportQueryError(
384+
str(result.errors[0]), errors=result.errors, data=result.data
385+
)
386+
387+
elif result.data is not None:
388+
yield result.data
389+
finally:
390+
await inner_generator.aclose()
386391

387392
async def _execute(
388393
self, document: DocumentNode, *args, **kwargs

tests/test_websocket_subscription.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ async def test_websocket_subscription_break(
163163

164164
if count <= 5:
165165
# Note: the following line is only necessary for pypy3 v3.6.1
166-
await session._generator.aclose()
166+
if sys.version_info < (3, 7):
167+
await session._generator.aclose()
167168
break
168169

169170
count -= 1

0 commit comments

Comments
 (0)