Author: Matti Picus <[email protected]>
Branch: py3.6
Changeset: r97382:585e24d5f093
Date: 2019-09-05 21:45 +0200
http://bitbucket.org/pypy/pypy/changeset/585e24d5f093/
Log: test, fix for bpo-33786: handle generator exit in athrow()
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -777,13 +777,12 @@
def handle_error(self, e):
space = self.space
self.state = self.ST_CLOSED
- if e.match(space, space.w_StopAsyncIteration):
+ if (e.match(space, space.w_StopAsyncIteration) or
+ e.match(space, space.w_StopIteration)):
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.
+ # StopAsyncIteration or GeneratorExit; just raise
+ # StopIteration, signalling that this 'aclose()' await
+ # 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 e
diff --git a/pypy/interpreter/test/test_generator.py
b/pypy/interpreter/test/test_generator.py
--- a/pypy/interpreter/test/test_generator.py
+++ b/pypy/interpreter/test/test_generator.py
@@ -539,6 +539,104 @@
raises(TypeError, g.send, 2)
+class AppTestAsyncGenerator(object):
+
+ def test_async_gen_exception_11(self):
+ """
+ # bpo-33786
+ def compare_generators(sync_gen, async_gen):
+ def sync_iterate(g):
+ res = []
+ while True:
+ try:
+ res.append(g.__next__())
+ except StopIteration:
+ res.append('STOP')
+ break
+ except Exception as ex:
+ res.append(str(type(ex)))
+ return res
+
+ def async_iterate(g):
+ res = []
+ while True:
+ an = g.__anext__()
+ try:
+ while True:
+ try:
+ an.__next__()
+ except StopIteration as ex:
+ if ex.args:
+ res.append(ex.args[0])
+ break
+ else:
+ res.append('EMPTY StopIteration')
+ break
+ except StopAsyncIteration:
+ raise
+ except Exception as ex:
+ res.append(str(type(ex)))
+ break
+ except StopAsyncIteration:
+ res.append('STOP')
+ break
+ return res
+
+ def async_iterate(g):
+ res = []
+ while True:
+ try:
+ g.__anext__().__next__()
+ except StopAsyncIteration:
+ res.append('STOP')
+ break
+ except StopIteration as ex:
+ if ex.args:
+ res.append(ex.args[0])
+ else:
+ res.append('EMPTY StopIteration')
+ break
+ except Exception as ex:
+ res.append(str(type(ex)))
+ return res
+
+ sync_gen_result = sync_iterate(sync_gen)
+ async_gen_result = async_iterate(async_gen)
+ assert sync_gen_result == async_gen_result, "%s != %s" %
(str(sync_gen_result), str(async_gen_result))
+ return async_gen_result
+
+ def sync_gen():
+ yield 10
+ yield 20
+
+ def sync_gen_wrapper():
+ yield 1
+ sg = sync_gen()
+ sg.send(None)
+ try:
+ sg.throw(GeneratorExit())
+ except GeneratorExit:
+ yield 2
+ yield 3
+
+ async def async_gen():
+ yield 10
+ yield 20
+
+ async def async_gen_wrapper():
+ yield 1
+ asg = async_gen()
+ await asg.asend(None)
+ try:
+ await asg.athrow(GeneratorExit())
+ except GeneratorExit:
+ yield 2
+ yield 3
+
+ compare_generators(sync_gen_wrapper(), async_gen_wrapper())
+ """
+
+
def test_should_not_inline(space):
from pypy.interpreter.generator import should_not_inline
w_co = space.appexec([], '''():
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit