mirror of https://github.com/python/cpython
GH-117536: GH-117894: fix athrow().throw(...) unawaited warning (GH-117851)
This commit is contained in:
parent
975081b11e
commit
7d369d471c
|
@ -399,9 +399,8 @@ class AsyncGenTest(unittest.TestCase):
|
||||||
|
|
||||||
with self.assertWarns(DeprecationWarning):
|
with self.assertWarns(DeprecationWarning):
|
||||||
x = gen().athrow(GeneratorExit, GeneratorExit(), None)
|
x = gen().athrow(GeneratorExit, GeneratorExit(), None)
|
||||||
with self.assertWarnsRegex(RuntimeWarning,
|
with self.assertRaises(GeneratorExit):
|
||||||
f"coroutine method 'athrow' of '{gen.__qualname__}' "
|
x.send(None)
|
||||||
f"was never awaited"):
|
|
||||||
del x
|
del x
|
||||||
gc_collect()
|
gc_collect()
|
||||||
|
|
||||||
|
@ -1572,11 +1571,6 @@ class AsyncGenAsyncioTest(unittest.TestCase):
|
||||||
self.assertIsInstance(message['exception'], ZeroDivisionError)
|
self.assertIsInstance(message['exception'], ZeroDivisionError)
|
||||||
self.assertIn('unhandled exception during asyncio.run() shutdown',
|
self.assertIn('unhandled exception during asyncio.run() shutdown',
|
||||||
message['message'])
|
message['message'])
|
||||||
with self.assertWarnsRegex(RuntimeWarning,
|
|
||||||
f"coroutine method 'aclose' of '{async_iterate.__qualname__}' "
|
|
||||||
f"was never awaited"):
|
|
||||||
del message, messages
|
|
||||||
gc_collect()
|
|
||||||
|
|
||||||
def test_async_gen_expression_01(self):
|
def test_async_gen_expression_01(self):
|
||||||
async def arange(n):
|
async def arange(n):
|
||||||
|
@ -1630,10 +1624,6 @@ class AsyncGenAsyncioTest(unittest.TestCase):
|
||||||
asyncio.run(main())
|
asyncio.run(main())
|
||||||
|
|
||||||
self.assertEqual([], messages)
|
self.assertEqual([], messages)
|
||||||
with self.assertWarnsRegex(RuntimeWarning,
|
|
||||||
f"coroutine method 'aclose' of '{async_iterate.__qualname__}' "
|
|
||||||
f"was never awaited"):
|
|
||||||
gc_collect()
|
|
||||||
|
|
||||||
def test_async_gen_await_same_anext_coro_twice(self):
|
def test_async_gen_await_same_anext_coro_twice(self):
|
||||||
async def async_iterate():
|
async def async_iterate():
|
||||||
|
@ -1671,6 +1661,62 @@ class AsyncGenAsyncioTest(unittest.TestCase):
|
||||||
|
|
||||||
self.loop.run_until_complete(run())
|
self.loop.run_until_complete(run())
|
||||||
|
|
||||||
|
def test_async_gen_throw_same_aclose_coro_twice(self):
|
||||||
|
async def async_iterate():
|
||||||
|
yield 1
|
||||||
|
yield 2
|
||||||
|
|
||||||
|
it = async_iterate()
|
||||||
|
nxt = it.aclose()
|
||||||
|
with self.assertRaises(StopIteration):
|
||||||
|
nxt.throw(GeneratorExit)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
RuntimeError,
|
||||||
|
r"cannot reuse already awaited aclose\(\)/athrow\(\)"
|
||||||
|
):
|
||||||
|
nxt.throw(GeneratorExit)
|
||||||
|
|
||||||
|
def test_async_gen_throw_custom_same_aclose_coro_twice(self):
|
||||||
|
async def async_iterate():
|
||||||
|
yield 1
|
||||||
|
yield 2
|
||||||
|
|
||||||
|
it = async_iterate()
|
||||||
|
|
||||||
|
class MyException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
nxt = it.aclose()
|
||||||
|
with self.assertRaises(MyException):
|
||||||
|
nxt.throw(MyException)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
RuntimeError,
|
||||||
|
r"cannot reuse already awaited aclose\(\)/athrow\(\)"
|
||||||
|
):
|
||||||
|
nxt.throw(MyException)
|
||||||
|
|
||||||
|
def test_async_gen_throw_custom_same_athrow_coro_twice(self):
|
||||||
|
async def async_iterate():
|
||||||
|
yield 1
|
||||||
|
yield 2
|
||||||
|
|
||||||
|
it = async_iterate()
|
||||||
|
|
||||||
|
class MyException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
nxt = it.athrow(MyException)
|
||||||
|
with self.assertRaises(MyException):
|
||||||
|
nxt.throw(MyException)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
RuntimeError,
|
||||||
|
r"cannot reuse already awaited aclose\(\)/athrow\(\)"
|
||||||
|
):
|
||||||
|
nxt.throw(MyException)
|
||||||
|
|
||||||
def test_async_gen_aclose_twice_with_different_coros(self):
|
def test_async_gen_aclose_twice_with_different_coros(self):
|
||||||
# Regression test for https://bugs.python.org/issue39606
|
# Regression test for https://bugs.python.org/issue39606
|
||||||
async def async_iterate():
|
async def async_iterate():
|
||||||
|
@ -1752,6 +1798,19 @@ class TestUnawaitedWarnings(unittest.TestCase):
|
||||||
g.aclose()
|
g.aclose()
|
||||||
gc_collect()
|
gc_collect()
|
||||||
|
|
||||||
|
def test_aclose_throw(self):
|
||||||
|
async def gen():
|
||||||
|
return
|
||||||
|
yield
|
||||||
|
|
||||||
|
class MyException(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
g = gen()
|
||||||
|
with self.assertRaises(MyException):
|
||||||
|
g.aclose().throw(MyException)
|
||||||
|
del g
|
||||||
|
gc_collect()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
Fix a :exc:`RuntimeWarning` when calling ``agen.aclose().throw(Exception)``.
|
|
@ -0,0 +1 @@
|
||||||
|
Prevent ``agen.aclose()`` objects being re-used after ``.throw()``.
|
|
@ -2208,7 +2208,11 @@ async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *const *args, Py_ssize_t na
|
||||||
|
|
||||||
retval = gen_throw((PyGenObject*)o->agt_gen, args, nargs);
|
retval = gen_throw((PyGenObject*)o->agt_gen, args, nargs);
|
||||||
if (o->agt_args) {
|
if (o->agt_args) {
|
||||||
return async_gen_unwrap_value(o->agt_gen, retval);
|
retval = async_gen_unwrap_value(o->agt_gen, retval);
|
||||||
|
if (retval == NULL) {
|
||||||
|
o->agt_state = AWAITABLE_STATE_CLOSED;
|
||||||
|
}
|
||||||
|
return retval;
|
||||||
} else {
|
} else {
|
||||||
/* aclose() mode */
|
/* aclose() mode */
|
||||||
if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) {
|
if (retval && _PyAsyncGenWrappedValue_CheckExact(retval)) {
|
||||||
|
@ -2218,6 +2222,9 @@ async_gen_athrow_throw(PyAsyncGenAThrow *o, PyObject *const *args, Py_ssize_t na
|
||||||
PyErr_SetString(PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
|
PyErr_SetString(PyExc_RuntimeError, ASYNC_GEN_IGNORED_EXIT_MSG);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
if (retval == NULL) {
|
||||||
|
o->agt_state = AWAITABLE_STATE_CLOSED;
|
||||||
|
}
|
||||||
if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) ||
|
if (PyErr_ExceptionMatches(PyExc_StopAsyncIteration) ||
|
||||||
PyErr_ExceptionMatches(PyExc_GeneratorExit))
|
PyErr_ExceptionMatches(PyExc_GeneratorExit))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue