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.
12 from _weakref
import (
21 from _weakrefset
import WeakSet
23 import collections
# Import after _weakref to avoid circular import.
25 ProxyTypes
= (ProxyType
, CallableProxyType
)
27 __all__
= ["ref", "proxy", "getweakrefcount", "getweakrefs",
28 "WeakKeyDictionary", "ReferenceType", "ProxyType",
29 "CallableProxyType", "ProxyTypes", "WeakValueDictionary",
33 class WeakValueDictionary(collections
.MutableMapping
):
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
)):
54 def __getitem__(self
, key
):
61 def __delitem__(self
, key
):
65 return sum(wr() is not None for wr
in self
.data
.values())
67 def __contains__(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():
88 def get(self
, key
, default
=None):
96 # This should only happen
103 for key
, wr
in self
.data
.items():
110 for wr
in self
.data
.values():
112 if value
is not None:
116 return iter(self
.data
.keys())
119 return iter(self
.data
.keys())
121 def itervaluerefs(self
):
122 """Return an iterator that yields the weak references to the values.
124 The references are not guaranteed to be 'live' at the time
125 they are used, so the result of calling the references needs
126 to be checked before being used. This can be used to avoid
127 creating references that will cause the garbage collector to
128 keep the values around longer than needed.
131 return self
.data
.values()
134 for wr
in self
.data
.values():
141 key
, wr
= self
.data
.popitem()
146 def pop(self
, key
, *args
):
148 o
= self
.data
.pop(key
)()
158 def setdefault(self
, key
, default
=None):
162 self
.data
[key
] = KeyedRef(default
, self
._remove
, key
)
167 def update(self
, dict=None, **kwargs
):
170 if not hasattr(dict, "items"):
171 dict = type({})(dict)
172 for key
, o
in dict.items():
173 d
[key
] = KeyedRef(o
, self
._remove
, key
)
178 """Return a list of weak references to the values.
180 The references are not guaranteed to be 'live' at the time
181 they are used, so the result of calling the references needs
182 to be checked before being used. This can be used to avoid
183 creating references that will cause the garbage collector to
184 keep the values around longer than needed.
187 return self
.data
.values()
191 """Specialized reference that includes a key corresponding to the value.
193 This is used in the WeakValueDictionary to avoid having to create
194 a function object for each key stored in the mapping. A shared
195 callback object can use the 'key' attribute of a KeyedRef instead
196 of getting a reference to the key from an enclosing scope.
202 def __new__(type, ob
, callback
, key
):
203 self
= ref
.__new
__(type, ob
, callback
)
207 def __init__(self
, ob
, callback
, key
):
208 super().__init
__(ob
, callback
)
211 class WeakKeyDictionary(collections
.MutableMapping
):
212 """ Mapping class that references keys weakly.
214 Entries in the dictionary will be discarded when there is no
215 longer a strong reference to the key. This can be used to
216 associate additional data with an object owned by other parts of
217 an application without adding attributes to those objects. This
218 can be especially useful with objects that override attribute
222 def __init__(self
, dict=None):
224 def remove(k
, selfref
=ref(self
)):
228 self
._remove
= remove
229 if dict is not None: self
.update(dict)
231 def __delitem__(self
, key
):
232 del self
.data
[ref(key
)]
234 def __getitem__(self
, key
):
235 return self
.data
[ref(key
)]
238 return len(self
.data
)
241 return "<WeakKeyDictionary at %s>" % id(self
)
243 def __setitem__(self
, key
, value
):
244 self
.data
[ref(key
, self
._remove
)] = value
247 new
= WeakKeyDictionary()
248 for key
, value
in self
.data
.items():
254 def get(self
, key
, default
=None):
255 return self
.data
.get(ref(key
),default
)
257 def __contains__(self
, key
):
262 return wr
in self
.data
265 for wr
, value
in self
.data
.items():
271 """Return an iterator that yields the weak references to the keys.
273 The references are not guaranteed to be 'live' at the time
274 they are used, so the result of calling the references needs
275 to be checked before being used. This can be used to avoid
276 creating references that will cause the garbage collector to
277 keep the keys around longer than needed.
280 return self
.data
.keys()
283 for wr
in self
.data
.keys():
289 return iter(self
.keys())
292 return iter(self
.data
.values())
295 """Return a list of weak references to the keys.
297 The references are not guaranteed to be 'live' at the time
298 they are used, so the result of calling the references needs
299 to be checked before being used. This can be used to avoid
300 creating references that will cause the garbage collector to
301 keep the keys around longer than needed.
304 return self
.data
.keys()
308 key
, value
= self
.data
.popitem()
313 def pop(self
, key
, *args
):
314 return self
.data
.pop(ref(key
), *args
)
316 def setdefault(self
, key
, default
=None):
317 return self
.data
.setdefault(ref(key
, self
._remove
),default
)
319 def update(self
, dict=None, **kwargs
):
322 if not hasattr(dict, "items"):
323 dict = type({})(dict)
324 for key
, value
in dict.items():
325 d
[ref(key
, self
._remove
)] = value