Updated for 2.1b2 distribution.
[python/dscho.git] / Lib / test / test_weakref.py
blob1e193f1920be3062dc61d454221a5a6d23680680
1 import sys
2 import unittest
3 import weakref
5 from test_support import run_unittest, verify
8 class C:
9 def method(self):
10 pass
13 class Callable:
14 bar = None
16 def __call__(self, x):
17 self.bar = x
20 def create_function():
21 def f(): pass
22 return f
24 def create_bound_method():
25 return C().method
27 def create_unbound_method():
28 return C.method
31 class TestBase(unittest.TestCase):
33 def setUp(self):
34 self.cbcalled = 0
36 def callback(self, ref):
37 self.cbcalled += 1
40 class ReferencesTestCase(TestBase):
42 def test_basic_ref(self):
43 self.check_basic_ref(C)
44 self.check_basic_ref(create_function)
45 self.check_basic_ref(create_bound_method)
46 self.check_basic_ref(create_unbound_method)
48 def test_basic_callback(self):
49 self.check_basic_callback(C)
50 self.check_basic_callback(create_function)
51 self.check_basic_callback(create_bound_method)
52 self.check_basic_callback(create_unbound_method)
54 def test_multiple_callbacks(self):
55 o = C()
56 ref1 = weakref.ref(o, self.callback)
57 ref2 = weakref.ref(o, self.callback)
58 del o
59 self.assert_(ref1() is None,
60 "expected reference to be invalidated")
61 self.assert_(ref2() is None,
62 "expected reference to be invalidated")
63 self.assert_(self.cbcalled == 2,
64 "callback not called the right number of times")
66 def test_proxy_ref(self):
67 o = C()
68 o.bar = 1
69 ref1 = weakref.proxy(o, self.callback)
70 ref2 = weakref.proxy(o, self.callback)
71 del o
73 def check(proxy):
74 proxy.bar
76 self.assertRaises(weakref.ReferenceError, check, ref1)
77 self.assertRaises(weakref.ReferenceError, check, ref2)
78 self.assert_(self.cbcalled == 2)
80 def check_basic_ref(self, factory):
81 o = factory()
82 ref = weakref.ref(o)
83 self.assert_(ref() is not None,
84 "weak reference to live object should be live")
85 o2 = ref()
86 self.assert_(o is o2,
87 "<ref>() should return original object if live")
89 def check_basic_callback(self, factory):
90 self.cbcalled = 0
91 o = factory()
92 ref = weakref.ref(o, self.callback)
93 del o
94 verify(self.cbcalled == 1,
95 "callback did not properly set 'cbcalled'")
96 verify(ref() is None,
97 "ref2 should be dead after deleting object reference")
99 def test_ref_reuse(self):
100 o = C()
101 ref1 = weakref.ref(o)
102 # create a proxy to make sure that there's an intervening creation
103 # between these two; it should make no difference
104 proxy = weakref.proxy(o)
105 ref2 = weakref.ref(o)
106 self.assert_(ref1 is ref2,
107 "reference object w/out callback should be re-used")
109 o = C()
110 proxy = weakref.proxy(o)
111 ref1 = weakref.ref(o)
112 ref2 = weakref.ref(o)
113 self.assert_(ref1 is ref2,
114 "reference object w/out callback should be re-used")
115 self.assert_(weakref.getweakrefcount(o) == 2,
116 "wrong weak ref count for object")
117 del proxy
118 self.assert_(weakref.getweakrefcount(o) == 1,
119 "wrong weak ref count for object after deleting proxy")
121 def test_proxy_reuse(self):
122 o = C()
123 proxy1 = weakref.proxy(o)
124 ref = weakref.ref(o)
125 proxy2 = weakref.proxy(o)
126 self.assert_(proxy1 is proxy2,
127 "proxy object w/out callback should have been re-used")
129 def test_basic_proxy(self):
130 o = C()
131 self.check_proxy(o, weakref.proxy(o))
133 def test_callable_proxy(self):
134 o = Callable()
135 ref1 = weakref.proxy(o)
137 self.check_proxy(o, ref1)
139 self.assert_(type(ref1) is weakref.CallableProxyType,
140 "proxy is not of callable type")
141 ref1('twinkies!')
142 self.assert_(o.bar == 'twinkies!',
143 "call through proxy not passed through to original")
145 # expect due to too few args
146 self.assertRaises(TypeError, ref1)
148 # expect due to too many args
149 self.assertRaises(TypeError, ref1, 1, 2, 3)
151 def check_proxy(self, o, proxy):
152 o.foo = 1
153 self.assert_(proxy.foo == 1,
154 "proxy does not reflect attribute addition")
155 o.foo = 2
156 self.assert_(proxy.foo == 2,
157 "proxy does not reflect attribute modification")
158 del o.foo
159 self.assert_(not hasattr(proxy, 'foo'),
160 "proxy does not reflect attribute removal")
162 proxy.foo = 1
163 self.assert_(o.foo == 1,
164 "object does not reflect attribute addition via proxy")
165 proxy.foo = 2
166 self.assert_(
167 o.foo == 2,
168 "object does not reflect attribute modification via proxy")
169 del proxy.foo
170 self.assert_(not hasattr(o, 'foo'),
171 "object does not reflect attribute removal via proxy")
173 def test_getweakrefcount(self):
174 o = C()
175 ref1 = weakref.ref(o)
176 ref2 = weakref.ref(o, self.callback)
177 self.assert_(weakref.getweakrefcount(o) == 2,
178 "got wrong number of weak reference objects")
180 proxy1 = weakref.proxy(o)
181 proxy2 = weakref.proxy(o, self.callback)
182 self.assert_(weakref.getweakrefcount(o) == 4,
183 "got wrong number of weak reference objects")
185 def test_getweakrefs(self):
186 o = C()
187 ref1 = weakref.ref(o, self.callback)
188 ref2 = weakref.ref(o, self.callback)
189 del ref1
190 self.assert_(weakref.getweakrefs(o) == [ref2],
191 "list of refs does not match")
193 o = C()
194 ref1 = weakref.ref(o, self.callback)
195 ref2 = weakref.ref(o, self.callback)
196 del ref2
197 self.assert_(weakref.getweakrefs(o) == [ref1],
198 "list of refs does not match")
201 class Object:
202 def __init__(self, arg):
203 self.arg = arg
204 def __repr__(self):
205 return "<Object %r>" % self.arg
208 class MappingTestCase(TestBase):
210 COUNT = 10
212 def test_weak_values(self):
213 dict = weakref.mapping()
214 objects = map(Object, range(self.COUNT))
215 for o in objects:
216 dict[o.arg] = o
218 for o in objects:
219 self.assert_(weakref.getweakrefcount(o) == 1,
220 "wrong number of weak references to %r!" % o)
221 self.assert_(o is dict[o.arg],
222 "wrong object returned by weak dict!")
223 items1 = dict.items()
224 items2 = dict.copy().items()
225 items1.sort()
226 items2.sort()
227 self.assert_(items1 == items2,
228 "cloning of weak-valued dictionary did not work!")
229 del items1, items2
230 self.assert_(len(dict) == self.COUNT)
231 del objects[0]
232 self.assert_(len(dict) == (self.COUNT - 1),
233 "deleting object did not cause dictionary update")
234 del objects, o
235 self.assert_(len(dict) == 0,
236 "deleting the values did not clear the dictionary")
238 def test_weak_keys(self):
239 dict = weakref.mapping(weakkeys=1)
240 objects = map(Object, range(self.COUNT))
241 for o in objects:
242 dict[o] = o.arg
244 for o in objects:
245 self.assert_(weakref.getweakrefcount(o) == 1,
246 "wrong number of weak references to %r!" % o)
247 self.assert_(o.arg is dict[o],
248 "wrong object returned by weak dict!")
249 items1 = dict.items()
250 items2 = dict.copy().items()
251 items1.sort()
252 items2.sort()
253 self.assert_(items1 == items2,
254 "cloning of weak-keyed dictionary did not work!")
255 del items1, items2
256 self.assert_(len(dict) == self.COUNT)
257 del objects[0]
258 self.assert_(len(dict) == (self.COUNT - 1),
259 "deleting object did not cause dictionary update")
260 del objects, o
261 self.assert_(len(dict) == 0,
262 "deleting the keys did not clear the dictionary")
265 run_unittest(ReferencesTestCase)
266 run_unittest(MappingTestCase)