Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions Lib/test/test_inspect/test_inspect.py
Original file line number Diff line number Diff line change
Expand Up @@ -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 legacy_coro():
# return a generator iterator so types.coroutine
# wraps it into types._GeneratorWrapper.
return gen()

g = legacy_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()
Expand Down
4 changes: 4 additions & 0 deletions Lib/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand Down
Original file line number Diff line number Diff line change
@@ -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.
Loading