@@ -136,6 +136,18 @@ def gen():
136136 self .assertEqual (len (resurrected ), 1 )
137137 self .assertIsInstance (resurrected [0 ].gi_code , types .CodeType )
138138
139+ def test_exhausted_generator_frame_cycle (self ):
140+ def g ():
141+ yield
142+
143+ generator = g ()
144+ frame = generator .gi_frame
145+ self .assertIsNone (frame .f_back )
146+ next (generator )
147+ self .assertIsNone (frame .f_back )
148+ next (generator , None )
149+ self .assertIsNone (frame .f_back )
150+
139151
140152class GeneratorTest (unittest .TestCase ):
141153
@@ -292,6 +304,33 @@ def __iter__(self):
292304
293305 self .assertEqual ([1 , 2 ], list (i for i in C ()))
294306
307+ def test_close_clears_frame (self ):
308+ # gh-142766: Test that closing a generator clears its frame
309+ class DetectDelete :
310+ def __init__ (self ):
311+ DetectDelete .deleted = False
312+
313+ def __del__ (self ):
314+ DetectDelete .deleted = True
315+
316+ def generator (arg ):
317+ yield
318+
319+ # Test a freshly created generator (not suspended)
320+ g = generator (DetectDelete ())
321+ g .close ()
322+ self .assertTrue (DetectDelete .deleted )
323+
324+ # Test a suspended generator
325+ g = generator (DetectDelete ())
326+ next (g )
327+ g .close ()
328+ self .assertTrue (DetectDelete .deleted )
329+
330+ # Clear via gi_frame.clear()
331+ g = generator (DetectDelete ())
332+ g .gi_frame .clear ()
333+ self .assertTrue (DetectDelete .deleted )
295334
296335class ModifyUnderlyingIterableTest (unittest .TestCase ):
297336 iterables = [
0 commit comments