]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.13] gh-143999: Fix: handle suspended state on types.coroutine wrappers (GH-144000...
authorMiss Islington (bot) <31488909+miss-islington@users.noreply.github.com>
Tue, 20 Jan 2026 10:59:24 +0000 (11:59 +0100)
committerGitHub <noreply@github.com>
Tue, 20 Jan 2026 10:59:24 +0000 (12:59 +0200)
(cherry picked from commit 76b484b9d16d6a3b1749dc89d99773b5b4a5c4a5)

Co-authored-by: Yongtao Huang <yongtaoh2022@gmail.com>
Lib/test/test_inspect/test_inspect.py
Lib/types.py
Misc/NEWS.d/next/Library/2026-01-18-14-35-37.gh-issue-143999.MneN4O.rst [new file with mode: 0644]

index 49996bba2ca9edf98ca3caa2c9961a2bbc5ec83a..beab76b516d48d4d9ba671002462999ab7c8629f 100644 (file)
@@ -2962,6 +2962,30 @@ class TestGetGeneratorState(unittest.TestCase):
         # 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()
index 1484c22ee9dffab216d187a8a20fd61351621855..ff474c1414462cad580c53d226e06ab1238a8122 100644 (file)
@@ -261,10 +261,14 @@ class _GeneratorWrapper:
     @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 (file)
index 0000000..dc87411
--- /dev/null
@@ -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.