diff options
author | Antoine Pitrou <solipsis@pitrou.net> | 2013-05-08 16:12:35 (GMT) |
---|---|---|
committer | Antoine Pitrou <solipsis@pitrou.net> | 2013-05-08 16:12:35 (GMT) |
commit | 04e70d19e7a5ab0cea7d3d231606180226e16f06 (patch) | |
tree | a1956f14fe0e89e656fd2161178dad0e25ff4b14 /Lib/test/test_generators.py | |
parent | 070cb3c9bed3fbdbda42c257e05d46adcbeb784e (diff) | |
download | cpython-04e70d19e7a5ab0cea7d3d231606180226e16f06.zip cpython-04e70d19e7a5ab0cea7d3d231606180226e16f06.tar.gz cpython-04e70d19e7a5ab0cea7d3d231606180226e16f06.tar.bz2 |
Issue #17807: Generators can now be finalized even when they are part of a reference cycle.
Diffstat (limited to 'Lib/test/test_generators.py')
-rw-r--r-- | Lib/test/test_generators.py | 53 |
1 files changed, 53 insertions, 0 deletions
diff --git a/Lib/test/test_generators.py b/Lib/test/test_generators.py index edf3443..4e92117 100644 --- a/Lib/test/test_generators.py +++ b/Lib/test/test_generators.py @@ -1,3 +1,55 @@ +import gc +import sys +import unittest +import weakref + +from test import support + + +class FinalizationTest(unittest.TestCase): + + def test_frame_resurrect(self): + # A generator frame can be resurrected by a generator's finalization. + def gen(): + nonlocal frame + try: + yield + finally: + frame = sys._getframe() + + g = gen() + wr = weakref.ref(g) + next(g) + del g + support.gc_collect() + self.assertIs(wr(), None) + self.assertTrue(frame) + del frame + support.gc_collect() + + def test_refcycle(self): + # A generator caught in a refcycle gets finalized anyway. + old_garbage = gc.garbage[:] + finalized = False + def gen(): + nonlocal finalized + try: + g = yield + yield 1 + finally: + finalized = True + + g = gen() + next(g) + g.send(g) + self.assertGreater(sys.getrefcount(g), 2) + self.assertFalse(finalized) + del g + support.gc_collect() + self.assertTrue(finalized) + self.assertEqual(gc.garbage, old_garbage) + + tutorial_tests = """ Let's try a simple generator: @@ -1880,6 +1932,7 @@ __test__ = {"tut": tutorial_tests, # so this works as expected in both ways of running regrtest. def test_main(verbose=None): from test import support, test_generators + support.run_unittest(__name__) support.run_doctest(test_generators, verbose) # This part isn't needed for regrtest, but for running the test directly. |