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:
"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
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;
}