blob: 753f07291e20e8411d5d768ef94eac720af0f8a1 [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
Serhiy Storchaka81108372017-09-26 00:55:55 +030024import _collections_abc # 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
Serhiy Storchaka81108372017-09-26 00:55:55 +030090class WeakValueDictionary(_collections_abc.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()
Fish96d37db2019-02-07 14:51:59 -0500174 with _IterationGuard(self):
175 for key, wr in self.data.items():
176 o = wr()
177 if o is not None:
178 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +0000179 return new
Fred Drake41deb1e2001-02-01 05:27:45 +0000180
Antoine Pitrou6e610062009-05-15 17:04:50 +0000181 __copy__ = copy
182
183 def __deepcopy__(self, memo):
184 from copy import deepcopy
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100185 if self._pending_removals:
186 self._commit_removals()
Antoine Pitrou6e610062009-05-15 17:04:50 +0000187 new = self.__class__()
Fish96d37db2019-02-07 14:51:59 -0500188 with _IterationGuard(self):
189 for key, wr in self.data.items():
190 o = wr()
191 if o is not None:
192 new[deepcopy(key, memo)] = o
Antoine Pitrou6e610062009-05-15 17:04:50 +0000193 return new
194
Fred Drake1d9e4b72001-04-16 17:34:48 +0000195 def get(self, key, default=None):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100196 if self._pending_removals:
197 self._commit_removals()
Fred Drake41deb1e2001-02-01 05:27:45 +0000198 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000199 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000200 except KeyError:
201 return default
202 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000203 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000204 if o is None:
205 # This should only happen
206 return default
207 else:
208 return o
209
210 def items(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100211 if self._pending_removals:
212 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000213 with _IterationGuard(self):
214 for k, wr in self.data.items():
215 v = wr()
216 if v is not None:
217 yield k, v
Fred Drake101209d2001-05-02 05:43:09 +0000218
Barry Warsawecaab832008-09-04 01:42:51 +0000219 def keys(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100220 if self._pending_removals:
221 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000222 with _IterationGuard(self):
223 for k, wr in self.data.items():
224 if wr() is not None:
225 yield k
Raymond Hettinger61146792004-08-19 21:32:06 +0000226
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000227 __iter__ = keys
Fred Drake101209d2001-05-02 05:43:09 +0000228
Thomas Wouters477c8d52006-05-27 19:21:47 +0000229 def itervaluerefs(self):
230 """Return an iterator that yields the 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 """
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100239 if self._pending_removals:
240 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000241 with _IterationGuard(self):
Philip Jenvey4993cc02012-10-01 12:53:43 -0700242 yield from self.data.values()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000243
Barry Warsawecaab832008-09-04 01:42:51 +0000244 def values(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100245 if self._pending_removals:
246 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000247 with _IterationGuard(self):
248 for wr in self.data.values():
249 obj = wr()
250 if obj is not None:
251 yield obj
Fred Drake101209d2001-05-02 05:43:09 +0000252
Fred Drake41deb1e2001-02-01 05:27:45 +0000253 def popitem(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000254 if self._pending_removals:
255 self._commit_removals()
Georg Brandlbd87d082010-12-03 07:49:09 +0000256 while True:
Fred Drakebd7f8182001-04-19 16:26:06 +0000257 key, wr = self.data.popitem()
258 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000259 if o is not None:
260 return key, o
261
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000262 def pop(self, key, *args):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000263 if self._pending_removals:
264 self._commit_removals()
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000265 try:
266 o = self.data.pop(key)()
267 except KeyError:
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100268 o = None
269 if o is None:
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000270 if args:
271 return args[0]
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100272 else:
273 raise KeyError(key)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000274 else:
275 return o
276
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000277 def setdefault(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000278 try:
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100279 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +0000280 except KeyError:
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100281 o = None
282 if o is None:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000283 if self._pending_removals:
284 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +0000285 self.data[key] = KeyedRef(default, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000286 return default
287 else:
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100288 return o
Fred Drake41deb1e2001-02-01 05:27:45 +0000289
Serhiy Storchakab5102e32015-09-29 23:52:09 +0300290 def update(*args, **kwargs):
291 if not args:
292 raise TypeError("descriptor 'update' of 'WeakValueDictionary' "
293 "object needs an argument")
294 self, *args = args
295 if len(args) > 1:
296 raise TypeError('expected at most 1 arguments, got %d' % len(args))
297 dict = args[0] if args else None
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000298 if self._pending_removals:
299 self._commit_removals()
Fred Drake41deb1e2001-02-01 05:27:45 +0000300 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000301 if dict is not None:
302 if not hasattr(dict, "items"):
303 dict = type({})(dict)
304 for key, o in dict.items():
Fred Drake0a4dd392004-07-02 18:57:45 +0000305 d[key] = KeyedRef(o, self._remove, key)
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000306 if len(kwargs):
307 self.update(kwargs)
Fred Drake41deb1e2001-02-01 05:27:45 +0000308
Thomas Wouters477c8d52006-05-27 19:21:47 +0000309 def valuerefs(self):
310 """Return a list of weak references to the values.
311
312 The references are not guaranteed to be 'live' at the time
313 they are used, so the result of calling the references needs
314 to be checked before being used. This can be used to avoid
315 creating references that will cause the garbage collector to
316 keep the values around longer than needed.
317
318 """
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100319 if self._pending_removals:
320 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000321 return list(self.data.values())
Thomas Wouters477c8d52006-05-27 19:21:47 +0000322
Fred Drake0a4dd392004-07-02 18:57:45 +0000323
324class KeyedRef(ref):
325 """Specialized reference that includes a key corresponding to the value.
326
327 This is used in the WeakValueDictionary to avoid having to create
328 a function object for each key stored in the mapping. A shared
329 callback object can use the 'key' attribute of a KeyedRef instead
330 of getting a reference to the key from an enclosing scope.
331
332 """
333
334 __slots__ = "key",
335
336 def __new__(type, ob, callback, key):
337 self = ref.__new__(type, ob, callback)
338 self.key = key
339 return self
340
341 def __init__(self, ob, callback, key):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000342 super().__init__(ob, callback)
Fred Drake746fe0f2001-09-28 19:01:26 +0000343
Fred Drake41deb1e2001-02-01 05:27:45 +0000344
Serhiy Storchaka81108372017-09-26 00:55:55 +0300345class WeakKeyDictionary(_collections_abc.MutableMapping):
Fred Drakebd7f8182001-04-19 16:26:06 +0000346 """ Mapping class that references keys weakly.
347
348 Entries in the dictionary will be discarded when there is no
349 longer a strong reference to the key. This can be used to
350 associate additional data with an object owned by other parts of
351 an application without adding attributes to those objects. This
352 can be especially useful with objects that override attribute
353 accesses.
354 """
Martin v. Löwis5e163332001-02-27 18:36:56 +0000355
356 def __init__(self, dict=None):
357 self.data = {}
Fred Drake746fe0f2001-09-28 19:01:26 +0000358 def remove(k, selfref=ref(self)):
359 self = selfref()
360 if self is not None:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000361 if self._iterating:
362 self._pending_removals.append(k)
363 else:
364 del self.data[k]
Martin v. Löwis5e163332001-02-27 18:36:56 +0000365 self._remove = remove
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000366 # A list of dead weakrefs (keys to be removed)
367 self._pending_removals = []
368 self._iterating = set()
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200369 self._dirty_len = False
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000370 if dict is not None:
371 self.update(dict)
372
373 def _commit_removals(self):
374 # NOTE: We don't need to call this method before mutating the dict,
375 # because a dead weakref never compares equal to a live weakref,
376 # even if they happened to refer to equal objects.
377 # However, it means keys may already have been removed.
378 l = self._pending_removals
379 d = self.data
380 while l:
381 try:
382 del d[l.pop()]
383 except KeyError:
384 pass
Martin v. Löwis5e163332001-02-27 18:36:56 +0000385
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200386 def _scrub_removals(self):
387 d = self.data
388 self._pending_removals = [k for k in self._pending_removals if k in d]
389 self._dirty_len = False
390
Fred Drakeb663a2c2001-09-06 14:51:01 +0000391 def __delitem__(self, key):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200392 self._dirty_len = True
Tim Peters886128f2003-05-25 01:45:11 +0000393 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000394
Martin v. Löwis5e163332001-02-27 18:36:56 +0000395 def __getitem__(self, key):
396 return self.data[ref(key)]
397
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000398 def __len__(self):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200399 if self._dirty_len and self._pending_removals:
400 # self._pending_removals may still contain keys which were
401 # explicitly removed, we have to scrub them (see issue #21173).
402 self._scrub_removals()
Antoine Pitroubbe2f602012-03-01 16:26:35 +0100403 return len(self.data) - len(self._pending_removals)
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000404
Martin v. Löwis5e163332001-02-27 18:36:56 +0000405 def __repr__(self):
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300406 return "<%s at %#x>" % (self.__class__.__name__, id(self))
Martin v. Löwis5e163332001-02-27 18:36:56 +0000407
408 def __setitem__(self, key, value):
409 self.data[ref(key, self._remove)] = value
410
411 def copy(self):
412 new = WeakKeyDictionary()
Fish96d37db2019-02-07 14:51:59 -0500413 with _IterationGuard(self):
414 for key, value in self.data.items():
415 o = key()
416 if o is not None:
417 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000418 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000419
Antoine Pitrou6e610062009-05-15 17:04:50 +0000420 __copy__ = copy
421
422 def __deepcopy__(self, memo):
423 from copy import deepcopy
424 new = self.__class__()
Fish96d37db2019-02-07 14:51:59 -0500425 with _IterationGuard(self):
426 for key, value in self.data.items():
427 o = key()
428 if o is not None:
429 new[o] = deepcopy(value, memo)
Antoine Pitrou6e610062009-05-15 17:04:50 +0000430 return new
431
Fred Drake1d9e4b72001-04-16 17:34:48 +0000432 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000433 return self.data.get(ref(key),default)
434
Raymond Hettinger54f02222002-06-01 14:18:47 +0000435 def __contains__(self, key):
436 try:
437 wr = ref(key)
438 except TypeError:
Georg Brandlbd87d082010-12-03 07:49:09 +0000439 return False
Raymond Hettinger54f02222002-06-01 14:18:47 +0000440 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000441
Martin v. Löwis5e163332001-02-27 18:36:56 +0000442 def items(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000443 with _IterationGuard(self):
444 for wr, value in self.data.items():
445 key = wr()
446 if key is not None:
447 yield key, value
Thomas Wouters477c8d52006-05-27 19:21:47 +0000448
Barry Warsawecaab832008-09-04 01:42:51 +0000449 def keys(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000450 with _IterationGuard(self):
451 for wr in self.data:
452 obj = wr()
453 if obj is not None:
454 yield obj
Raymond Hettinger61146792004-08-19 21:32:06 +0000455
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000456 __iter__ = keys
Fred Drake101209d2001-05-02 05:43:09 +0000457
Barry Warsawecaab832008-09-04 01:42:51 +0000458 def values(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000459 with _IterationGuard(self):
460 for wr, value in self.data.items():
461 if wr() is not None:
462 yield value
Fred Drake101209d2001-05-02 05:43:09 +0000463
Thomas Wouters477c8d52006-05-27 19:21:47 +0000464 def keyrefs(self):
465 """Return a list of weak references to the keys.
466
467 The references are not guaranteed to be 'live' at the time
468 they are used, so the result of calling the references needs
469 to be checked before being used. This can be used to avoid
470 creating references that will cause the garbage collector to
471 keep the keys around longer than needed.
472
473 """
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000474 return list(self.data)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000475
Martin v. Löwis5e163332001-02-27 18:36:56 +0000476 def popitem(self):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200477 self._dirty_len = True
Georg Brandlbd87d082010-12-03 07:49:09 +0000478 while True:
Martin v. Löwis5e163332001-02-27 18:36:56 +0000479 key, value = self.data.popitem()
480 o = key()
481 if o is not None:
482 return o, value
483
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000484 def pop(self, key, *args):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200485 self._dirty_len = True
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000486 return self.data.pop(ref(key), *args)
487
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000488 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000489 return self.data.setdefault(ref(key, self._remove),default)
490
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000491 def update(self, dict=None, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000492 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000493 if dict is not None:
494 if not hasattr(dict, "items"):
495 dict = type({})(dict)
496 for key, value in dict.items():
497 d[ref(key, self._remove)] = value
498 if len(kwargs):
499 self.update(kwargs)
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100500
501
502class finalize:
503 """Class for finalization of weakrefable objects
504
505 finalize(obj, func, *args, **kwargs) returns a callable finalizer
506 object which will be called when obj is garbage collected. The
507 first time the finalizer is called it evaluates func(*arg, **kwargs)
508 and returns the result. After this the finalizer is dead, and
509 calling it just returns None.
510
511 When the program exits any remaining finalizers for which the
512 atexit attribute is true will be run in reverse order of creation.
513 By default atexit is true.
514 """
515
516 # Finalizer objects don't have any state of their own. They are
517 # just used as keys to lookup _Info objects in the registry. This
518 # ensures that they cannot be part of a ref-cycle.
519
520 __slots__ = ()
521 _registry = {}
522 _shutdown = False
523 _index_iter = itertools.count()
524 _dirty = False
Richard Oudkerka81dd652013-06-08 16:52:29 +0100525 _registered_with_atexit = False
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100526
527 class _Info:
528 __slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index")
529
530 def __init__(self, obj, func, *args, **kwargs):
Richard Oudkerka81dd652013-06-08 16:52:29 +0100531 if not self._registered_with_atexit:
532 # We may register the exit function more than once because
533 # of a thread race, but that is harmless
534 import atexit
535 atexit.register(self._exitfunc)
536 finalize._registered_with_atexit = True
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100537 info = self._Info()
538 info.weakref = ref(obj, self)
539 info.func = func
540 info.args = args
541 info.kwargs = kwargs or None
542 info.atexit = True
543 info.index = next(self._index_iter)
544 self._registry[self] = info
545 finalize._dirty = True
546
547 def __call__(self, _=None):
548 """If alive then mark as dead and return func(*args, **kwargs);
549 otherwise return None"""
550 info = self._registry.pop(self, None)
551 if info and not self._shutdown:
552 return info.func(*info.args, **(info.kwargs or {}))
553
554 def detach(self):
555 """If alive then mark as dead and return (obj, func, args, kwargs);
556 otherwise return None"""
557 info = self._registry.get(self)
558 obj = info and info.weakref()
559 if obj is not None and self._registry.pop(self, None):
560 return (obj, info.func, info.args, info.kwargs or {})
561
562 def peek(self):
563 """If alive then return (obj, func, args, kwargs);
564 otherwise return None"""
565 info = self._registry.get(self)
566 obj = info and info.weakref()
567 if obj is not None:
568 return (obj, info.func, info.args, info.kwargs or {})
569
570 @property
571 def alive(self):
572 """Whether finalizer is alive"""
573 return self in self._registry
574
575 @property
576 def atexit(self):
577 """Whether finalizer should be called at exit"""
578 info = self._registry.get(self)
579 return bool(info) and info.atexit
580
581 @atexit.setter
582 def atexit(self, value):
583 info = self._registry.get(self)
584 if info:
585 info.atexit = bool(value)
586
587 def __repr__(self):
588 info = self._registry.get(self)
589 obj = info and info.weakref()
590 if obj is None:
591 return '<%s object at %#x; dead>' % (type(self).__name__, id(self))
592 else:
593 return '<%s object at %#x; for %r at %#x>' % \
594 (type(self).__name__, id(self), type(obj).__name__, id(obj))
595
596 @classmethod
597 def _select_for_exit(cls):
598 # Return live finalizers marked for exit, oldest first
599 L = [(f,i) for (f,i) in cls._registry.items() if i.atexit]
600 L.sort(key=lambda item:item[1].index)
601 return [f for (f,i) in L]
602
603 @classmethod
604 def _exitfunc(cls):
605 # At shutdown invoke finalizers for which atexit is true.
606 # This is called once all other non-daemonic threads have been
607 # joined.
608 reenable_gc = False
609 try:
610 if cls._registry:
611 import gc
612 if gc.isenabled():
613 reenable_gc = True
614 gc.disable()
615 pending = None
616 while True:
617 if pending is None or finalize._dirty:
618 pending = cls._select_for_exit()
619 finalize._dirty = False
620 if not pending:
621 break
622 f = pending.pop()
623 try:
624 # gc is disabled, so (assuming no daemonic
625 # threads) the following is the only line in
626 # this function which might trigger creation
627 # of a new finalizer
628 f()
629 except Exception:
630 sys.excepthook(*sys.exc_info())
631 assert f not in cls._registry
632 finally:
633 # prevent any more finalizers from executing during shutdown
634 finalize._shutdown = True
635 if reenable_gc:
636 gc.enable()