bpo-35409: Ignore GeneratorExit in async_gen_athrow_throw (GH-14755)

Ignore `GeneratorExit` exceptions when throwing an exception into the `aclose` coroutine of an asynchronous generator.

https://bugs.python.org/issue35409
(cherry picked from commit 8e0de2a480)

Co-authored-by: Vincent Michel <vxgmichel@gmail.com>
This commit is contained in:
Miss Islington (bot) 2019-11-19 06:12:06 -08:00 committed by GitHub
parent c749326d24
commit 6c3b471c8c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 40 additions and 0 deletions

View File

@ -735,6 +735,33 @@ class AsyncGenAsyncioTest(unittest.TestCase):
self.loop.run_until_complete(run()) self.loop.run_until_complete(run())
self.assertEqual(DONE, 10) self.assertEqual(DONE, 10)
def test_async_gen_asyncio_aclose_12(self):
DONE = 0
async def target():
await asyncio.sleep(0.01)
1 / 0
async def foo():
nonlocal DONE
task = asyncio.create_task(target())
try:
yield 1
finally:
try:
await task
except ZeroDivisionError:
DONE = 1
async def run():
gen = foo()
it = gen.__aiter__()
await it.__anext__()
await gen.aclose()
self.loop.run_until_complete(run())
self.assertEqual(DONE, 1)
def test_async_gen_asyncio_asend_01(self): def test_async_gen_asyncio_asend_01(self):
DONE = 0 DONE = 0

View File

@ -0,0 +1,2 @@
Ignore GeneratorExit exceptions when throwing an exception into the aclose
coroutine of an asynchronous generator.

View File

@ -1947,6 +1947,17 @@ async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *args)
PyErr_SetString(PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG); PyErr_SetString(PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
return NULL; return NULL;
} }
if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) ||
PyErr_ExceptionMatches(PyExc_GeneratorExit))
{
/* when aclose() is called we don't want to propagate
StopAsyncIteration or GeneratorExit; just raise
StopIteration, signalling that this 'aclose()' await
is done.
*/
PyErr_Clear();
PyErr_SetNone(PyExc_StopIteration);
}
return retval; return retval;
} }
} }