[Python-checkins] bpo-33786: Fix asynchronous generators to handle GeneratorExit in athrow() (GH-7467) (GH-7507)

Yury Selivanov webhook-mailer at python.org
Thu Jun 7 21:32:50 EDT 2018


https://github.com/python/cpython/commit/8de73d5a6914cfe55c23b0ad829cd2ba8954bc2e
commit: 8de73d5a6914cfe55c23b0ad829cd2ba8954bc2e
branch: 3.6
author: Yury Selivanov <yury at magic.io>
committer: GitHub <noreply at github.com>
date: 2018年06月07日T21:32:43-04:00
summary:
bpo-33786: Fix asynchronous generators to handle GeneratorExit in athrow() (GH-7467) (GH-7507)
files:
A Misc/NEWS.d/next/Core and Builtins/2018-06-06-23-24-40.bpo-33786.lBvT8z.rst
M Lib/test/test_asyncgen.py
M Objects/genobject.c
diff --git a/Lib/test/test_asyncgen.py b/Lib/test/test_asyncgen.py
index 34ab8a04eee2..45cc2754a98a 100644
--- a/Lib/test/test_asyncgen.py
+++ b/Lib/test/test_asyncgen.py
@@ -111,6 +111,31 @@ def sync_iterate(g):
 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:
@@ -300,6 +325,37 @@ def test_async_gen_exception_10(self):
 "non-None value .* async generator"):
 gen().__anext__().send(100)
 
+ def test_async_gen_exception_11(self):
+ 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
+
+ self.compare_generators(sync_gen_wrapper(), async_gen_wrapper())
+
 def test_async_gen_api_01(self):
 async def gen():
 yield 123
diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-06-06-23-24-40.bpo-33786.lBvT8z.rst b/Misc/NEWS.d/next/Core and Builtins/2018-06-06-23-24-40.bpo-33786.lBvT8z.rst
new file mode 100644
index 000000000000..57deefe339b5
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2018-06-06-23-24-40.bpo-33786.lBvT8z.rst	
@@ -0,0 +1 @@
+Fix asynchronous generators to handle GeneratorExit in athrow() correctly
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 1c29e296afe2..f226dbebaf4a 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -1939,21 +1939,20 @@ async_gen_athrow_send(PyAsyncGenAThrow *o, PyObject *arg)
 return NULL;
 
 check_error:
- if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration)) {
+ if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) ||
+ PyErr_ExceptionMatches(PyExc_GeneratorExit))
+ {
 o->agt_state = AWAITABLE_STATE_CLOSED;
 if (o->agt_args == NULL) {
 /* 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.
+ */
 PyErr_Clear();
 PyErr_SetNone(PyExc_StopIteration);
 }
 }
- else if (PyErr_ExceptionMatches(PyExc_GeneratorExit)) {
- o->agt_state = AWAITABLE_STATE_CLOSED;
- PyErr_Clear(); /* ignore these errors */
- PyErr_SetNone(PyExc_StopIteration);
- }
 return NULL;
 }
 


More information about the Python-checkins mailing list

AltStyle によって変換されたページ (->オリジナル) /