mirror of https://github.com/python/cpython
gh-111058: Change coro.cr_frame/gen.gi_frame to be None for a closed coroutine/generator. (#112428)
This commit is contained in:
parent
a65a3d4806
commit
bfb576ee23
|
@ -2216,6 +2216,14 @@ class CoroutineTest(unittest.TestCase):
|
||||||
gen.cr_frame.clear()
|
gen.cr_frame.clear()
|
||||||
gen.close()
|
gen.close()
|
||||||
|
|
||||||
|
def test_cr_frame_after_close(self):
|
||||||
|
async def f():
|
||||||
|
pass
|
||||||
|
gen = f()
|
||||||
|
self.assertIsNotNone(gen.cr_frame)
|
||||||
|
gen.close()
|
||||||
|
self.assertIsNone(gen.cr_frame)
|
||||||
|
|
||||||
def test_stack_in_coroutine_throw(self):
|
def test_stack_in_coroutine_throw(self):
|
||||||
# Regression test for https://github.com/python/cpython/issues/93592
|
# Regression test for https://github.com/python/cpython/issues/93592
|
||||||
async def a():
|
async def a():
|
||||||
|
|
|
@ -2384,6 +2384,10 @@ class TestGetGeneratorState(unittest.TestCase):
|
||||||
self.generator.throw(RuntimeError)
|
self.generator.throw(RuntimeError)
|
||||||
self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
|
self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
|
||||||
|
|
||||||
|
def test_closed_after_close(self):
|
||||||
|
self.generator.close()
|
||||||
|
self.assertEqual(self._generatorstate(), inspect.GEN_CLOSED)
|
||||||
|
|
||||||
def test_running(self):
|
def test_running(self):
|
||||||
# As mentioned on issue #10220, checking for the RUNNING state only
|
# As mentioned on issue #10220, checking for the RUNNING state only
|
||||||
# makes sense inside the generator itself.
|
# makes sense inside the generator itself.
|
||||||
|
@ -2493,6 +2497,10 @@ class TestGetCoroutineState(unittest.TestCase):
|
||||||
self.coroutine.throw(RuntimeError)
|
self.coroutine.throw(RuntimeError)
|
||||||
self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
|
self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
|
||||||
|
|
||||||
|
def test_closed_after_close(self):
|
||||||
|
self.coroutine.close()
|
||||||
|
self.assertEqual(self._coroutinestate(), inspect.CORO_CLOSED)
|
||||||
|
|
||||||
def test_easy_debugging(self):
|
def test_easy_debugging(self):
|
||||||
# repr() and str() of a coroutine state should contain the state name
|
# repr() and str() of a coroutine state should contain the state name
|
||||||
names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
|
names = 'CORO_CREATED CORO_RUNNING CORO_SUSPENDED CORO_CLOSED'.split()
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
Change coro.cr_frame/gen.gi_frame to return ``None`` after the coroutine/generator has been closed.
|
||||||
|
This fixes a bug where :func:`~inspect.getcoroutinestate` and :func:`~inspect.getgeneratorstate`
|
||||||
|
return the wrong state for a closed coroutine/generator.
|
|
@ -732,7 +732,7 @@ _gen_getframe(PyGenObject *gen, const char *const name)
|
||||||
if (PySys_Audit("object.__getattr__", "Os", gen, name) < 0) {
|
if (PySys_Audit("object.__getattr__", "Os", gen, name) < 0) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
if (gen->gi_frame_state == FRAME_CLEARED) {
|
if (FRAME_STATE_FINISHED(gen->gi_frame_state)) {
|
||||||
Py_RETURN_NONE;
|
Py_RETURN_NONE;
|
||||||
}
|
}
|
||||||
return _Py_XNewRef((PyObject *)_PyFrame_GetFrameObject((_PyInterpreterFrame *)gen->gi_iframe));
|
return _Py_XNewRef((PyObject *)_PyFrame_GetFrameObject((_PyInterpreterFrame *)gen->gi_iframe));
|
||||||
|
|
Loading…
Reference in New Issue