gh-142766: Clear frame when `generator.close()` is called (gh-142838) · python/cpython@25397f9

GitHub

File tree

Lib/test

Misc/NEWS.d/next/Core_and_Builtins

Objects

Original file line numberDiff line numberDiff line change@@ -290,6 +290,33 @@ def __iter__(self):

290290291291self.assertEqual([1,2], list(iforiinC()))

292292293+deftest_close_clears_frame(self):

294+# gh-142766: Test that closing a generator clears its frame

295+classDetectDelete:

296+def__init__(self):

297+DetectDelete.deleted=False

298+299+def__del__(self):

300+DetectDelete.deleted=True

301+302+defgenerator(arg):

303+yield

304+305+# Test a freshly created generator (not suspended)

306+g=generator(DetectDelete())

307+g.close()

308+self.assertTrue(DetectDelete.deleted)

309+310+# Test a suspended generator

311+g=generator(DetectDelete())

312+next(g)

313+g.close()

314+self.assertTrue(DetectDelete.deleted)

315+316+# Clear via gi_frame.clear()

317+g=generator(DetectDelete())

318+g.gi_frame.clear()

319+self.assertTrue(DetectDelete.deleted)

293320294321classModifyUnderlyingIterableTest(unittest.TestCase):

295322iterables= [

Original file line numberDiff line numberDiff line change@@ -0,0 +1 @@

1+Clear the frame of a generator when :meth:`generator.close` is called.

Original file line numberDiff line numberDiff line change@@ -390,6 +390,7 @@ gen_close(PyObject *self, PyObject *args)

390390391391if (gen->gi_frame_state==FRAME_CREATED) {

392392gen->gi_frame_state=FRAME_COMPLETED;

393+gen_clear_frame(gen);

393394Py_RETURN_NONE;

394395 }

395396if (FRAME_STATE_FINISHED(gen->gi_frame_state)) {