This commit was manufactured by cvs2svn to create tag 'r22a4-fork'.
[python/dscho.git] / Lib / weakref.py
blobc71d04b85358205d2ea717cb62df4a065cf25417
1 """Weak reference support for Python.
3 This module is an implementation of PEP 205:
5 http://python.sourceforge.net/peps/pep-0205.html
6 """
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 import UserDict
14 from _weakref import \
15 getweakrefcount, \
16 getweakrefs, \
17 ref, \
18 proxy, \
19 ReferenceError, \
20 CallableProxyType, \
21 ProxyType, \
22 ReferenceType
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
36 """
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
41 # way in).
43 def __getitem__(self, key):
44 o = self.data[key]()
45 if o is None:
46 raise KeyError, key
47 else:
48 return o
50 def __repr__(self):
51 return "<WeakValueDictionary at %s>" % id(self)
53 def __setitem__(self, key, value):
54 def remove(o, data=self.data, key=key):
55 del data[key]
56 self.data[key] = ref(value, remove)
58 def copy(self):
59 new = WeakValueDictionary()
60 for key, wr in self.data.items():
61 o = wr()
62 if o is not None:
63 new[key] = o
64 return new
66 def get(self, key, default=None):
67 try:
68 wr = self.data[key]
69 except KeyError:
70 return default
71 else:
72 o = wr()
73 if o is None:
74 # This should only happen
75 return default
76 else:
77 return o
79 def items(self):
80 L = []
81 for key, wr in self.data.items():
82 o = wr()
83 if o is not None:
84 L.append((key, o))
85 return L
87 def iteritems(self):
88 return WeakValuedItemIterator(self)
90 def iterkeys(self):
91 return self.data.iterkeys()
92 __iter__ = iterkeys
94 def itervalues(self):
95 return WeakValuedValueIterator(self)
97 def popitem(self):
98 while 1:
99 key, wr = self.data.popitem()
100 o = wr()
101 if o is not None:
102 return key, o
104 def setdefault(self, key, default):
105 try:
106 wr = self.data[key]
107 except KeyError:
108 def remove(o, data=self.data, key=key):
109 del data[key]
110 self.data[key] = ref(default, remove)
111 return default
112 else:
113 return wr()
115 def update(self, dict):
116 d = self.data
117 for key, o in dict.items():
118 def remove(o, data=d, key=key):
119 del data[key]
120 d[key] = ref(o, remove)
122 def values(self):
123 L = []
124 for wr in self.data.values():
125 o = wr()
126 if o is not None:
127 L.append(o)
128 return L
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
139 accesses.
142 def __init__(self, dict=None):
143 self.data = {}
144 if dict is not None: self.update(dict)
145 def remove(k, data=self.data):
146 del data[k]
147 self._remove = remove
149 def __delitem__(self, key):
150 for ref in self.data.iterkeys():
151 o = ref()
152 if o == key:
153 del self.data[ref]
154 return
156 def __getitem__(self, key):
157 return self.data[ref(key)]
159 def __repr__(self):
160 return "<WeakKeyDictionary at %s>" % id(self)
162 def __setitem__(self, key, value):
163 self.data[ref(key, self._remove)] = value
165 def copy(self):
166 new = WeakKeyDictionary()
167 for key, value in self.data.items():
168 o = key()
169 if o is not None:
170 new[o] = value
171 return new
173 def get(self, key, default=None):
174 return self.data.get(ref(key),default)
176 def has_key(self, key):
177 return self.data.has_key(ref(key))
179 def items(self):
180 L = []
181 for key, value in self.data.items():
182 o = key()
183 if o is not None:
184 L.append((o, value))
185 return L
187 def iteritems(self):
188 return WeakKeyedItemIterator(self)
190 def iterkeys(self):
191 return WeakKeyedKeyIterator(self)
192 __iter__ = iterkeys
194 def itervalues(self):
195 return self.data.itervalues()
197 def keys(self):
198 L = []
199 for wr in self.data.keys():
200 o = wr()
201 if o is not None:
202 L.append(o)
203 return L
205 def popitem(self):
206 while 1:
207 key, value = self.data.popitem()
208 o = key()
209 if o is not None:
210 return o, value
212 def setdefault(self, key, default):
213 return self.data.setdefault(ref(key, self._remove),default)
215 def update(self, dict):
216 d = self.data
217 for key, value in dict.items():
218 d[ref(key, self._remove)] = value
221 class BaseIter:
222 def __iter__(self):
223 return self
226 class WeakKeyedKeyIterator(BaseIter):
227 def __init__(self, weakdict):
228 self._next = weakdict.data.iterkeys().next
230 def next(self):
231 while 1:
232 wr = self._next()
233 obj = wr()
234 if obj is not None:
235 return obj
238 class WeakKeyedItemIterator(BaseIter):
239 def __init__(self, weakdict):
240 self._next = weakdict.data.iteritems().next
242 def next(self):
243 while 1:
244 wr, value = self._next()
245 key = wr()
246 if key is not None:
247 return key, value
250 class WeakValuedValueIterator(BaseIter):
251 def __init__(self, weakdict):
252 self._next = weakdict.data.itervalues().next
254 def next(self):
255 while 1:
256 wr = self._next()
257 obj = wr()
258 if obj is not None:
259 return obj
262 class WeakValuedItemIterator(BaseIter):
263 def __init__(self, weakdict):
264 self._next = weakdict.data.iteritems().next
266 def next(self):
267 while 1:
268 key, wr = self._next()
269 value = wr()
270 if value is not None:
271 return key, value
274 # no longer needed
275 del UserDict