summaryrefslogtreecommitdiffstats
path: root/Objects/genobject.c
diff options
context:
space:
mode:
Diffstat (limited to 'Objects/genobject.c')
-rw-r--r--Objects/genobject.c57
1 files changed, 36 insertions, 21 deletions
diff --git a/Objects/genobject.c b/Objects/genobject.c
index d093f3d..46b0190 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -87,7 +87,7 @@ _PyGen_Finalize(PyObject *self)
issue a RuntimeWarning. */
if (gen->gi_code != NULL &&
((PyCodeObject *)gen->gi_code)->co_flags & CO_COROUTINE &&
- ((InterpreterFrame *)gen->gi_iframe)->f_lasti == -1)
+ ((InterpreterFrame *)gen->gi_iframe)->f_state == FRAME_CREATED)
{
_PyErr_WarnUnawaitedCoroutine((PyObject *)gen);
}
@@ -133,7 +133,7 @@ gen_dealloc(PyGenObject *gen)
if (gen->gi_frame_valid) {
InterpreterFrame *frame = (InterpreterFrame *)gen->gi_iframe;
gen->gi_frame_valid = 0;
- frame->generator = NULL;
+ frame->is_generator = false;
frame->previous = NULL;
_PyFrame_Clear(frame);
}
@@ -156,7 +156,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
PyObject *result;
*presult = NULL;
- if (frame->f_lasti < 0 && arg && arg != Py_None) {
+ if (frame->f_state == FRAME_CREATED && arg && arg != Py_None) {
const char *msg = "can't send non-None value to a "
"just-started generator";
if (PyCoro_CheckExact(gen)) {
@@ -265,7 +265,7 @@ gen_send_ex2(PyGenObject *gen, PyObject *arg, PyObject **presult,
/* first clean reference cycle through stored exception traceback */
_PyErr_ClearExcState(&gen->gi_exc_state);
- frame->generator = NULL;
+ frame->is_generator = false;
gen->gi_frame_valid = 0;
_PyFrame_Clear(frame);
*presult = result;
@@ -754,6 +754,15 @@ gen_getrunning(PyGenObject *gen, void *Py_UNUSED(ignored))
}
static PyObject *
+gen_getsuspended(PyGenObject *gen, void *Py_UNUSED(ignored))
+{
+ if (gen->gi_frame_valid == 0) {
+ Py_RETURN_FALSE;
+ }
+ return PyBool_FromLong(((InterpreterFrame *)gen->gi_iframe)->f_state == FRAME_SUSPENDED);
+}
+
+static PyObject *
_gen_getframe(PyGenObject *gen, const char *const name)
{
if (PySys_Audit("object.__getattr__", "Os", gen, name) < 0) {
@@ -780,6 +789,7 @@ static PyGetSetDef gen_getsetlist[] = {
PyDoc_STR("object being iterated by yield from, or None")},
{"gi_running", (getter)gen_getrunning, NULL, NULL},
{"gi_frame", (getter)gen_getframe, NULL, NULL},
+ {"gi_suspended", (getter)gen_getsuspended, NULL, NULL},
{NULL} /* Sentinel */
};
@@ -886,22 +896,16 @@ make_gen(PyTypeObject *type, PyFunctionObject *func)
gen->gi_weakreflist = NULL;
gen->gi_exc_state.exc_value = NULL;
gen->gi_exc_state.previous_item = NULL;
- if (func->func_name != NULL)
- gen->gi_name = func->func_name;
- else
- gen->gi_name = gen->gi_code->co_name;
- Py_INCREF(gen->gi_name);
- if (func->func_qualname != NULL)
- gen->gi_qualname = func->func_qualname;
- else
- gen->gi_qualname = gen->gi_name;
- Py_INCREF(gen->gi_qualname);
+ assert(func->func_name != NULL);
+ gen->gi_name = Py_NewRef(func->func_name);
+ assert(func->func_qualname != NULL);
+ gen->gi_qualname = Py_NewRef(func->func_qualname);
_PyObject_GC_TRACK(gen);
return (PyObject *)gen;
}
static PyObject *
-compute_cr_origin(int origin_depth);
+compute_cr_origin(int origin_depth, InterpreterFrame *current_frame);
PyObject *
_Py_MakeCoro(PyFunctionObject *func)
@@ -935,7 +939,8 @@ _Py_MakeCoro(PyFunctionObject *func)
if (origin_depth == 0) {
((PyCoroObject *)coro)->cr_origin_or_finalizer = NULL;
} else {
- PyObject *cr_origin = compute_cr_origin(origin_depth);
+ assert(_PyEval_GetFrame());
+ PyObject *cr_origin = compute_cr_origin(origin_depth, _PyEval_GetFrame()->previous);
((PyCoroObject *)coro)->cr_origin_or_finalizer = cr_origin;
if (!cr_origin) {
Py_DECREF(coro);
@@ -965,7 +970,7 @@ gen_new_with_qualname(PyTypeObject *type, PyFrameObject *f,
assert(frame->frame_obj == f);
f->f_owns_frame = 0;
f->f_frame = frame;
- frame->generator = (PyObject *) gen;
+ frame->is_generator = true;
assert(PyObject_GC_IsTracked((PyObject *)f));
gen->gi_code = PyFrame_GetCode(f);
Py_INCREF(gen->gi_code);
@@ -1098,6 +1103,15 @@ coro_get_cr_await(PyCoroObject *coro, void *Py_UNUSED(ignored))
}
static PyObject *
+cr_getsuspended(PyCoroObject *coro, void *Py_UNUSED(ignored))
+{
+ if (coro->cr_frame_valid == 0) {
+ Py_RETURN_FALSE;
+ }
+ return PyBool_FromLong(((InterpreterFrame *)coro->cr_iframe)->f_state == FRAME_SUSPENDED);
+}
+
+static PyObject *
cr_getrunning(PyCoroObject *coro, void *Py_UNUSED(ignored))
{
if (coro->cr_frame_valid == 0) {
@@ -1122,6 +1136,7 @@ static PyGetSetDef coro_getsetlist[] = {
PyDoc_STR("object being awaited on, or None")},
{"cr_running", (getter)cr_getrunning, NULL, NULL},
{"cr_frame", (getter)cr_getframe, NULL, NULL},
+ {"cr_suspended", (getter)cr_getsuspended, NULL, NULL},
{NULL} /* Sentinel */
};
@@ -1299,9 +1314,9 @@ PyTypeObject _PyCoroWrapper_Type = {
};
static PyObject *
-compute_cr_origin(int origin_depth)
+compute_cr_origin(int origin_depth, InterpreterFrame *current_frame)
{
- InterpreterFrame *frame = _PyEval_GetFrame();
+ InterpreterFrame *frame = current_frame;
/* First count how many frames we have */
int frame_count = 0;
for (; frame && frame_count < origin_depth; ++frame_count) {
@@ -1313,7 +1328,7 @@ compute_cr_origin(int origin_depth)
if (cr_origin == NULL) {
return NULL;
}
- frame = _PyEval_GetFrame();
+ frame = current_frame;
for (int i = 0; i < frame_count; ++i) {
PyCodeObject *code = frame->f_code;
PyObject *frameinfo = Py_BuildValue("OiO",
@@ -1345,7 +1360,7 @@ PyCoro_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
if (origin_depth == 0) {
((PyCoroObject *)coro)->cr_origin_or_finalizer = NULL;
} else {
- PyObject *cr_origin = compute_cr_origin(origin_depth);
+ PyObject *cr_origin = compute_cr_origin(origin_depth, _PyEval_GetFrame());
((PyCoroObject *)coro)->cr_origin_or_finalizer = cr_origin;
if (!cr_origin) {
Py_DECREF(coro);