Skip to content

Commit 11bf6ef

Browse files
[3.13] gh-143999: Fix: handle suspended state on types.coroutine wrappers (GH-144000) (GH-144065)
(cherry picked from commit 76b484b) Co-authored-by: Yongtao Huang <yongtaoh2022@gmail.com>
1 parent 746d2f9 commit 11bf6ef

File tree

3 files changed

+29
-0
lines changed

3 files changed

+29
-0
lines changed

Lib/test/test_inspect/test_inspect.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2962,6 +2962,30 @@ def running_check_generator():
29622962
# Running after the first yield
29632963
next(self.generator)
29642964

2965+
def test_types_coroutine_wrapper_state(self):
2966+
def gen():
2967+
yield 1
2968+
yield 2
2969+
2970+
@types.coroutine
2971+
def wrapped_generator_coro():
2972+
# return a generator iterator so types.coroutine
2973+
# wraps it into types._GeneratorWrapper.
2974+
return gen()
2975+
2976+
g = wrapped_generator_coro()
2977+
self.addCleanup(g.close)
2978+
self.assertIs(type(g), types._GeneratorWrapper)
2979+
2980+
# _GeneratorWrapper must provide gi_suspended/cr_suspended
2981+
# so inspect.get*state() doesn't raise AttributeError.
2982+
self.assertEqual(inspect.getgeneratorstate(g), inspect.GEN_CREATED)
2983+
self.assertEqual(inspect.getcoroutinestate(g), inspect.CORO_CREATED)
2984+
2985+
next(g)
2986+
self.assertEqual(inspect.getgeneratorstate(g), inspect.GEN_SUSPENDED)
2987+
self.assertEqual(inspect.getcoroutinestate(g), inspect.CORO_SUSPENDED)
2988+
29652989
def test_easy_debugging(self):
29662990
# repr() and str() of a generator state should contain the state name
29672991
names = 'GEN_CREATED GEN_RUNNING GEN_SUSPENDED GEN_CLOSED'.split()

Lib/types.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,10 +261,14 @@ def gi_running(self):
261261
@property
262262
def gi_yieldfrom(self):
263263
return self.__wrapped.gi_yieldfrom
264+
@property
265+
def gi_suspended(self):
266+
return self.__wrapped.gi_suspended
264267
cr_code = gi_code
265268
cr_frame = gi_frame
266269
cr_running = gi_running
267270
cr_await = gi_yieldfrom
271+
cr_suspended = gi_suspended
268272
def __next__(self):
269273
return next(self.__wrapped)
270274
def __iter__(self):
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
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.

0 commit comments

Comments
 (0)