Add NEWS entry as per RDM's suggestion (the bug was actually present
[python.git] / Lib / weakref.py
blob84d81a27347b55fe922f63f096dd656be1e98cf2
1 """Weak reference support for Python.
3 This module is an implementation of PEP 205:
5 http://www.python.org/dev/peps/pep-0205/
6 """
8 # Naming convention: Variables named "wr" are weak reference objects;
9 # they are called this instead of "ref" to avoid name collisions with
10 # the module-global ref() function imported from _weakref.
12 import UserDict
14 from _weakref import (
15 getweakrefcount,
16 getweakrefs,
17 ref,
18 proxy,
19 CallableProxyType,
20 ProxyType,
21 ReferenceType)
23 from exceptions import ReferenceError
26 ProxyTypes = (ProxyType, CallableProxyType)
28 __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
29 "WeakKeyDictionary", "ReferenceError", "ReferenceType", "ProxyType",
30 "CallableProxyType", "ProxyTypes", "WeakValueDictionary"]
33 class WeakValueDictionary(UserDict.UserDict):
34 """Mapping class that references values weakly.
36 Entries in the dictionary will be discarded when no strong
37 reference to the value exists anymore
38 """
39 # We inherit the constructor without worrying about the input
40 # dictionary; since it uses our .update() method, we get the right
41 # checks (if the other dictionary is a WeakValueDictionary,
42 # objects are unwrapped on the way out, and we always wrap on the
43 # way in).
45 def __init__(self, *args, **kw):
46 def remove(wr, selfref=ref(self)):
47 self = selfref()
48 if self is not None:
49 del self.data[wr.key]
50 self._remove = remove
51 UserDict.UserDict.__init__(self, *args, **kw)
53 def __getitem__(self, key):
54 o = self.data[key]()
55 if o is None:
56 raise KeyError, key
57 else:
58 return o
60 def __contains__(self, key):
61 try:
62 o = self.data[key]()
63 except KeyError:
64 return False
65 return o is not None
67 def has_key(self, key):
68 try:
69 o = self.data[key]()
70 except KeyError:
71 return False
72 return o is not None
74 def __repr__(self):
75 return "<WeakValueDictionary at %s>" % id(self)
77 def __setitem__(self, key, value):
78 self.data[key] = KeyedRef(value, self._remove, key)
80 def copy(self):
81 new = WeakValueDictionary()
82 for key, wr in self.data.items():
83 o = wr()
84 if o is not None:
85 new[key] = o
86 return new
88 __copy__ = copy
90 def __deepcopy__(self, memo):
91 from copy import deepcopy
92 new = self.__class__()
93 for key, wr in self.data.items():
94 o = wr()
95 if o is not None:
96 new[deepcopy(key, memo)] = o
97 return new
99 def get(self, key, default=None):
100 try:
101 wr = self.data[key]
102 except KeyError:
103 return default
104 else:
105 o = wr()
106 if o is None:
107 # This should only happen
108 return default
109 else:
110 return o
112 def items(self):
113 L = []
114 for key, wr in self.data.items():
115 o = wr()
116 if o is not None:
117 L.append((key, o))
118 return L
120 def iteritems(self):
121 for wr in self.data.itervalues():
122 value = wr()
123 if value is not None:
124 yield wr.key, value
126 def iterkeys(self):
127 return self.data.iterkeys()
129 def __iter__(self):
130 return self.data.iterkeys()
132 def itervaluerefs(self):
133 """Return an iterator that yields the weak references to the values.
135 The references are not guaranteed to be 'live' at the time
136 they are used, so the result of calling the references needs
137 to be checked before being used. This can be used to avoid
138 creating references that will cause the garbage collector to
139 keep the values around longer than needed.
142 return self.data.itervalues()
144 def itervalues(self):
145 for wr in self.data.itervalues():
146 obj = wr()
147 if obj is not None:
148 yield obj
150 def popitem(self):
151 while 1:
152 key, wr = self.data.popitem()
153 o = wr()
154 if o is not None:
155 return key, o
157 def pop(self, key, *args):
158 try:
159 o = self.data.pop(key)()
160 except KeyError:
161 if args:
162 return args[0]
163 raise
164 if o is None:
165 raise KeyError, key
166 else:
167 return o
169 def setdefault(self, key, default=None):
170 try:
171 wr = self.data[key]
172 except KeyError:
173 self.data[key] = KeyedRef(default, self._remove, key)
174 return default
175 else:
176 return wr()
178 def update(self, dict=None, **kwargs):
179 d = self.data
180 if dict is not None:
181 if not hasattr(dict, "items"):
182 dict = type({})(dict)
183 for key, o in dict.items():
184 d[key] = KeyedRef(o, self._remove, key)
185 if len(kwargs):
186 self.update(kwargs)
188 def valuerefs(self):
189 """Return a list of weak references to the values.
191 The references are not guaranteed to be 'live' at the time
192 they are used, so the result of calling the references needs
193 to be checked before being used. This can be used to avoid
194 creating references that will cause the garbage collector to
195 keep the values around longer than needed.
198 return self.data.values()
200 def values(self):
201 L = []
202 for wr in self.data.values():
203 o = wr()
204 if o is not None:
205 L.append(o)
206 return L
209 class KeyedRef(ref):
210 """Specialized reference that includes a key corresponding to the value.
212 This is used in the WeakValueDictionary to avoid having to create
213 a function object for each key stored in the mapping. A shared
214 callback object can use the 'key' attribute of a KeyedRef instead
215 of getting a reference to the key from an enclosing scope.
219 __slots__ = "key",
221 def __new__(type, ob, callback, key):
222 self = ref.__new__(type, ob, callback)
223 self.key = key
224 return self
226 def __init__(self, ob, callback, key):
227 super(KeyedRef, self).__init__(ob, callback)
230 class WeakKeyDictionary(UserDict.UserDict):
231 """ Mapping class that references keys weakly.
233 Entries in the dictionary will be discarded when there is no
234 longer a strong reference to the key. This can be used to
235 associate additional data with an object owned by other parts of
236 an application without adding attributes to those objects. This
237 can be especially useful with objects that override attribute
238 accesses.
241 def __init__(self, dict=None):
242 self.data = {}
243 def remove(k, selfref=ref(self)):
244 self = selfref()
245 if self is not None:
246 del self.data[k]
247 self._remove = remove
248 if dict is not None: self.update(dict)
250 def __delitem__(self, key):
251 del self.data[ref(key)]
253 def __getitem__(self, key):
254 return self.data[ref(key)]
256 def __repr__(self):
257 return "<WeakKeyDictionary at %s>" % id(self)
259 def __setitem__(self, key, value):
260 self.data[ref(key, self._remove)] = value
262 def copy(self):
263 new = WeakKeyDictionary()
264 for key, value in self.data.items():
265 o = key()
266 if o is not None:
267 new[o] = value
268 return new
270 __copy__ = copy
272 def __deepcopy__(self, memo):
273 from copy import deepcopy
274 new = self.__class__()
275 for key, value in self.data.items():
276 o = key()
277 if o is not None:
278 new[o] = deepcopy(value, memo)
279 return new
281 def get(self, key, default=None):
282 return self.data.get(ref(key),default)
284 def has_key(self, key):
285 try:
286 wr = ref(key)
287 except TypeError:
288 return 0
289 return wr in self.data
291 def __contains__(self, key):
292 try:
293 wr = ref(key)
294 except TypeError:
295 return 0
296 return wr in self.data
298 def items(self):
299 L = []
300 for key, value in self.data.items():
301 o = key()
302 if o is not None:
303 L.append((o, value))
304 return L
306 def iteritems(self):
307 for wr, value in self.data.iteritems():
308 key = wr()
309 if key is not None:
310 yield key, value
312 def iterkeyrefs(self):
313 """Return an iterator that yields the weak references to the keys.
315 The references are not guaranteed to be 'live' at the time
316 they are used, so the result of calling the references needs
317 to be checked before being used. This can be used to avoid
318 creating references that will cause the garbage collector to
319 keep the keys around longer than needed.
322 return self.data.iterkeys()
324 def iterkeys(self):
325 for wr in self.data.iterkeys():
326 obj = wr()
327 if obj is not None:
328 yield obj
330 def __iter__(self):
331 return self.iterkeys()
333 def itervalues(self):
334 return self.data.itervalues()
336 def keyrefs(self):
337 """Return a list of weak references to the keys.
339 The references are not guaranteed to be 'live' at the time
340 they are used, so the result of calling the references needs
341 to be checked before being used. This can be used to avoid
342 creating references that will cause the garbage collector to
343 keep the keys around longer than needed.
346 return self.data.keys()
348 def keys(self):
349 L = []
350 for wr in self.data.keys():
351 o = wr()
352 if o is not None:
353 L.append(o)
354 return L
356 def popitem(self):
357 while 1:
358 key, value = self.data.popitem()
359 o = key()
360 if o is not None:
361 return o, value
363 def pop(self, key, *args):
364 return self.data.pop(ref(key), *args)
366 def setdefault(self, key, default=None):
367 return self.data.setdefault(ref(key, self._remove),default)
369 def update(self, dict=None, **kwargs):
370 d = self.data
371 if dict is not None:
372 if not hasattr(dict, "items"):
373 dict = type({})(dict)
374 for key, value in dict.items():
375 d[ref(key, self._remove)] = value
376 if len(kwargs):
377 self.update(kwargs)