blob: 5e6cc8be3a056183080af8850a7d9cd3c46ec6f9 [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
Raymond Hettinger93fa6082008-02-05 00:20:01 +000021from _weakrefset import WeakSet
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:
49 del self.data[wr.key]
50 self._remove = remove
Raymond Hettinger7ac60952008-02-05 01:15:57 +000051 self.data = d = {}
Antoine Pitrouc06de472009-05-30 21:04:26 +000052 self.update(*args, **kw)
Fred Drake0a4dd392004-07-02 18:57:45 +000053
Fred Drake41deb1e2001-02-01 05:27:45 +000054 def __getitem__(self, key):
Fred Drake4fd06e02001-08-03 04:11:27 +000055 o = self.data[key]()
Fred Drake41deb1e2001-02-01 05:27:45 +000056 if o is None:
Collin Winterce36ad82007-08-30 01:19:48 +000057 raise KeyError(key)
Fred Drake41deb1e2001-02-01 05:27:45 +000058 else:
59 return o
60
Raymond Hettinger7ac60952008-02-05 01:15:57 +000061 def __delitem__(self, key):
62 del self.data[key]
63
64 def __len__(self):
65 return sum(wr() is not None for wr in self.data.values())
66
Raymond Hettinger61146792004-08-19 21:32:06 +000067 def __contains__(self, key):
68 try:
69 o = self.data[key]()
70 except KeyError:
71 return False
72 return o is not None
73
Fred Drake41deb1e2001-02-01 05:27:45 +000074 def __repr__(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000075 return "<WeakValueDictionary at %s>" % id(self)
Fred Drake41deb1e2001-02-01 05:27:45 +000076
77 def __setitem__(self, key, value):
Fred Drake0a4dd392004-07-02 18:57:45 +000078 self.data[key] = KeyedRef(value, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +000079
80 def copy(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000081 new = WeakValueDictionary()
Fred Drakebd7f8182001-04-19 16:26:06 +000082 for key, wr in self.data.items():
83 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +000084 if o is not None:
85 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +000086 return new
Fred Drake41deb1e2001-02-01 05:27:45 +000087
Antoine Pitrou6e610062009-05-15 17:04:50 +000088 __copy__ = copy
89
90 def __deepcopy__(self, memo):
91 from copy import deepcopy
92 new = self.__class__()
93 for key, wr in self.data.items():
94 o = wr()
95 if o is not None:
96 new[deepcopy(key, memo)] = o
97 return new
98
Fred Drake1d9e4b72001-04-16 17:34:48 +000099 def get(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000100 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000101 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000102 except KeyError:
103 return default
104 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000105 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000106 if o is None:
107 # This should only happen
108 return default
109 else:
110 return o
111
112 def items(self):
Fred Drake312a5dc2001-02-02 15:13:24 +0000113 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000114 for key, wr in self.data.items():
115 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000116 if o is not None:
Fred Drake312a5dc2001-02-02 15:13:24 +0000117 L.append((key, o))
Fred Drake41deb1e2001-02-01 05:27:45 +0000118 return L
119
Barry Warsawecaab832008-09-04 01:42:51 +0000120 def items(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000121 for wr in self.data.values():
Raymond Hettinger61146792004-08-19 21:32:06 +0000122 value = wr()
123 if value is not None:
124 yield wr.key, value
Fred Drake101209d2001-05-02 05:43:09 +0000125
Barry Warsawecaab832008-09-04 01:42:51 +0000126 def keys(self):
Guido van Rossum07f24362007-02-11 22:59:48 +0000127 return iter(self.data.keys())
Raymond Hettinger61146792004-08-19 21:32:06 +0000128
129 def __iter__(self):
Guido van Rossum07f24362007-02-11 22:59:48 +0000130 return iter(self.data.keys())
Fred Drake101209d2001-05-02 05:43:09 +0000131
Thomas Wouters477c8d52006-05-27 19:21:47 +0000132 def itervaluerefs(self):
133 """Return an iterator that yields the weak references to the values.
134
135 The references are not guaranteed to be 'live' at the time
136 they are used, so the result of calling the references needs
137 to be checked before being used. This can be used to avoid
138 creating references that will cause the garbage collector to
139 keep the values around longer than needed.
140
141 """
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000142 return self.data.values()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000143
Barry Warsawecaab832008-09-04 01:42:51 +0000144 def values(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000145 for wr in self.data.values():
Raymond Hettinger61146792004-08-19 21:32:06 +0000146 obj = wr()
147 if obj is not None:
148 yield obj
Fred Drake101209d2001-05-02 05:43:09 +0000149
Fred Drake41deb1e2001-02-01 05:27:45 +0000150 def popitem(self):
151 while 1:
Fred Drakebd7f8182001-04-19 16:26:06 +0000152 key, wr = self.data.popitem()
153 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000154 if o is not None:
155 return key, o
156
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000157 def pop(self, key, *args):
158 try:
159 o = self.data.pop(key)()
160 except KeyError:
161 if args:
162 return args[0]
163 raise
164 if o is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000165 raise KeyError(key)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000166 else:
167 return o
168
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000169 def setdefault(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000170 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000171 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000172 except KeyError:
Fred Drake0a4dd392004-07-02 18:57:45 +0000173 self.data[key] = KeyedRef(default, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000174 return default
175 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000176 return wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000177
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000178 def update(self, dict=None, **kwargs):
Fred Drake41deb1e2001-02-01 05:27:45 +0000179 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000180 if dict is not None:
181 if not hasattr(dict, "items"):
182 dict = type({})(dict)
183 for key, o in dict.items():
Fred Drake0a4dd392004-07-02 18:57:45 +0000184 d[key] = KeyedRef(o, self._remove, key)
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000185 if len(kwargs):
186 self.update(kwargs)
Fred Drake41deb1e2001-02-01 05:27:45 +0000187
Thomas Wouters477c8d52006-05-27 19:21:47 +0000188 def valuerefs(self):
189 """Return a list of weak references to the values.
190
191 The references are not guaranteed to be 'live' at the time
192 they are used, so the result of calling the references needs
193 to be checked before being used. This can be used to avoid
194 creating references that will cause the garbage collector to
195 keep the values around longer than needed.
196
197 """
198 return self.data.values()
199
Fred Drake0a4dd392004-07-02 18:57:45 +0000200
201class KeyedRef(ref):
202 """Specialized reference that includes a key corresponding to the value.
203
204 This is used in the WeakValueDictionary to avoid having to create
205 a function object for each key stored in the mapping. A shared
206 callback object can use the 'key' attribute of a KeyedRef instead
207 of getting a reference to the key from an enclosing scope.
208
209 """
210
211 __slots__ = "key",
212
213 def __new__(type, ob, callback, key):
214 self = ref.__new__(type, ob, callback)
215 self.key = key
216 return self
217
218 def __init__(self, ob, callback, key):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000219 super().__init__(ob, callback)
Fred Drake746fe0f2001-09-28 19:01:26 +0000220
Fred Drake41deb1e2001-02-01 05:27:45 +0000221
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000222class WeakKeyDictionary(collections.MutableMapping):
Fred Drakebd7f8182001-04-19 16:26:06 +0000223 """ Mapping class that references keys weakly.
224
225 Entries in the dictionary will be discarded when there is no
226 longer a strong reference to the key. This can be used to
227 associate additional data with an object owned by other parts of
228 an application without adding attributes to those objects. This
229 can be especially useful with objects that override attribute
230 accesses.
231 """
Martin v. Löwis5e163332001-02-27 18:36:56 +0000232
233 def __init__(self, dict=None):
234 self.data = {}
Fred Drake746fe0f2001-09-28 19:01:26 +0000235 def remove(k, selfref=ref(self)):
236 self = selfref()
237 if self is not None:
238 del self.data[k]
Martin v. Löwis5e163332001-02-27 18:36:56 +0000239 self._remove = remove
Guido van Rossum009afb72002-06-10 20:00:52 +0000240 if dict is not None: self.update(dict)
Martin v. Löwis5e163332001-02-27 18:36:56 +0000241
Fred Drakeb663a2c2001-09-06 14:51:01 +0000242 def __delitem__(self, key):
Tim Peters886128f2003-05-25 01:45:11 +0000243 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000244
Martin v. Löwis5e163332001-02-27 18:36:56 +0000245 def __getitem__(self, key):
246 return self.data[ref(key)]
247
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000248 def __len__(self):
249 return len(self.data)
250
Martin v. Löwis5e163332001-02-27 18:36:56 +0000251 def __repr__(self):
252 return "<WeakKeyDictionary at %s>" % id(self)
253
254 def __setitem__(self, key, value):
255 self.data[ref(key, self._remove)] = value
256
257 def copy(self):
258 new = WeakKeyDictionary()
259 for key, value in self.data.items():
260 o = key()
261 if o is not None:
262 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000263 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000264
Antoine Pitrou6e610062009-05-15 17:04:50 +0000265 __copy__ = copy
266
267 def __deepcopy__(self, memo):
268 from copy import deepcopy
269 new = self.__class__()
270 for key, value in self.data.items():
271 o = key()
272 if o is not None:
273 new[o] = deepcopy(value, memo)
274 return new
275
Fred Drake1d9e4b72001-04-16 17:34:48 +0000276 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000277 return self.data.get(ref(key),default)
278
Raymond Hettinger54f02222002-06-01 14:18:47 +0000279 def __contains__(self, key):
280 try:
281 wr = ref(key)
282 except TypeError:
283 return 0
284 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000285
Martin v. Löwis5e163332001-02-27 18:36:56 +0000286 def items(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000287 for wr, value in self.data.items():
Raymond Hettinger61146792004-08-19 21:32:06 +0000288 key = wr()
289 if key is not None:
290 yield key, value
Fred Drake101209d2001-05-02 05:43:09 +0000291
Barry Warsawecaab832008-09-04 01:42:51 +0000292 def keyrefs(self):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000293 """Return an iterator that yields the weak references to the keys.
294
295 The references are not guaranteed to be 'live' at the time
296 they are used, so the result of calling the references needs
297 to be checked before being used. This can be used to avoid
298 creating references that will cause the garbage collector to
299 keep the keys around longer than needed.
300
301 """
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000302 return self.data.keys()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000303
Barry Warsawecaab832008-09-04 01:42:51 +0000304 def keys(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000305 for wr in self.data.keys():
Raymond Hettinger61146792004-08-19 21:32:06 +0000306 obj = wr()
307 if obj is not None:
308 yield obj
309
310 def __iter__(self):
Guido van Rossum07f24362007-02-11 22:59:48 +0000311 return iter(self.keys())
Fred Drake101209d2001-05-02 05:43:09 +0000312
Barry Warsawecaab832008-09-04 01:42:51 +0000313 def values(self):
Guido van Rossum07f24362007-02-11 22:59:48 +0000314 return iter(self.data.values())
Fred Drake101209d2001-05-02 05:43:09 +0000315
Thomas Wouters477c8d52006-05-27 19:21:47 +0000316 def keyrefs(self):
317 """Return a list of weak references to the keys.
318
319 The references are not guaranteed to be 'live' at the time
320 they are used, so the result of calling the references needs
321 to be checked before being used. This can be used to avoid
322 creating references that will cause the garbage collector to
323 keep the keys around longer than needed.
324
325 """
326 return self.data.keys()
327
Martin v. Löwis5e163332001-02-27 18:36:56 +0000328 def popitem(self):
329 while 1:
330 key, value = self.data.popitem()
331 o = key()
332 if o is not None:
333 return o, value
334
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000335 def pop(self, key, *args):
336 return self.data.pop(ref(key), *args)
337
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000338 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000339 return self.data.setdefault(ref(key, self._remove),default)
340
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000341 def update(self, dict=None, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000342 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000343 if dict is not None:
344 if not hasattr(dict, "items"):
345 dict = type({})(dict)
346 for key, value in dict.items():
347 d[ref(key, self._remove)] = value
348 if len(kwargs):
349 self.update(kwargs)