blob: 84d81a27347b55fe922f63f096dd656be1e98cf2 [file] [log] [blame]
Fred Drake41deb1e2001-02-01 05:27:45 +00001"""Weak reference support for Python.
2
3This module is an implementation of PEP 205:
4
Alexandre Vassalottiba08f072008-04-27 00:52:24 +00005http://www.python.org/dev/peps/pep-0205/
Fred Drake41deb1e2001-02-01 05:27:45 +00006"""
7
Fred Drakebd7f8182001-04-19 16:26:06 +00008# 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.
11
Fred Drake41deb1e2001-02-01 05:27:45 +000012import UserDict
13
Andrew M. Kuchling33ad28b2004-08-31 11:38:12 +000014from _weakref import (
15 getweakrefcount,
16 getweakrefs,
17 ref,
18 proxy,
19 CallableProxyType,
20 ProxyType,
21 ReferenceType)
Fred Drake41deb1e2001-02-01 05:27:45 +000022
Fred Drakee0292422001-10-05 21:54:09 +000023from exceptions import ReferenceError
24
25
Fred Drake41deb1e2001-02-01 05:27:45 +000026ProxyTypes = (ProxyType, CallableProxyType)
27
Fred Drake9a9d2192001-04-10 19:11:23 +000028__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
Brett Cannon88f801d2008-08-18 00:46:22 +000029 "WeakKeyDictionary", "ReferenceError", "ReferenceType", "ProxyType",
Skip Montanaro40fc1602001-03-01 04:27:19 +000030 "CallableProxyType", "ProxyTypes", "WeakValueDictionary"]
Fred Drake41deb1e2001-02-01 05:27:45 +000031
Fred Drake41deb1e2001-02-01 05:27:45 +000032
Fred Drakebd7f8182001-04-19 16:26:06 +000033class WeakValueDictionary(UserDict.UserDict):
34 """Mapping class that references values weakly.
35
36 Entries in the dictionary will be discarded when no strong
37 reference to the value exists anymore
38 """
Fred Drake41deb1e2001-02-01 05:27:45 +000039 # We inherit the constructor without worrying about the input
40 # dictionary; since it uses our .update() method, we get the right
Fred Drake9d2c85d2001-03-01 03:06:03 +000041 # checks (if the other dictionary is a WeakValueDictionary,
42 # objects are unwrapped on the way out, and we always wrap on the
43 # way in).
Fred Drake41deb1e2001-02-01 05:27:45 +000044
Fred Drake0a4dd392004-07-02 18:57:45 +000045 def __init__(self, *args, **kw):
Fred Drake0a4dd392004-07-02 18:57:45 +000046 def remove(wr, selfref=ref(self)):
47 self = selfref()
48 if self is not None:
49 del self.data[wr.key]
50 self._remove = remove
Georg Brandl9166e1a2005-06-04 09:20:03 +000051 UserDict.UserDict.__init__(self, *args, **kw)
Fred Drake0a4dd392004-07-02 18:57:45 +000052
Fred Drake41deb1e2001-02-01 05:27:45 +000053 def __getitem__(self, key):
Fred Drake4fd06e02001-08-03 04:11:27 +000054 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +000055 if o is None:
56 raise KeyError, key
57 else:
58 return o
59
Raymond Hettinger61146792004-08-19 21:32:06 +000060 def __contains__(self, key):
61 try:
62 o = self.data[key]()
63 except KeyError:
64 return False
65 return o is not None
66
67 def has_key(self, key):
68 try:
69 o = self.data[key]()
70 except KeyError:
71 return False
72 return o is not None
73
Fred Drake41deb1e2001-02-01 05:27:45 +000074 def __repr__(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000075 return "<WeakValueDictionary at %s>" % id(self)
Fred Drake41deb1e2001-02-01 05:27:45 +000076
77 def __setitem__(self, key, value):
Fred Drake0a4dd392004-07-02 18:57:45 +000078 self.data[key] = KeyedRef(value, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +000079
80 def copy(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000081 new = WeakValueDictionary()
Fred Drakebd7f8182001-04-19 16:26:06 +000082 for key, wr in self.data.items():
83 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +000084 if o is not None:
85 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +000086 return new
Fred Drake41deb1e2001-02-01 05:27:45 +000087
Antoine Pitrou775fd662009-05-15 16:54:52 +000088 __copy__ = copy
89
90 def __deepcopy__(self, memo):
91 from copy import deepcopy
92 new = self.__class__()
93 for key, wr in self.data.items():
94 o = wr()
95 if o is not None:
96 new[deepcopy(key, memo)] = o
97 return new
98
Fred Drake1d9e4b72001-04-16 17:34:48 +000099 def get(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000100 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000101 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000102 except KeyError:
103 return default
104 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000105 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000106 if o is None:
107 # This should only happen
108 return default
109 else:
110 return o
111
112 def items(self):
Fred Drake312a5dc2001-02-02 15:13:24 +0000113 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000114 for key, wr in self.data.items():
115 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000116 if o is not None:
Fred Drake312a5dc2001-02-02 15:13:24 +0000117 L.append((key, o))
Fred Drake41deb1e2001-02-01 05:27:45 +0000118 return L
119
Fred Drake101209d2001-05-02 05:43:09 +0000120 def iteritems(self):
Raymond Hettinger61146792004-08-19 21:32:06 +0000121 for wr in self.data.itervalues():
122 value = wr()
123 if value is not None:
124 yield wr.key, value
Fred Drake101209d2001-05-02 05:43:09 +0000125
126 def iterkeys(self):
127 return self.data.iterkeys()
Raymond Hettinger61146792004-08-19 21:32:06 +0000128
129 def __iter__(self):
130 return self.data.iterkeys()
Fred Drake101209d2001-05-02 05:43:09 +0000131
Fred Drake017e68c2006-05-02 06:53:59 +0000132 def itervaluerefs(self):
133 """Return an iterator that yields the weak references to the values.
134
135 The references are not guaranteed to be 'live' at the time
136 they are used, so the result of calling the references needs
137 to be checked before being used. This can be used to avoid
138 creating references that will cause the garbage collector to
139 keep the values around longer than needed.
140
141 """
142 return self.data.itervalues()
143
Fred Drake101209d2001-05-02 05:43:09 +0000144 def itervalues(self):
Raymond Hettinger61146792004-08-19 21:32:06 +0000145 for wr in self.data.itervalues():
146 obj = wr()
147 if obj is not None:
148 yield obj
Fred Drake101209d2001-05-02 05:43:09 +0000149
Fred Drake41deb1e2001-02-01 05:27:45 +0000150 def popitem(self):
151 while 1:
Fred Drakebd7f8182001-04-19 16:26:06 +0000152 key, wr = self.data.popitem()
153 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000154 if o is not None:
155 return key, o
156
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000157 def pop(self, key, *args):
158 try:
159 o = self.data.pop(key)()
160 except KeyError:
161 if args:
162 return args[0]
163 raise
164 if o is None:
165 raise KeyError, key
166 else:
167 return o
168
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000169 def setdefault(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000170 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000171 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000172 except KeyError:
Fred Drake0a4dd392004-07-02 18:57:45 +0000173 self.data[key] = KeyedRef(default, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000174 return default
175 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000176 return wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000177
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000178 def update(self, dict=None, **kwargs):
Fred Drake41deb1e2001-02-01 05:27:45 +0000179 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000180 if dict is not None:
181 if not hasattr(dict, "items"):
182 dict = type({})(dict)
183 for key, o in dict.items():
Fred Drake0a4dd392004-07-02 18:57:45 +0000184 d[key] = KeyedRef(o, self._remove, key)
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000185 if len(kwargs):
186 self.update(kwargs)
Fred Drake41deb1e2001-02-01 05:27:45 +0000187
Fred Drake017e68c2006-05-02 06:53:59 +0000188 def valuerefs(self):
189 """Return a list of weak references to the values.
190
191 The references are not guaranteed to be 'live' at the time
192 they are used, so the result of calling the references needs
193 to be checked before being used. This can be used to avoid
194 creating references that will cause the garbage collector to
195 keep the values around longer than needed.
196
197 """
198 return self.data.values()
199
Fred Drake41deb1e2001-02-01 05:27:45 +0000200 def values(self):
201 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000202 for wr in self.data.values():
203 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000204 if o is not None:
205 L.append(o)
206 return L
207
Fred Drake0a4dd392004-07-02 18:57:45 +0000208
209class KeyedRef(ref):
210 """Specialized reference that includes a key corresponding to the value.
211
212 This is used in the WeakValueDictionary to avoid having to create
213 a function object for each key stored in the mapping. A shared
214 callback object can use the 'key' attribute of a KeyedRef instead
215 of getting a reference to the key from an enclosing scope.
216
217 """
218
219 __slots__ = "key",
220
221 def __new__(type, ob, callback, key):
222 self = ref.__new__(type, ob, callback)
223 self.key = key
224 return self
225
226 def __init__(self, ob, callback, key):
227 super(KeyedRef, self).__init__(ob, callback)
Fred Drake746fe0f2001-09-28 19:01:26 +0000228
Fred Drake41deb1e2001-02-01 05:27:45 +0000229
Martin v. Löwis5e163332001-02-27 18:36:56 +0000230class WeakKeyDictionary(UserDict.UserDict):
Fred Drakebd7f8182001-04-19 16:26:06 +0000231 """ Mapping class that references keys weakly.
232
233 Entries in the dictionary will be discarded when there is no
234 longer a strong reference to the key. This can be used to
235 associate additional data with an object owned by other parts of
236 an application without adding attributes to those objects. This
237 can be especially useful with objects that override attribute
238 accesses.
239 """
Martin v. Löwis5e163332001-02-27 18:36:56 +0000240
241 def __init__(self, dict=None):
242 self.data = {}
Fred Drake746fe0f2001-09-28 19:01:26 +0000243 def remove(k, selfref=ref(self)):
244 self = selfref()
245 if self is not None:
246 del self.data[k]
Martin v. Löwis5e163332001-02-27 18:36:56 +0000247 self._remove = remove
Guido van Rossum009afb72002-06-10 20:00:52 +0000248 if dict is not None: self.update(dict)
Martin v. Löwis5e163332001-02-27 18:36:56 +0000249
Fred Drakeb663a2c2001-09-06 14:51:01 +0000250 def __delitem__(self, key):
Tim Peters886128f2003-05-25 01:45:11 +0000251 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000252
Martin v. Löwis5e163332001-02-27 18:36:56 +0000253 def __getitem__(self, key):
254 return self.data[ref(key)]
255
256 def __repr__(self):
257 return "<WeakKeyDictionary at %s>" % id(self)
258
259 def __setitem__(self, key, value):
260 self.data[ref(key, self._remove)] = value
261
262 def copy(self):
263 new = WeakKeyDictionary()
264 for key, value in self.data.items():
265 o = key()
266 if o is not None:
267 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000268 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000269
Antoine Pitrou775fd662009-05-15 16:54:52 +0000270 __copy__ = copy
271
272 def __deepcopy__(self, memo):
273 from copy import deepcopy
274 new = self.__class__()
275 for key, value in self.data.items():
276 o = key()
277 if o is not None:
278 new[o] = deepcopy(value, memo)
279 return new
280
Fred Drake1d9e4b72001-04-16 17:34:48 +0000281 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000282 return self.data.get(ref(key),default)
283
Fred Drake1d9e4b72001-04-16 17:34:48 +0000284 def has_key(self, key):
Fred Drake3bae7dd2001-11-06 16:36:53 +0000285 try:
286 wr = ref(key)
287 except TypeError:
288 return 0
Raymond Hettinger54f02222002-06-01 14:18:47 +0000289 return wr in self.data
Fred Drake1d9e4b72001-04-16 17:34:48 +0000290
Raymond Hettinger54f02222002-06-01 14:18:47 +0000291 def __contains__(self, key):
292 try:
293 wr = ref(key)
294 except TypeError:
295 return 0
296 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000297
Martin v. Löwis5e163332001-02-27 18:36:56 +0000298 def items(self):
299 L = []
300 for key, value in self.data.items():
301 o = key()
302 if o is not None:
303 L.append((o, value))
304 return L
305
Fred Drake101209d2001-05-02 05:43:09 +0000306 def iteritems(self):
Raymond Hettinger61146792004-08-19 21:32:06 +0000307 for wr, value in self.data.iteritems():
308 key = wr()
309 if key is not None:
310 yield key, value
Fred Drake101209d2001-05-02 05:43:09 +0000311
Fred Drake017e68c2006-05-02 06:53:59 +0000312 def iterkeyrefs(self):
313 """Return an iterator that yields the weak references to the keys.
314
315 The references are not guaranteed to be 'live' at the time
316 they are used, so the result of calling the references needs
317 to be checked before being used. This can be used to avoid
318 creating references that will cause the garbage collector to
319 keep the keys around longer than needed.
320
321 """
322 return self.data.iterkeys()
323
Fred Drake101209d2001-05-02 05:43:09 +0000324 def iterkeys(self):
Raymond Hettinger61146792004-08-19 21:32:06 +0000325 for wr in self.data.iterkeys():
326 obj = wr()
327 if obj is not None:
328 yield obj
329
330 def __iter__(self):
331 return self.iterkeys()
Fred Drake101209d2001-05-02 05:43:09 +0000332
333 def itervalues(self):
334 return self.data.itervalues()
335
Fred Drake017e68c2006-05-02 06:53:59 +0000336 def keyrefs(self):
337 """Return a list of weak references to the keys.
338
339 The references are not guaranteed to be 'live' at the time
340 they are used, so the result of calling the references needs
341 to be checked before being used. This can be used to avoid
342 creating references that will cause the garbage collector to
343 keep the keys around longer than needed.
344
345 """
346 return self.data.keys()
347
Fred Drake1d9e4b72001-04-16 17:34:48 +0000348 def keys(self):
349 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000350 for wr in self.data.keys():
351 o = wr()
Fred Drake1d9e4b72001-04-16 17:34:48 +0000352 if o is not None:
353 L.append(o)
354 return L
355
Martin v. Löwis5e163332001-02-27 18:36:56 +0000356 def popitem(self):
357 while 1:
358 key, value = self.data.popitem()
359 o = key()
360 if o is not None:
361 return o, value
362
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000363 def pop(self, key, *args):
364 return self.data.pop(ref(key), *args)
365
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000366 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000367 return self.data.setdefault(ref(key, self._remove),default)
368
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000369 def update(self, dict=None, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000370 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000371 if dict is not None:
372 if not hasattr(dict, "items"):
373 dict = type({})(dict)
374 for key, value in dict.items():
375 d[ref(key, self._remove)] = value
376 if len(kwargs):
377 self.update(kwargs)