1 """Weak reference support for Python.
3 This module is an implementation of PEP 205:
5 http://www.python.org/dev/peps/pep-0205/
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.
14 from _weakref
import (
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
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
45 def __init__(self
, *args
, **kw
):
46 def remove(wr
, selfref
=ref(self
)):
51 UserDict
.UserDict
.__init
__(self
, *args
, **kw
)
53 def __getitem__(self
, key
):
60 def __contains__(self
, key
):
67 def has_key(self
, key
):
75 return "<WeakValueDictionary at %s>" % id(self
)
77 def __setitem__(self
, key
, value
):
78 self
.data
[key
] = KeyedRef(value
, self
._remove
, key
)
81 new
= WeakValueDictionary()
82 for key
, wr
in self
.data
.items():
90 def __deepcopy__(self
, memo
):
91 from copy
import deepcopy
92 new
= self
.__class
__()
93 for key
, wr
in self
.data
.items():
96 new
[deepcopy(key
, memo
)] = o
99 def get(self
, key
, default
=None):
107 # This should only happen
114 for key
, wr
in self
.data
.items():
121 for wr
in self
.data
.itervalues():
123 if value
is not None:
127 return self
.data
.iterkeys()
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():
152 key
, wr
= self
.data
.popitem()
157 def pop(self
, key
, *args
):
159 o
= self
.data
.pop(key
)()
169 def setdefault(self
, key
, default
=None):
173 self
.data
[key
] = KeyedRef(default
, self
._remove
, key
)
178 def update(self
, dict=None, **kwargs
):
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
)
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()
202 for wr
in self
.data
.values():
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.
221 def __new__(type, ob
, callback
, key
):
222 self
= ref
.__new
__(type, ob
, callback
)
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
241 def __init__(self
, dict=None):
243 def remove(k
, selfref
=ref(self
)):
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
)]
257 return "<WeakKeyDictionary at %s>" % id(self
)
259 def __setitem__(self
, key
, value
):
260 self
.data
[ref(key
, self
._remove
)] = value
263 new
= WeakKeyDictionary()
264 for key
, value
in self
.data
.items():
272 def __deepcopy__(self
, memo
):
273 from copy
import deepcopy
274 new
= self
.__class
__()
275 for key
, value
in self
.data
.items():
278 new
[o
] = deepcopy(value
, memo
)
281 def get(self
, key
, default
=None):
282 return self
.data
.get(ref(key
),default
)
284 def has_key(self
, key
):
289 return wr
in self
.data
291 def __contains__(self
, key
):
296 return wr
in self
.data
300 for key
, value
in self
.data
.items():
307 for wr
, value
in self
.data
.iteritems():
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()
325 for wr
in self
.data
.iterkeys():
331 return self
.iterkeys()
333 def itervalues(self
):
334 return self
.data
.itervalues()
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()
350 for wr
in self
.data
.keys():
358 key
, value
= self
.data
.popitem()
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
):
372 if not hasattr(dict, "items"):
373 dict = type({})(dict)
374 for key
, value
in dict.items():
375 d
[ref(key
, self
._remove
)] = value