| import gc | 
 | import sys | 
 | import unittest | 
 | import weakref | 
 |  | 
 | from test import support | 
 |  | 
 |  | 
 | class ClearTest(unittest.TestCase): | 
 |     """ | 
 |     Tests for frame.clear(). | 
 |     """ | 
 |  | 
 |     def inner(self, x=5, **kwargs): | 
 |         1/0 | 
 |  | 
 |     def outer(self, **kwargs): | 
 |         try: | 
 |             self.inner(**kwargs) | 
 |         except ZeroDivisionError as e: | 
 |             exc = e | 
 |         return exc | 
 |  | 
 |     def clear_traceback_frames(self, tb): | 
 |         """ | 
 |         Clear all frames in a traceback. | 
 |         """ | 
 |         while tb is not None: | 
 |             tb.tb_frame.clear() | 
 |             tb = tb.tb_next | 
 |  | 
 |     def test_clear_locals(self): | 
 |         class C: | 
 |             pass | 
 |         c = C() | 
 |         wr = weakref.ref(c) | 
 |         exc = self.outer(c=c) | 
 |         del c | 
 |         support.gc_collect() | 
 |         # A reference to c is held through the frames | 
 |         self.assertIsNot(None, wr()) | 
 |         self.clear_traceback_frames(exc.__traceback__) | 
 |         support.gc_collect() | 
 |         # The reference was released by .clear() | 
 |         self.assertIs(None, wr()) | 
 |  | 
 |     def test_clear_generator(self): | 
 |         endly = False | 
 |         def g(): | 
 |             nonlocal endly | 
 |             try: | 
 |                 yield | 
 |                 inner() | 
 |             finally: | 
 |                 endly = True | 
 |         gen = g() | 
 |         next(gen) | 
 |         self.assertFalse(endly) | 
 |         # Clearing the frame closes the generator | 
 |         gen.gi_frame.clear() | 
 |         self.assertTrue(endly) | 
 |  | 
 |     def test_clear_executing(self): | 
 |         # Attempting to clear an executing frame is forbidden. | 
 |         try: | 
 |             1/0 | 
 |         except ZeroDivisionError as e: | 
 |             f = e.__traceback__.tb_frame | 
 |         with self.assertRaises(RuntimeError): | 
 |             f.clear() | 
 |         with self.assertRaises(RuntimeError): | 
 |             f.f_back.clear() | 
 |  | 
 |     def test_clear_executing_generator(self): | 
 |         # Attempting to clear an executing generator frame is forbidden. | 
 |         endly = False | 
 |         def g(): | 
 |             nonlocal endly | 
 |             try: | 
 |                 1/0 | 
 |             except ZeroDivisionError as e: | 
 |                 f = e.__traceback__.tb_frame | 
 |                 with self.assertRaises(RuntimeError): | 
 |                     f.clear() | 
 |                 with self.assertRaises(RuntimeError): | 
 |                     f.f_back.clear() | 
 |                 yield f | 
 |             finally: | 
 |                 endly = True | 
 |         gen = g() | 
 |         f = next(gen) | 
 |         self.assertFalse(endly) | 
 |         # Clearing the frame closes the generator | 
 |         f.clear() | 
 |         self.assertTrue(endly) | 
 |  | 
 |     @support.cpython_only | 
 |     def test_clear_refcycles(self): | 
 |         # .clear() doesn't leave any refcycle behind | 
 |         with support.disable_gc(): | 
 |             class C: | 
 |                 pass | 
 |             c = C() | 
 |             wr = weakref.ref(c) | 
 |             exc = self.outer(c=c) | 
 |             del c | 
 |             self.assertIsNot(None, wr()) | 
 |             self.clear_traceback_frames(exc.__traceback__) | 
 |             self.assertIs(None, wr()) | 
 |  | 
 |  | 
 | def test_main(): | 
 |     support.run_unittest(__name__) | 
 |  | 
 | if __name__ == "__main__": | 
 |     test_main() |