blob: 88c60e7197419b8f93273a04a6b30da18cbca8df [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
Alexandre Vassalottiba08f072008-04-27 00:52:24 +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
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
Michael Foorde6410c52010-03-29 20:04:23 +000023from _weakrefset import WeakSet
24
Fred Drakee0292422001-10-05 21:54:09 +000025from exceptions import ReferenceError
26
27
Fred Drake41deb1e2001-02-01 05:27:45 +000028ProxyTypes = (ProxyType, CallableProxyType)
29
Fred Drake9a9d2192001-04-10 19:11:23 +000030__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
Brett Cannon88f801d2008-08-18 00:46:22 +000031 "WeakKeyDictionary", "ReferenceError", "ReferenceType", "ProxyType",
Michael Foorde6410c52010-03-29 20:04:23 +000032 "CallableProxyType", "ProxyTypes", "WeakValueDictionary", 'WeakSet']
Fred Drake41deb1e2001-02-01 05:27:45 +000033
Fred Drake41deb1e2001-02-01 05:27:45 +000034
Fred Drakebd7f8182001-04-19 16:26:06 +000035class WeakValueDictionary(UserDict.UserDict):
36 """Mapping class that references values weakly.
37
38 Entries in the dictionary will be discarded when no strong
39 reference to the value exists anymore
40 """
Fred Drake41deb1e2001-02-01 05:27:45 +000041 # We inherit the constructor without worrying about the input
42 # dictionary; since it uses our .update() method, we get the right
Fred Drake9d2c85d2001-03-01 03:06:03 +000043 # checks (if the other dictionary is a WeakValueDictionary,
44 # objects are unwrapped on the way out, and we always wrap on the
45 # way in).
Fred Drake41deb1e2001-02-01 05:27:45 +000046
Fred Drake0a4dd392004-07-02 18:57:45 +000047 def __init__(self, *args, **kw):
Fred Drake0a4dd392004-07-02 18:57:45 +000048 def remove(wr, selfref=ref(self)):
49 self = selfref()
50 if self is not None:
51 del self.data[wr.key]
52 self._remove = remove
Georg Brandl9166e1a2005-06-04 09:20:03 +000053 UserDict.UserDict.__init__(self, *args, **kw)
Fred Drake0a4dd392004-07-02 18:57:45 +000054
Fred Drake41deb1e2001-02-01 05:27:45 +000055 def __getitem__(self, key):
Fred Drake4fd06e02001-08-03 04:11:27 +000056 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +000057 if o is None:
58 raise KeyError, key
59 else:
60 return o
61
Raymond Hettinger61146792004-08-19 21:32:06 +000062 def __contains__(self, key):
63 try:
64 o = self.data[key]()
65 except KeyError:
66 return False
67 return o is not None
68
69 def has_key(self, key):
70 try:
71 o = self.data[key]()
72 except KeyError:
73 return False
74 return o is not None
75
Fred Drake41deb1e2001-02-01 05:27:45 +000076 def __repr__(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000077 return "<WeakValueDictionary at %s>" % id(self)
Fred Drake41deb1e2001-02-01 05:27:45 +000078
79 def __setitem__(self, key, value):
Fred Drake0a4dd392004-07-02 18:57:45 +000080 self.data[key] = KeyedRef(value, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +000081
82 def copy(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000083 new = WeakValueDictionary()
Fred Drakebd7f8182001-04-19 16:26:06 +000084 for key, wr in self.data.items():
85 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +000086 if o is not None:
87 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +000088 return new
Fred Drake41deb1e2001-02-01 05:27:45 +000089
Antoine Pitrou775fd662009-05-15 16:54:52 +000090 __copy__ = copy
91
92 def __deepcopy__(self, memo):
93 from copy import deepcopy
94 new = self.__class__()
95 for key, wr in self.data.items():
96 o = wr()
97 if o is not None:
98 new[deepcopy(key, memo)] = o
99 return new
100
Fred Drake1d9e4b72001-04-16 17:34:48 +0000101 def get(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000102 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000103 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000104 except KeyError:
105 return default
106 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000107 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000108 if o is None:
109 # This should only happen
110 return default
111 else:
112 return o
113
114 def items(self):
Fred Drake312a5dc2001-02-02 15:13:24 +0000115 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000116 for key, wr in self.data.items():
117 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000118 if o is not None:
Fred Drake312a5dc2001-02-02 15:13:24 +0000119 L.append((key, o))
Fred Drake41deb1e2001-02-01 05:27:45 +0000120 return L
121
Fred Drake101209d2001-05-02 05:43:09 +0000122 def iteritems(self):
Raymond Hettinger61146792004-08-19 21:32:06 +0000123 for wr in self.data.itervalues():
124 value = wr()
125 if value is not None:
126 yield wr.key, value
Fred Drake101209d2001-05-02 05:43:09 +0000127
128 def iterkeys(self):
129 return self.data.iterkeys()
Raymond Hettinger61146792004-08-19 21:32:06 +0000130
131 def __iter__(self):
132 return self.data.iterkeys()
Fred Drake101209d2001-05-02 05:43:09 +0000133
Fred Drake017e68c2006-05-02 06:53:59 +0000134 def itervaluerefs(self):
135 """Return an iterator that yields the weak references to the values.
136
137 The references are not guaranteed to be 'live' at the time
138 they are used, so the result of calling the references needs
139 to be checked before being used. This can be used to avoid
140 creating references that will cause the garbage collector to
141 keep the values around longer than needed.
142
143 """
144 return self.data.itervalues()
145
Fred Drake101209d2001-05-02 05:43:09 +0000146 def itervalues(self):
Raymond Hettinger61146792004-08-19 21:32:06 +0000147 for wr in self.data.itervalues():
148 obj = wr()
149 if obj is not None:
150 yield obj
Fred Drake101209d2001-05-02 05:43:09 +0000151
Fred Drake41deb1e2001-02-01 05:27:45 +0000152 def popitem(self):
153 while 1:
Fred Drakebd7f8182001-04-19 16:26:06 +0000154 key, wr = self.data.popitem()
155 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000156 if o is not None:
157 return key, o
158
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000159 def pop(self, key, *args):
160 try:
161 o = self.data.pop(key)()
162 except KeyError:
163 if args:
164 return args[0]
165 raise
166 if o is None:
167 raise KeyError, key
168 else:
169 return o
170
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000171 def setdefault(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000172 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000173 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000174 except KeyError:
Fred Drake0a4dd392004-07-02 18:57:45 +0000175 self.data[key] = KeyedRef(default, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000176 return default
177 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000178 return wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000179
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000180 def update(self, dict=None, **kwargs):
Fred Drake41deb1e2001-02-01 05:27:45 +0000181 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000182 if dict is not None:
183 if not hasattr(dict, "items"):
184 dict = type({})(dict)
185 for key, o in dict.items():
Fred Drake0a4dd392004-07-02 18:57:45 +0000186 d[key] = KeyedRef(o, self._remove, key)
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000187 if len(kwargs):
188 self.update(kwargs)
Fred Drake41deb1e2001-02-01 05:27:45 +0000189
Fred Drake017e68c2006-05-02 06:53:59 +0000190 def valuerefs(self):
191 """Return a list of weak references to the values.
192
193 The references are not guaranteed to be 'live' at the time
194 they are used, so the result of calling the references needs
195 to be checked before being used. This can be used to avoid
196 creating references that will cause the garbage collector to
197 keep the values around longer than needed.
198
199 """
200 return self.data.values()
201
Fred Drake41deb1e2001-02-01 05:27:45 +0000202 def values(self):
203 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000204 for wr in self.data.values():
205 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000206 if o is not None:
207 L.append(o)
208 return L
209
Fred Drake0a4dd392004-07-02 18:57:45 +0000210
211class KeyedRef(ref):
212 """Specialized reference that includes a key corresponding to the value.
213
214 This is used in the WeakValueDictionary to avoid having to create
215 a function object for each key stored in the mapping. A shared
216 callback object can use the 'key' attribute of a KeyedRef instead
217 of getting a reference to the key from an enclosing scope.
218
219 """
220
221 __slots__ = "key",
222
223 def __new__(type, ob, callback, key):
224 self = ref.__new__(type, ob, callback)
225 self.key = key
226 return self
227
228 def __init__(self, ob, callback, key):
229 super(KeyedRef, self).__init__(ob, callback)
Fred Drake746fe0f2001-09-28 19:01:26 +0000230
Fred Drake41deb1e2001-02-01 05:27:45 +0000231
Martin v. Löwis5e163332001-02-27 18:36:56 +0000232class WeakKeyDictionary(UserDict.UserDict):
Fred Drakebd7f8182001-04-19 16:26:06 +0000233 """ Mapping class that references keys weakly.
234
235 Entries in the dictionary will be discarded when there is no
236 longer a strong reference to the key. This can be used to
237 associate additional data with an object owned by other parts of
238 an application without adding attributes to those objects. This
239 can be especially useful with objects that override attribute
240 accesses.
241 """
Martin v. Löwis5e163332001-02-27 18:36:56 +0000242
243 def __init__(self, dict=None):
244 self.data = {}
Fred Drake746fe0f2001-09-28 19:01:26 +0000245 def remove(k, selfref=ref(self)):
246 self = selfref()
247 if self is not None:
248 del self.data[k]
Martin v. Löwis5e163332001-02-27 18:36:56 +0000249 self._remove = remove
Guido van Rossum009afb72002-06-10 20:00:52 +0000250 if dict is not None: self.update(dict)
Martin v. Löwis5e163332001-02-27 18:36:56 +0000251
Fred Drakeb663a2c2001-09-06 14:51:01 +0000252 def __delitem__(self, key):
Tim Peters886128f2003-05-25 01:45:11 +0000253 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000254
Martin v. Löwis5e163332001-02-27 18:36:56 +0000255 def __getitem__(self, key):
256 return self.data[ref(key)]
257
258 def __repr__(self):
259 return "<WeakKeyDictionary at %s>" % id(self)
260
261 def __setitem__(self, key, value):
262 self.data[ref(key, self._remove)] = value
263
264 def copy(self):
265 new = WeakKeyDictionary()
266 for key, value in self.data.items():
267 o = key()
268 if o is not None:
269 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000270 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000271
Antoine Pitrou775fd662009-05-15 16:54:52 +0000272 __copy__ = copy
273
274 def __deepcopy__(self, memo):
275 from copy import deepcopy
276 new = self.__class__()
277 for key, value in self.data.items():
278 o = key()
279 if o is not None:
280 new[o] = deepcopy(value, memo)
281 return new
282
Fred Drake1d9e4b72001-04-16 17:34:48 +0000283 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000284 return self.data.get(ref(key),default)
285
Fred Drake1d9e4b72001-04-16 17:34:48 +0000286 def has_key(self, key):
Fred Drake3bae7dd2001-11-06 16:36:53 +0000287 try:
288 wr = ref(key)
289 except TypeError:
290 return 0
Raymond Hettinger54f02222002-06-01 14:18:47 +0000291 return wr in self.data
Fred Drake1d9e4b72001-04-16 17:34:48 +0000292
Raymond Hettinger54f02222002-06-01 14:18:47 +0000293 def __contains__(self, key):
294 try:
295 wr = ref(key)
296 except TypeError:
297 return 0
298 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000299
Martin v. Löwis5e163332001-02-27 18:36:56 +0000300 def items(self):
301 L = []
302 for key, value in self.data.items():
303 o = key()
304 if o is not None:
305 L.append((o, value))
306 return L
307
Fred Drake101209d2001-05-02 05:43:09 +0000308 def iteritems(self):
Raymond Hettinger61146792004-08-19 21:32:06 +0000309 for wr, value in self.data.iteritems():
310 key = wr()
311 if key is not None:
312 yield key, value
Fred Drake101209d2001-05-02 05:43:09 +0000313
Fred Drake017e68c2006-05-02 06:53:59 +0000314 def iterkeyrefs(self):
315 """Return an iterator that yields the weak references to the keys.
316
317 The references are not guaranteed to be 'live' at the time
318 they are used, so the result of calling the references needs
319 to be checked before being used. This can be used to avoid
320 creating references that will cause the garbage collector to
321 keep the keys around longer than needed.
322
323 """
324 return self.data.iterkeys()
325
Fred Drake101209d2001-05-02 05:43:09 +0000326 def iterkeys(self):
Raymond Hettinger61146792004-08-19 21:32:06 +0000327 for wr in self.data.iterkeys():
328 obj = wr()
329 if obj is not None:
330 yield obj
331
332 def __iter__(self):
333 return self.iterkeys()
Fred Drake101209d2001-05-02 05:43:09 +0000334
335 def itervalues(self):
336 return self.data.itervalues()
337
Fred Drake017e68c2006-05-02 06:53:59 +0000338 def keyrefs(self):
339 """Return a list of weak references to the keys.
340
341 The references are not guaranteed to be 'live' at the time
342 they are used, so the result of calling the references needs
343 to be checked before being used. This can be used to avoid
344 creating references that will cause the garbage collector to
345 keep the keys around longer than needed.
346
347 """
348 return self.data.keys()
349
Fred Drake1d9e4b72001-04-16 17:34:48 +0000350 def keys(self):
351 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000352 for wr in self.data.keys():
353 o = wr()
Fred Drake1d9e4b72001-04-16 17:34:48 +0000354 if o is not None:
355 L.append(o)
356 return L
357
Martin v. Löwis5e163332001-02-27 18:36:56 +0000358 def popitem(self):
359 while 1:
360 key, value = self.data.popitem()
361 o = key()
362 if o is not None:
363 return o, value
364
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000365 def pop(self, key, *args):
366 return self.data.pop(ref(key), *args)
367
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000368 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000369 return self.data.setdefault(ref(key, self._remove),default)
370
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000371 def update(self, dict=None, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000372 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000373 if dict is not None:
374 if not hasattr(dict, "items"):
375 dict = type({})(dict)
376 for key, value in dict.items():
377 d[ref(key, self._remove)] = value
378 if len(kwargs):
379 self.update(kwargs)