blob: 787c8851dd3d3453e75511051358c4f16f74c49e [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
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +000023from _weakrefset import WeakSet, _IterationGuard
Michael Foorde6410c52010-03-29 20:04:23 +000024
Fred Drakee0292422001-10-05 21:54:09 +000025from exceptions import ReferenceError
26
27
Fred Drake41deb1e2001-02-01 05:27:45 +000028ProxyTypes = (ProxyType, CallableProxyType)
29
Fred Drake9a9d2192001-04-10 19:11:23 +000030__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
Brett Cannon88f801d2008-08-18 00:46:22 +000031 "WeakKeyDictionary", "ReferenceError", "ReferenceType", "ProxyType",
Michael Foorde6410c52010-03-29 20:04:23 +000032 "CallableProxyType", "ProxyTypes", "WeakValueDictionary", 'WeakSet']
Fred Drake41deb1e2001-02-01 05:27:45 +000033
Fred Drake41deb1e2001-02-01 05:27:45 +000034
Fred Drakebd7f8182001-04-19 16:26:06 +000035class WeakValueDictionary(UserDict.UserDict):
36 """Mapping class that references values weakly.
37
38 Entries in the dictionary will be discarded when no strong
39 reference to the value exists anymore
40 """
Fred Drake41deb1e2001-02-01 05:27:45 +000041 # We inherit the constructor without worrying about the input
42 # dictionary; since it uses our .update() method, we get the right
Fred Drake9d2c85d2001-03-01 03:06:03 +000043 # checks (if the other dictionary is a WeakValueDictionary,
44 # objects are unwrapped on the way out, and we always wrap on the
45 # way in).
Fred Drake41deb1e2001-02-01 05:27:45 +000046
Fred Drake0a4dd392004-07-02 18:57:45 +000047 def __init__(self, *args, **kw):
Fred Drake0a4dd392004-07-02 18:57:45 +000048 def remove(wr, selfref=ref(self)):
49 self = selfref()
50 if self is not None:
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +000051 if self._iterating:
52 self._pending_removals.append(wr.key)
53 else:
54 del self.data[wr.key]
Fred Drake0a4dd392004-07-02 18:57:45 +000055 self._remove = remove
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +000056 # A list of keys to be removed
57 self._pending_removals = []
58 self._iterating = set()
Georg Brandl9166e1a2005-06-04 09:20:03 +000059 UserDict.UserDict.__init__(self, *args, **kw)
Fred Drake0a4dd392004-07-02 18:57:45 +000060
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +000061 def _commit_removals(self):
62 l = self._pending_removals
63 d = self.data
64 # We shouldn't encounter any KeyError, because this method should
65 # always be called *before* mutating the dict.
66 while l:
67 del d[l.pop()]
68
Fred Drake41deb1e2001-02-01 05:27:45 +000069 def __getitem__(self, key):
Fred Drake4fd06e02001-08-03 04:11:27 +000070 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +000071 if o is None:
72 raise KeyError, key
73 else:
74 return o
75
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +000076 def __delitem__(self, key):
77 if self._pending_removals:
78 self._commit_removals()
79 del self.data[key]
80
Raymond Hettinger61146792004-08-19 21:32:06 +000081 def __contains__(self, key):
82 try:
83 o = self.data[key]()
84 except KeyError:
85 return False
86 return o is not None
87
88 def has_key(self, key):
89 try:
90 o = self.data[key]()
91 except KeyError:
92 return False
93 return o is not None
94
Fred Drake41deb1e2001-02-01 05:27:45 +000095 def __repr__(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000096 return "<WeakValueDictionary at %s>" % id(self)
Fred Drake41deb1e2001-02-01 05:27:45 +000097
98 def __setitem__(self, key, value):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +000099 if self._pending_removals:
100 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +0000101 self.data[key] = KeyedRef(value, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000102
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000103 def clear(self):
104 if self._pending_removals:
105 self._commit_removals()
106 self.data.clear()
107
Fred Drake41deb1e2001-02-01 05:27:45 +0000108 def copy(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +0000109 new = WeakValueDictionary()
Fred Drakebd7f8182001-04-19 16:26:06 +0000110 for key, wr in self.data.items():
111 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000112 if o is not None:
113 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +0000114 return new
Fred Drake41deb1e2001-02-01 05:27:45 +0000115
Antoine Pitrou775fd662009-05-15 16:54:52 +0000116 __copy__ = copy
117
118 def __deepcopy__(self, memo):
119 from copy import deepcopy
120 new = self.__class__()
121 for key, wr in self.data.items():
122 o = wr()
123 if o is not None:
124 new[deepcopy(key, memo)] = o
125 return new
126
Fred Drake1d9e4b72001-04-16 17:34:48 +0000127 def get(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000128 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000129 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000130 except KeyError:
131 return default
132 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000133 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000134 if o is None:
135 # This should only happen
136 return default
137 else:
138 return o
139
140 def items(self):
Fred Drake312a5dc2001-02-02 15:13:24 +0000141 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000142 for key, wr in self.data.items():
143 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000144 if o is not None:
Fred Drake312a5dc2001-02-02 15:13:24 +0000145 L.append((key, o))
Fred Drake41deb1e2001-02-01 05:27:45 +0000146 return L
147
Fred Drake101209d2001-05-02 05:43:09 +0000148 def iteritems(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000149 with _IterationGuard(self):
150 for wr in self.data.itervalues():
151 value = wr()
152 if value is not None:
153 yield wr.key, value
Fred Drake101209d2001-05-02 05:43:09 +0000154
155 def iterkeys(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000156 with _IterationGuard(self):
157 for k in self.data.iterkeys():
158 yield k
Raymond Hettinger61146792004-08-19 21:32:06 +0000159
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000160 __iter__ = iterkeys
Fred Drake101209d2001-05-02 05:43:09 +0000161
Fred Drake017e68c2006-05-02 06:53:59 +0000162 def itervaluerefs(self):
163 """Return an iterator that yields the weak references to the values.
164
165 The references are not guaranteed to be 'live' at the time
166 they are used, so the result of calling the references needs
167 to be checked before being used. This can be used to avoid
168 creating references that will cause the garbage collector to
169 keep the values around longer than needed.
170
171 """
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000172 with _IterationGuard(self):
173 for wr in self.data.itervalues():
174 yield wr
Fred Drake017e68c2006-05-02 06:53:59 +0000175
Fred Drake101209d2001-05-02 05:43:09 +0000176 def itervalues(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000177 with _IterationGuard(self):
178 for wr in self.data.itervalues():
179 obj = wr()
180 if obj is not None:
181 yield obj
Fred Drake101209d2001-05-02 05:43:09 +0000182
Fred Drake41deb1e2001-02-01 05:27:45 +0000183 def popitem(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000184 if self._pending_removals:
185 self._commit_removals()
Fred Drake41deb1e2001-02-01 05:27:45 +0000186 while 1:
Fred Drakebd7f8182001-04-19 16:26:06 +0000187 key, wr = self.data.popitem()
188 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000189 if o is not None:
190 return key, o
191
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000192 def pop(self, key, *args):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000193 if self._pending_removals:
194 self._commit_removals()
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000195 try:
196 o = self.data.pop(key)()
197 except KeyError:
198 if args:
199 return args[0]
200 raise
201 if o is None:
202 raise KeyError, key
203 else:
204 return o
205
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000206 def setdefault(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000207 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000208 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000209 except KeyError:
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000210 if self._pending_removals:
211 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +0000212 self.data[key] = KeyedRef(default, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000213 return default
214 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000215 return wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000216
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000217 def update(self, dict=None, **kwargs):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000218 if self._pending_removals:
219 self._commit_removals()
Fred Drake41deb1e2001-02-01 05:27:45 +0000220 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000221 if dict is not None:
222 if not hasattr(dict, "items"):
223 dict = type({})(dict)
224 for key, o in dict.items():
Fred Drake0a4dd392004-07-02 18:57:45 +0000225 d[key] = KeyedRef(o, self._remove, key)
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000226 if len(kwargs):
227 self.update(kwargs)
Fred Drake41deb1e2001-02-01 05:27:45 +0000228
Fred Drake017e68c2006-05-02 06:53:59 +0000229 def valuerefs(self):
230 """Return a list of weak references to the values.
231
232 The references are not guaranteed to be 'live' at the time
233 they are used, so the result of calling the references needs
234 to be checked before being used. This can be used to avoid
235 creating references that will cause the garbage collector to
236 keep the values around longer than needed.
237
238 """
239 return self.data.values()
240
Fred Drake41deb1e2001-02-01 05:27:45 +0000241 def values(self):
242 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000243 for wr in self.data.values():
244 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000245 if o is not None:
246 L.append(o)
247 return L
248
Fred Drake0a4dd392004-07-02 18:57:45 +0000249
250class KeyedRef(ref):
251 """Specialized reference that includes a key corresponding to the value.
252
253 This is used in the WeakValueDictionary to avoid having to create
254 a function object for each key stored in the mapping. A shared
255 callback object can use the 'key' attribute of a KeyedRef instead
256 of getting a reference to the key from an enclosing scope.
257
258 """
259
260 __slots__ = "key",
261
262 def __new__(type, ob, callback, key):
263 self = ref.__new__(type, ob, callback)
264 self.key = key
265 return self
266
267 def __init__(self, ob, callback, key):
268 super(KeyedRef, self).__init__(ob, callback)
Fred Drake746fe0f2001-09-28 19:01:26 +0000269
Fred Drake41deb1e2001-02-01 05:27:45 +0000270
Martin v. Löwis5e163332001-02-27 18:36:56 +0000271class WeakKeyDictionary(UserDict.UserDict):
Fred Drakebd7f8182001-04-19 16:26:06 +0000272 """ Mapping class that references keys weakly.
273
274 Entries in the dictionary will be discarded when there is no
275 longer a strong reference to the key. This can be used to
276 associate additional data with an object owned by other parts of
277 an application without adding attributes to those objects. This
278 can be especially useful with objects that override attribute
279 accesses.
280 """
Martin v. Löwis5e163332001-02-27 18:36:56 +0000281
282 def __init__(self, dict=None):
283 self.data = {}
Fred Drake746fe0f2001-09-28 19:01:26 +0000284 def remove(k, selfref=ref(self)):
285 self = selfref()
286 if self is not None:
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000287 if self._iterating:
288 self._pending_removals.append(k)
289 else:
290 del self.data[k]
Martin v. Löwis5e163332001-02-27 18:36:56 +0000291 self._remove = remove
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000292 # A list of dead weakrefs (keys to be removed)
293 self._pending_removals = []
294 self._iterating = set()
295 if dict is not None:
296 self.update(dict)
297
298 def _commit_removals(self):
299 # NOTE: We don't need to call this method before mutating the dict,
300 # because a dead weakref never compares equal to a live weakref,
301 # even if they happened to refer to equal objects.
302 # However, it means keys may already have been removed.
303 l = self._pending_removals
304 d = self.data
305 while l:
306 try:
307 del d[l.pop()]
308 except KeyError:
309 pass
Martin v. Löwis5e163332001-02-27 18:36:56 +0000310
Fred Drakeb663a2c2001-09-06 14:51:01 +0000311 def __delitem__(self, key):
Tim Peters886128f2003-05-25 01:45:11 +0000312 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000313
Martin v. Löwis5e163332001-02-27 18:36:56 +0000314 def __getitem__(self, key):
315 return self.data[ref(key)]
316
317 def __repr__(self):
318 return "<WeakKeyDictionary at %s>" % id(self)
319
320 def __setitem__(self, key, value):
321 self.data[ref(key, self._remove)] = value
322
323 def copy(self):
324 new = WeakKeyDictionary()
325 for key, value in self.data.items():
326 o = key()
327 if o is not None:
328 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000329 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000330
Antoine Pitrou775fd662009-05-15 16:54:52 +0000331 __copy__ = copy
332
333 def __deepcopy__(self, memo):
334 from copy import deepcopy
335 new = self.__class__()
336 for key, value in self.data.items():
337 o = key()
338 if o is not None:
339 new[o] = deepcopy(value, memo)
340 return new
341
Fred Drake1d9e4b72001-04-16 17:34:48 +0000342 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000343 return self.data.get(ref(key),default)
344
Fred Drake1d9e4b72001-04-16 17:34:48 +0000345 def has_key(self, key):
Fred Drake3bae7dd2001-11-06 16:36:53 +0000346 try:
347 wr = ref(key)
348 except TypeError:
349 return 0
Raymond Hettinger54f02222002-06-01 14:18:47 +0000350 return wr in self.data
Fred Drake1d9e4b72001-04-16 17:34:48 +0000351
Raymond Hettinger54f02222002-06-01 14:18:47 +0000352 def __contains__(self, key):
353 try:
354 wr = ref(key)
355 except TypeError:
356 return 0
357 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000358
Martin v. Löwis5e163332001-02-27 18:36:56 +0000359 def items(self):
360 L = []
361 for key, value in self.data.items():
362 o = key()
363 if o is not None:
364 L.append((o, value))
365 return L
366
Fred Drake101209d2001-05-02 05:43:09 +0000367 def iteritems(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000368 with _IterationGuard(self):
369 for wr, value in self.data.iteritems():
370 key = wr()
371 if key is not None:
372 yield key, value
Fred Drake101209d2001-05-02 05:43:09 +0000373
Fred Drake017e68c2006-05-02 06:53:59 +0000374 def iterkeyrefs(self):
375 """Return an iterator that yields the weak references to the keys.
376
377 The references are not guaranteed to be 'live' at the time
378 they are used, so the result of calling the references needs
379 to be checked before being used. This can be used to avoid
380 creating references that will cause the garbage collector to
381 keep the keys around longer than needed.
382
383 """
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000384 with _IterationGuard(self):
385 for wr in self.data.iterkeys():
386 yield wr
Fred Drake017e68c2006-05-02 06:53:59 +0000387
Fred Drake101209d2001-05-02 05:43:09 +0000388 def iterkeys(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000389 with _IterationGuard(self):
390 for wr in self.data.iterkeys():
391 obj = wr()
392 if obj is not None:
393 yield obj
Raymond Hettinger61146792004-08-19 21:32:06 +0000394
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000395 __iter__ = iterkeys
Fred Drake101209d2001-05-02 05:43:09 +0000396
397 def itervalues(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000398 with _IterationGuard(self):
399 for value in self.data.itervalues():
400 yield value
Fred Drake101209d2001-05-02 05:43:09 +0000401
Fred Drake017e68c2006-05-02 06:53:59 +0000402 def keyrefs(self):
403 """Return a list of weak references to the keys.
404
405 The references are not guaranteed to be 'live' at the time
406 they are used, so the result of calling the references needs
407 to be checked before being used. This can be used to avoid
408 creating references that will cause the garbage collector to
409 keep the keys around longer than needed.
410
411 """
412 return self.data.keys()
413
Fred Drake1d9e4b72001-04-16 17:34:48 +0000414 def keys(self):
415 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000416 for wr in self.data.keys():
417 o = wr()
Fred Drake1d9e4b72001-04-16 17:34:48 +0000418 if o is not None:
419 L.append(o)
420 return L
421
Martin v. Löwis5e163332001-02-27 18:36:56 +0000422 def popitem(self):
423 while 1:
424 key, value = self.data.popitem()
425 o = key()
426 if o is not None:
427 return o, value
428
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000429 def pop(self, key, *args):
430 return self.data.pop(ref(key), *args)
431
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000432 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000433 return self.data.setdefault(ref(key, self._remove),default)
434
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000435 def update(self, dict=None, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000436 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000437 if dict is not None:
438 if not hasattr(dict, "items"):
439 dict = type({})(dict)
440 for key, value in dict.items():
441 d[ref(key, self._remove)] = value
442 if len(kwargs):
443 self.update(kwargs)