1 """Weak reference support for Python.
3 This module is an implementation of PEP 205:
5 http://python.sourceforge.net/peps/pep-0205.html
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", "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 __getitem__(self
, key
):
53 return "<WeakValueDictionary at %s>" % id(self
)
55 def __setitem__(self
, key
, value
):
56 self
.data
[key
] = ref(value
, self
.__makeremove
(key
))
59 new
= WeakValueDictionary()
60 for key
, wr
in self
.data
.items():
66 def get(self
, key
, default
=None):
74 # This should only happen
81 for key
, wr
in self
.data
.items():
88 return WeakValuedItemIterator(self
)
91 return self
.data
.iterkeys()
95 return WeakValuedValueIterator(self
)
99 key
, wr
= self
.data
.popitem()
104 def pop(self
, key
, *args
):
106 o
= self
.data
.pop(key
)()
116 def setdefault(self
, key
, default
):
120 self
.data
[key
] = ref(default
, self
.__makeremove
(key
))
125 def update(self
, dict):
127 for key
, o
in dict.items():
128 d
[key
] = ref(o
, self
.__makeremove
(key
))
132 for wr
in self
.data
.values():
138 def __makeremove(self
, key
):
139 def remove(o
, selfref
=ref(self
), key
=key
):
146 class WeakKeyDictionary(UserDict
.UserDict
):
147 """ Mapping class that references keys weakly.
149 Entries in the dictionary will be discarded when there is no
150 longer a strong reference to the key. This can be used to
151 associate additional data with an object owned by other parts of
152 an application without adding attributes to those objects. This
153 can be especially useful with objects that override attribute
157 def __init__(self
, dict=None):
159 def remove(k
, selfref
=ref(self
)):
163 self
._remove
= remove
164 if dict is not None: self
.update(dict)
166 def __delitem__(self
, key
):
167 for ref
in self
.data
.iterkeys():
173 def __getitem__(self
, key
):
174 return self
.data
[ref(key
)]
177 return "<WeakKeyDictionary at %s>" % id(self
)
179 def __setitem__(self
, key
, value
):
180 self
.data
[ref(key
, self
._remove
)] = value
183 new
= WeakKeyDictionary()
184 for key
, value
in self
.data
.items():
190 def get(self
, key
, default
=None):
191 return self
.data
.get(ref(key
),default
)
193 def has_key(self
, key
):
198 return wr
in self
.data
200 def __contains__(self
, key
):
205 return wr
in self
.data
209 for key
, value
in self
.data
.items():
216 return WeakKeyedItemIterator(self
)
219 return WeakKeyedKeyIterator(self
)
222 def itervalues(self
):
223 return self
.data
.itervalues()
227 for wr
in self
.data
.keys():
235 key
, value
= self
.data
.popitem()
240 def pop(self
, key
, *args
):
241 return self
.data
.pop(ref(key
), *args
)
243 def setdefault(self
, key
, default
):
244 return self
.data
.setdefault(ref(key
, self
._remove
),default
)
246 def update(self
, dict):
248 for key
, value
in dict.items():
249 d
[ref(key
, self
._remove
)] = value
257 class WeakKeyedKeyIterator(BaseIter
):
258 def __init__(self
, weakdict
):
259 self
._next
= weakdict
.data
.iterkeys().next
269 class WeakKeyedItemIterator(BaseIter
):
270 def __init__(self
, weakdict
):
271 self
._next
= weakdict
.data
.iteritems().next
275 wr
, value
= self
._next
()
281 class WeakValuedValueIterator(BaseIter
):
282 def __init__(self
, weakdict
):
283 self
._next
= weakdict
.data
.itervalues().next
293 class WeakValuedItemIterator(BaseIter
):
294 def __init__(self
, weakdict
):
295 self
._next
= weakdict
.data
.iteritems().next
299 key
, wr
= self
._next
()
301 if value
is not None: