https://github.com/python/cpython/commit/76b484b9d16d6a3b1749dc89d99773b5b4a5c4a5
commit: 76b484b9d16d6a3b1749dc89d99773b5b4a5c4a5
branch: main
author: Yongtao Huang <[email protected]>
committer: serhiy-storchaka <[email protected]>
date: 2026-01-20T10:20:06Z
summary:
gh-143999: Fix: handle suspended state on types.coroutine wrappers (GH-144000)
files:
A Misc/NEWS.d/next/Library/2026-01-18-14-35-37.gh-issue-143999.MneN4O.rst
M Lib/test/test_inspect/test_inspect.py
M Lib/types.py
diff --git a/Lib/test/test_inspect/test_inspect.py
b/Lib/test/test_inspect/test_inspect.py
index b25414bea659b7..1999aa770ecc56 100644
--- a/Lib/test/test_inspect/test_inspect.py
+++ b/Lib/test/test_inspect/test_inspect.py
@@ -2804,6 +2804,30 @@ def running_check_generator():
# Running after the first yield
next(self.generator)
+ def test_types_coroutine_wrapper_state(self):
+ def gen():
+ yield 1
+ yield 2
+
+ @types.coroutine
+ def wrapped_generator_coro():
+ # return a generator iterator so types.coroutine
+ # wraps it into types._GeneratorWrapper.
+ return gen()
+
+ g = wrapped_generator_coro()
+ self.addCleanup(g.close)
+ self.assertIs(type(g), types._GeneratorWrapper)
+
+ # _GeneratorWrapper must provide gi_suspended/cr_suspended
+ # so inspect.get*state() doesn't raise AttributeError.
+ self.assertEqual(inspect.getgeneratorstate(g), inspect.GEN_CREATED)
+ self.assertEqual(inspect.getcoroutinestate(g), inspect.CORO_CREATED)
+
+ next(g)
+ self.assertEqual(inspect.getgeneratorstate(g), inspect.GEN_SUSPENDED)
+ self.assertEqual(inspect.getcoroutinestate(g), inspect.CORO_SUSPENDED)
+
def test_easy_debugging(self):
# repr() and str() of a generator state should contain the state name
names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()
diff --git a/Lib/types.py b/Lib/types.py
index f96c75b46daba7..73a69c40c8d4b8 100644
--- a/Lib/types.py
+++ b/Lib/types.py
@@ -276,10 +276,14 @@ def gi_running(self):
@property
def gi_yieldfrom(self):
return self.__wrapped.gi_yieldfrom
+ @property
+ def gi_suspended(self):
+ return self.__wrapped.gi_suspended
cr_code = gi_code
cr_frame = gi_frame
cr_running = gi_running
cr_await = gi_yieldfrom
+ cr_suspended = gi_suspended
def __next__(self):
return next(self.__wrapped)
def __iter__(self):
diff --git
a/Misc/NEWS.d/next/Library/2026-01-18-14-35-37.gh-issue-143999.MneN4O.rst
b/Misc/NEWS.d/next/Library/2026-01-18-14-35-37.gh-issue-143999.MneN4O.rst
new file mode 100644
index 00000000000000..dc87411aacc821
--- /dev/null
+++ b/Misc/NEWS.d/next/Library/2026-01-18-14-35-37.gh-issue-143999.MneN4O.rst
@@ -0,0 +1 @@
+Fix an issue where :func:`inspect.getgeneratorstate` and
:func:`inspect.getcoroutinestate` could fail for generators wrapped by
:func:`types.coroutine` in the suspended state.
_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]