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 \
24 ProxyTypes
= (ProxyType
, CallableProxyType
)
26 __all__
= ["ref", "proxy", "getweakrefcount", "getweakrefs",
27 "WeakKeyDictionary", "ReferenceType", "ProxyType",
28 "CallableProxyType", "ProxyTypes", "WeakValueDictionary"]
31 class WeakValueDictionary(UserDict
.UserDict
):
32 """Mapping class that references values weakly.
34 Entries in the dictionary will be discarded when no strong
35 reference to the value exists anymore
37 # We inherit the constructor without worrying about the input
38 # dictionary; since it uses our .update() method, we get the right
39 # checks (if the other dictionary is a WeakValueDictionary,
40 # objects are unwrapped on the way out, and we always wrap on the
43 def __getitem__(self
, key
):
51 return "<WeakValueDictionary at %s>" % id(self
)
53 def __setitem__(self
, key
, value
):
54 def remove(o
, data
=self
.data
, key
=key
):
56 self
.data
[key
] = ref(value
, remove
)
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 def remove(o
, data
=self
.data
, key
=key
):
110 self
.data
[key
] = ref(default
, remove
)
115 def update(self
, dict):
117 for key
, o
in dict.items():
118 def remove(o
, data
=d
, key
=key
):
120 d
[key
] = ref(o
, remove
)
124 for wr
in self
.data
.values():
131 class WeakKeyDictionary(UserDict
.UserDict
):
132 """ Mapping class that references keys weakly.
134 Entries in the dictionary will be discarded when there is no
135 longer a strong reference to the key. This can be used to
136 associate additional data with an object owned by other parts of
137 an application without adding attributes to those objects. This
138 can be especially useful with objects that override attribute
142 def __init__(self
, dict=None):
144 if dict is not None: self
.update(dict)
145 def remove(k
, data
=self
.data
):
147 self
._remove
= remove
149 def __getitem__(self
, key
):
150 return self
.data
[ref(key
)]
153 return "<WeakKeyDictionary at %s>" % id(self
)
155 def __setitem__(self
, key
, value
):
156 self
.data
[ref(key
, self
._remove
)] = value
159 new
= WeakKeyDictionary()
160 for key
, value
in self
.data
.items():
166 def get(self
, key
, default
=None):
167 return self
.data
.get(ref(key
),default
)
169 def has_key(self
, key
):
170 return self
.data
.has_key(ref(key
))
174 for key
, value
in self
.data
.items():
181 return WeakKeyedItemIterator(self
)
184 return WeakKeyedKeyIterator(self
)
187 def itervalues(self
):
188 return self
.data
.itervalues()
192 for wr
in self
.data
.keys():
200 key
, value
= self
.data
.popitem()
205 def setdefault(self
, key
, default
):
206 return self
.data
.setdefault(ref(key
, self
._remove
),default
)
208 def update(self
, dict):
210 for key
, value
in dict.items():
211 d
[ref(key
, self
._remove
)] = value
219 class WeakKeyedKeyIterator(BaseIter
):
220 def __init__(self
, weakdict
):
221 self
._next
= weakdict
.data
.iterkeys().next
231 class WeakKeyedItemIterator(BaseIter
):
232 def __init__(self
, weakdict
):
233 self
._next
= weakdict
.data
.iteritems().next
237 wr
, value
= self
._next
()
243 class WeakValuedValueIterator(BaseIter
):
244 def __init__(self
, weakdict
):
245 self
._next
= weakdict
.data
.itervalues().next
255 class WeakValuedItemIterator(BaseIter
):
256 def __init__(self
, weakdict
):
257 self
._next
= weakdict
.data
.iteritems().next
261 key
, wr
= self
._next
()
263 if value
is not None: