cpython: e16084e07761 (original) (raw)
Mercurial > cpython
changeset 100400:e16084e07761 3.5
coroutines: Error when awaiting on coroutine that's being awaited Issue #25888 [#25888]
Yury Selivanov yselivanov@sprymix.com | |
---|---|
date | Wed, 02 Mar 2016 11:30:46 -0500 |
parents | bbc8cb86f05e |
children | 2218ce5c592f 256339c28d42 |
files | Include/genobject.h Lib/test/test_coroutines.py Objects/genobject.c Python/ceval.c |
diffstat | 4 files changed, 40 insertions(+), 6 deletions(-)[+] [-] Include/genobject.h 1 Lib/test/test_coroutines.py 18 Objects/genobject.c 12 Python/ceval.c 15 |
line wrap: on
line diff
--- a/Include/genobject.h +++ b/Include/genobject.h @@ -43,6 +43,7 @@ PyAPI_FUNC(PyObject *) PyGen_NewWithQual PyAPI_FUNC(int) PyGen_NeedsFinalizing(PyGenObject *); PyAPI_FUNC(int) _PyGen_FetchStopIterationValue(PyObject **); PyObject *_PyGen_Send(PyGenObject *, PyObject *); +PyObject *_PyGen_yf(PyGenObject *); PyAPI_FUNC(void) _PyGen_Finalize(PyObject *self); #ifndef Py_LIMITED_API
--- a/Lib/test/test_coroutines.py +++ b/Lib/test/test_coroutines.py @@ -942,6 +942,24 @@ class CoroutineTest(unittest.TestCase): with self.assertRaises(Marker): c.throw(ZeroDivisionError)
async def coroutine():[](#l2.12)
await nop()[](#l2.13)
async def waiter(coro):[](#l2.15)
await coro[](#l2.16)
coro = coroutine()[](#l2.18)
coro.send(None)[](#l2.19)
with self.assertRaisesRegex(RuntimeError,[](#l2.21)
"coroutine is being awaited already"):[](#l2.22)
waiter(coro).send(None)[](#l2.23)
+ def test_with_1(self): class Manager: def init(self, name):
--- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -267,8 +267,8 @@ gen_close_iter(PyObject *yf) return 0; } -static PyObject * -gen_yf(PyGenObject *gen) +PyObject * +_PyGen_yf(PyGenObject *gen) { PyObject *yf = NULL; PyFrameObject *f = gen->gi_frame; @@ -290,7 +290,7 @@ static PyObject * gen_close(PyGenObject *gen, PyObject *args) { PyObject *retval;
- PyObject *yf = _PyGen_yf(gen); int err = 0; if (yf) { @@ -330,7 +330,7 @@ gen_throw(PyGenObject *gen, PyObject *ar PyObject *typ; PyObject *tb = NULL; PyObject *val = NULL;
- PyObject *yf = _PyGen_yf(gen); _Py_IDENTIFIER(throw); if (!PyArg_UnpackTuple(args, "throw", 1, 3, &typ, &val, &tb)) @@ -564,7 +564,7 @@ gen_set_qualname(PyGenObject *op, PyObje static PyObject * gen_getyieldfrom(PyGenObject *gen) {
- PyObject *yf = _PyGen_yf(gen); if (yf == NULL) Py_RETURN_NONE; return yf; @@ -799,7 +799,7 @@ coro_await(PyCoroObject *coro) static PyObject * coro_get_cr_await(PyCoroObject *coro) {
--- a/Python/ceval.c +++ b/Python/ceval.c @@ -2021,6 +2021,21 @@ PyEval_EvalFrameEx(PyFrameObject *f, int Py_DECREF(iterable);
if (iter != NULL && PyCoro_CheckExact(iter)) {[](#l4.7)
PyObject *yf = _PyGen_yf((PyGenObject*)iter);[](#l4.8)
if (yf != NULL) {[](#l4.9)
/* `iter` is a coroutine object that is being[](#l4.10)
awaited, `yf` is a pointer to the current awaitable[](#l4.11)
being awaited on. */[](#l4.12)
Py_DECREF(yf);[](#l4.13)
Py_CLEAR(iter);[](#l4.14)
PyErr_SetString([](#l4.15)
PyExc_RuntimeError,[](#l4.16)
"coroutine is being awaited already");[](#l4.17)
/* The code below jumps to `error` if `iter` is NULL. */[](#l4.18)
}[](#l4.19)
}[](#l4.20)
+ SET_TOP(iter); /* Even if it's NULL */ if (iter == NULL) {