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:
parent
c749326d24
commit
6c3b471c8c
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
Ignore GeneratorExit exceptions when throwing an exception into the aclose
|
||||||
|
coroutine of an asynchronous generator.
|
|
@ -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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue