add release date
[python/dscho.git] / Lib / weakref.py
blob88c60e7197419b8f93273a04a6b30da18cbca8df
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 _weakrefset import WeakSet
25 from exceptions import ReferenceError
28 ProxyTypes = (ProxyType, CallableProxyType)
30 __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
31 "WeakKeyDictionary", "ReferenceError", "ReferenceType", "ProxyType",
32 "CallableProxyType", "ProxyTypes", "WeakValueDictionary", 'WeakSet']
35 class WeakValueDictionary(UserDict.UserDict):
36 """Mapping class that references values weakly.
38 Entries in the dictionary will be discarded when no strong
39 reference to the value exists anymore
40 """
41 # We inherit the constructor without worrying about the input
42 # dictionary; since it uses our .update() method, we get the right
43 # checks (if the other dictionary is a WeakValueDictionary,
44 # objects are unwrapped on the way out, and we always wrap on the
45 # way in).
47 def __init__(self, *args, **kw):
48 def remove(wr, selfref=ref(self)):
49 self = selfref()
50 if self is not None:
51 del self.data[wr.key]
52 self._remove = remove
53 UserDict.UserDict.__init__(self, *args, **kw)
55 def __getitem__(self, key):
56 o = self.data[key]()
57 if o is None:
58 raise KeyError, key
59 else:
60 return o
62 def __contains__(self, key):
63 try:
64 o = self.data[key]()
65 except KeyError:
66 return False
67 return o is not None
69 def has_key(self, key):
70 try:
71 o = self.data[key]()
72 except KeyError:
73 return False
74 return o is not None
76 def __repr__(self):
77 return "<WeakValueDictionary at %s>" % id(self)
79 def __setitem__(self, key, value):
80 self.data[key] = KeyedRef(value, self._remove, key)
82 def copy(self):
83 new = WeakValueDictionary()
84 for key, wr in self.data.items():
85 o = wr()
86 if o is not None:
87 new[key] = o
88 return new
90 __copy__ = copy
92 def __deepcopy__(self, memo):
93 from copy import deepcopy
94 new = self.__class__()
95 for key, wr in self.data.items():
96 o = wr()
97 if o is not None:
98 new[deepcopy(key, memo)] = o
99 return new
101 def get(self, key, default=None):
102 try:
103 wr = self.data[key]
104 except KeyError:
105 return default
106 else:
107 o = wr()
108 if o is None:
109 # This should only happen
110 return default
111 else:
112 return o
114 def items(self):
115 L = []
116 for key, wr in self.data.items():
117 o = wr()
118 if o is not None:
119 L.append((key, o))
120 return L
122 def iteritems(self):
123 for wr in self.data.itervalues():
124 value = wr()
125 if value is not None:
126 yield wr.key, value
128 def iterkeys(self):
129 return self.data.iterkeys()
131 def __iter__(self):
132 return self.data.iterkeys()
134 def itervaluerefs(self):
135 """Return an iterator that yields the weak references to the values.
137 The references are not guaranteed to be 'live' at the time
138 they are used, so the result of calling the references needs
139 to be checked before being used. This can be used to avoid
140 creating references that will cause the garbage collector to
141 keep the values around longer than needed.
144 return self.data.itervalues()
146 def itervalues(self):
147 for wr in self.data.itervalues():
148 obj = wr()
149 if obj is not None:
150 yield obj
152 def popitem(self):
153 while 1:
154 key, wr = self.data.popitem()
155 o = wr()
156 if o is not None:
157 return key, o
159 def pop(self, key, *args):
160 try:
161 o = self.data.pop(key)()
162 except KeyError:
163 if args:
164 return args[0]
165 raise
166 if o is None:
167 raise KeyError, key
168 else:
169 return o
171 def setdefault(self, key, default=None):
172 try:
173 wr = self.data[key]
174 except KeyError:
175 self.data[key] = KeyedRef(default, self._remove, key)
176 return default
177 else:
178 return wr()
180 def update(self, dict=None, **kwargs):
181 d = self.data
182 if dict is not None:
183 if not hasattr(dict, "items"):
184 dict = type({})(dict)
185 for key, o in dict.items():
186 d[key] = KeyedRef(o, self._remove, key)
187 if len(kwargs):
188 self.update(kwargs)
190 def valuerefs(self):
191 """Return a list of weak references to the values.
193 The references are not guaranteed to be 'live' at the time
194 they are used, so the result of calling the references needs
195 to be checked before being used. This can be used to avoid
196 creating references that will cause the garbage collector to
197 keep the values around longer than needed.
200 return self.data.values()
202 def values(self):
203 L = []
204 for wr in self.data.values():
205 o = wr()
206 if o is not None:
207 L.append(o)
208 return L
211 class KeyedRef(ref):
212 """Specialized reference that includes a key corresponding to the value.
214 This is used in the WeakValueDictionary to avoid having to create
215 a function object for each key stored in the mapping. A shared
216 callback object can use the 'key' attribute of a KeyedRef instead
217 of getting a reference to the key from an enclosing scope.
221 __slots__ = "key",
223 def __new__(type, ob, callback, key):
224 self = ref.__new__(type, ob, callback)
225 self.key = key
226 return self
228 def __init__(self, ob, callback, key):
229 super(KeyedRef, self).__init__(ob, callback)
232 class WeakKeyDictionary(UserDict.UserDict):
233 """ Mapping class that references keys weakly.
235 Entries in the dictionary will be discarded when there is no
236 longer a strong reference to the key. This can be used to
237 associate additional data with an object owned by other parts of
238 an application without adding attributes to those objects. This
239 can be especially useful with objects that override attribute
240 accesses.
243 def __init__(self, dict=None):
244 self.data = {}
245 def remove(k, selfref=ref(self)):
246 self = selfref()
247 if self is not None:
248 del self.data[k]
249 self._remove = remove
250 if dict is not None: self.update(dict)
252 def __delitem__(self, key):
253 del self.data[ref(key)]
255 def __getitem__(self, key):
256 return self.data[ref(key)]
258 def __repr__(self):
259 return "<WeakKeyDictionary at %s>" % id(self)
261 def __setitem__(self, key, value):
262 self.data[ref(key, self._remove)] = value
264 def copy(self):
265 new = WeakKeyDictionary()
266 for key, value in self.data.items():
267 o = key()
268 if o is not None:
269 new[o] = value
270 return new
272 __copy__ = copy
274 def __deepcopy__(self, memo):
275 from copy import deepcopy
276 new = self.__class__()
277 for key, value in self.data.items():
278 o = key()
279 if o is not None:
280 new[o] = deepcopy(value, memo)
281 return new
283 def get(self, key, default=None):
284 return self.data.get(ref(key),default)
286 def has_key(self, key):
287 try:
288 wr = ref(key)
289 except TypeError:
290 return 0
291 return wr in self.data
293 def __contains__(self, key):
294 try:
295 wr = ref(key)
296 except TypeError:
297 return 0
298 return wr in self.data
300 def items(self):
301 L = []
302 for key, value in self.data.items():
303 o = key()
304 if o is not None:
305 L.append((o, value))
306 return L
308 def iteritems(self):
309 for wr, value in self.data.iteritems():
310 key = wr()
311 if key is not None:
312 yield key, value
314 def iterkeyrefs(self):
315 """Return an iterator that yields the weak references to the keys.
317 The references are not guaranteed to be 'live' at the time
318 they are used, so the result of calling the references needs
319 to be checked before being used. This can be used to avoid
320 creating references that will cause the garbage collector to
321 keep the keys around longer than needed.
324 return self.data.iterkeys()
326 def iterkeys(self):
327 for wr in self.data.iterkeys():
328 obj = wr()
329 if obj is not None:
330 yield obj
332 def __iter__(self):
333 return self.iterkeys()
335 def itervalues(self):
336 return self.data.itervalues()
338 def keyrefs(self):
339 """Return a list of weak references to the keys.
341 The references are not guaranteed to be 'live' at the time
342 they are used, so the result of calling the references needs
343 to be checked before being used. This can be used to avoid
344 creating references that will cause the garbage collector to
345 keep the keys around longer than needed.
348 return self.data.keys()
350 def keys(self):
351 L = []
352 for wr in self.data.keys():
353 o = wr()
354 if o is not None:
355 L.append(o)
356 return L
358 def popitem(self):
359 while 1:
360 key, value = self.data.popitem()
361 o = key()
362 if o is not None:
363 return o, value
365 def pop(self, key, *args):
366 return self.data.pop(ref(key), *args)
368 def setdefault(self, key, default=None):
369 return self.data.setdefault(ref(key, self._remove),default)
371 def update(self, dict=None, **kwargs):
372 d = self.data
373 if dict is not None:
374 if not hasattr(dict, "items"):
375 dict = type({})(dict)
376 for key, value in dict.items():
377 d[ref(key, self._remove)] = value
378 if len(kwargs):
379 self.update(kwargs)