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 setdefault(self
, key
, default
):
108 self
.data
[key
] = ref(default
, self
.__makeremove
(key
))
113 def update(self
, dict):
115 for key
, o
in dict.items():
116 d
[key
] = ref(o
, self
.__makeremove
(key
))
120 for wr
in self
.data
.values():
126 def __makeremove(self
, key
):
127 def remove(o
, selfref
=ref(self
), key
=key
):
134 class WeakKeyDictionary(UserDict
.UserDict
):
135 """ Mapping class that references keys weakly.
137 Entries in the dictionary will be discarded when there is no
138 longer a strong reference to the key. This can be used to
139 associate additional data with an object owned by other parts of
140 an application without adding attributes to those objects. This
141 can be especially useful with objects that override attribute
145 def __init__(self
, dict=None):
147 if dict is not None: self
.update(dict)
148 def remove(k
, selfref
=ref(self
)):
152 self
._remove
= remove
154 def __delitem__(self
, key
):
155 for ref
in self
.data
.iterkeys():
161 def __getitem__(self
, key
):
162 return self
.data
[ref(key
)]
165 return "<WeakKeyDictionary at %s>" % id(self
)
167 def __setitem__(self
, key
, value
):
168 self
.data
[ref(key
, self
._remove
)] = value
171 new
= WeakKeyDictionary()
172 for key
, value
in self
.data
.items():
178 def get(self
, key
, default
=None):
179 return self
.data
.get(ref(key
),default
)
181 def has_key(self
, key
):
186 return self
.data
.has_key(wr
)
190 for key
, value
in self
.data
.items():
197 return WeakKeyedItemIterator(self
)
200 return WeakKeyedKeyIterator(self
)
203 def itervalues(self
):
204 return self
.data
.itervalues()
208 for wr
in self
.data
.keys():
216 key
, value
= self
.data
.popitem()
221 def setdefault(self
, key
, default
):
222 return self
.data
.setdefault(ref(key
, self
._remove
),default
)
224 def update(self
, dict):
226 for key
, value
in dict.items():
227 d
[ref(key
, self
._remove
)] = value
235 class WeakKeyedKeyIterator(BaseIter
):
236 def __init__(self
, weakdict
):
237 self
._next
= weakdict
.data
.iterkeys().next
247 class WeakKeyedItemIterator(BaseIter
):
248 def __init__(self
, weakdict
):
249 self
._next
= weakdict
.data
.iteritems().next
253 wr
, value
= self
._next
()
259 class WeakValuedValueIterator(BaseIter
):
260 def __init__(self
, weakdict
):
261 self
._next
= weakdict
.data
.itervalues().next
271 class WeakValuedItemIterator(BaseIter
):
272 def __init__(self
, weakdict
):
273 self
._next
= weakdict
.data
.iteritems().next
277 key
, wr
= self
._next
()
279 if value
is not None: