Skip to content

Commit 76b484b

Browse files
gh-143999: Fix: handle suspended state on types.coroutine wrappers (GH-144000)
1 parent fa44efa commit 76b484b

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
@@ -2804,6 +2804,30 @@ def running_check_generator():
28042804
# Running after the first yield
28052805
next(self.generator)
28062806

2807+
def test_types_coroutine_wrapper_state(self):
2808+
def gen():
2809+
yield 1
2810+
yield 2
2811+
2812+
@types.coroutine
2813+
def wrapped_generator_coro():
2814+
# return a generator iterator so types.coroutine
2815+
# wraps it into types._GeneratorWrapper.
2816+
return gen()
2817+
2818+
g = wrapped_generator_coro()
2819+
self.addCleanup(g.close)
2820+
self.assertIs(type(g), types._GeneratorWrapper)
2821+
2822+
# _GeneratorWrapper must provide gi_suspended/cr_suspended
2823+
# so inspect.get*state() doesn't raise AttributeError.
2824+
self.assertEqual(inspect.getgeneratorstate(g), inspect.GEN_CREATED)
2825+
self.assertEqual(inspect.getcoroutinestate(g), inspect.CORO_CREATED)
2826+
2827+
next(g)
2828+
self.assertEqual(inspect.getgeneratorstate(g), inspect.GEN_SUSPENDED)
2829+
self.assertEqual(inspect.getcoroutinestate(g), inspect.CORO_SUSPENDED)
2830+
28072831
def test_easy_debugging(self):
28082832
# repr() and str() of a generator state should contain the state name
28092833
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
@@ -276,10 +276,14 @@ def gi_running(self):
276276
@property
277277
def gi_yieldfrom(self):
278278
return self.__wrapped.gi_yieldfrom
279+
@property
280+
def gi_suspended(self):
281+
return self.__wrapped.gi_suspended
279282
cr_code = gi_code
280283
cr_frame = gi_frame
281284
cr_running = gi_running
282285
cr_await = gi_yieldfrom
286+
cr_suspended = gi_suspended
283287
def __next__(self):
284288
return next(self.__wrapped)
285289
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)