annotate Lib/test/test_finalization.py @ 87690:66c1c9f32567 default tip

Add use_weakref option to functools.lru_cache The use_weakref option makes lru_cache create weak references to the function arguments when creating the cache key, which prevents them from staying in the memory forever even after all other references to them are gone. This is a proof of concept for http://bugs.python.org/issue19859
author Radomir Dopieralski <devel@sheep.art.pl>
date Tue, 03 Dec 2013 16:02:48 +0100
parents 3f994367a979
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
84911
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
1 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
2 Tests for object finalization semantics, as outlined in PEP 442.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
3 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
4
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
5 import contextlib
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
6 import gc
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
7 import unittest
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
8 import weakref
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
9
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
10 import _testcapi
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
11 from test import support
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
12
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
13
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
14 class NonGCSimpleBase:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
15 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
16 The base class for all the objects under test, equipped with various
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
17 testing features.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
18 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
19
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
20 survivors = []
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
21 del_calls = []
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
22 tp_del_calls = []
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
23 errors = []
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
24
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
25 _cleaning = False
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
26
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
27 __slots__ = ()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
28
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
29 @classmethod
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
30 def _cleanup(cls):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
31 cls.survivors.clear()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
32 cls.errors.clear()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
33 gc.garbage.clear()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
34 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
35 cls.del_calls.clear()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
36 cls.tp_del_calls.clear()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
37
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
38 @classmethod
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
39 @contextlib.contextmanager
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
40 def test(cls):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
41 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
42 A context manager to use around all finalization tests.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
43 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
44 with support.disable_gc():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
45 cls.del_calls.clear()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
46 cls.tp_del_calls.clear()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
47 NonGCSimpleBase._cleaning = False
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
48 try:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
49 yield
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
50 if cls.errors:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
51 raise cls.errors[0]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
52 finally:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
53 NonGCSimpleBase._cleaning = True
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
54 cls._cleanup()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
55
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
56 def check_sanity(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
57 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
58 Check the object is sane (non-broken).
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
59 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
60
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
61 def __del__(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
62 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
63 PEP 442 finalizer. Record that this was called, check the
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
64 object is in a sane state, and invoke a side effect.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
65 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
66 try:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
67 if not self._cleaning:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
68 self.del_calls.append(id(self))
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
69 self.check_sanity()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
70 self.side_effect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
71 except Exception as e:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
72 self.errors.append(e)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
73
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
74 def side_effect(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
75 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
76 A side effect called on destruction.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
77 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
78
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
79
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
80 class SimpleBase(NonGCSimpleBase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
81
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
82 def __init__(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
83 self.id_ = id(self)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
84
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
85 def check_sanity(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
86 assert self.id_ == id(self)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
87
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
88
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
89 class NonGC(NonGCSimpleBase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
90 __slots__ = ()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
91
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
92 class NonGCResurrector(NonGCSimpleBase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
93 __slots__ = ()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
94
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
95 def side_effect(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
96 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
97 Resurrect self by storing self in a class-wide list.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
98 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
99 self.survivors.append(self)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
100
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
101 class Simple(SimpleBase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
102 pass
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
103
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
104 class SimpleResurrector(NonGCResurrector, SimpleBase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
105 pass
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
106
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
107
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
108 class TestBase:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
109
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
110 def setUp(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
111 self.old_garbage = gc.garbage[:]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
112 gc.garbage[:] = []
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
113
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
114 def tearDown(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
115 # None of the tests here should put anything in gc.garbage
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
116 try:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
117 self.assertEqual(gc.garbage, [])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
118 finally:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
119 del self.old_garbage
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
120 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
121
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
122 def assert_del_calls(self, ids):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
123 self.assertEqual(sorted(SimpleBase.del_calls), sorted(ids))
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
124
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
125 def assert_tp_del_calls(self, ids):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
126 self.assertEqual(sorted(SimpleBase.tp_del_calls), sorted(ids))
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
127
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
128 def assert_survivors(self, ids):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
129 self.assertEqual(sorted(id(x) for x in SimpleBase.survivors), sorted(ids))
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
130
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
131 def assert_garbage(self, ids):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
132 self.assertEqual(sorted(id(x) for x in gc.garbage), sorted(ids))
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
133
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
134 def clear_survivors(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
135 SimpleBase.survivors.clear()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
136
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
137
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
138 class SimpleFinalizationTest(TestBase, unittest.TestCase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
139 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
140 Test finalization without refcycles.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
141 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
142
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
143 def test_simple(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
144 with SimpleBase.test():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
145 s = Simple()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
146 ids = [id(s)]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
147 wr = weakref.ref(s)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
148 del s
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
149 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
150 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
151 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
152 self.assertIs(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
153 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
154 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
155 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
156
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
157 def test_simple_resurrect(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
158 with SimpleBase.test():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
159 s = SimpleResurrector()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
160 ids = [id(s)]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
161 wr = weakref.ref(s)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
162 del s
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
163 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
164 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
165 self.assert_survivors(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
166 self.assertIsNot(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
167 self.clear_survivors()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
168 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
169 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
170 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
171 self.assertIs(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
172
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
173 def test_non_gc(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
174 with SimpleBase.test():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
175 s = NonGC()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
176 self.assertFalse(gc.is_tracked(s))
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
177 ids = [id(s)]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
178 del s
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
179 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
180 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
181 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
182 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
183 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
184 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
185
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
186 def test_non_gc_resurrect(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
187 with SimpleBase.test():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
188 s = NonGCResurrector()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
189 self.assertFalse(gc.is_tracked(s))
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
190 ids = [id(s)]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
191 del s
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
192 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
193 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
194 self.assert_survivors(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
195 self.clear_survivors()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
196 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
197 self.assert_del_calls(ids * 2)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
198 self.assert_survivors(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
199
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
200
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
201 class SelfCycleBase:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
202
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
203 def __init__(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
204 super().__init__()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
205 self.ref = self
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
206
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
207 def check_sanity(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
208 super().check_sanity()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
209 assert self.ref is self
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
210
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
211 class SimpleSelfCycle(SelfCycleBase, Simple):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
212 pass
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
213
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
214 class SelfCycleResurrector(SelfCycleBase, SimpleResurrector):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
215 pass
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
216
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
217 class SuicidalSelfCycle(SelfCycleBase, Simple):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
218
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
219 def side_effect(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
220 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
221 Explicitly break the reference cycle.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
222 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
223 self.ref = None
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
224
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
225
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
226 class SelfCycleFinalizationTest(TestBase, unittest.TestCase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
227 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
228 Test finalization of an object having a single cyclic reference to
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
229 itself.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
230 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
231
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
232 def test_simple(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
233 with SimpleBase.test():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
234 s = SimpleSelfCycle()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
235 ids = [id(s)]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
236 wr = weakref.ref(s)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
237 del s
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
238 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
239 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
240 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
241 self.assertIs(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
242 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
243 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
244 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
245
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
246 def test_simple_resurrect(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
247 # Test that __del__ can resurrect the object being finalized.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
248 with SimpleBase.test():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
249 s = SelfCycleResurrector()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
250 ids = [id(s)]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
251 wr = weakref.ref(s)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
252 del s
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
253 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
254 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
255 self.assert_survivors(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
256 # XXX is this desirable?
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
257 self.assertIs(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
258 # When trying to destroy the object a second time, __del__
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
259 # isn't called anymore (and the object isn't resurrected).
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
260 self.clear_survivors()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
261 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
262 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
263 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
264 self.assertIs(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
265
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
266 def test_simple_suicide(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
267 # Test the GC is able to deal with an object that kills its last
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
268 # reference during __del__.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
269 with SimpleBase.test():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
270 s = SuicidalSelfCycle()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
271 ids = [id(s)]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
272 wr = weakref.ref(s)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
273 del s
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
274 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
275 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
276 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
277 self.assertIs(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
278 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
279 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
280 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
281 self.assertIs(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
282
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
283
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
284 class ChainedBase:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
285
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
286 def chain(self, left):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
287 self.suicided = False
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
288 self.left = left
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
289 left.right = self
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
290
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
291 def check_sanity(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
292 super().check_sanity()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
293 if self.suicided:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
294 assert self.left is None
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
295 assert self.right is None
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
296 else:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
297 left = self.left
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
298 if left.suicided:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
299 assert left.right is None
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
300 else:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
301 assert left.right is self
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
302 right = self.right
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
303 if right.suicided:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
304 assert right.left is None
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
305 else:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
306 assert right.left is self
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
307
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
308 class SimpleChained(ChainedBase, Simple):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
309 pass
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
310
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
311 class ChainedResurrector(ChainedBase, SimpleResurrector):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
312 pass
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
313
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
314 class SuicidalChained(ChainedBase, Simple):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
315
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
316 def side_effect(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
317 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
318 Explicitly break the reference cycle.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
319 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
320 self.suicided = True
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
321 self.left = None
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
322 self.right = None
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
323
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
324
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
325 class CycleChainFinalizationTest(TestBase, unittest.TestCase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
326 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
327 Test finalization of a cyclic chain. These tests are similar in
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
328 spirit to the self-cycle tests above, but the collectable object
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
329 graph isn't trivial anymore.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
330 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
331
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
332 def build_chain(self, classes):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
333 nodes = [cls() for cls in classes]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
334 for i in range(len(nodes)):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
335 nodes[i].chain(nodes[i-1])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
336 return nodes
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
337
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
338 def check_non_resurrecting_chain(self, classes):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
339 N = len(classes)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
340 with SimpleBase.test():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
341 nodes = self.build_chain(classes)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
342 ids = [id(s) for s in nodes]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
343 wrs = [weakref.ref(s) for s in nodes]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
344 del nodes
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
345 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
346 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
347 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
348 self.assertEqual([wr() for wr in wrs], [None] * N)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
349 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
350 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
351
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
352 def check_resurrecting_chain(self, classes):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
353 N = len(classes)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
354 with SimpleBase.test():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
355 nodes = self.build_chain(classes)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
356 N = len(nodes)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
357 ids = [id(s) for s in nodes]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
358 survivor_ids = [id(s) for s in nodes if isinstance(s, SimpleResurrector)]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
359 wrs = [weakref.ref(s) for s in nodes]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
360 del nodes
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
361 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
362 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
363 self.assert_survivors(survivor_ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
364 # XXX desirable?
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
365 self.assertEqual([wr() for wr in wrs], [None] * N)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
366 self.clear_survivors()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
367 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
368 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
369 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
370
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
371 def test_homogenous(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
372 self.check_non_resurrecting_chain([SimpleChained] * 3)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
373
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
374 def test_homogenous_resurrect(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
375 self.check_resurrecting_chain([ChainedResurrector] * 3)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
376
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
377 def test_homogenous_suicidal(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
378 self.check_non_resurrecting_chain([SuicidalChained] * 3)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
379
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
380 def test_heterogenous_suicidal_one(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
381 self.check_non_resurrecting_chain([SuicidalChained, SimpleChained] * 2)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
382
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
383 def test_heterogenous_suicidal_two(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
384 self.check_non_resurrecting_chain(
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
385 [SuicidalChained] * 2 + [SimpleChained] * 2)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
386
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
387 def test_heterogenous_resurrect_one(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
388 self.check_resurrecting_chain([ChainedResurrector, SimpleChained] * 2)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
389
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
390 def test_heterogenous_resurrect_two(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
391 self.check_resurrecting_chain(
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
392 [ChainedResurrector, SimpleChained, SuicidalChained] * 2)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
393
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
394 def test_heterogenous_resurrect_three(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
395 self.check_resurrecting_chain(
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
396 [ChainedResurrector] * 2 + [SimpleChained] * 2 + [SuicidalChained] * 2)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
397
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
398
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
399 # NOTE: the tp_del slot isn't automatically inherited, so we have to call
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
400 # with_tp_del() for each instantiated class.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
401
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
402 class LegacyBase(SimpleBase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
403
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
404 def __del__(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
405 try:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
406 # Do not invoke side_effect here, since we are now exercising
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
407 # the tp_del slot.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
408 if not self._cleaning:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
409 self.del_calls.append(id(self))
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
410 self.check_sanity()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
411 except Exception as e:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
412 self.errors.append(e)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
413
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
414 def __tp_del__(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
415 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
416 Legacy (pre-PEP 442) finalizer, mapped to a tp_del slot.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
417 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
418 try:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
419 if not self._cleaning:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
420 self.tp_del_calls.append(id(self))
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
421 self.check_sanity()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
422 self.side_effect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
423 except Exception as e:
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
424 self.errors.append(e)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
425
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
426 @_testcapi.with_tp_del
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
427 class Legacy(LegacyBase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
428 pass
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
429
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
430 @_testcapi.with_tp_del
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
431 class LegacyResurrector(LegacyBase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
432
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
433 def side_effect(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
434 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
435 Resurrect self by storing self in a class-wide list.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
436 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
437 self.survivors.append(self)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
438
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
439 @_testcapi.with_tp_del
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
440 class LegacySelfCycle(SelfCycleBase, LegacyBase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
441 pass
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
442
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
443
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
444 class LegacyFinalizationTest(TestBase, unittest.TestCase):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
445 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
446 Test finalization of objects with a tp_del.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
447 """
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
448
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
449 def tearDown(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
450 # These tests need to clean up a bit more, since they create
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
451 # uncollectable objects.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
452 gc.garbage.clear()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
453 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
454 super().tearDown()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
455
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
456 def test_legacy(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
457 with SimpleBase.test():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
458 s = Legacy()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
459 ids = [id(s)]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
460 wr = weakref.ref(s)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
461 del s
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
462 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
463 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
464 self.assert_tp_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
465 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
466 self.assertIs(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
467 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
468 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
469 self.assert_tp_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
470
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
471 def test_legacy_resurrect(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
472 with SimpleBase.test():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
473 s = LegacyResurrector()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
474 ids = [id(s)]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
475 wr = weakref.ref(s)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
476 del s
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
477 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
478 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
479 self.assert_tp_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
480 self.assert_survivors(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
481 # weakrefs are cleared before tp_del is called.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
482 self.assertIs(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
483 self.clear_survivors()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
484 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
485 self.assert_del_calls(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
486 self.assert_tp_del_calls(ids * 2)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
487 self.assert_survivors(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
488 self.assertIs(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
489
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
490 def test_legacy_self_cycle(self):
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
491 # Self-cycles with legacy finalizers end up in gc.garbage.
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
492 with SimpleBase.test():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
493 s = LegacySelfCycle()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
494 ids = [id(s)]
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
495 wr = weakref.ref(s)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
496 del s
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
497 gc.collect()
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
498 self.assert_del_calls([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
499 self.assert_tp_del_calls([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
500 self.assert_survivors([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
501 self.assert_garbage(ids)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
502 self.assertIsNot(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
503 # Break the cycle to allow collection
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
504 gc.garbage[0].ref = None
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
505 self.assert_garbage([])
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
506 self.assertIs(wr(), None)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
507
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
508
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
509 def test_main():
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
510 support.run_unittest(__name__)
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
511
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
512 if __name__ == "__main__":
3f994367a979 Issue #18112: PEP 442 implementation (safe object finalization).
Antoine Pitrou <solipsis@pitrou.net>
parents:
diff changeset
513 test_main()