[pypy-commit] pypy bpo-35409: Ignore GeneratorExit when throwing into the aclose coroutine of an asynchronous generator
vxgmichel
pypy.commits at gmail.com
Sun Jul 14 08:14:18 EDT 2019
Author: Vincent Michel <vxgmichel at gmail.com>
Branch: bpo-35409
Changeset: r96993:f29b8a6e72dd
Date: 2019-07-13 18:12 +0200
http://bitbucket.org/pypy/pypy/changeset/f29b8a6e72dd/
Log: Ignore GeneratorExit when throwing into the aclose coroutine of an
asynchronous generator
Related issues and pull requests on cpython:
- https://bugs.python.org/issue35409
- https://github.com/python/cpython/pull/14755
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -770,7 +770,20 @@
raise
def descr_throw(self, w_type, w_val=None, w_tb=None):
+ space = self.space
if self.state == self.ST_INIT:
raise OperationError(self.space.w_RuntimeError,
- self.space.newtext("can't do async_generator.athrow().throw()"))
- return AsyncGenABase.descr_throw(self, w_type, w_val, w_tb)
+ space.newtext("can't do async_generator.athrow().throw()"))
+ try:
+ return AsyncGenABase.descr_throw(self, w_type, w_val, w_tb)
+ except OperationError as e:
+ if e.match(space, space.w_StopAsyncIteration):
+ if self.w_exc_type is None:
+ # When aclose() is called we don't want to propagate
+ # StopAsyncIteration; just raise StopIteration, signalling
+ # that 'aclose()' is done.
+ raise OperationError(space.w_StopIteration, space.w_None)
+ if e.match(space, space.w_GeneratorExit):
+ # Ignore this error.
+ raise OperationError(space.w_StopIteration, space.w_None)
+ raise
diff --git a/pypy/interpreter/test/test_coroutine.py b/pypy/interpreter/test/test_coroutine.py
--- a/pypy/interpreter/test/test_coroutine.py
+++ b/pypy/interpreter/test/test_coroutine.py
@@ -558,6 +558,42 @@
assert state == 2
"""
+ def test_async_aclose_await_in_finally_with_exception(self): """
+ import types
+
+ @types.coroutine
+ def coro():
+ yield 'coro'
+
+ state = 0
+ async def ag():
+ nonlocal state
+ try:
+ yield
+ finally:
+ state = 1
+ try:
+ await coro()
+ except Exception as exc:
+ state = exc
+
+ async def run():
+ a = ag()
+ async for i in a:
+ break
+ await a.aclose()
+ a = run()
+ assert state == 0
+ assert a.send(None) == 'coro'
+ assert state == 1
+ exc = RuntimeError()
+ try:
+ a.throw(exc)
+ except StopIteration:
+ pass
+ assert state == exc
+ """
+
def test_async_aclose_in_finalize_hook_await_in_finally(self): """
import gc
import sys
More information about the pypy-commit
mailing list