blob: 6663c262d1469a1b8c01da847445790873e95642 [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 = {}
52 d.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
Fred Drake1d9e4b72001-04-16 17:34:48 +000088 def get(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +000089 try:
Fred Drakebd7f8182001-04-19 16:26:06 +000090 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +000091 except KeyError:
92 return default
93 else:
Fred Drakebd7f8182001-04-19 16:26:06 +000094 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +000095 if o is None:
96 # This should only happen
97 return default
98 else:
99 return o
100
101 def items(self):
Fred Drake312a5dc2001-02-02 15:13:24 +0000102 L = []
Fred Drakebd7f8182001-04-19 16:26:06 +0000103 for key, wr in self.data.items():
104 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000105 if o is not None:
Fred Drake312a5dc2001-02-02 15:13:24 +0000106 L.append((key, o))
Fred Drake41deb1e2001-02-01 05:27:45 +0000107 return L
108
Barry Warsawecaab832008-09-04 01:42:51 +0000109 def items(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000110 for wr in self.data.values():
Raymond Hettinger61146792004-08-19 21:32:06 +0000111 value = wr()
112 if value is not None:
113 yield wr.key, value
Fred Drake101209d2001-05-02 05:43:09 +0000114
Barry Warsawecaab832008-09-04 01:42:51 +0000115 def keys(self):
Guido van Rossum07f24362007-02-11 22:59:48 +0000116 return iter(self.data.keys())
Raymond Hettinger61146792004-08-19 21:32:06 +0000117
118 def __iter__(self):
Guido van Rossum07f24362007-02-11 22:59:48 +0000119 return iter(self.data.keys())
Fred Drake101209d2001-05-02 05:43:09 +0000120
Thomas Wouters477c8d52006-05-27 19:21:47 +0000121 def itervaluerefs(self):
122 """Return an iterator that yields the weak references to the values.
123
124 The references are not guaranteed to be 'live' at the time
125 they are used, so the result of calling the references needs
126 to be checked before being used. This can be used to avoid
127 creating references that will cause the garbage collector to
128 keep the values around longer than needed.
129
130 """
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000131 return self.data.values()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000132
Barry Warsawecaab832008-09-04 01:42:51 +0000133 def values(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000134 for wr in self.data.values():
Raymond Hettinger61146792004-08-19 21:32:06 +0000135 obj = wr()
136 if obj is not None:
137 yield obj
Fred Drake101209d2001-05-02 05:43:09 +0000138
Fred Drake41deb1e2001-02-01 05:27:45 +0000139 def popitem(self):
140 while 1:
Fred Drakebd7f8182001-04-19 16:26:06 +0000141 key, wr = self.data.popitem()
142 o = wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000143 if o is not None:
144 return key, o
145
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000146 def pop(self, key, *args):
147 try:
148 o = self.data.pop(key)()
149 except KeyError:
150 if args:
151 return args[0]
152 raise
153 if o is None:
Collin Winterce36ad82007-08-30 01:19:48 +0000154 raise KeyError(key)
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000155 else:
156 return o
157
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000158 def setdefault(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +0000159 try:
Fred Drakebd7f8182001-04-19 16:26:06 +0000160 wr = self.data[key]
Fred Drake41deb1e2001-02-01 05:27:45 +0000161 except KeyError:
Fred Drake0a4dd392004-07-02 18:57:45 +0000162 self.data[key] = KeyedRef(default, self._remove, key)
Fred Drake41deb1e2001-02-01 05:27:45 +0000163 return default
164 else:
Fred Drakebd7f8182001-04-19 16:26:06 +0000165 return wr()
Fred Drake41deb1e2001-02-01 05:27:45 +0000166
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000167 def update(self, dict=None, **kwargs):
Fred Drake41deb1e2001-02-01 05:27:45 +0000168 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000169 if dict is not None:
170 if not hasattr(dict, "items"):
171 dict = type({})(dict)
172 for key, o in dict.items():
Fred Drake0a4dd392004-07-02 18:57:45 +0000173 d[key] = KeyedRef(o, self._remove, key)
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000174 if len(kwargs):
175 self.update(kwargs)
Fred Drake41deb1e2001-02-01 05:27:45 +0000176
Thomas Wouters477c8d52006-05-27 19:21:47 +0000177 def valuerefs(self):
178 """Return a list of weak references to the values.
179
180 The references are not guaranteed to be 'live' at the time
181 they are used, so the result of calling the references needs
182 to be checked before being used. This can be used to avoid
183 creating references that will cause the garbage collector to
184 keep the values around longer than needed.
185
186 """
187 return self.data.values()
188
Fred Drake0a4dd392004-07-02 18:57:45 +0000189
190class KeyedRef(ref):
191 """Specialized reference that includes a key corresponding to the value.
192
193 This is used in the WeakValueDictionary to avoid having to create
194 a function object for each key stored in the mapping. A shared
195 callback object can use the 'key' attribute of a KeyedRef instead
196 of getting a reference to the key from an enclosing scope.
197
198 """
199
200 __slots__ = "key",
201
202 def __new__(type, ob, callback, key):
203 self = ref.__new__(type, ob, callback)
204 self.key = key
205 return self
206
207 def __init__(self, ob, callback, key):
Guido van Rossumcd16bf62007-06-13 18:07:49 +0000208 super().__init__(ob, callback)
Fred Drake746fe0f2001-09-28 19:01:26 +0000209
Fred Drake41deb1e2001-02-01 05:27:45 +0000210
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000211class WeakKeyDictionary(collections.MutableMapping):
Fred Drakebd7f8182001-04-19 16:26:06 +0000212 """ Mapping class that references keys weakly.
213
214 Entries in the dictionary will be discarded when there is no
215 longer a strong reference to the key. This can be used to
216 associate additional data with an object owned by other parts of
217 an application without adding attributes to those objects. This
218 can be especially useful with objects that override attribute
219 accesses.
220 """
Martin v. Löwis5e163332001-02-27 18:36:56 +0000221
222 def __init__(self, dict=None):
223 self.data = {}
Fred Drake746fe0f2001-09-28 19:01:26 +0000224 def remove(k, selfref=ref(self)):
225 self = selfref()
226 if self is not None:
227 del self.data[k]
Martin v. Löwis5e163332001-02-27 18:36:56 +0000228 self._remove = remove
Guido van Rossum009afb72002-06-10 20:00:52 +0000229 if dict is not None: self.update(dict)
Martin v. Löwis5e163332001-02-27 18:36:56 +0000230
Fred Drakeb663a2c2001-09-06 14:51:01 +0000231 def __delitem__(self, key):
Tim Peters886128f2003-05-25 01:45:11 +0000232 del self.data[ref(key)]
Fred Drakeb663a2c2001-09-06 14:51:01 +0000233
Martin v. Löwis5e163332001-02-27 18:36:56 +0000234 def __getitem__(self, key):
235 return self.data[ref(key)]
236
Raymond Hettinger7ac60952008-02-05 01:15:57 +0000237 def __len__(self):
238 return len(self.data)
239
Martin v. Löwis5e163332001-02-27 18:36:56 +0000240 def __repr__(self):
241 return "<WeakKeyDictionary at %s>" % id(self)
242
243 def __setitem__(self, key, value):
244 self.data[ref(key, self._remove)] = value
245
246 def copy(self):
247 new = WeakKeyDictionary()
248 for key, value in self.data.items():
249 o = key()
250 if o is not None:
251 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000252 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000253
Fred Drake1d9e4b72001-04-16 17:34:48 +0000254 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000255 return self.data.get(ref(key),default)
256
Raymond Hettinger54f02222002-06-01 14:18:47 +0000257 def __contains__(self, key):
258 try:
259 wr = ref(key)
260 except TypeError:
261 return 0
262 return wr in self.data
Tim Petersc411dba2002-07-16 21:35:23 +0000263
Martin v. Löwis5e163332001-02-27 18:36:56 +0000264 def items(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000265 for wr, value in self.data.items():
Raymond Hettinger61146792004-08-19 21:32:06 +0000266 key = wr()
267 if key is not None:
268 yield key, value
Fred Drake101209d2001-05-02 05:43:09 +0000269
Barry Warsawecaab832008-09-04 01:42:51 +0000270 def keyrefs(self):
Thomas Wouters477c8d52006-05-27 19:21:47 +0000271 """Return an iterator that yields the weak references to the keys.
272
273 The references are not guaranteed to be 'live' at the time
274 they are used, so the result of calling the references needs
275 to be checked before being used. This can be used to avoid
276 creating references that will cause the garbage collector to
277 keep the keys around longer than needed.
278
279 """
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000280 return self.data.keys()
Thomas Wouters477c8d52006-05-27 19:21:47 +0000281
Barry Warsawecaab832008-09-04 01:42:51 +0000282 def keys(self):
Guido van Rossumcc2b0162007-02-11 06:12:03 +0000283 for wr in self.data.keys():
Raymond Hettinger61146792004-08-19 21:32:06 +0000284 obj = wr()
285 if obj is not None:
286 yield obj
287
288 def __iter__(self):
Guido van Rossum07f24362007-02-11 22:59:48 +0000289 return iter(self.keys())
Fred Drake101209d2001-05-02 05:43:09 +0000290
Barry Warsawecaab832008-09-04 01:42:51 +0000291 def values(self):
Guido van Rossum07f24362007-02-11 22:59:48 +0000292 return iter(self.data.values())
Fred Drake101209d2001-05-02 05:43:09 +0000293
Thomas Wouters477c8d52006-05-27 19:21:47 +0000294 def keyrefs(self):
295 """Return a list of weak references to the keys.
296
297 The references are not guaranteed to be 'live' at the time
298 they are used, so the result of calling the references needs
299 to be checked before being used. This can be used to avoid
300 creating references that will cause the garbage collector to
301 keep the keys around longer than needed.
302
303 """
304 return self.data.keys()
305
Martin v. Löwis5e163332001-02-27 18:36:56 +0000306 def popitem(self):
307 while 1:
308 key, value = self.data.popitem()
309 o = key()
310 if o is not None:
311 return o, value
312
Raymond Hettinger2c2d3222003-03-09 07:05:43 +0000313 def pop(self, key, *args):
314 return self.data.pop(ref(key), *args)
315
Walter Dörwald80ce6dd2004-05-27 18:16:25 +0000316 def setdefault(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000317 return self.data.setdefault(ref(key, self._remove),default)
318
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000319 def update(self, dict=None, **kwargs):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000320 d = self.data
Raymond Hettinger31017ae2004-03-04 08:25:44 +0000321 if dict is not None:
322 if not hasattr(dict, "items"):
323 dict = type({})(dict)
324 for key, value in dict.items():
325 d[ref(key, self._remove)] = value
326 if len(kwargs):
327 self.update(kwargs)