blob: 339fcf4718d5da377e1d06753865dcba5607a0df [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.
24
Fred Drake41deb1e2001-02-01 05:27:45 +000025ProxyTypes = (ProxyType, CallableProxyType)
26
Fred Drake9a9d2192001-04-10 19:11:23 +000027__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
Gregory P. Smith7d10c2b2008-08-18 03:41:46 +000028 "WeakKeyDictionary", "ReferenceType", "ProxyType",
Raymond Hettinger93fa6082008-02-05 00:20:01 +000029 "CallableProxyType", "ProxyTypes", "WeakValueDictionary",
30 "WeakSet"]
Fred Drake41deb1e2001-02-01 05:27:45 +000031
Fred Drake41deb1e2001-02-01 05:27:45 +000032
Raymond Hettinger7ac60952008-02-05 01:15:57 +000033class WeakValueDictionary(collections.MutableMapping):
Fred Drakebd7f8182001-04-19 16:26:06 +000034 """Mapping class that references values weakly.
35
36 Entries in the dictionary will be discarded when no strong
37 reference to the value exists anymore
38 """
Fred Drake41deb1e2001-02-01 05:27:45 +000039 # We inherit the constructor without worrying about the input
40 # dictionary; since it uses our .update() method, we get the right
Fred Drake9d2c85d2001-03-01 03:06:03 +000041 # checks (if the other dictionary is a WeakValueDictionary,
42 # objects are unwrapped on the way out, and we always wrap on the
43 # way in).
Fred Drake41deb1e2001-02-01 05:27:45 +000044
Fred Drake0a4dd392004-07-02 18:57:45 +000045 def __init__(self, *args, **kw):
Fred Drake0a4dd392004-07-02 18:57:45 +000046 def remove(wr, selfref=ref(self)):
47 self = selfref()
48 if self is not None:
Antoine Pitrouc1baa602010-01-08 17:54:23 +000049 if self._iterating:
50 self._pending_removals.append(wr.key)
51 else:
52 del self.data[wr.key]
Fred Drake0a4dd392004-07-02 18:57:45 +000053 self._remove = remove
Antoine Pitrouc1baa602010-01-08 17:54:23 +000054 # A list of keys to be removed
55 self._pending_removals = []
56 self._iterating = set()
Raymond Hettinger7ac60952008-02-05 01:15:57 +000057 self.data = d = {}
Antoine Pitrouc06de472009-05-30 21:04:26 +000058 self.update(*args, **kw)
Fred Drake0a4dd392004-07-02 18:57:45 +000059
Antoine Pitrouc1baa602010-01-08 17:54:23 +000060 def _commit_removals(self):
61 l = self._pending_removals
62 d = self.data
63 # We shouldn't encounter any KeyError, because this method should
64 # always be called *before* mutating the dict.
65 while l:
66 del d[l.pop()]
67
Fred Drake41deb1e2001-02-01 05:27:45 +000068 def __getitem__(self, key):
Fred Drake4fd06e02001-08-03 04:11:27 +000069 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +000070 if o is None:
Collin Winterce36ad82007-08-30 01:19:48 +000071 raise KeyError(key)
Fred Drake41deb1e2001-02-01 05:27:45 +000072 else:
73 return o
74
Raymond Hettinger7ac60952008-02-05 01:15:57 +000075 def __delitem__(self, key):
Antoine Pitrouc1baa602010-01-08 17:54:23 +000076 if self._pending_removals:
77 self._commit_removals()
Raymond Hettinger7ac60952008-02-05 01:15:57 +000078 del self.data[key]
79
80 def __len__(self):
Antoine Pitroubbe2f602012-03-01 16:26:35 +010081 return len(self.data) - len(self._pending_removals)
Raymond Hettinger7ac60952008-02-05 01:15:57 +000082
Raymond Hettinger61146792004-08-19 21:32:06 +000083 def __contains__(self, key):
84 try:
85 o = self.data[key]()
86 except KeyError:
87 return False
88 return o is not None
89
Fred Drake41deb1e2001-02-01 05:27:45 +000090 def __repr__(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000091 return "<WeakValueDictionary at %s>" % id(self)
Fred Drake41deb1e2001-02-01 05:27:45 +000092
93 def __setitem__(self, key, value):
Antoine Pitrouc1baa602010-01-08 17:54:23 +000094 if self._pending_removals:
95 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +000096 self.data[key] = KeyedRef(value, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +000097
98 def copy(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000099 new = WeakValueDictionary()
Fred Drakebd7f8182001-04-19 16:26:06 +0000100 for key, wr in self.data.items():
101 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000102 if o is not None:
103 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +0000104 return new
Fred Drake41deb1e2001-02-01 05:27:45 +0000105
Antoine Pitrou6e610062009-05-15 17:04:50 +0000106 __copy__ = copy
107
108 def __deepcopy__(self, memo):
109 from copy import deepcopy
110 new = self.__class__()
111 for key, wr in self.data.items():
112 o = wr()
113 if o is not None:
114 new[deepcopy(key, memo)] = o
115 return new
116
Fred Drake1d9e4b72001-04-16 17:34:48 +0000117 def get(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000118 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000119 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000120 except KeyError:
121 return default
122 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000123 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000124 if o is None:
125 # This should only happen
126 return default
127 else:
128 return o
129
130 def items(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000131 with _IterationGuard(self):
132 for k, wr in self.data.items():
133 v = wr()
134 if v is not None:
135 yield k, v
Fred Drake101209d2001-05-02 05:43:09 +0000136
Barry Warsawecaab832008-09-04 01:42:51 +0000137 def keys(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000138 with _IterationGuard(self):
139 for k, wr in self.data.items():
140 if wr() is not None:
141 yield k
Raymond Hettinger61146792004-08-19 21:32:06 +0000142
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000143 __iter__ = keys
Fred Drake101209d2001-05-02 05:43:09 +0000144
Thomas Wouters477c8d52006-05-27 19:21:47 +0000145 def itervaluerefs(self):
146 """Return an iterator that yields the weak references to the values.
147
148 The references are not guaranteed to be 'live' at the time
149 they are used, so the result of calling the references needs
150 to be checked before being used. This can be used to avoid
151 creating references that will cause the garbage collector to
152 keep the values around longer than needed.
153
154 """
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000155 with _IterationGuard(self):
Philip Jenvey4993cc02012-10-01 12:53:43 -0700156 yield from self.data.values()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000157
Barry Warsawecaab832008-09-04 01:42:51 +0000158 def values(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000159 with _IterationGuard(self):
160 for wr in self.data.values():
161 obj = wr()
162 if obj is not None:
163 yield obj
Fred Drake101209d2001-05-02 05:43:09 +0000164
Fred Drake41deb1e2001-02-01 05:27:45 +0000165 def popitem(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000166 if self._pending_removals:
167 self._commit_removals()
Georg Brandlbd87d082010-12-03 07:49:09 +0000168 while True:
Fred Drakebd7f8182001-04-19 16:26:06 +0000169 key, wr = self.data.popitem()
170 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000171 if o is not None:
172 return key, o
173
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000174 def pop(self, key, *args):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000175 if self._pending_removals:
176 self._commit_removals()
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000177 try:
178 o = self.data.pop(key)()
179 except KeyError:
180 if args:
181 return args[0]
182 raise
183 if o is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000184 raise KeyError(key)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000185 else:
186 return o
187
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000188 def setdefault(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000189 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000190 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000191 except KeyError:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000192 if self._pending_removals:
193 self._commit_removals()
Fred Drake0a4dd392004-07-02 18:57:45 +0000194 self.data[key] = KeyedRef(default, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000195 return default
196 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000197 return wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000198
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000199 def update(self, dict=None, **kwargs):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000200 if self._pending_removals:
201 self._commit_removals()
Fred Drake41deb1e2001-02-01 05:27:45 +0000202 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000203 if dict is not None:
204 if not hasattr(dict, "items"):
205 dict = type({})(dict)
206 for key, o in dict.items():
Fred Drake0a4dd392004-07-02 18:57:45 +0000207 d[key] = KeyedRef(o, self._remove, key)
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000208 if len(kwargs):
209 self.update(kwargs)
Fred Drake41deb1e2001-02-01 05:27:45 +0000210
Thomas Wouters477c8d52006-05-27 19:21:47 +0000211 def valuerefs(self):
212 """Return a list of weak references to the values.
213
214 The references are not guaranteed to be 'live' at the time
215 they are used, so the result of calling the references needs
216 to be checked before being used. This can be used to avoid
217 creating references that will cause the garbage collector to
218 keep the values around longer than needed.
219
220 """
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000221 return list(self.data.values())
Thomas Wouters477c8d52006-05-27 19:21:47 +0000222
Fred Drake0a4dd392004-07-02 18:57:45 +0000223
224class KeyedRef(ref):
225 """Specialized reference that includes a key corresponding to the value.
226
227 This is used in the WeakValueDictionary to avoid having to create
228 a function object for each key stored in the mapping. A shared
229 callback object can use the 'key' attribute of a KeyedRef instead
230 of getting a reference to the key from an enclosing scope.
231
232 """
233
234 __slots__ = "key",
235
236 def __new__(type, ob, callback, key):
237 self = ref.__new__(type, ob, callback)
238 self.key = key
239 return self
240
241 def __init__(self, ob, callback, key):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000242 super().__init__(ob, callback)
Fred Drake746fe0f2001-09-28 19:01:26 +0000243
Fred Drake41deb1e2001-02-01 05:27:45 +0000244
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000245class WeakKeyDictionary(collections.MutableMapping):
Fred Drakebd7f8182001-04-19 16:26:06 +0000246 """ Mapping class that references keys weakly.
247
248 Entries in the dictionary will be discarded when there is no
249 longer a strong reference to the key. This can be used to
250 associate additional data with an object owned by other parts of
251 an application without adding attributes to those objects. This
252 can be especially useful with objects that override attribute
253 accesses.
254 """
Martin v. Löwis5e163332001-02-27 18:36:56 +0000255
256 def __init__(self, dict=None):
257 self.data = {}
Fred Drake746fe0f2001-09-28 19:01:26 +0000258 def remove(k, selfref=ref(self)):
259 self = selfref()
260 if self is not None:
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000261 if self._iterating:
262 self._pending_removals.append(k)
263 else:
264 del self.data[k]
Martin v. Löwis5e163332001-02-27 18:36:56 +0000265 self._remove = remove
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000266 # A list of dead weakrefs (keys to be removed)
267 self._pending_removals = []
268 self._iterating = set()
269 if dict is not None:
270 self.update(dict)
271
272 def _commit_removals(self):
273 # NOTE: We don't need to call this method before mutating the dict,
274 # because a dead weakref never compares equal to a live weakref,
275 # even if they happened to refer to equal objects.
276 # However, it means keys may already have been removed.
277 l = self._pending_removals
278 d = self.data
279 while l:
280 try:
281 del d[l.pop()]
282 except KeyError:
283 pass
Martin v. Löwis5e163332001-02-27 18:36:56 +0000284
Fred Drakeb663a2c2001-09-06 14:51:01 +0000285 def __delitem__(self, key):
Tim Peters886128f2003-05-25 01:45:11 +0000286 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000287
Martin v. Löwis5e163332001-02-27 18:36:56 +0000288 def __getitem__(self, key):
289 return self.data[ref(key)]
290
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000291 def __len__(self):
Antoine Pitroubbe2f602012-03-01 16:26:35 +0100292 return len(self.data) - len(self._pending_removals)
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000293
Martin v. Löwis5e163332001-02-27 18:36:56 +0000294 def __repr__(self):
295 return "<WeakKeyDictionary at %s>" % id(self)
296
297 def __setitem__(self, key, value):
298 self.data[ref(key, self._remove)] = value
299
300 def copy(self):
301 new = WeakKeyDictionary()
302 for key, value in self.data.items():
303 o = key()
304 if o is not None:
305 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000306 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000307
Antoine Pitrou6e610062009-05-15 17:04:50 +0000308 __copy__ = copy
309
310 def __deepcopy__(self, memo):
311 from copy import deepcopy
312 new = self.__class__()
313 for key, value in self.data.items():
314 o = key()
315 if o is not None:
316 new[o] = deepcopy(value, memo)
317 return new
318
Fred Drake1d9e4b72001-04-16 17:34:48 +0000319 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000320 return self.data.get(ref(key),default)
321
Raymond Hettinger54f02222002-06-01 14:18:47 +0000322 def __contains__(self, key):
323 try:
324 wr = ref(key)
325 except TypeError:
Georg Brandlbd87d082010-12-03 07:49:09 +0000326 return False
Raymond Hettinger54f02222002-06-01 14:18:47 +0000327 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000328
Martin v. Löwis5e163332001-02-27 18:36:56 +0000329 def items(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000330 with _IterationGuard(self):
331 for wr, value in self.data.items():
332 key = wr()
333 if key is not None:
334 yield key, value
Thomas Wouters477c8d52006-05-27 19:21:47 +0000335
Barry Warsawecaab832008-09-04 01:42:51 +0000336 def keys(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000337 with _IterationGuard(self):
338 for wr in self.data:
339 obj = wr()
340 if obj is not None:
341 yield obj
Raymond Hettinger61146792004-08-19 21:32:06 +0000342
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000343 __iter__ = keys
Fred Drake101209d2001-05-02 05:43:09 +0000344
Barry Warsawecaab832008-09-04 01:42:51 +0000345 def values(self):
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000346 with _IterationGuard(self):
347 for wr, value in self.data.items():
348 if wr() is not None:
349 yield value
Fred Drake101209d2001-05-02 05:43:09 +0000350
Thomas Wouters477c8d52006-05-27 19:21:47 +0000351 def keyrefs(self):
352 """Return a list of weak references to the keys.
353
354 The references are not guaranteed to be 'live' at the time
355 they are used, so the result of calling the references needs
356 to be checked before being used. This can be used to avoid
357 creating references that will cause the garbage collector to
358 keep the keys around longer than needed.
359
360 """
Antoine Pitrouc1baa602010-01-08 17:54:23 +0000361 return list(self.data)
Thomas Wouters477c8d52006-05-27 19:21:47 +0000362
Martin v. Löwis5e163332001-02-27 18:36:56 +0000363 def popitem(self):
Georg Brandlbd87d082010-12-03 07:49:09 +0000364 while True:
Martin v. Löwis5e163332001-02-27 18:36:56 +0000365 key, value = self.data.popitem()
366 o = key()
367 if o is not None:
368 return o, value
369
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000370 def pop(self, key, *args):
371 return self.data.pop(ref(key), *args)
372
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000373 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000374 return self.data.setdefault(ref(key, self._remove),default)
375
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000376 def update(self, dict=None, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000377 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000378 if dict is not None:
379 if not hasattr(dict, "items"):
380 dict = type({})(dict)
381 for key, value in dict.items():
382 d[ref(key, self._remove)] = value
383 if len(kwargs):
384 self.update(kwargs)