blob: def955f72dd34ea6f5f56326b8efc758a4650bfc [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
Serhiy Storchakaf522bbc2015-09-29 23:51:27 +030047 def __init__(*args, **kw):
48 if not args:
49 raise TypeError("descriptor '__init__' of 'WeakValueDictionary' "
50 "object needs an argument")
51 self = args[0]
52 args = args[1:]
53 if len(args) > 1:
54 raise TypeError('expected at most 1 arguments, got %d' % len(args))
Fred Drake0a4dd392004-07-02 18:57:45 +000055 def remove(wr, selfref=ref(self)):
56 self = selfref()
57 if self is not None:
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +000058 if self._iterating:
59 self._pending_removals.append(wr.key)
60 else:
61 del self.data[wr.key]
Fred Drake0a4dd392004-07-02 18:57:45 +000062 self._remove = remove
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +000063 # A list of keys to be removed
64 self._pending_removals = []
65 self._iterating = set()
Georg Brandl9166e1a2005-06-04 09:20:03 +000066 UserDict.UserDict.__init__(self, *args, **kw)
Fred Drake0a4dd392004-07-02 18:57:45 +000067
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +000068 def _commit_removals(self):
69 l = self._pending_removals
70 d = self.data
71 # We shouldn't encounter any KeyError, because this method should
72 # always be called *before* mutating the dict.
73 while l:
74 del d[l.pop()]
75
Fred Drake41deb1e2001-02-01 05:27:45 +000076 def __getitem__(self, key):
Fred Drake4fd06e02001-08-03 04:11:27 +000077 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +000078 if o is None:
79 raise KeyError, key
80 else:
81 return o
82
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +000083 def __delitem__(self, key):
84 if self._pending_removals:
85 self._commit_removals()
86 del self.data[key]
87
Raymond Hettinger61146792004-08-19 21:32:06 +000088 def __contains__(self, key):
89 try:
90 o = self.data[key]()
91 except KeyError:
92 return False
93 return o is not None
94
95 def has_key(self, key):
96 try:
97 o = self.data[key]()
98 except KeyError:
99 return False
100 return o is not None
101
Fred Drake41deb1e2001-02-01 05:27:45 +0000102 def __repr__(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +0000103 return "<WeakValueDictionary at %s>" % id(self)
Fred Drake41deb1e2001-02-01 05:27:45 +0000104
105 def __setitem__(self, key, value):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000106 if self._pending_removals:
107 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +0000108 self.data[key] = KeyedRef(value, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000109
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000110 def clear(self):
111 if self._pending_removals:
112 self._commit_removals()
113 self.data.clear()
114
Fred Drake41deb1e2001-02-01 05:27:45 +0000115 def copy(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +0000116 new = WeakValueDictionary()
Fred Drakebd7f8182001-04-19 16:26:06 +0000117 for key, wr in self.data.items():
118 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000119 if o is not None:
120 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +0000121 return new
Fred Drake41deb1e2001-02-01 05:27:45 +0000122
Antoine Pitrou775fd662009-05-15 16:54:52 +0000123 __copy__ = copy
124
125 def __deepcopy__(self, memo):
126 from copy import deepcopy
127 new = self.__class__()
128 for key, wr in self.data.items():
129 o = wr()
130 if o is not None:
131 new[deepcopy(key, memo)] = o
132 return new
133
Fred Drake1d9e4b72001-04-16 17:34:48 +0000134 def get(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000135 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000136 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000137 except KeyError:
138 return default
139 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000140 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000141 if o is None:
142 # This should only happen
143 return default
144 else:
145 return o
146
147 def items(self):
Fred Drake312a5dc2001-02-02 15:13:24 +0000148 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000149 for key, wr in self.data.items():
150 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000151 if o is not None:
Fred Drake312a5dc2001-02-02 15:13:24 +0000152 L.append((key, o))
Fred Drake41deb1e2001-02-01 05:27:45 +0000153 return L
154
Fred Drake101209d2001-05-02 05:43:09 +0000155 def iteritems(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000156 with _IterationGuard(self):
157 for wr in self.data.itervalues():
158 value = wr()
159 if value is not None:
160 yield wr.key, value
Fred Drake101209d2001-05-02 05:43:09 +0000161
162 def iterkeys(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000163 with _IterationGuard(self):
164 for k in self.data.iterkeys():
165 yield k
Raymond Hettinger61146792004-08-19 21:32:06 +0000166
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000167 __iter__ = iterkeys
Fred Drake101209d2001-05-02 05:43:09 +0000168
Fred Drake017e68c2006-05-02 06:53:59 +0000169 def itervaluerefs(self):
170 """Return an iterator that yields the weak references to the values.
171
172 The references are not guaranteed to be 'live' at the time
173 they are used, so the result of calling the references needs
174 to be checked before being used. This can be used to avoid
175 creating references that will cause the garbage collector to
176 keep the values around longer than needed.
177
178 """
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000179 with _IterationGuard(self):
180 for wr in self.data.itervalues():
181 yield wr
Fred Drake017e68c2006-05-02 06:53:59 +0000182
Fred Drake101209d2001-05-02 05:43:09 +0000183 def itervalues(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000184 with _IterationGuard(self):
185 for wr in self.data.itervalues():
186 obj = wr()
187 if obj is not None:
188 yield obj
Fred Drake101209d2001-05-02 05:43:09 +0000189
Fred Drake41deb1e2001-02-01 05:27:45 +0000190 def popitem(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000191 if self._pending_removals:
192 self._commit_removals()
Fred Drake41deb1e2001-02-01 05:27:45 +0000193 while 1:
Fred Drakebd7f8182001-04-19 16:26:06 +0000194 key, wr = self.data.popitem()
195 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000196 if o is not None:
197 return key, o
198
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000199 def pop(self, key, *args):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000200 if self._pending_removals:
201 self._commit_removals()
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000202 try:
203 o = self.data.pop(key)()
204 except KeyError:
Antoine Pitrou805f2832016-12-19 11:12:58 +0100205 o = None
206 if o is None:
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000207 if args:
208 return args[0]
Antoine Pitrou805f2832016-12-19 11:12:58 +0100209 else:
210 raise KeyError, key
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000211 else:
212 return o
213
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000214 def setdefault(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000215 try:
Antoine Pitrou805f2832016-12-19 11:12:58 +0100216 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +0000217 except KeyError:
Antoine Pitrou805f2832016-12-19 11:12:58 +0100218 o = None
219 if o is None:
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000220 if self._pending_removals:
221 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +0000222 self.data[key] = KeyedRef(default, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000223 return default
224 else:
Antoine Pitrou805f2832016-12-19 11:12:58 +0100225 return o
Fred Drake41deb1e2001-02-01 05:27:45 +0000226
Serhiy Storchakaf522bbc2015-09-29 23:51:27 +0300227 def update(*args, **kwargs):
228 if not args:
229 raise TypeError("descriptor 'update' of 'WeakValueDictionary' "
230 "object needs an argument")
231 self = args[0]
232 args = args[1:]
233 if len(args) > 1:
234 raise TypeError('expected at most 1 arguments, got %d' % len(args))
235 dict = args[0] if args else None
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000236 if self._pending_removals:
237 self._commit_removals()
Fred Drake41deb1e2001-02-01 05:27:45 +0000238 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000239 if dict is not None:
240 if not hasattr(dict, "items"):
241 dict = type({})(dict)
242 for key, o in dict.items():
Fred Drake0a4dd392004-07-02 18:57:45 +0000243 d[key] = KeyedRef(o, self._remove, key)
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000244 if len(kwargs):
245 self.update(kwargs)
Fred Drake41deb1e2001-02-01 05:27:45 +0000246
Fred Drake017e68c2006-05-02 06:53:59 +0000247 def valuerefs(self):
248 """Return a list of weak references to the values.
249
250 The references are not guaranteed to be 'live' at the time
251 they are used, so the result of calling the references needs
252 to be checked before being used. This can be used to avoid
253 creating references that will cause the garbage collector to
254 keep the values around longer than needed.
255
256 """
257 return self.data.values()
258
Fred Drake41deb1e2001-02-01 05:27:45 +0000259 def values(self):
260 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000261 for wr in self.data.values():
262 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000263 if o is not None:
264 L.append(o)
265 return L
266
Fred Drake0a4dd392004-07-02 18:57:45 +0000267
268class KeyedRef(ref):
269 """Specialized reference that includes a key corresponding to the value.
270
271 This is used in the WeakValueDictionary to avoid having to create
272 a function object for each key stored in the mapping. A shared
273 callback object can use the 'key' attribute of a KeyedRef instead
274 of getting a reference to the key from an enclosing scope.
275
276 """
277
278 __slots__ = "key",
279
280 def __new__(type, ob, callback, key):
281 self = ref.__new__(type, ob, callback)
282 self.key = key
283 return self
284
285 def __init__(self, ob, callback, key):
286 super(KeyedRef, self).__init__(ob, callback)
Fred Drake746fe0f2001-09-28 19:01:26 +0000287
Fred Drake41deb1e2001-02-01 05:27:45 +0000288
Martin v. Löwis5e163332001-02-27 18:36:56 +0000289class WeakKeyDictionary(UserDict.UserDict):
Fred Drakebd7f8182001-04-19 16:26:06 +0000290 """ Mapping class that references keys weakly.
291
292 Entries in the dictionary will be discarded when there is no
293 longer a strong reference to the key. This can be used to
294 associate additional data with an object owned by other parts of
295 an application without adding attributes to those objects. This
296 can be especially useful with objects that override attribute
297 accesses.
298 """
Martin v. Löwis5e163332001-02-27 18:36:56 +0000299
300 def __init__(self, dict=None):
301 self.data = {}
Fred Drake746fe0f2001-09-28 19:01:26 +0000302 def remove(k, selfref=ref(self)):
303 self = selfref()
304 if self is not None:
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000305 if self._iterating:
306 self._pending_removals.append(k)
307 else:
308 del self.data[k]
Martin v. Löwis5e163332001-02-27 18:36:56 +0000309 self._remove = remove
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000310 # A list of dead weakrefs (keys to be removed)
311 self._pending_removals = []
312 self._iterating = set()
313 if dict is not None:
314 self.update(dict)
315
316 def _commit_removals(self):
317 # NOTE: We don't need to call this method before mutating the dict,
318 # because a dead weakref never compares equal to a live weakref,
319 # even if they happened to refer to equal objects.
320 # However, it means keys may already have been removed.
321 l = self._pending_removals
322 d = self.data
323 while l:
324 try:
325 del d[l.pop()]
326 except KeyError:
327 pass
Martin v. Löwis5e163332001-02-27 18:36:56 +0000328
Fred Drakeb663a2c2001-09-06 14:51:01 +0000329 def __delitem__(self, key):
Tim Peters886128f2003-05-25 01:45:11 +0000330 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000331
Martin v. Löwis5e163332001-02-27 18:36:56 +0000332 def __getitem__(self, key):
333 return self.data[ref(key)]
334
335 def __repr__(self):
336 return "<WeakKeyDictionary at %s>" % id(self)
337
338 def __setitem__(self, key, value):
339 self.data[ref(key, self._remove)] = value
340
341 def copy(self):
342 new = WeakKeyDictionary()
343 for key, value in self.data.items():
344 o = key()
345 if o is not None:
346 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000347 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000348
Antoine Pitrou775fd662009-05-15 16:54:52 +0000349 __copy__ = copy
350
351 def __deepcopy__(self, memo):
352 from copy import deepcopy
353 new = self.__class__()
354 for key, value in self.data.items():
355 o = key()
356 if o is not None:
357 new[o] = deepcopy(value, memo)
358 return new
359
Fred Drake1d9e4b72001-04-16 17:34:48 +0000360 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000361 return self.data.get(ref(key),default)
362
Fred Drake1d9e4b72001-04-16 17:34:48 +0000363 def has_key(self, key):
Fred Drake3bae7dd2001-11-06 16:36:53 +0000364 try:
365 wr = ref(key)
366 except TypeError:
367 return 0
Raymond Hettinger54f02222002-06-01 14:18:47 +0000368 return wr in self.data
Fred Drake1d9e4b72001-04-16 17:34:48 +0000369
Raymond Hettinger54f02222002-06-01 14:18:47 +0000370 def __contains__(self, key):
371 try:
372 wr = ref(key)
373 except TypeError:
374 return 0
375 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000376
Martin v. Löwis5e163332001-02-27 18:36:56 +0000377 def items(self):
378 L = []
379 for key, value in self.data.items():
380 o = key()
381 if o is not None:
382 L.append((o, value))
383 return L
384
Fred Drake101209d2001-05-02 05:43:09 +0000385 def iteritems(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000386 with _IterationGuard(self):
387 for wr, value in self.data.iteritems():
388 key = wr()
389 if key is not None:
390 yield key, value
Fred Drake101209d2001-05-02 05:43:09 +0000391
Fred Drake017e68c2006-05-02 06:53:59 +0000392 def iterkeyrefs(self):
393 """Return an iterator that yields the weak references to the keys.
394
395 The references are not guaranteed to be 'live' at the time
396 they are used, so the result of calling the references needs
397 to be checked before being used. This can be used to avoid
398 creating references that will cause the garbage collector to
399 keep the keys around longer than needed.
400
401 """
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000402 with _IterationGuard(self):
403 for wr in self.data.iterkeys():
404 yield wr
Fred Drake017e68c2006-05-02 06:53:59 +0000405
Fred Drake101209d2001-05-02 05:43:09 +0000406 def iterkeys(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000407 with _IterationGuard(self):
408 for wr in self.data.iterkeys():
409 obj = wr()
410 if obj is not None:
411 yield obj
Raymond Hettinger61146792004-08-19 21:32:06 +0000412
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000413 __iter__ = iterkeys
Fred Drake101209d2001-05-02 05:43:09 +0000414
415 def itervalues(self):
Kristján Valur Jónsson222b2842013-12-05 10:03:45 +0000416 with _IterationGuard(self):
417 for value in self.data.itervalues():
418 yield value
Fred Drake101209d2001-05-02 05:43:09 +0000419
Fred Drake017e68c2006-05-02 06:53:59 +0000420 def keyrefs(self):
421 """Return a list of weak references to the keys.
422
423 The references are not guaranteed to be 'live' at the time
424 they are used, so the result of calling the references needs
425 to be checked before being used. This can be used to avoid
426 creating references that will cause the garbage collector to
427 keep the keys around longer than needed.
428
429 """
430 return self.data.keys()
431
Fred Drake1d9e4b72001-04-16 17:34:48 +0000432 def keys(self):
433 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000434 for wr in self.data.keys():
435 o = wr()
Fred Drake1d9e4b72001-04-16 17:34:48 +0000436 if o is not None:
437 L.append(o)
438 return L
439
Martin v. Löwis5e163332001-02-27 18:36:56 +0000440 def popitem(self):
441 while 1:
442 key, value = self.data.popitem()
443 o = key()
444 if o is not None:
445 return o, value
446
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000447 def pop(self, key, *args):
448 return self.data.pop(ref(key), *args)
449
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000450 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000451 return self.data.setdefault(ref(key, self._remove),default)
452
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000453 def update(self, dict=None, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000454 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000455 if dict is not None:
456 if not hasattr(dict, "items"):
457 dict = type({})(dict)
458 for key, value in dict.items():
459 d[ref(key, self._remove)] = value
460 if len(kwargs):
461 self.update(kwargs)