blob: c54a0729d495c735caf9325f0b2f0ac8af954c5d [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
5http://python.sourceforge.net/peps/pep-0205.html
6"""
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
Fred Drake41deb1e2001-02-01 05:27:45 +000012import UserDict
13
Andrew M. Kuchling33ad28b2004-08-31 11:38:12 +000014from _weakref import (
15 getweakrefcount,
16 getweakrefs,
17 ref,
18 proxy,
19 CallableProxyType,
20 ProxyType,
21 ReferenceType)
Fred Drake41deb1e2001-02-01 05:27:45 +000022
Fred Drakee0292422001-10-05 21:54:09 +000023
Fred Drake41deb1e2001-02-01 05:27:45 +000024ProxyTypes = (ProxyType, CallableProxyType)
25
Fred Drake9a9d2192001-04-10 19:11:23 +000026__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
Skip Montanaro40fc1602001-03-01 04:27:19 +000027 "WeakKeyDictionary", "ReferenceType", "ProxyType",
28 "CallableProxyType", "ProxyTypes", "WeakValueDictionary"]
Fred Drake41deb1e2001-02-01 05:27:45 +000029
Fred Drake41deb1e2001-02-01 05:27:45 +000030
Fred Drakebd7f8182001-04-19 16:26:06 +000031class WeakValueDictionary(UserDict.UserDict):
32 """Mapping class that references values weakly.
33
34 Entries in the dictionary will be discarded when no strong
35 reference to the value exists anymore
36 """
Fred Drake41deb1e2001-02-01 05:27:45 +000037 # We inherit the constructor without worrying about the input
38 # dictionary; since it uses our .update() method, we get the right
Fred Drake9d2c85d2001-03-01 03:06:03 +000039 # checks (if the other dictionary is a WeakValueDictionary,
40 # objects are unwrapped on the way out, and we always wrap on the
41 # way in).
Fred Drake41deb1e2001-02-01 05:27:45 +000042
Fred Drake0a4dd392004-07-02 18:57:45 +000043 def __init__(self, *args, **kw):
Fred Drake0a4dd392004-07-02 18:57:45 +000044 def remove(wr, selfref=ref(self)):
45 self = selfref()
46 if self is not None:
47 del self.data[wr.key]
48 self._remove = remove
Georg Brandl9166e1a2005-06-04 09:20:03 +000049 UserDict.UserDict.__init__(self, *args, **kw)
Fred Drake0a4dd392004-07-02 18:57:45 +000050
Fred Drake41deb1e2001-02-01 05:27:45 +000051 def __getitem__(self, key):
Fred Drake4fd06e02001-08-03 04:11:27 +000052 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +000053 if o is None:
Collin Winterce36ad82007-08-30 01:19:48 +000054 raise KeyError(key)
Fred Drake41deb1e2001-02-01 05:27:45 +000055 else:
56 return o
57
Raymond Hettinger61146792004-08-19 21:32:06 +000058 def __contains__(self, key):
59 try:
60 o = self.data[key]()
61 except KeyError:
62 return False
63 return o is not None
64
Fred Drake41deb1e2001-02-01 05:27:45 +000065 def __repr__(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000066 return "<WeakValueDictionary at %s>" % id(self)
Fred Drake41deb1e2001-02-01 05:27:45 +000067
68 def __setitem__(self, key, value):
Fred Drake0a4dd392004-07-02 18:57:45 +000069 self.data[key] = KeyedRef(value, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +000070
71 def copy(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000072 new = WeakValueDictionary()
Fred Drakebd7f8182001-04-19 16:26:06 +000073 for key, wr in self.data.items():
74 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +000075 if o is not None:
76 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +000077 return new
Fred Drake41deb1e2001-02-01 05:27:45 +000078
Fred Drake1d9e4b72001-04-16 17:34:48 +000079 def get(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +000080 try:
Fred Drakebd7f8182001-04-19 16:26:06 +000081 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +000082 except KeyError:
83 return default
84 else:
Fred Drakebd7f8182001-04-19 16:26:06 +000085 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +000086 if o is None:
87 # This should only happen
88 return default
89 else:
90 return o
91
92 def items(self):
Fred Drake312a5dc2001-02-02 15:13:24 +000093 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +000094 for key, wr in self.data.items():
95 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +000096 if o is not None:
Fred Drake312a5dc2001-02-02 15:13:24 +000097 L.append((key, o))
Fred Drake41deb1e2001-02-01 05:27:45 +000098 return L
99
Fred Drake101209d2001-05-02 05:43:09 +0000100 def iteritems(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000101 for wr in self.data.values():
Raymond Hettinger61146792004-08-19 21:32:06 +0000102 value = wr()
103 if value is not None:
104 yield wr.key, value
Fred Drake101209d2001-05-02 05:43:09 +0000105
106 def iterkeys(self):
Guido van Rossum07f24362007-02-11 22:59:48 +0000107 return iter(self.data.keys())
Raymond Hettinger61146792004-08-19 21:32:06 +0000108
109 def __iter__(self):
Guido van Rossum07f24362007-02-11 22:59:48 +0000110 return iter(self.data.keys())
Fred Drake101209d2001-05-02 05:43:09 +0000111
Thomas Wouters477c8d52006-05-27 19:21:47 +0000112 def itervaluerefs(self):
113 """Return an iterator that yields the weak references to the values.
114
115 The references are not guaranteed to be 'live' at the time
116 they are used, so the result of calling the references needs
117 to be checked before being used. This can be used to avoid
118 creating references that will cause the garbage collector to
119 keep the values around longer than needed.
120
121 """
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000122 return self.data.values()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000123
Fred Drake101209d2001-05-02 05:43:09 +0000124 def itervalues(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000125 for wr in self.data.values():
Raymond Hettinger61146792004-08-19 21:32:06 +0000126 obj = wr()
127 if obj is not None:
128 yield obj
Fred Drake101209d2001-05-02 05:43:09 +0000129
Fred Drake41deb1e2001-02-01 05:27:45 +0000130 def popitem(self):
131 while 1:
Fred Drakebd7f8182001-04-19 16:26:06 +0000132 key, wr = self.data.popitem()
133 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000134 if o is not None:
135 return key, o
136
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000137 def pop(self, key, *args):
138 try:
139 o = self.data.pop(key)()
140 except KeyError:
141 if args:
142 return args[0]
143 raise
144 if o is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000145 raise KeyError(key)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000146 else:
147 return o
148
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000149 def setdefault(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000150 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000151 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000152 except KeyError:
Fred Drake0a4dd392004-07-02 18:57:45 +0000153 self.data[key] = KeyedRef(default, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000154 return default
155 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000156 return wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000157
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000158 def update(self, dict=None, **kwargs):
Fred Drake41deb1e2001-02-01 05:27:45 +0000159 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000160 if dict is not None:
161 if not hasattr(dict, "items"):
162 dict = type({})(dict)
163 for key, o in dict.items():
Fred Drake0a4dd392004-07-02 18:57:45 +0000164 d[key] = KeyedRef(o, self._remove, key)
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000165 if len(kwargs):
166 self.update(kwargs)
Fred Drake41deb1e2001-02-01 05:27:45 +0000167
Thomas Wouters477c8d52006-05-27 19:21:47 +0000168 def valuerefs(self):
169 """Return a list of weak references to the values.
170
171 The references are not guaranteed to be 'live' at the time
172 they are used, so the result of calling the references needs
173 to be checked before being used. This can be used to avoid
174 creating references that will cause the garbage collector to
175 keep the values around longer than needed.
176
177 """
178 return self.data.values()
179
Fred Drake41deb1e2001-02-01 05:27:45 +0000180 def values(self):
181 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000182 for wr in self.data.values():
183 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000184 if o is not None:
185 L.append(o)
186 return L
187
Fred Drake0a4dd392004-07-02 18:57:45 +0000188
189class KeyedRef(ref):
190 """Specialized reference that includes a key corresponding to the value.
191
192 This is used in the WeakValueDictionary to avoid having to create
193 a function object for each key stored in the mapping. A shared
194 callback object can use the 'key' attribute of a KeyedRef instead
195 of getting a reference to the key from an enclosing scope.
196
197 """
198
199 __slots__ = "key",
200
201 def __new__(type, ob, callback, key):
202 self = ref.__new__(type, ob, callback)
203 self.key = key
204 return self
205
206 def __init__(self, ob, callback, key):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000207 super().__init__(ob, callback)
Fred Drake746fe0f2001-09-28 19:01:26 +0000208
Fred Drake41deb1e2001-02-01 05:27:45 +0000209
Martin v. Löwis5e163332001-02-27 18:36:56 +0000210class WeakKeyDictionary(UserDict.UserDict):
Fred Drakebd7f8182001-04-19 16:26:06 +0000211 """ Mapping class that references keys weakly.
212
213 Entries in the dictionary will be discarded when there is no
214 longer a strong reference to the key. This can be used to
215 associate additional data with an object owned by other parts of
216 an application without adding attributes to those objects. This
217 can be especially useful with objects that override attribute
218 accesses.
219 """
Martin v. Löwis5e163332001-02-27 18:36:56 +0000220
221 def __init__(self, dict=None):
222 self.data = {}
Fred Drake746fe0f2001-09-28 19:01:26 +0000223 def remove(k, selfref=ref(self)):
224 self = selfref()
225 if self is not None:
226 del self.data[k]
Martin v. Löwis5e163332001-02-27 18:36:56 +0000227 self._remove = remove
Guido van Rossum009afb72002-06-10 20:00:52 +0000228 if dict is not None: self.update(dict)
Martin v. Löwis5e163332001-02-27 18:36:56 +0000229
Fred Drakeb663a2c2001-09-06 14:51:01 +0000230 def __delitem__(self, key):
Tim Peters886128f2003-05-25 01:45:11 +0000231 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000232
Martin v. Löwis5e163332001-02-27 18:36:56 +0000233 def __getitem__(self, key):
234 return self.data[ref(key)]
235
236 def __repr__(self):
237 return "<WeakKeyDictionary at %s>" % id(self)
238
239 def __setitem__(self, key, value):
240 self.data[ref(key, self._remove)] = value
241
242 def copy(self):
243 new = WeakKeyDictionary()
244 for key, value in self.data.items():
245 o = key()
246 if o is not None:
247 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000248 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000249
Fred Drake1d9e4b72001-04-16 17:34:48 +0000250 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000251 return self.data.get(ref(key),default)
252
Raymond Hettinger54f02222002-06-01 14:18:47 +0000253 def __contains__(self, key):
254 try:
255 wr = ref(key)
256 except TypeError:
257 return 0
258 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000259
Martin v. Löwis5e163332001-02-27 18:36:56 +0000260 def items(self):
261 L = []
262 for key, value in self.data.items():
263 o = key()
264 if o is not None:
265 L.append((o, value))
266 return L
267
Fred Drake101209d2001-05-02 05:43:09 +0000268 def iteritems(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000269 for wr, value in self.data.items():
Raymond Hettinger61146792004-08-19 21:32:06 +0000270 key = wr()
271 if key is not None:
272 yield key, value
Fred Drake101209d2001-05-02 05:43:09 +0000273
Thomas Wouters477c8d52006-05-27 19:21:47 +0000274 def iterkeyrefs(self):
275 """Return an iterator that yields the weak references to the keys.
276
277 The references are not guaranteed to be 'live' at the time
278 they are used, so the result of calling the references needs
279 to be checked before being used. This can be used to avoid
280 creating references that will cause the garbage collector to
281 keep the keys around longer than needed.
282
283 """
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000284 return self.data.keys()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000285
Fred Drake101209d2001-05-02 05:43:09 +0000286 def iterkeys(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000287 for wr in self.data.keys():
Raymond Hettinger61146792004-08-19 21:32:06 +0000288 obj = wr()
289 if obj is not None:
290 yield obj
291
292 def __iter__(self):
Guido van Rossum07f24362007-02-11 22:59:48 +0000293 return iter(self.keys())
Fred Drake101209d2001-05-02 05:43:09 +0000294
295 def itervalues(self):
Guido van Rossum07f24362007-02-11 22:59:48 +0000296 return iter(self.data.values())
Fred Drake101209d2001-05-02 05:43:09 +0000297
Thomas Wouters477c8d52006-05-27 19:21:47 +0000298 def keyrefs(self):
299 """Return a list of weak references to the keys.
300
301 The references are not guaranteed to be 'live' at the time
302 they are used, so the result of calling the references needs
303 to be checked before being used. This can be used to avoid
304 creating references that will cause the garbage collector to
305 keep the keys around longer than needed.
306
307 """
308 return self.data.keys()
309
Fred Drake1d9e4b72001-04-16 17:34:48 +0000310 def keys(self):
311 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000312 for wr in self.data.keys():
313 o = wr()
Fred Drake1d9e4b72001-04-16 17:34:48 +0000314 if o is not None:
315 L.append(o)
316 return L
317
Martin v. Löwis5e163332001-02-27 18:36:56 +0000318 def popitem(self):
319 while 1:
320 key, value = self.data.popitem()
321 o = key()
322 if o is not None:
323 return o, value
324
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000325 def pop(self, key, *args):
326 return self.data.pop(ref(key), *args)
327
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000328 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000329 return self.data.setdefault(ref(key, self._remove),default)
330
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000331 def update(self, dict=None, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000332 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000333 if dict is not None:
334 if not hasattr(dict, "items"):
335 dict = type({})(dict)
336 for key, value in dict.items():
337 d[ref(key, self._remove)] = value
338 if len(kwargs):
339 self.update(kwargs)
Georg Brandl3b8cb172007-10-23 06:26:46 +0000340
341
342class WeakSet:
343 def __init__(self, data=None):
344 self.data = set()
345 def _remove(item, selfref=ref(self)):
346 self = selfref()
347 if self is not None:
348 self.data.discard(item)
349 self._remove = _remove
350 if data is not None:
351 self.update(data)
352
353 def __iter__(self):
354 for itemref in self.data:
355 item = itemref()
356 if item is not None:
357 yield item
358
359 def __contains__(self, item):
360 return ref(item) in self.data
361
362 def __reduce__(self):
363 return (self.__class__, (list(self),),
364 getattr(self, '__dict__', None))
365
366 def add(self, item):
367 self.data.add(ref(item, self._remove))
368
369 def clear(self):
370 self.data.clear()
371
372 def copy(self):
373 return self.__class__(self)
374
375 def pop(self):
376 while True:
377 itemref = self.data.pop()
378 item = itemref()
379 if item is not None:
380 return item
381
382 def remove(self, item):
383 self.data.remove(ref(item))
384
385 def discard(self, item):
386 self.data.discard(ref(item))
387
388 def update(self, other):
389 if isinstance(other, self.__class__):
390 self.data.update(other.data)
391 else:
392 for element in other:
393 self.add(element)
394 __ior__ = update
395
396 # Helper functions for simple delegating methods.
397 def _apply(self, other, method):
398 if not isinstance(other, self.__class__):
399 other = self.__class__(other)
400 newdata = method(other.data)
401 newset = self.__class__()
402 newset.data = newdata
403 return newset
404
405 def _apply_mutate(self, other, method):
406 if not isinstance(other, self.__class__):
407 other = self.__class__(other)
408 method(other)
409
410 def difference(self, other):
411 return self._apply(other, self.data.difference)
412 __sub__ = difference
413
414 def difference_update(self, other):
415 self._apply_mutate(self, self.data.difference_update)
416 __isub__ = difference_update
417
418 def intersection(self, other):
419 return self._apply(other, self.data.intersection)
420 __and__ = intersection
421
422 def intersection_update(self, other):
423 self._apply_mutate(self, self.data.intersection_update)
424 __iand__ = intersection_update
425
426 def issubset(self, other):
427 return self.data.issubset(ref(item) for item in other)
428 __lt__ = issubset
429
430 def issuperset(self, other):
431 return self.data.issuperset(ref(item) for item in other)
432 __gt__ = issuperset
433
434 def symmetric_difference(self, other):
435 return self._apply(other, self.data.symmetric_difference)
436 __xor__ = symmetric_difference
437
438 def symmetric_difference_update(self, other):
439 self._apply_mutate(other, self.data.symmetric_difference_update)
440 __ixor__ = symmetric_difference_update
441
442 def union(self, other):
443 self._apply_mutate(other, self.data.union)
444 __or__ = union