blob: 5fa851dd6d771cded9eb7d1fac099e99d09c0ed9 [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
Raymond Hettinger84ac4372019-11-10 20:12:04 -080036_collections_abc.Set.register(WeakSet)
37_collections_abc.MutableSet.register(WeakSet)
38
Antoine Pitrouc3afba12012-11-17 18:57:38 +010039class WeakMethod(ref):
40 """
41 A custom `weakref.ref` subclass which simulates a weak reference to
42 a bound method, working around the lifetime problem of bound methods.
43 """
44
45 __slots__ = "_func_ref", "_meth_type", "_alive", "__weakref__"
46
47 def __new__(cls, meth, callback=None):
48 try:
49 obj = meth.__self__
50 func = meth.__func__
51 except AttributeError:
52 raise TypeError("argument should be a bound method, not {}"
53 .format(type(meth))) from None
54 def _cb(arg):
55 # The self-weakref trick is needed to avoid creating a reference
56 # cycle.
57 self = self_wr()
58 if self._alive:
59 self._alive = False
60 if callback is not None:
61 callback(self)
62 self = ref.__new__(cls, obj, _cb)
63 self._func_ref = ref(func, _cb)
64 self._meth_type = type(meth)
65 self._alive = True
66 self_wr = ref(self)
67 return self
68
69 def __call__(self):
70 obj = super().__call__()
71 func = self._func_ref()
72 if obj is None or func is None:
73 return None
74 return self._meth_type(func, obj)
75
76 def __eq__(self, other):
77 if isinstance(other, WeakMethod):
78 if not self._alive or not other._alive:
79 return self is other
80 return ref.__eq__(self, other) and self._func_ref == other._func_ref
Serhiy Storchaka662db122019-08-08 08:42:54 +030081 return NotImplemented
Antoine Pitrouc3afba12012-11-17 18:57:38 +010082
83 def __ne__(self, other):
84 if isinstance(other, WeakMethod):
85 if not self._alive or not other._alive:
86 return self is not other
87 return ref.__ne__(self, other) or self._func_ref != other._func_ref
Serhiy Storchaka662db122019-08-08 08:42:54 +030088 return NotImplemented
Antoine Pitrouc3afba12012-11-17 18:57:38 +010089
90 __hash__ = ref.__hash__
Fred Drake41deb1e2001-02-01 05:27:45 +000091
Fred Drake41deb1e2001-02-01 05:27:45 +000092
Serhiy Storchaka81108372017-09-26 00:55:55 +030093class WeakValueDictionary(_collections_abc.MutableMapping):
Fred Drakebd7f8182001-04-19 16:26:06 +000094 """Mapping class that references values weakly.
95
96 Entries in the dictionary will be discarded when no strong
97 reference to the value exists anymore
98 """
Fred Drake41deb1e2001-02-01 05:27:45 +000099 # We inherit the constructor without worrying about the input
100 # dictionary; since it uses our .update() method, we get the right
Fred Drake9d2c85d2001-03-01 03:06:03 +0000101 # checks (if the other dictionary is a WeakValueDictionary,
102 # objects are unwrapped on the way out, and we always wrap on the
103 # way in).
Fred Drake41deb1e2001-02-01 05:27:45 +0000104
Serhiy Storchaka2085bd02019-06-01 11:00:15 +0300105 def __init__(self, other=(), /, **kw):
Ɓukasz Langa9cd7e172017-02-10 00:14:55 -0800106 def remove(wr, selfref=ref(self), _atomic_removal=_remove_dead_weakref):
Fred Drake0a4dd392004-07-02 18:57:45 +0000107 self = selfref()
108 if self is not None:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000109 if self._iterating:
110 self._pending_removals.append(wr.key)
111 else:
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100112 # Atomic removal is necessary since this function
113 # can be called asynchronously by the GC
Victor Stinnera2af05a2019-09-09 16:55:58 +0200114 _atomic_removal(self.data, wr.key)
Fred Drake0a4dd392004-07-02 18:57:45 +0000115 self._remove = remove
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000116 # A list of keys to be removed
117 self._pending_removals = []
118 self._iterating = set()
Victor Stinnera2af05a2019-09-09 16:55:58 +0200119 self.data = {}
Serhiy Storchaka2085bd02019-06-01 11:00:15 +0300120 self.update(other, **kw)
Fred Drake0a4dd392004-07-02 18:57:45 +0000121
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000122 def _commit_removals(self):
123 l = self._pending_removals
124 d = self.data
125 # We shouldn't encounter any KeyError, because this method should
126 # always be called *before* mutating the dict.
127 while l:
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100128 key = l.pop()
129 _remove_dead_weakref(d, key)
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000130
Fred Drake41deb1e2001-02-01 05:27:45 +0000131 def __getitem__(self, key):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100132 if self._pending_removals:
133 self._commit_removals()
Fred Drake4fd06e02001-08-03 04:11:27 +0000134 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +0000135 if o is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000136 raise KeyError(key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000137 else:
138 return o
139
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000140 def __delitem__(self, key):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000141 if self._pending_removals:
142 self._commit_removals()
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000143 del self.data[key]
144
145 def __len__(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100146 if self._pending_removals:
147 self._commit_removals()
148 return len(self.data)
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000149
Raymond Hettinger61146792004-08-19 21:32:06 +0000150 def __contains__(self, key):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100151 if self._pending_removals:
152 self._commit_removals()
Raymond Hettinger61146792004-08-19 21:32:06 +0000153 try:
154 o = self.data[key]()
155 except KeyError:
156 return False
157 return o is not None
158
Fred Drake41deb1e2001-02-01 05:27:45 +0000159 def __repr__(self):
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300160 return "<%s at %#x>" % (self.__class__.__name__, id(self))
Fred Drake41deb1e2001-02-01 05:27:45 +0000161
162 def __setitem__(self, key, value):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000163 if self._pending_removals:
164 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +0000165 self.data[key] = KeyedRef(value, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000166
167 def copy(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100168 if self._pending_removals:
169 self._commit_removals()
Fred Drake9d2c85d2001-03-01 03:06:03 +0000170 new = WeakValueDictionary()
Fish96d37db2019-02-07 14:51:59 -0500171 with _IterationGuard(self):
172 for key, wr in self.data.items():
173 o = wr()
174 if o is not None:
175 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +0000176 return new
Fred Drake41deb1e2001-02-01 05:27:45 +0000177
Antoine Pitrou6e610062009-05-15 17:04:50 +0000178 __copy__ = copy
179
180 def __deepcopy__(self, memo):
181 from copy import deepcopy
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100182 if self._pending_removals:
183 self._commit_removals()
Antoine Pitrou6e610062009-05-15 17:04:50 +0000184 new = self.__class__()
Fish96d37db2019-02-07 14:51:59 -0500185 with _IterationGuard(self):
186 for key, wr in self.data.items():
187 o = wr()
188 if o is not None:
189 new[deepcopy(key, memo)] = o
Antoine Pitrou6e610062009-05-15 17:04:50 +0000190 return new
191
Fred Drake1d9e4b72001-04-16 17:34:48 +0000192 def get(self, key, default=None):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100193 if self._pending_removals:
194 self._commit_removals()
Fred Drake41deb1e2001-02-01 05:27:45 +0000195 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000196 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000197 except KeyError:
198 return default
199 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000200 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000201 if o is None:
202 # This should only happen
203 return default
204 else:
205 return o
206
207 def items(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100208 if self._pending_removals:
209 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000210 with _IterationGuard(self):
211 for k, wr in self.data.items():
212 v = wr()
213 if v is not None:
214 yield k, v
Fred Drake101209d2001-05-02 05:43:09 +0000215
Barry Warsawecaab832008-09-04 01:42:51 +0000216 def keys(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100217 if self._pending_removals:
218 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000219 with _IterationGuard(self):
220 for k, wr in self.data.items():
221 if wr() is not None:
222 yield k
Raymond Hettinger61146792004-08-19 21:32:06 +0000223
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000224 __iter__ = keys
Fred Drake101209d2001-05-02 05:43:09 +0000225
Thomas Wouters477c8d52006-05-27 19:21:47 +0000226 def itervaluerefs(self):
227 """Return an iterator that yields the weak references to the values.
228
229 The references are not guaranteed to be 'live' at the time
230 they are used, so the result of calling the references needs
231 to be checked before being used. This can be used to avoid
232 creating references that will cause the garbage collector to
233 keep the values around longer than needed.
234
235 """
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100236 if self._pending_removals:
237 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000238 with _IterationGuard(self):
Philip Jenvey4993cc02012-10-01 12:53:43 -0700239 yield from self.data.values()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000240
Barry Warsawecaab832008-09-04 01:42:51 +0000241 def values(self):
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100242 if self._pending_removals:
243 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000244 with _IterationGuard(self):
245 for wr in self.data.values():
246 obj = wr()
247 if obj is not None:
248 yield obj
Fred Drake101209d2001-05-02 05:43:09 +0000249
Fred Drake41deb1e2001-02-01 05:27:45 +0000250 def popitem(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000251 if self._pending_removals:
252 self._commit_removals()
Georg Brandlbd87d082010-12-03 07:49:09 +0000253 while True:
Fred Drakebd7f8182001-04-19 16:26:06 +0000254 key, wr = self.data.popitem()
255 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000256 if o is not None:
257 return key, o
258
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000259 def pop(self, key, *args):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000260 if self._pending_removals:
261 self._commit_removals()
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000262 try:
263 o = self.data.pop(key)()
264 except KeyError:
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100265 o = None
266 if o is None:
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000267 if args:
268 return args[0]
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100269 else:
270 raise KeyError(key)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000271 else:
272 return o
273
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000274 def setdefault(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000275 try:
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100276 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +0000277 except KeyError:
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100278 o = None
279 if o is None:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000280 if self._pending_removals:
281 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +0000282 self.data[key] = KeyedRef(default, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000283 return default
284 else:
Antoine Pitrouc1ee4882016-12-19 10:56:40 +0100285 return o
Fred Drake41deb1e2001-02-01 05:27:45 +0000286
Serhiy Storchaka2085bd02019-06-01 11:00:15 +0300287 def update(self, other=None, /, **kwargs):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000288 if self._pending_removals:
289 self._commit_removals()
Fred Drake41deb1e2001-02-01 05:27:45 +0000290 d = self.data
Serhiy Storchaka2085bd02019-06-01 11:00:15 +0300291 if other is not None:
292 if not hasattr(other, "items"):
293 other = dict(other)
294 for key, o in other.items():
Fred Drake0a4dd392004-07-02 18:57:45 +0000295 d[key] = KeyedRef(o, self._remove, key)
Serhiy Storchaka2085bd02019-06-01 11:00:15 +0300296 for key, o in kwargs.items():
297 d[key] = KeyedRef(o, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000298
Thomas Wouters477c8d52006-05-27 19:21:47 +0000299 def valuerefs(self):
300 """Return a list of weak references to the values.
301
302 The references are not guaranteed to be 'live' at the time
303 they are used, so the result of calling the references needs
304 to be checked before being used. This can be used to avoid
305 creating references that will cause the garbage collector to
306 keep the values around longer than needed.
307
308 """
Antoine Pitroue10ca3a2016-12-27 14:19:20 +0100309 if self._pending_removals:
310 self._commit_removals()
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000311 return list(self.data.values())
Thomas Wouters477c8d52006-05-27 19:21:47 +0000312
Curtis Bucher8f1ed212020-03-24 18:51:29 -0700313 def __ior__(self, other):
314 self.update(other)
315 return self
316
317 def __or__(self, other):
318 if isinstance(other, _collections_abc.Mapping):
319 c = self.copy()
320 c.update(other)
321 return c
322 return NotImplemented
323
324 def __ror__(self, other):
325 if isinstance(other, _collections_abc.Mapping):
326 c = self.__class__()
327 c.update(other)
328 c.update(self)
329 return c
330 return NotImplemented
331
Fred Drake0a4dd392004-07-02 18:57:45 +0000332
333class KeyedRef(ref):
334 """Specialized reference that includes a key corresponding to the value.
335
336 This is used in the WeakValueDictionary to avoid having to create
337 a function object for each key stored in the mapping. A shared
338 callback object can use the 'key' attribute of a KeyedRef instead
339 of getting a reference to the key from an enclosing scope.
340
341 """
342
343 __slots__ = "key",
344
345 def __new__(type, ob, callback, key):
346 self = ref.__new__(type, ob, callback)
347 self.key = key
348 return self
349
350 def __init__(self, ob, callback, key):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000351 super().__init__(ob, callback)
Fred Drake746fe0f2001-09-28 19:01:26 +0000352
Fred Drake41deb1e2001-02-01 05:27:45 +0000353
Serhiy Storchaka81108372017-09-26 00:55:55 +0300354class WeakKeyDictionary(_collections_abc.MutableMapping):
Fred Drakebd7f8182001-04-19 16:26:06 +0000355 """ Mapping class that references keys weakly.
356
357 Entries in the dictionary will be discarded when there is no
358 longer a strong reference to the key. This can be used to
359 associate additional data with an object owned by other parts of
360 an application without adding attributes to those objects. This
361 can be especially useful with objects that override attribute
362 accesses.
363 """
Martin v. Löwis5e163332001-02-27 18:36:56 +0000364
365 def __init__(self, dict=None):
366 self.data = {}
Fred Drake746fe0f2001-09-28 19:01:26 +0000367 def remove(k, selfref=ref(self)):
368 self = selfref()
369 if self is not None:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000370 if self._iterating:
371 self._pending_removals.append(k)
372 else:
373 del self.data[k]
Martin v. Löwis5e163332001-02-27 18:36:56 +0000374 self._remove = remove
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000375 # A list of dead weakrefs (keys to be removed)
376 self._pending_removals = []
377 self._iterating = set()
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200378 self._dirty_len = False
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000379 if dict is not None:
380 self.update(dict)
381
382 def _commit_removals(self):
383 # NOTE: We don't need to call this method before mutating the dict,
384 # because a dead weakref never compares equal to a live weakref,
385 # even if they happened to refer to equal objects.
386 # However, it means keys may already have been removed.
387 l = self._pending_removals
388 d = self.data
389 while l:
390 try:
391 del d[l.pop()]
392 except KeyError:
393 pass
Martin v. Löwis5e163332001-02-27 18:36:56 +0000394
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200395 def _scrub_removals(self):
396 d = self.data
397 self._pending_removals = [k for k in self._pending_removals if k in d]
398 self._dirty_len = False
399
Fred Drakeb663a2c2001-09-06 14:51:01 +0000400 def __delitem__(self, key):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200401 self._dirty_len = True
Tim Peters886128f2003-05-25 01:45:11 +0000402 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000403
Martin v. Löwis5e163332001-02-27 18:36:56 +0000404 def __getitem__(self, key):
405 return self.data[ref(key)]
406
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000407 def __len__(self):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200408 if self._dirty_len and self._pending_removals:
409 # self._pending_removals may still contain keys which were
410 # explicitly removed, we have to scrub them (see issue #21173).
411 self._scrub_removals()
Antoine Pitroubbe2f602012-03-01 16:26:35 +0100412 return len(self.data) - len(self._pending_removals)
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000413
Martin v. Löwis5e163332001-02-27 18:36:56 +0000414 def __repr__(self):
Serhiy Storchaka465e60e2014-07-25 23:36:00 +0300415 return "<%s at %#x>" % (self.__class__.__name__, id(self))
Martin v. Löwis5e163332001-02-27 18:36:56 +0000416
417 def __setitem__(self, key, value):
418 self.data[ref(key, self._remove)] = value
419
420 def copy(self):
421 new = WeakKeyDictionary()
Fish96d37db2019-02-07 14:51:59 -0500422 with _IterationGuard(self):
423 for key, value in self.data.items():
424 o = key()
425 if o is not None:
426 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000427 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000428
Antoine Pitrou6e610062009-05-15 17:04:50 +0000429 __copy__ = copy
430
431 def __deepcopy__(self, memo):
432 from copy import deepcopy
433 new = self.__class__()
Fish96d37db2019-02-07 14:51:59 -0500434 with _IterationGuard(self):
435 for key, value in self.data.items():
436 o = key()
437 if o is not None:
438 new[o] = deepcopy(value, memo)
Antoine Pitrou6e610062009-05-15 17:04:50 +0000439 return new
440
Fred Drake1d9e4b72001-04-16 17:34:48 +0000441 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000442 return self.data.get(ref(key),default)
443
Raymond Hettinger54f02222002-06-01 14:18:47 +0000444 def __contains__(self, key):
445 try:
446 wr = ref(key)
447 except TypeError:
Georg Brandlbd87d082010-12-03 07:49:09 +0000448 return False
Raymond Hettinger54f02222002-06-01 14:18:47 +0000449 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000450
Martin v. Löwis5e163332001-02-27 18:36:56 +0000451 def items(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000452 with _IterationGuard(self):
453 for wr, value in self.data.items():
454 key = wr()
455 if key is not None:
456 yield key, value
Thomas Wouters477c8d52006-05-27 19:21:47 +0000457
Barry Warsawecaab832008-09-04 01:42:51 +0000458 def keys(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000459 with _IterationGuard(self):
460 for wr in self.data:
461 obj = wr()
462 if obj is not None:
463 yield obj
Raymond Hettinger61146792004-08-19 21:32:06 +0000464
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000465 __iter__ = keys
Fred Drake101209d2001-05-02 05:43:09 +0000466
Barry Warsawecaab832008-09-04 01:42:51 +0000467 def values(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000468 with _IterationGuard(self):
469 for wr, value in self.data.items():
470 if wr() is not None:
471 yield value
Fred Drake101209d2001-05-02 05:43:09 +0000472
Thomas Wouters477c8d52006-05-27 19:21:47 +0000473 def keyrefs(self):
474 """Return a list of weak references to the keys.
475
476 The references are not guaranteed to be 'live' at the time
477 they are used, so the result of calling the references needs
478 to be checked before being used. This can be used to avoid
479 creating references that will cause the garbage collector to
480 keep the keys around longer than needed.
481
482 """
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000483 return list(self.data)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000484
Martin v. Löwis5e163332001-02-27 18:36:56 +0000485 def popitem(self):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200486 self._dirty_len = True
Georg Brandlbd87d082010-12-03 07:49:09 +0000487 while True:
Martin v. Löwis5e163332001-02-27 18:36:56 +0000488 key, value = self.data.popitem()
489 o = key()
490 if o is not None:
491 return o, value
492
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000493 def pop(self, key, *args):
Antoine Pitrou1bf974d2014-10-05 20:02:28 +0200494 self._dirty_len = True
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000495 return self.data.pop(ref(key), *args)
496
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000497 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000498 return self.data.setdefault(ref(key, self._remove),default)
499
Serhiy Storchaka2085bd02019-06-01 11:00:15 +0300500 def update(self, dict=None, /, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000501 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000502 if dict is not None:
503 if not hasattr(dict, "items"):
504 dict = type({})(dict)
505 for key, value in dict.items():
506 d[ref(key, self._remove)] = value
507 if len(kwargs):
508 self.update(kwargs)
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100509
Curtis Bucher25e580a2020-03-23 13:49:46 -0700510 def __ior__(self, other):
511 self.update(other)
512 return self
513
514 def __or__(self, other):
515 if isinstance(other, _collections_abc.Mapping):
516 c = self.copy()
517 c.update(other)
518 return c
519 return NotImplemented
520
521 def __ror__(self, other):
522 if isinstance(other, _collections_abc.Mapping):
523 c = self.__class__()
524 c.update(other)
525 c.update(self)
526 return c
527 return NotImplemented
528
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100529
530class finalize:
531 """Class for finalization of weakrefable objects
532
533 finalize(obj, func, *args, **kwargs) returns a callable finalizer
534 object which will be called when obj is garbage collected. The
535 first time the finalizer is called it evaluates func(*arg, **kwargs)
536 and returns the result. After this the finalizer is dead, and
537 calling it just returns None.
538
539 When the program exits any remaining finalizers for which the
540 atexit attribute is true will be run in reverse order of creation.
541 By default atexit is true.
542 """
543
544 # Finalizer objects don't have any state of their own. They are
545 # just used as keys to lookup _Info objects in the registry. This
546 # ensures that they cannot be part of a ref-cycle.
547
548 __slots__ = ()
549 _registry = {}
550 _shutdown = False
551 _index_iter = itertools.count()
552 _dirty = False
Richard Oudkerka81dd652013-06-08 16:52:29 +0100553 _registered_with_atexit = False
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100554
555 class _Info:
556 __slots__ = ("weakref", "func", "args", "kwargs", "atexit", "index")
557
Serhiy Storchaka142566c2019-06-05 18:22:31 +0300558 def __init__(self, obj, func, /, *args, **kwargs):
Richard Oudkerka81dd652013-06-08 16:52:29 +0100559 if not self._registered_with_atexit:
560 # We may register the exit function more than once because
561 # of a thread race, but that is harmless
562 import atexit
563 atexit.register(self._exitfunc)
564 finalize._registered_with_atexit = True
Richard Oudkerk7a3dae02013-05-05 23:05:00 +0100565 info = self._Info()
566 info.weakref = ref(obj, self)
567 info.func = func
568 info.args = args
569 info.kwargs = kwargs or None
570 info.atexit = True
571 info.index = next(self._index_iter)
572 self._registry[self] = info
573 finalize._dirty = True
574
575 def __call__(self, _=None):
576 """If alive then mark as dead and return func(*args, **kwargs);
577 otherwise return None"""
578 info = self._registry.pop(self, None)
579 if info and not self._shutdown:
580 return info.func(*info.args, **(info.kwargs or {}))
581
582 def detach(self):
583 """If alive then mark as dead and return (obj, func, args, kwargs);
584 otherwise return None"""
585 info = self._registry.get(self)
586 obj = info and info.weakref()
587 if obj is not None and self._registry.pop(self, None):
588 return (obj, info.func, info.args, info.kwargs or {})
589
590 def peek(self):
591 """If alive then return (obj, func, args, kwargs);
592 otherwise return None"""
593 info = self._registry.get(self)
594 obj = info and info.weakref()
595 if obj is not None:
596 return (obj, info.func, info.args, info.kwargs or {})
597
598 @property
599 def alive(self):
600 """Whether finalizer is alive"""
601 return self in self._registry
602
603 @property
604 def atexit(self):
605 """Whether finalizer should be called at exit"""
606 info = self._registry.get(self)
607 return bool(info) and info.atexit
608
609 @atexit.setter
610 def atexit(self, value):
611 info = self._registry.get(self)
612 if info:
613 info.atexit = bool(value)
614
615 def __repr__(self):
616 info = self._registry.get(self)
617 obj = info and info.weakref()
618 if obj is None:
619 return '<%s object at %#x; dead>' % (type(self).__name__, id(self))
620 else:
621 return '<%s object at %#x; for %r at %#x>' % \
622 (type(self).__name__, id(self), type(obj).__name__, id(obj))
623
624 @classmethod
625 def _select_for_exit(cls):
626 # Return live finalizers marked for exit, oldest first
627 L = [(f,i) for (f,i) in cls._registry.items() if i.atexit]
628 L.sort(key=lambda item:item[1].index)
629 return [f for (f,i) in L]
630
631 @classmethod
632 def _exitfunc(cls):
633 # At shutdown invoke finalizers for which atexit is true.
634 # This is called once all other non-daemonic threads have been
635 # joined.
636 reenable_gc = False
637 try:
638 if cls._registry:
639 import gc
640 if gc.isenabled():
641 reenable_gc = True
642 gc.disable()
643 pending = None
644 while True:
645 if pending is None or finalize._dirty:
646 pending = cls._select_for_exit()
647 finalize._dirty = False
648 if not pending:
649 break
650 f = pending.pop()
651 try:
652 # gc is disabled, so (assuming no daemonic
653 # threads) the following is the only line in
654 # this function which might trigger creation
655 # of a new finalizer
656 f()
657 except Exception:
658 sys.excepthook(*sys.exc_info())
659 assert f not in cls._registry
660 finally:
661 # prevent any more finalizers from executing during shutdown
662 finalize._shutdown = True
663 if reenable_gc:
664 gc.enable()