see if we can get this to work on windows
[python/dscho.git] / Lib / weakref.py
blob6663c262d1469a1b8c01da847445790873e95642
1 """Weak reference support for Python.
3 This module is an implementation of PEP 205:
5 http://www.python.org/dev/peps/pep-0205/
6 """
8 # 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.
12 from _weakref import (
13 getweakrefcount,
14 getweakrefs,
15 ref,
16 proxy,
17 CallableProxyType,
18 ProxyType,
19 ReferenceType)
21 from _weakrefset import WeakSet
23 import collections # Import after _weakref to avoid circular import.
25 ProxyTypes = (ProxyType, CallableProxyType)
27 __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
28 "WeakKeyDictionary", "ReferenceType", "ProxyType",
29 "CallableProxyType", "ProxyTypes", "WeakValueDictionary",
30 "WeakSet"]
33 class WeakValueDictionary(collections.MutableMapping):
34 """Mapping class that references values weakly.
36 Entries in the dictionary will be discarded when no strong
37 reference to the value exists anymore
38 """
39 # We inherit the constructor without worrying about the input
40 # dictionary; since it uses our .update() method, we get the right
41 # 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).
45 def __init__(self, *args, **kw):
46 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
51 self.data = d = {}
52 d.update(*args, **kw)
54 def __getitem__(self, key):
55 o = self.data[key]()
56 if o is None:
57 raise KeyError(key)
58 else:
59 return o
61 def __delitem__(self, key):
62 del self.data[key]
64 def __len__(self):
65 return sum(wr() is not None for wr in self.data.values())
67 def __contains__(self, key):
68 try:
69 o = self.data[key]()
70 except KeyError:
71 return False
72 return o is not None
74 def __repr__(self):
75 return "<WeakValueDictionary at %s>" % id(self)
77 def __setitem__(self, key, value):
78 self.data[key] = KeyedRef(value, self._remove, key)
80 def copy(self):
81 new = WeakValueDictionary()
82 for key, wr in self.data.items():
83 o = wr()
84 if o is not None:
85 new[key] = o
86 return new
88 def get(self, key, default=None):
89 try:
90 wr = self.data[key]
91 except KeyError:
92 return default
93 else:
94 o = wr()
95 if o is None:
96 # This should only happen
97 return default
98 else:
99 return o
101 def items(self):
102 L = []
103 for key, wr in self.data.items():
104 o = wr()
105 if o is not None:
106 L.append((key, o))
107 return L
109 def items(self):
110 for wr in self.data.values():
111 value = wr()
112 if value is not None:
113 yield wr.key, value
115 def keys(self):
116 return iter(self.data.keys())
118 def __iter__(self):
119 return iter(self.data.keys())
121 def itervaluerefs(self):
122 """Return an iterator that yields the weak references to the values.
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.
131 return self.data.values()
133 def values(self):
134 for wr in self.data.values():
135 obj = wr()
136 if obj is not None:
137 yield obj
139 def popitem(self):
140 while 1:
141 key, wr = self.data.popitem()
142 o = wr()
143 if o is not None:
144 return key, o
146 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:
154 raise KeyError(key)
155 else:
156 return o
158 def setdefault(self, key, default=None):
159 try:
160 wr = self.data[key]
161 except KeyError:
162 self.data[key] = KeyedRef(default, self._remove, key)
163 return default
164 else:
165 return wr()
167 def update(self, dict=None, **kwargs):
168 d = self.data
169 if dict is not None:
170 if not hasattr(dict, "items"):
171 dict = type({})(dict)
172 for key, o in dict.items():
173 d[key] = KeyedRef(o, self._remove, key)
174 if len(kwargs):
175 self.update(kwargs)
177 def valuerefs(self):
178 """Return a list of weak references to the values.
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.
187 return self.data.values()
190 class KeyedRef(ref):
191 """Specialized reference that includes a key corresponding to the value.
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.
200 __slots__ = "key",
202 def __new__(type, ob, callback, key):
203 self = ref.__new__(type, ob, callback)
204 self.key = key
205 return self
207 def __init__(self, ob, callback, key):
208 super().__init__(ob, callback)
211 class WeakKeyDictionary(collections.MutableMapping):
212 """ Mapping class that references keys weakly.
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.
222 def __init__(self, dict=None):
223 self.data = {}
224 def remove(k, selfref=ref(self)):
225 self = selfref()
226 if self is not None:
227 del self.data[k]
228 self._remove = remove
229 if dict is not None: self.update(dict)
231 def __delitem__(self, key):
232 del self.data[ref(key)]
234 def __getitem__(self, key):
235 return self.data[ref(key)]
237 def __len__(self):
238 return len(self.data)
240 def __repr__(self):
241 return "<WeakKeyDictionary at %s>" % id(self)
243 def __setitem__(self, key, value):
244 self.data[ref(key, self._remove)] = value
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
252 return new
254 def get(self, key, default=None):
255 return self.data.get(ref(key),default)
257 def __contains__(self, key):
258 try:
259 wr = ref(key)
260 except TypeError:
261 return 0
262 return wr in self.data
264 def items(self):
265 for wr, value in self.data.items():
266 key = wr()
267 if key is not None:
268 yield key, value
270 def keyrefs(self):
271 """Return an iterator that yields the weak references to the keys.
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.
280 return self.data.keys()
282 def keys(self):
283 for wr in self.data.keys():
284 obj = wr()
285 if obj is not None:
286 yield obj
288 def __iter__(self):
289 return iter(self.keys())
291 def values(self):
292 return iter(self.data.values())
294 def keyrefs(self):
295 """Return a list of weak references to the keys.
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.
304 return self.data.keys()
306 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
313 def pop(self, key, *args):
314 return self.data.pop(ref(key), *args)
316 def setdefault(self, key, default=None):
317 return self.data.setdefault(ref(key, self._remove),default)
319 def update(self, dict=None, **kwargs):
320 d = self.data
321 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)