blob: f6a40ca4bf7d613c452ffb2c4a0ac4905b385477 [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,
19 ReferenceType)
Fred Drake41deb1e2001-02-01 05:27:45 +000020
Antoine Pitrouc1baa602010-01-08 17:54:23 +000021from _weakrefset import WeakSet, _IterationGuard
Fred Drakee0292422001-10-05 21:54:09 +000022
Brett Cannon663fffa2009-03-25 23:31:22 +000023import collections # Import after _weakref to avoid circular import.
Richard Oudkerk7a3dae02013-05-05 23:05:00 +010024import sys
25import itertools
Brett Cannon663fffa2009-03-25 23:31:22 +000026
Fred Drake41deb1e2001-02-01 05:27:45 +000027ProxyTypes = (ProxyType, CallableProxyType)
28
Fred Drake9a9d2192001-04-10 19:11:23 +000029__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
Gregory P. Smith7d10c2b2008-08-18 03:41:46 +000030 "WeakKeyDictionary", "ReferenceType", "ProxyType",
Raymond Hettinger93fa6082008-02-05 00:20:01 +000031 "CallableProxyType", "ProxyTypes", "WeakValueDictionary",
Richard Oudkerk7a3dae02013-05-05 23:05:00 +010032 "WeakSet", "WeakMethod", "finalize"]
Antoine Pitrouc3afba12012-11-17 18:57:38 +010033
34
35class WeakMethod(ref):
36 """
37 A custom `weakref.ref` subclass which simulates a weak reference to
38 a bound method, working around the lifetime problem of bound methods.
39 """
40
41 __slots__ = "_func_ref", "_meth_type", "_alive", "__weakref__"
42
43 def __new__(cls, meth, callback=None):
44 try:
45 obj = meth.__self__
46 func = meth.__func__
47 except AttributeError:
48 raise TypeError("argument should be a bound method, not {}"
49 .format(type(meth))) from None
50 def _cb(arg):
51 # The self-weakref trick is needed to avoid creating a reference
52 # cycle.
53 self = self_wr()
54 if self._alive:
55 self._alive = False
56 if callback is not None:
57 callback(self)
58 self = ref.__new__(cls, obj, _cb)
59 self._func_ref = ref(func, _cb)
60 self._meth_type = type(meth)
61 self._alive = True
62 self_wr = ref(self)
63 return self
64
65 def __call__(self):
66 obj = super().__call__()
67 func = self._func_ref()
68 if obj is None or func is None:
69 return None
70 return self._meth_type(func, obj)
71
72 def __eq__(self, other):
73 if isinstance(other, WeakMethod):
74 if not self._alive or not other._alive:
75 return self is other
76 return ref.__eq__(self, other) and self._func_ref == other._func_ref
77 return False
78
79 def __ne__(self, other):
80 if isinstance(other, WeakMethod):
81 if not self._alive or not other._alive:
82 return self is not other
83 return ref.__ne__(self, other) or self._func_ref != other._func_ref
84 return True
85
86 __hash__ = ref.__hash__
Fred Drake41deb1e2001-02-01 05:27:45 +000087
Fred Drake41deb1e2001-02-01 05:27:45 +000088
Raymond Hettinger7ac60952008-02-05 01:15:57 +000089class WeakValueDictionary(collections.MutableMapping):
Fred Drakebd7f8182001-04-19 16:26:06 +000090 """Mapping class that references values weakly.
91
92 Entries in the dictionary will be discarded when no strong
93 reference to the value exists anymore
94 """
Fred Drake41deb1e2001-02-01 05:27:45 +000095 # We inherit the constructor without worrying about the input
96 # dictionary; since it uses our .update() method, we get the right
Fred Drake9d2c85d2001-03-01 03:06:03 +000097 # checks (if the other dictionary is a WeakValueDictionary,
98 # objects are unwrapped on the way out, and we always wrap on the
99 # way in).
Fred Drake41deb1e2001-02-01 05:27:45 +0000100
Fred Drake0a4dd392004-07-02 18:57:45 +0000101 def __init__(self, *args, **kw):
Fred Drake0a4dd392004-07-02 18:57:45 +0000102 def remove(wr, selfref=ref(self)):
103 self = selfref()
104 if self is not None:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000105 if self._iterating:
106 self._pending_removals.append(wr.key)
107 else:
108 del self.data[wr.key]
Fred Drake0a4dd392004-07-02 18:57:45 +0000109 self._remove = remove
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000110 # A list of keys to be removed
111 self._pending_removals = []
112 self._iterating = set()
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000113 self.data = d = {}
Antoine Pitrouc06de472009-05-30 21:04:26 +0000114 self.update(*args, **kw)
Fred Drake0a4dd392004-07-02 18:57:45 +0000115
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000116 def _commit_removals(self):
117 l = self._pending_removals
118 d = self.data
119 # We shouldn't encounter any KeyError, because this method should
120 # always be called *before* mutating the dict.
121 while l:
122 del d[l.pop()]
123
Fred Drake41deb1e2001-02-01 05:27:45 +0000124 def __getitem__(self, key):
Fred Drake4fd06e02001-08-03 04:11:27 +0000125 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +0000126 if o is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000127 raise KeyError(key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000128 else:
129 return o
130
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000131 def __delitem__(self, key):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000132 if self._pending_removals:
133 self._commit_removals()
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000134 del self.data[key]
135
136 def __len__(self):
Antoine Pitroubbe2f602012-03-01 16:26:35 +0100137 return len(self.data) - len(self._pending_removals)
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000138
Raymond Hettinger61146792004-08-19 21:32:06 +0000139 def __contains__(self, key):
140 try:
141 o = self.data[key]()
142 except KeyError:
143 return False
144 return o is not None
145
Fred Drake41deb1e2001-02-01 05:27:45 +0000146 def __repr__(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +0000147 return "<WeakValueDictionary at %s>" % id(self)
Fred Drake41deb1e2001-02-01 05:27:45 +0000148
149 def __setitem__(self, key, value):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000150 if self._pending_removals:
151 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +0000152 self.data[key] = KeyedRef(value, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000153
154 def copy(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +0000155 new = WeakValueDictionary()
Fred Drakebd7f8182001-04-19 16:26:06 +0000156 for key, wr in self.data.items():
157 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000158 if o is not None:
159 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +0000160 return new
Fred Drake41deb1e2001-02-01 05:27:45 +0000161
Antoine Pitrou6e610062009-05-15 17:04:50 +0000162 __copy__ = copy
163
164 def __deepcopy__(self, memo):
165 from copy import deepcopy
166 new = self.__class__()
167 for key, wr in self.data.items():
168 o = wr()
169 if o is not None:
170 new[deepcopy(key, memo)] = o
171 return new
172
Fred Drake1d9e4b72001-04-16 17:34:48 +0000173 def get(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000174 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000175 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000176 except KeyError:
177 return default
178 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000179 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000180 if o is None:
181 # This should only happen
182 return default
183 else:
184 return o
185
186 def items(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000187 with _IterationGuard(self):
188 for k, wr in self.data.items():
189 v = wr()
190 if v is not None:
191 yield k, v
Fred Drake101209d2001-05-02 05:43:09 +0000192
Barry Warsawecaab832008-09-04 01:42:51 +0000193 def keys(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000194 with _IterationGuard(self):
195 for k, wr in self.data.items():
196 if wr() is not None:
197 yield k
Raymond Hettinger61146792004-08-19 21:32:06 +0000198
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000199 __iter__ = keys
Fred Drake101209d2001-05-02 05:43:09 +0000200
Thomas Wouters477c8d52006-05-27 19:21:47 +0000201 def itervaluerefs(self):
202 """Return an iterator that yields the weak references to the values.
203
204 The references are not guaranteed to be 'live' at the time
205 they are used, so the result of calling the references needs
206 to be checked before being used. This can be used to avoid
207 creating references that will cause the garbage collector to
208 keep the values around longer than needed.
209
210 """
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000211 with _IterationGuard(self):
Philip Jenvey4993cc02012-10-01 12:53:43 -0700212 yield from self.data.values()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000213
Barry Warsawecaab832008-09-04 01:42:51 +0000214 def values(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000215 with _IterationGuard(self):
216 for wr in self.data.values():
217 obj = wr()
218 if obj is not None:
219 yield obj
Fred Drake101209d2001-05-02 05:43:09 +0000220
Fred Drake41deb1e2001-02-01 05:27:45 +0000221 def popitem(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000222 if self._pending_removals:
223 self._commit_removals()
Georg Brandlbd87d082010-12-03 07:49:09 +0000224 while True:
Fred Drakebd7f8182001-04-19 16:26:06 +0000225 key, wr = self.data.popitem()
226 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000227 if o is not None:
228 return key, o
229
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000230 def pop(self, key, *args):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000231 if self._pending_removals:
232 self._commit_removals()
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000233 try:
234 o = self.data.pop(key)()
235 except KeyError:
236 if args:
237 return args[0]
238 raise
239 if o is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000240 raise KeyError(key)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000241 else:
242 return o
243
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000244 def setdefault(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000245 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000246 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000247 except KeyError:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000248 if self._pending_removals:
249 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +0000250 self.data[key] = KeyedRef(default, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000251 return default
252 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000253 return wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000254
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000255 def update(self, dict=None, **kwargs):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000256 if self._pending_removals:
257 self._commit_removals()
Fred Drake41deb1e2001-02-01 05:27:45 +0000258 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000259 if dict is not None:
260 if not hasattr(dict, "items"):
261 dict = type({})(dict)
262 for key, o in dict.items():
Fred Drake0a4dd392004-07-02 18:57:45 +0000263 d[key] = KeyedRef(o, self._remove, key)
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000264 if len(kwargs):
265 self.update(kwargs)
Fred Drake41deb1e2001-02-01 05:27:45 +0000266
Thomas Wouters477c8d52006-05-27 19:21:47 +0000267 def valuerefs(self):
268 """Return a list of weak references to the values.
269
270 The references are not guaranteed to be 'live' at the time
271 they are used, so the result of calling the references needs
272 to be checked before being used. This can be used to avoid
273 creating references that will cause the garbage collector to
274 keep the values around longer than needed.
275
276 """
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000277 return list(self.data.values())
Thomas Wouters477c8d52006-05-27 19:21:47 +0000278
Fred Drake0a4dd392004-07-02 18:57:45 +0000279
280class KeyedRef(ref):
281 """Specialized reference that includes a key corresponding to the value.
282
283 This is used in the WeakValueDictionary to avoid having to create
284 a function object for each key stored in the mapping. A shared
285 callback object can use the 'key' attribute of a KeyedRef instead
286 of getting a reference to the key from an enclosing scope.
287
288 """
289
290 __slots__ = "key",
291
292 def __new__(type, ob, callback, key):
293 self = ref.__new__(type, ob, callback)
294 self.key = key
295 return self
296
297 def __init__(self, ob, callback, key):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000298 super().__init__(ob, callback)
Fred Drake746fe0f2001-09-28 19:01:26 +0000299
Fred Drake41deb1e2001-02-01 05:27:45 +0000300
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000301class WeakKeyDictionary(collections.MutableMapping):
Fred Drakebd7f8182001-04-19 16:26:06 +0000302 """ Mapping class that references keys weakly.
303
304 Entries in the dictionary will be discarded when there is no
305 longer a strong reference to the key. This can be used to
306 associate additional data with an object owned by other parts of
307 an application without adding attributes to those objects. This
308 can be especially useful with objects that override attribute
309 accesses.
310 """
Martin v. Löwis5e163332001-02-27 18:36:56 +0000311
312 def __init__(self, dict=None):
313 self.data = {}
Fred Drake746fe0f2001-09-28 19:01:26 +0000314 def remove(k, selfref=ref(self)):
315 self = selfref()
316 if self is not None:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000317 if self._iterating:
318 self._pending_removals.append(k)
319 else:
320 del self.data[k]
Martin v. Löwis5e163332001-02-27 18:36:56 +0000321 self._remove = remove
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000322 # A list of dead weakrefs (keys to be removed)
323 self._pending_removals = []
324 self._iterating = set()
325 if dict is not None:
326 self.update(dict)
327
328 def _commit_removals(self):
329 # NOTE: We don't need to call this method before mutating the dict,
330 # because a dead weakref never compares equal to a live weakref,
331 # even if they happened to refer to equal objects.
332 # However, it means keys may already have been removed.
333 l = self._pending_removals
334 d = self.data
335 while l:
336 try:
337 del d[l.pop()]
338 except KeyError:
339 pass
Martin v. Löwis5e163332001-02-27 18:36:56 +0000340
Fred Drakeb663a2c2001-09-06 14:51:01 +0000341 def __delitem__(self, key):
Tim Peters886128f2003-05-25 01:45:11 +0000342 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000343
Martin v. Löwis5e163332001-02-27 18:36:56 +0000344 def __getitem__(self, key):
345 return self.data[ref(key)]
346
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000347 def __len__(self):
Antoine Pitroubbe2f602012-03-01 16:26:35 +0100348 return len(self.data) - len(self._pending_removals)
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000349
Martin v. Löwis5e163332001-02-27 18:36:56 +0000350 def __repr__(self):
351 return "<WeakKeyDictionary at %s>" % id(self)
352
353 def __setitem__(self, key, value):
354 self.data[ref(key, self._remove)] = value
355
356 def copy(self):
357 new = WeakKeyDictionary()
358 for key, value in self.data.items():
359 o = key()
360 if o is not None:
361 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000362 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000363
Antoine Pitrou6e610062009-05-15 17:04:50 +0000364 __copy__ = copy
365
366 def __deepcopy__(self, memo):
367 from copy import deepcopy
368 new = self.__class__()
369 for key, value in self.data.items():
370 o = key()
371 if o is not None:
372 new[o] = deepcopy(value, memo)
373 return new
374
Fred Drake1d9e4b72001-04-16 17:34:48 +0000375 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000376 return self.data.get(ref(key),default)
377
Raymond Hettinger54f02222002-06-01 14:18:47 +0000378 def __contains__(self, key):
379 try:
380 wr = ref(key)
381 except TypeError:
Georg Brandlbd87d082010-12-03 07:49:09 +0000382 return False
Raymond Hettinger54f02222002-06-01 14:18:47 +0000383 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000384
Martin v. Löwis5e163332001-02-27 18:36:56 +0000385 def items(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000386 with _IterationGuard(self):
387 for wr, value in self.data.items():
388 key = wr()
389 if key is not None:
390 yield key, value
Thomas Wouters477c8d52006-05-27 19:21:47 +0000391
Barry Warsawecaab832008-09-04 01:42:51 +0000392 def keys(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000393 with _IterationGuard(self):
394 for wr in self.data:
395 obj = wr()
396 if obj is not None:
397 yield obj
Raymond Hettinger61146792004-08-19 21:32:06 +0000398
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000399 __iter__ = keys
Fred Drake101209d2001-05-02 05:43:09 +0000400
Barry Warsawecaab832008-09-04 01:42:51 +0000401 def values(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000402 with _IterationGuard(self):
403 for wr, value in self.data.items():
404 if wr() is not None:
405 yield value
Fred Drake101209d2001-05-02 05:43:09 +0000406
Thomas Wouters477c8d52006-05-27 19:21:47 +0000407 def keyrefs(self):
408 """Return a list of weak references to the keys.
409
410 The references are not guaranteed to be 'live' at the time
411 they are used, so the result of calling the references needs
412 to be checked before being used. This can be used to avoid
413 creating references that will cause the garbage collector to
414 keep the keys around longer than needed.
415
416 """
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000417 return list(self.data)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000418
Martin v. Löwis5e163332001-02-27 18:36:56 +0000419 def popitem(self):
Georg Brandlbd87d082010-12-03 07:49:09 +0000420 while True:
Martin v. Löwis5e163332001-02-27 18:36:56 +0000421 key, value = self.data.popitem()
422 o = key()
423 if o is not None:
424 return o, value
425
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000426 def pop(self, key, *args):
427 return self.data.pop(ref(key), *args)
428
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000429 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000430 return self.data.setdefault(ref(key, self._remove),default)
431
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000432 def update(self, dict=None, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000433 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000434 if dict is not None:
435 if not hasattr(dict, "items"):
436 dict = type({})(dict)
437 for key, value in dict.items():
438 d[ref(key, self._remove)] = value
439 if len(kwargs):
440 self.update(kwargs)
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100441
442
443class finalize:
444 """Class for finalization of weakrefable objects
445
446 finalize(obj, func, *args, **kwargs) returns a callable finalizer
447 object which will be called when obj is garbage collected. The
448 first time the finalizer is called it evaluates func(*arg, **kwargs)
449 and returns the result. After this the finalizer is dead, and
450 calling it just returns None.
451
452 When the program exits any remaining finalizers for which the
453 atexit attribute is true will be run in reverse order of creation.
454 By default atexit is true.
455 """
456
457 # Finalizer objects don't have any state of their own. They are
458 # just used as keys to lookup _Info objects in the registry. This
459 # ensures that they cannot be part of a ref-cycle.
460
461 __slots__ = ()
462 _registry = {}
463 _shutdown = False
464 _index_iter = itertools.count()
465 _dirty = False
Richard Oudkerka81dd652013-06-08 16:52:29 +0100466 _registered_with_atexit = False
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100467
468 class _Info:
469 __slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index")
470
471 def __init__(self, obj, func, *args, **kwargs):
Richard Oudkerka81dd652013-06-08 16:52:29 +0100472 if not self._registered_with_atexit:
473 # We may register the exit function more than once because
474 # of a thread race, but that is harmless
475 import atexit
476 atexit.register(self._exitfunc)
477 finalize._registered_with_atexit = True
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100478 info = self._Info()
479 info.weakref = ref(obj, self)
480 info.func = func
481 info.args = args
482 info.kwargs = kwargs or None
483 info.atexit = True
484 info.index = next(self._index_iter)
485 self._registry[self] = info
486 finalize._dirty = True
487
488 def __call__(self, _=None):
489 """If alive then mark as dead and return func(*args, **kwargs);
490 otherwise return None"""
491 info = self._registry.pop(self, None)
492 if info and not self._shutdown:
493 return info.func(*info.args, **(info.kwargs or {}))
494
495 def detach(self):
496 """If alive then mark as dead and return (obj, func, args, kwargs);
497 otherwise return None"""
498 info = self._registry.get(self)
499 obj = info and info.weakref()
500 if obj is not None and self._registry.pop(self, None):
501 return (obj, info.func, info.args, info.kwargs or {})
502
503 def peek(self):
504 """If alive then return (obj, func, args, kwargs);
505 otherwise return None"""
506 info = self._registry.get(self)
507 obj = info and info.weakref()
508 if obj is not None:
509 return (obj, info.func, info.args, info.kwargs or {})
510
511 @property
512 def alive(self):
513 """Whether finalizer is alive"""
514 return self in self._registry
515
516 @property
517 def atexit(self):
518 """Whether finalizer should be called at exit"""
519 info = self._registry.get(self)
520 return bool(info) and info.atexit
521
522 @atexit.setter
523 def atexit(self, value):
524 info = self._registry.get(self)
525 if info:
526 info.atexit = bool(value)
527
528 def __repr__(self):
529 info = self._registry.get(self)
530 obj = info and info.weakref()
531 if obj is None:
532 return '<%s object at %#x; dead>' % (type(self).__name__, id(self))
533 else:
534 return '<%s object at %#x; for %r at %#x>' % \
535 (type(self).__name__, id(self), type(obj).__name__, id(obj))
536
537 @classmethod
538 def _select_for_exit(cls):
539 # Return live finalizers marked for exit, oldest first
540 L = [(f,i) for (f,i) in cls._registry.items() if i.atexit]
541 L.sort(key=lambda item:item[1].index)
542 return [f for (f,i) in L]
543
544 @classmethod
545 def _exitfunc(cls):
546 # At shutdown invoke finalizers for which atexit is true.
547 # This is called once all other non-daemonic threads have been
548 # joined.
549 reenable_gc = False
550 try:
551 if cls._registry:
552 import gc
553 if gc.isenabled():
554 reenable_gc = True
555 gc.disable()
556 pending = None
557 while True:
558 if pending is None or finalize._dirty:
559 pending = cls._select_for_exit()
560 finalize._dirty = False
561 if not pending:
562 break
563 f = pending.pop()
564 try:
565 # gc is disabled, so (assuming no daemonic
566 # threads) the following is the only line in
567 # this function which might trigger creation
568 # of a new finalizer
569 f()
570 except Exception:
571 sys.excepthook(*sys.exc_info())
572 assert f not in cls._registry
573 finally:
574 # prevent any more finalizers from executing during shutdown
575 finalize._shutdown = True
576 if reenable_gc:
577 gc.enable()