blob: 12bf9754c52e4ddd7e02e8906950192464e8bf56 [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()
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200325 self._dirty_len = False
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000326 if dict is not None:
327 self.update(dict)
328
329 def _commit_removals(self):
330 # NOTE: We don't need to call this method before mutating the dict,
331 # because a dead weakref never compares equal to a live weakref,
332 # even if they happened to refer to equal objects.
333 # However, it means keys may already have been removed.
334 l = self._pending_removals
335 d = self.data
336 while l:
337 try:
338 del d[l.pop()]
339 except KeyError:
340 pass
Martin v. Löwis5e163332001-02-27 18:36:56 +0000341
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200342 def _scrub_removals(self):
343 d = self.data
344 self._pending_removals = [k for k in self._pending_removals if k in d]
345 self._dirty_len = False
346
Fred Drakeb663a2c2001-09-06 14:51:01 +0000347 def __delitem__(self, key):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200348 self._dirty_len = True
Tim Peters886128f2003-05-25 01:45:11 +0000349 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000350
Martin v. Löwis5e163332001-02-27 18:36:56 +0000351 def __getitem__(self, key):
352 return self.data[ref(key)]
353
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000354 def __len__(self):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200355 if self._dirty_len and self._pending_removals:
356 # self._pending_removals may still contain keys which were
357 # explicitly removed, we have to scrub them (see issue #21173).
358 self._scrub_removals()
Antoine Pitroubbe2f602012-03-01 16:26:35 +0100359 return len(self.data) - len(self._pending_removals)
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000360
Martin v. Löwis5e163332001-02-27 18:36:56 +0000361 def __repr__(self):
362 return "<WeakKeyDictionary at %s>" % id(self)
363
364 def __setitem__(self, key, value):
365 self.data[ref(key, self._remove)] = value
366
367 def copy(self):
368 new = WeakKeyDictionary()
369 for key, value in self.data.items():
370 o = key()
371 if o is not None:
372 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000373 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000374
Antoine Pitrou6e610062009-05-15 17:04:50 +0000375 __copy__ = copy
376
377 def __deepcopy__(self, memo):
378 from copy import deepcopy
379 new = self.__class__()
380 for key, value in self.data.items():
381 o = key()
382 if o is not None:
383 new[o] = deepcopy(value, memo)
384 return new
385
Fred Drake1d9e4b72001-04-16 17:34:48 +0000386 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000387 return self.data.get(ref(key),default)
388
Raymond Hettinger54f02222002-06-01 14:18:47 +0000389 def __contains__(self, key):
390 try:
391 wr = ref(key)
392 except TypeError:
Georg Brandlbd87d082010-12-03 07:49:09 +0000393 return False
Raymond Hettinger54f02222002-06-01 14:18:47 +0000394 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000395
Martin v. Löwis5e163332001-02-27 18:36:56 +0000396 def items(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000397 with _IterationGuard(self):
398 for wr, value in self.data.items():
399 key = wr()
400 if key is not None:
401 yield key, value
Thomas Wouters477c8d52006-05-27 19:21:47 +0000402
Barry Warsawecaab832008-09-04 01:42:51 +0000403 def keys(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000404 with _IterationGuard(self):
405 for wr in self.data:
406 obj = wr()
407 if obj is not None:
408 yield obj
Raymond Hettinger61146792004-08-19 21:32:06 +0000409
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000410 __iter__ = keys
Fred Drake101209d2001-05-02 05:43:09 +0000411
Barry Warsawecaab832008-09-04 01:42:51 +0000412 def values(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000413 with _IterationGuard(self):
414 for wr, value in self.data.items():
415 if wr() is not None:
416 yield value
Fred Drake101209d2001-05-02 05:43:09 +0000417
Thomas Wouters477c8d52006-05-27 19:21:47 +0000418 def keyrefs(self):
419 """Return a list of weak references to the keys.
420
421 The references are not guaranteed to be 'live' at the time
422 they are used, so the result of calling the references needs
423 to be checked before being used. This can be used to avoid
424 creating references that will cause the garbage collector to
425 keep the keys around longer than needed.
426
427 """
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000428 return list(self.data)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000429
Martin v. Löwis5e163332001-02-27 18:36:56 +0000430 def popitem(self):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200431 self._dirty_len = True
Georg Brandlbd87d082010-12-03 07:49:09 +0000432 while True:
Martin v. Löwis5e163332001-02-27 18:36:56 +0000433 key, value = self.data.popitem()
434 o = key()
435 if o is not None:
436 return o, value
437
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000438 def pop(self, key, *args):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200439 self._dirty_len = True
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000440 return self.data.pop(ref(key), *args)
441
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000442 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000443 return self.data.setdefault(ref(key, self._remove),default)
444
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000445 def update(self, dict=None, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000446 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000447 if dict is not None:
448 if not hasattr(dict, "items"):
449 dict = type({})(dict)
450 for key, value in dict.items():
451 d[ref(key, self._remove)] = value
452 if len(kwargs):
453 self.update(kwargs)
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100454
455
456class finalize:
457 """Class for finalization of weakrefable objects
458
459 finalize(obj, func, *args, **kwargs) returns a callable finalizer
460 object which will be called when obj is garbage collected. The
461 first time the finalizer is called it evaluates func(*arg, **kwargs)
462 and returns the result. After this the finalizer is dead, and
463 calling it just returns None.
464
465 When the program exits any remaining finalizers for which the
466 atexit attribute is true will be run in reverse order of creation.
467 By default atexit is true.
468 """
469
470 # Finalizer objects don't have any state of their own. They are
471 # just used as keys to lookup _Info objects in the registry. This
472 # ensures that they cannot be part of a ref-cycle.
473
474 __slots__ = ()
475 _registry = {}
476 _shutdown = False
477 _index_iter = itertools.count()
478 _dirty = False
Richard Oudkerka81dd652013-06-08 16:52:29 +0100479 _registered_with_atexit = False
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100480
481 class _Info:
482 __slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index")
483
484 def __init__(self, obj, func, *args, **kwargs):
Richard Oudkerka81dd652013-06-08 16:52:29 +0100485 if not self._registered_with_atexit:
486 # We may register the exit function more than once because
487 # of a thread race, but that is harmless
488 import atexit
489 atexit.register(self._exitfunc)
490 finalize._registered_with_atexit = True
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100491 info = self._Info()
492 info.weakref = ref(obj, self)
493 info.func = func
494 info.args = args
495 info.kwargs = kwargs or None
496 info.atexit = True
497 info.index = next(self._index_iter)
498 self._registry[self] = info
499 finalize._dirty = True
500
501 def __call__(self, _=None):
502 """If alive then mark as dead and return func(*args, **kwargs);
503 otherwise return None"""
504 info = self._registry.pop(self, None)
505 if info and not self._shutdown:
506 return info.func(*info.args, **(info.kwargs or {}))
507
508 def detach(self):
509 """If alive then mark as dead and return (obj, func, args, kwargs);
510 otherwise return None"""
511 info = self._registry.get(self)
512 obj = info and info.weakref()
513 if obj is not None and self._registry.pop(self, None):
514 return (obj, info.func, info.args, info.kwargs or {})
515
516 def peek(self):
517 """If alive then return (obj, func, args, kwargs);
518 otherwise return None"""
519 info = self._registry.get(self)
520 obj = info and info.weakref()
521 if obj is not None:
522 return (obj, info.func, info.args, info.kwargs or {})
523
524 @property
525 def alive(self):
526 """Whether finalizer is alive"""
527 return self in self._registry
528
529 @property
530 def atexit(self):
531 """Whether finalizer should be called at exit"""
532 info = self._registry.get(self)
533 return bool(info) and info.atexit
534
535 @atexit.setter
536 def atexit(self, value):
537 info = self._registry.get(self)
538 if info:
539 info.atexit = bool(value)
540
541 def __repr__(self):
542 info = self._registry.get(self)
543 obj = info and info.weakref()
544 if obj is None:
545 return '<%s object at %#x; dead>' % (type(self).__name__, id(self))
546 else:
547 return '<%s object at %#x; for %r at %#x>' % \
548 (type(self).__name__, id(self), type(obj).__name__, id(obj))
549
550 @classmethod
551 def _select_for_exit(cls):
552 # Return live finalizers marked for exit, oldest first
553 L = [(f,i) for (f,i) in cls._registry.items() if i.atexit]
554 L.sort(key=lambda item:item[1].index)
555 return [f for (f,i) in L]
556
557 @classmethod
558 def _exitfunc(cls):
559 # At shutdown invoke finalizers for which atexit is true.
560 # This is called once all other non-daemonic threads have been
561 # joined.
562 reenable_gc = False
563 try:
564 if cls._registry:
565 import gc
566 if gc.isenabled():
567 reenable_gc = True
568 gc.disable()
569 pending = None
570 while True:
571 if pending is None or finalize._dirty:
572 pending = cls._select_for_exit()
573 finalize._dirty = False
574 if not pending:
575 break
576 f = pending.pop()
577 try:
578 # gc is disabled, so (assuming no daemonic
579 # threads) the following is the only line in
580 # this function which might trigger creation
581 # of a new finalizer
582 f()
583 except Exception:
584 sys.excepthook(*sys.exc_info())
585 assert f not in cls._registry
586 finally:
587 # prevent any more finalizers from executing during shutdown
588 finalize._shutdown = True
589 if reenable_gc:
590 gc.enable()