blob: 787e33a327c4f63e0ae874cfcbe6fdb8770d4271 [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
Christian Heimes81ee3ef2008-05-04 22:42:01 +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
Andrew M. Kuchling33ad28b2004-08-31 11:38:12 +000012from _weakref import (
13 getweakrefcount,
14 getweakrefs,
15 ref,
16 proxy,
17 CallableProxyType,
18 ProxyType,
Antoine Pitroue10ca3a2016-12-27 14:19:20 +010019 ReferenceType,
20 _remove_dead_weakref)
Fred Drake41deb1e2001-02-01 05:27:45 +000021
Antoine Pitrouc1baa602010-01-08 17:54:23 +000022from _weakrefset import WeakSet, _IterationGuard
Fred Drakee0292422001-10-05 21:54:09 +000023
Brett Cannon663fffa2009-03-25 23:31:22 +000024import collections # Import after _weakref to avoid circular import.
Richard Oudkerk7a3dae02013-05-05 23:05:00 +010025import sys
26import itertools
Brett Cannon663fffa2009-03-25 23:31:22 +000027
Fred Drake41deb1e2001-02-01 05:27:45 +000028ProxyTypes = (ProxyType, CallableProxyType)
29
Fred Drake9a9d2192001-04-10 19:11:23 +000030__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
Gregory P. Smith7d10c2b2008-08-18 03:41:46 +000031 "WeakKeyDictionary", "ReferenceType", "ProxyType",
Raymond Hettinger93fa6082008-02-05 00:20:01 +000032 "CallableProxyType", "ProxyTypes", "WeakValueDictionary",
Richard Oudkerk7a3dae02013-05-05 23:05:00 +010033 "WeakSet", "WeakMethod", "finalize"]
Antoine Pitrouc3afba12012-11-17 18:57:38 +010034
35
36class WeakMethod(ref):
37 """
38 A custom `weakref.ref` subclass which simulates a weak reference to
39 a bound method, working around the lifetime problem of bound methods.
40 """
41
42 __slots__ = "_func_ref", "_meth_type", "_alive", "__weakref__"
43
44 def __new__(cls, meth, callback=None):
45 try:
46 obj = meth.__self__
47 func = meth.__func__
48 except AttributeError:
49 raise TypeError("argument should be a bound method, not {}"
50 .format(type(meth))) from None
51 def _cb(arg):
52 # The self-weakref trick is needed to avoid creating a reference
53 # cycle.
54 self = self_wr()
55 if self._alive:
56 self._alive = False
57 if callback is not None:
58 callback(self)
59 self = ref.__new__(cls, obj, _cb)
60 self._func_ref = ref(func, _cb)
61 self._meth_type = type(meth)
62 self._alive = True
63 self_wr = ref(self)
64 return self
65
66 def __call__(self):
67 obj = super().__call__()
68 func = self._func_ref()
69 if obj is None or func is None:
70 return None
71 return self._meth_type(func, obj)
72
73 def __eq__(self, other):
74 if isinstance(other, WeakMethod):
75 if not self._alive or not other._alive:
76 return self is other
77 return ref.__eq__(self, other) and self._func_ref == other._func_ref
78 return False
79
80 def __ne__(self, other):
81 if isinstance(other, WeakMethod):
82 if not self._alive or not other._alive:
83 return self is not other
84 return ref.__ne__(self, other) or self._func_ref != other._func_ref
85 return True
86
87 __hash__ = ref.__hash__
Fred Drake41deb1e2001-02-01 05:27:45 +000088
Fred Drake41deb1e2001-02-01 05:27:45 +000089
Raymond Hettinger7ac60952008-02-05 01:15:57 +000090class WeakValueDictionary(collections.MutableMapping):
Fred Drakebd7f8182001-04-19 16:26:06 +000091 """Mapping class that references values weakly.
92
93 Entries in the dictionary will be discarded when no strong
94 reference to the value exists anymore
95 """
Fred Drake41deb1e2001-02-01 05:27:45 +000096 # We inherit the constructor without worrying about the input
97 # dictionary; since it uses our .update() method, we get the right
Fred Drake9d2c85d2001-03-01 03:06:03 +000098 # checks (if the other dictionary is a WeakValueDictionary,
99 # objects are unwrapped on the way out, and we always wrap on the
100 # way in).
Fred Drake41deb1e2001-02-01 05:27:45 +0000101
Serhiy Storchakab5102e32015-09-29 23:52:09 +0300102 def __init__(*args, **kw):
103 if not args:
104 raise TypeError("descriptor '__init__' of 'WeakValueDictionary' "
105 "object needs an argument")
106 self, *args = args
107 if len(args) > 1:
108 raise TypeError('expected at most 1 arguments, got %d' % len(args))
Łukasz Langa9cd7e172017-02-10 00:14:55 -0800109 def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):
Fred Drake0a4dd392004-07-02 18:57:45 +0000110 self = selfref()
111 if self is not None:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000112 if self._iterating:
113 self._pending_removals.append(wr.key)
114 else:
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100115 # Atomic removal is necessary since this function
116 # can be called asynchronously by the GC
Łukasz Langa9cd7e172017-02-10 00:14:55 -0800117 _atomic_removal(d, wr.key)
Fred Drake0a4dd392004-07-02 18:57:45 +0000118 self._remove = remove
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000119 # A list of keys to be removed
120 self._pending_removals = []
121 self._iterating = set()
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000122 self.data = d = {}
Antoine Pitrouc06de472009-05-30 21:04:26 +0000123 self.update(*args, **kw)
Fred Drake0a4dd392004-07-02 18:57:45 +0000124
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000125 def _commit_removals(self):
126 l = self._pending_removals
127 d = self.data
128 # We shouldn't encounter any KeyError, because this method should
129 # always be called *before* mutating the dict.
130 while l:
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100131 key = l.pop()
132 _remove_dead_weakref(d, key)
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000133
Fred Drake41deb1e2001-02-01 05:27:45 +0000134 def __getitem__(self, key):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100135 if self._pending_removals:
136 self._commit_removals()
Fred Drake4fd06e02001-08-03 04:11:27 +0000137 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +0000138 if o is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000139 raise KeyError(key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000140 else:
141 return o
142
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000143 def __delitem__(self, key):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000144 if self._pending_removals:
145 self._commit_removals()
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000146 del self.data[key]
147
148 def __len__(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100149 if self._pending_removals:
150 self._commit_removals()
151 return len(self.data)
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000152
Raymond Hettinger61146792004-08-19 21:32:06 +0000153 def __contains__(self, key):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100154 if self._pending_removals:
155 self._commit_removals()
Raymond Hettinger61146792004-08-19 21:32:06 +0000156 try:
157 o = self.data[key]()
158 except KeyError:
159 return False
160 return o is not None
161
Fred Drake41deb1e2001-02-01 05:27:45 +0000162 def __repr__(self):
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300163 return "<%s at %#x>" % (self.__class__.__name__, id(self))
Fred Drake41deb1e2001-02-01 05:27:45 +0000164
165 def __setitem__(self, key, value):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000166 if self._pending_removals:
167 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +0000168 self.data[key] = KeyedRef(value, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000169
170 def copy(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100171 if self._pending_removals:
172 self._commit_removals()
Fred Drake9d2c85d2001-03-01 03:06:03 +0000173 new = WeakValueDictionary()
Fred Drakebd7f8182001-04-19 16:26:06 +0000174 for key, wr in self.data.items():
175 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000176 if o is not None:
177 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +0000178 return new
Fred Drake41deb1e2001-02-01 05:27:45 +0000179
Antoine Pitrou6e610062009-05-15 17:04:50 +0000180 __copy__ = copy
181
182 def __deepcopy__(self, memo):
183 from copy import deepcopy
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100184 if self._pending_removals:
185 self._commit_removals()
Antoine Pitrou6e610062009-05-15 17:04:50 +0000186 new = self.__class__()
187 for key, wr in self.data.items():
188 o = wr()
189 if o is not None:
190 new[deepcopy(key, memo)] = o
191 return new
192
Fred Drake1d9e4b72001-04-16 17:34:48 +0000193 def get(self, key, default=None):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100194 if self._pending_removals:
195 self._commit_removals()
Fred Drake41deb1e2001-02-01 05:27:45 +0000196 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000197 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000198 except KeyError:
199 return default
200 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000201 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000202 if o is None:
203 # This should only happen
204 return default
205 else:
206 return o
207
208 def items(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100209 if self._pending_removals:
210 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000211 with _IterationGuard(self):
212 for k, wr in self.data.items():
213 v = wr()
214 if v is not None:
215 yield k, v
Fred Drake101209d2001-05-02 05:43:09 +0000216
Barry Warsawecaab832008-09-04 01:42:51 +0000217 def keys(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100218 if self._pending_removals:
219 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000220 with _IterationGuard(self):
221 for k, wr in self.data.items():
222 if wr() is not None:
223 yield k
Raymond Hettinger61146792004-08-19 21:32:06 +0000224
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000225 __iter__ = keys
Fred Drake101209d2001-05-02 05:43:09 +0000226
Thomas Wouters477c8d52006-05-27 19:21:47 +0000227 def itervaluerefs(self):
228 """Return an iterator that yields the weak references to the values.
229
230 The references are not guaranteed to be 'live' at the time
231 they are used, so the result of calling the references needs
232 to be checked before being used. This can be used to avoid
233 creating references that will cause the garbage collector to
234 keep the values around longer than needed.
235
236 """
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100237 if self._pending_removals:
238 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000239 with _IterationGuard(self):
Philip Jenvey4993cc02012-10-01 12:53:43 -0700240 yield from self.data.values()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000241
Barry Warsawecaab832008-09-04 01:42:51 +0000242 def values(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100243 if self._pending_removals:
244 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000245 with _IterationGuard(self):
246 for wr in self.data.values():
247 obj = wr()
248 if obj is not None:
249 yield obj
Fred Drake101209d2001-05-02 05:43:09 +0000250
Fred Drake41deb1e2001-02-01 05:27:45 +0000251 def popitem(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000252 if self._pending_removals:
253 self._commit_removals()
Georg Brandlbd87d082010-12-03 07:49:09 +0000254 while True:
Fred Drakebd7f8182001-04-19 16:26:06 +0000255 key, wr = self.data.popitem()
256 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000257 if o is not None:
258 return key, o
259
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000260 def pop(self, key, *args):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000261 if self._pending_removals:
262 self._commit_removals()
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000263 try:
264 o = self.data.pop(key)()
265 except KeyError:
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100266 o = None
267 if o is None:
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000268 if args:
269 return args[0]
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100270 else:
271 raise KeyError(key)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000272 else:
273 return o
274
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000275 def setdefault(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000276 try:
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100277 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +0000278 except KeyError:
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100279 o = None
280 if o is None:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000281 if self._pending_removals:
282 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +0000283 self.data[key] = KeyedRef(default, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000284 return default
285 else:
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100286 return o
Fred Drake41deb1e2001-02-01 05:27:45 +0000287
Serhiy Storchakab5102e32015-09-29 23:52:09 +0300288 def update(*args, **kwargs):
289 if not args:
290 raise TypeError("descriptor 'update' of 'WeakValueDictionary' "
291 "object needs an argument")
292 self, *args = args
293 if len(args) > 1:
294 raise TypeError('expected at most 1 arguments, got %d' % len(args))
295 dict = args[0] if args else None
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000296 if self._pending_removals:
297 self._commit_removals()
Fred Drake41deb1e2001-02-01 05:27:45 +0000298 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000299 if dict is not None:
300 if not hasattr(dict, "items"):
301 dict = type({})(dict)
302 for key, o in dict.items():
Fred Drake0a4dd392004-07-02 18:57:45 +0000303 d[key] = KeyedRef(o, self._remove, key)
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000304 if len(kwargs):
305 self.update(kwargs)
Fred Drake41deb1e2001-02-01 05:27:45 +0000306
Thomas Wouters477c8d52006-05-27 19:21:47 +0000307 def valuerefs(self):
308 """Return a list of weak references to the values.
309
310 The references are not guaranteed to be 'live' at the time
311 they are used, so the result of calling the references needs
312 to be checked before being used. This can be used to avoid
313 creating references that will cause the garbage collector to
314 keep the values around longer than needed.
315
316 """
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100317 if self._pending_removals:
318 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000319 return list(self.data.values())
Thomas Wouters477c8d52006-05-27 19:21:47 +0000320
Fred Drake0a4dd392004-07-02 18:57:45 +0000321
322class KeyedRef(ref):
323 """Specialized reference that includes a key corresponding to the value.
324
325 This is used in the WeakValueDictionary to avoid having to create
326 a function object for each key stored in the mapping. A shared
327 callback object can use the 'key' attribute of a KeyedRef instead
328 of getting a reference to the key from an enclosing scope.
329
330 """
331
332 __slots__ = "key",
333
334 def __new__(type, ob, callback, key):
335 self = ref.__new__(type, ob, callback)
336 self.key = key
337 return self
338
339 def __init__(self, ob, callback, key):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000340 super().__init__(ob, callback)
Fred Drake746fe0f2001-09-28 19:01:26 +0000341
Fred Drake41deb1e2001-02-01 05:27:45 +0000342
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000343class WeakKeyDictionary(collections.MutableMapping):
Fred Drakebd7f8182001-04-19 16:26:06 +0000344 """ Mapping class that references keys weakly.
345
346 Entries in the dictionary will be discarded when there is no
347 longer a strong reference to the key. This can be used to
348 associate additional data with an object owned by other parts of
349 an application without adding attributes to those objects. This
350 can be especially useful with objects that override attribute
351 accesses.
352 """
Martin v. Löwis5e163332001-02-27 18:36:56 +0000353
354 def __init__(self, dict=None):
355 self.data = {}
Fred Drake746fe0f2001-09-28 19:01:26 +0000356 def remove(k, selfref=ref(self)):
357 self = selfref()
358 if self is not None:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000359 if self._iterating:
360 self._pending_removals.append(k)
361 else:
362 del self.data[k]
Martin v. Löwis5e163332001-02-27 18:36:56 +0000363 self._remove = remove
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000364 # A list of dead weakrefs (keys to be removed)
365 self._pending_removals = []
366 self._iterating = set()
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200367 self._dirty_len = False
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000368 if dict is not None:
369 self.update(dict)
370
371 def _commit_removals(self):
372 # NOTE: We don't need to call this method before mutating the dict,
373 # because a dead weakref never compares equal to a live weakref,
374 # even if they happened to refer to equal objects.
375 # However, it means keys may already have been removed.
376 l = self._pending_removals
377 d = self.data
378 while l:
379 try:
380 del d[l.pop()]
381 except KeyError:
382 pass
Martin v. Löwis5e163332001-02-27 18:36:56 +0000383
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200384 def _scrub_removals(self):
385 d = self.data
386 self._pending_removals = [k for k in self._pending_removals if k in d]
387 self._dirty_len = False
388
Fred Drakeb663a2c2001-09-06 14:51:01 +0000389 def __delitem__(self, key):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200390 self._dirty_len = True
Tim Peters886128f2003-05-25 01:45:11 +0000391 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000392
Martin v. Löwis5e163332001-02-27 18:36:56 +0000393 def __getitem__(self, key):
394 return self.data[ref(key)]
395
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000396 def __len__(self):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200397 if self._dirty_len and self._pending_removals:
398 # self._pending_removals may still contain keys which were
399 # explicitly removed, we have to scrub them (see issue #21173).
400 self._scrub_removals()
Antoine Pitroubbe2f602012-03-01 16:26:35 +0100401 return len(self.data) - len(self._pending_removals)
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000402
Martin v. Löwis5e163332001-02-27 18:36:56 +0000403 def __repr__(self):
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300404 return "<%s at %#x>" % (self.__class__.__name__, id(self))
Martin v. Löwis5e163332001-02-27 18:36:56 +0000405
406 def __setitem__(self, key, value):
407 self.data[ref(key, self._remove)] = value
408
409 def copy(self):
410 new = WeakKeyDictionary()
411 for key, value in self.data.items():
412 o = key()
413 if o is not None:
414 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000415 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000416
Antoine Pitrou6e610062009-05-15 17:04:50 +0000417 __copy__ = copy
418
419 def __deepcopy__(self, memo):
420 from copy import deepcopy
421 new = self.__class__()
422 for key, value in self.data.items():
423 o = key()
424 if o is not None:
425 new[o] = deepcopy(value, memo)
426 return new
427
Fred Drake1d9e4b72001-04-16 17:34:48 +0000428 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000429 return self.data.get(ref(key),default)
430
Raymond Hettinger54f02222002-06-01 14:18:47 +0000431 def __contains__(self, key):
432 try:
433 wr = ref(key)
434 except TypeError:
Georg Brandlbd87d082010-12-03 07:49:09 +0000435 return False
Raymond Hettinger54f02222002-06-01 14:18:47 +0000436 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000437
Martin v. Löwis5e163332001-02-27 18:36:56 +0000438 def items(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000439 with _IterationGuard(self):
440 for wr, value in self.data.items():
441 key = wr()
442 if key is not None:
443 yield key, value
Thomas Wouters477c8d52006-05-27 19:21:47 +0000444
Barry Warsawecaab832008-09-04 01:42:51 +0000445 def keys(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000446 with _IterationGuard(self):
447 for wr in self.data:
448 obj = wr()
449 if obj is not None:
450 yield obj
Raymond Hettinger61146792004-08-19 21:32:06 +0000451
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000452 __iter__ = keys
Fred Drake101209d2001-05-02 05:43:09 +0000453
Barry Warsawecaab832008-09-04 01:42:51 +0000454 def values(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000455 with _IterationGuard(self):
456 for wr, value in self.data.items():
457 if wr() is not None:
458 yield value
Fred Drake101209d2001-05-02 05:43:09 +0000459
Thomas Wouters477c8d52006-05-27 19:21:47 +0000460 def keyrefs(self):
461 """Return a list of weak references to the keys.
462
463 The references are not guaranteed to be 'live' at the time
464 they are used, so the result of calling the references needs
465 to be checked before being used. This can be used to avoid
466 creating references that will cause the garbage collector to
467 keep the keys around longer than needed.
468
469 """
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000470 return list(self.data)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000471
Martin v. Löwis5e163332001-02-27 18:36:56 +0000472 def popitem(self):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200473 self._dirty_len = True
Georg Brandlbd87d082010-12-03 07:49:09 +0000474 while True:
Martin v. Löwis5e163332001-02-27 18:36:56 +0000475 key, value = self.data.popitem()
476 o = key()
477 if o is not None:
478 return o, value
479
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000480 def pop(self, key, *args):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200481 self._dirty_len = True
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000482 return self.data.pop(ref(key), *args)
483
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000484 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000485 return self.data.setdefault(ref(key, self._remove),default)
486
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000487 def update(self, dict=None, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000488 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000489 if dict is not None:
490 if not hasattr(dict, "items"):
491 dict = type({})(dict)
492 for key, value in dict.items():
493 d[ref(key, self._remove)] = value
494 if len(kwargs):
495 self.update(kwargs)
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100496
497
498class finalize:
499 """Class for finalization of weakrefable objects
500
501 finalize(obj, func, *args, **kwargs) returns a callable finalizer
502 object which will be called when obj is garbage collected. The
503 first time the finalizer is called it evaluates func(*arg, **kwargs)
504 and returns the result. After this the finalizer is dead, and
505 calling it just returns None.
506
507 When the program exits any remaining finalizers for which the
508 atexit attribute is true will be run in reverse order of creation.
509 By default atexit is true.
510 """
511
512 # Finalizer objects don't have any state of their own. They are
513 # just used as keys to lookup _Info objects in the registry. This
514 # ensures that they cannot be part of a ref-cycle.
515
516 __slots__ = ()
517 _registry = {}
518 _shutdown = False
519 _index_iter = itertools.count()
520 _dirty = False
Richard Oudkerka81dd652013-06-08 16:52:29 +0100521 _registered_with_atexit = False
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100522
523 class _Info:
524 __slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index")
525
526 def __init__(self, obj, func, *args, **kwargs):
Richard Oudkerka81dd652013-06-08 16:52:29 +0100527 if not self._registered_with_atexit:
528 # We may register the exit function more than once because
529 # of a thread race, but that is harmless
530 import atexit
531 atexit.register(self._exitfunc)
532 finalize._registered_with_atexit = True
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100533 info = self._Info()
534 info.weakref = ref(obj, self)
535 info.func = func
536 info.args = args
537 info.kwargs = kwargs or None
538 info.atexit = True
539 info.index = next(self._index_iter)
540 self._registry[self] = info
541 finalize._dirty = True
542
543 def __call__(self, _=None):
544 """If alive then mark as dead and return func(*args, **kwargs);
545 otherwise return None"""
546 info = self._registry.pop(self, None)
547 if info and not self._shutdown:
548 return info.func(*info.args, **(info.kwargs or {}))
549
550 def detach(self):
551 """If alive then mark as dead and return (obj, func, args, kwargs);
552 otherwise return None"""
553 info = self._registry.get(self)
554 obj = info and info.weakref()
555 if obj is not None and self._registry.pop(self, None):
556 return (obj, info.func, info.args, info.kwargs or {})
557
558 def peek(self):
559 """If alive then return (obj, func, args, kwargs);
560 otherwise return None"""
561 info = self._registry.get(self)
562 obj = info and info.weakref()
563 if obj is not None:
564 return (obj, info.func, info.args, info.kwargs or {})
565
566 @property
567 def alive(self):
568 """Whether finalizer is alive"""
569 return self in self._registry
570
571 @property
572 def atexit(self):
573 """Whether finalizer should be called at exit"""
574 info = self._registry.get(self)
575 return bool(info) and info.atexit
576
577 @atexit.setter
578 def atexit(self, value):
579 info = self._registry.get(self)
580 if info:
581 info.atexit = bool(value)
582
583 def __repr__(self):
584 info = self._registry.get(self)
585 obj = info and info.weakref()
586 if obj is None:
587 return '<%s object at %#x; dead>' % (type(self).__name__, id(self))
588 else:
589 return '<%s object at %#x; for %r at %#x>' % \
590 (type(self).__name__, id(self), type(obj).__name__, id(obj))
591
592 @classmethod
593 def _select_for_exit(cls):
594 # Return live finalizers marked for exit, oldest first
595 L = [(f,i) for (f,i) in cls._registry.items() if i.atexit]
596 L.sort(key=lambda item:item[1].index)
597 return [f for (f,i) in L]
598
599 @classmethod
600 def _exitfunc(cls):
601 # At shutdown invoke finalizers for which atexit is true.
602 # This is called once all other non-daemonic threads have been
603 # joined.
604 reenable_gc = False
605 try:
606 if cls._registry:
607 import gc
608 if gc.isenabled():
609 reenable_gc = True
610 gc.disable()
611 pending = None
612 while True:
613 if pending is None or finalize._dirty:
614 pending = cls._select_for_exit()
615 finalize._dirty = False
616 if not pending:
617 break
618 f = pending.pop()
619 try:
620 # gc is disabled, so (assuming no daemonic
621 # threads) the following is the only line in
622 # this function which might trigger creation
623 # of a new finalizer
624 f()
625 except Exception:
626 sys.excepthook(*sys.exc_info())
627 assert f not in cls._registry
628 finally:
629 # prevent any more finalizers from executing during shutdown
630 finalize._shutdown = True
631 if reenable_gc:
632 gc.enable()