From 43b157b5a628e8a36a98f928fe8f4cb5adcbd3d1 Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 Date: Fri, 9 Jan 2026 19:50:10 +0530 Subject: [PATCH 1/3] Fix inspect.getcoroutinestate for generator-based coroutines --- Lib/test/test_inspect/test_inspect.py | 12 +++++++++ Objects/genobject.c | 35 +++++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index 075e1802bebc3e..ea5e2e1d4afcdc 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -2878,6 +2878,17 @@ def _coroutinestate(self): def test_created(self): self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED) + + def test_generator_based_coroutine_introspection(self): + from inspect import getcoroutinestate + from types import coroutine + + @coroutine + def gen_coro(): + yield + + # Must not raise AttributeError + getcoroutinestate(gen_coro()) def test_suspended(self): self.coroutine.send(None) @@ -2927,6 +2938,7 @@ async def func(a=None): {'a': None, 'gencoro': gencoro, 'b': 'spam'}) + @support.requires_working_socket() class TestGetAsyncGenState(unittest.IsolatedAsyncioTestCase): diff --git a/Objects/genobject.c b/Objects/genobject.c index 09407d60af62be..d84f0226ad7b2e 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -935,6 +935,36 @@ gen_getcode(PyObject *self, void *Py_UNUSED(ignored)) return _gen_getcode(gen, "gi_code"); } +static PyObject * +gen_get_cr_frame(PyObject *self, void *closure) +{ + return gen_getframe((PyGenObject *)self, closure); +} + +static PyObject * +gen_get_cr_code(PyObject *self, void *closure) +{ + return gen_getcode((PyGenObject *)self, closure); +} + +static PyObject * +gen_get_cr_running(PyObject *self, void *closure) +{ + return gen_getrunning((PyGenObject *)self, closure); +} + +static PyObject * +gen_get_cr_suspended(PyObject *self, void *closure) +{ + return gen_getsuspended((PyGenObject *)self, closure); +} + +static PyObject * +gen_get_cr_origin(PyObject *self, void *closure) +{ + Py_RETURN_NONE; +} + static PyGetSetDef gen_getsetlist[] = { {"__name__", gen_get_name, gen_set_name, PyDoc_STR("name of the generator")}, @@ -946,6 +976,11 @@ static PyGetSetDef gen_getsetlist[] = { {"gi_frame", gen_getframe, NULL, NULL}, {"gi_suspended", gen_getsuspended, NULL, NULL}, {"gi_code", gen_getcode, NULL, NULL}, + {"cr_running", gen_get_cr_running, NULL, NULL}, + {"cr_frame", gen_get_cr_frame, NULL, NULL}, + {"cr_code", gen_get_cr_code, NULL, NULL}, + {"cr_suspended", gen_get_cr_suspended, NULL, NULL}, + {"cr_origin", gen_get_cr_origin, NULL, NULL}, {NULL} /* Sentinel */ }; From cc6a3b27b7695b822cc00742c7deaee69c4d861a Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 Date: Fri, 9 Jan 2026 19:59:28 +0530 Subject: [PATCH 2/3] Fix trailing whitespace in test_inspect --- Lib/test/test_inspect/test_inspect.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Lib/test/test_inspect/test_inspect.py b/Lib/test/test_inspect/test_inspect.py index ea5e2e1d4afcdc..775b985a3cd1f9 100644 --- a/Lib/test/test_inspect/test_inspect.py +++ b/Lib/test/test_inspect/test_inspect.py @@ -2878,7 +2878,7 @@ def _coroutinestate(self): def test_created(self): self.assertEqual(self._coroutinestate(), inspect.CORO_CREATED) - + def test_generator_based_coroutine_introspection(self): from inspect import getcoroutinestate from types import coroutine From 303ef4cee907038aa7d8f697110f43e136d18767 Mon Sep 17 00:00:00 2001 From: VanshAgarwal24036 Date: Fri, 9 Jan 2026 20:00:14 +0530 Subject: [PATCH 3/3] Fix pointer casts in generator coroutine getters --- Objects/genobject.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Objects/genobject.c b/Objects/genobject.c index d84f0226ad7b2e..3b8d433c7c58d7 100644 --- a/Objects/genobject.c +++ b/Objects/genobject.c @@ -938,25 +938,25 @@ gen_getcode(PyObject *self, void *Py_UNUSED(ignored)) static PyObject * gen_get_cr_frame(PyObject *self, void *closure) { - return gen_getframe((PyGenObject *)self, closure); + return gen_getframe((PyObject *)self, closure); } static PyObject * gen_get_cr_code(PyObject *self, void *closure) { - return gen_getcode((PyGenObject *)self, closure); + return gen_getcode((PyObject *)self, closure); } static PyObject * gen_get_cr_running(PyObject *self, void *closure) { - return gen_getrunning((PyGenObject *)self, closure); + return gen_getrunning((PyObject *)self, closure); } static PyObject * gen_get_cr_suspended(PyObject *self, void *closure) { - return gen_getsuspended((PyGenObject *)self, closure); + return gen_getsuspended((PyObject *)self, closure); } static PyObject *