]> rtime.felk.cvut.cz Git - l4.git/blob - l4/pkg/python/contrib/Lib/weakref.py
Inital import
[l4.git] / l4 / pkg / python / contrib / Lib / weakref.py
1 """Weak reference support for Python.
2
3 This module is an implementation of PEP 205:
4
5 http://www.python.org/dev/peps/pep-0205/
6 """
7
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.
11
12 import UserDict
13
14 from _weakref import (
15      getweakrefcount,
16      getweakrefs,
17      ref,
18      proxy,
19      CallableProxyType,
20      ProxyType,
21      ReferenceType)
22
23 from exceptions import ReferenceError
24
25
26 ProxyTypes = (ProxyType, CallableProxyType)
27
28 __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
29            "WeakKeyDictionary", "ReferenceError", "ReferenceType", "ProxyType",
30            "CallableProxyType", "ProxyTypes", "WeakValueDictionary"]
31
32
33 class WeakValueDictionary(UserDict.UserDict):
34     """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     """
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).
44
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         UserDict.UserDict.__init__(self, *args, **kw)
52
53     def __getitem__(self, key):
54         o = self.data[key]()
55         if o is None:
56             raise KeyError, key
57         else:
58             return o
59
60     def __contains__(self, key):
61         try:
62             o = self.data[key]()
63         except KeyError:
64             return False
65         return o is not None
66
67     def has_key(self, key):
68         try:
69             o = self.data[key]()
70         except KeyError:
71             return False
72         return o is not None
73
74     def __repr__(self):
75         return "<WeakValueDictionary at %s>" % id(self)
76
77     def __setitem__(self, key, value):
78         self.data[key] = KeyedRef(value, self._remove, key)
79
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
87
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
100
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
108
109     def iteritems(self):
110         for wr in self.data.itervalues():
111             value = wr()
112             if value is not None:
113                 yield wr.key, value
114
115     def iterkeys(self):
116         return self.data.iterkeys()
117
118     def __iter__(self):
119         return self.data.iterkeys()
120
121     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         """
131         return self.data.itervalues()
132
133     def itervalues(self):
134         for wr in self.data.itervalues():
135             obj = wr()
136             if obj is not None:
137                 yield obj
138
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
145
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
157
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()
166
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)
176
177     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
189     def values(self):
190         L = []
191         for wr in self.data.values():
192             o = wr()
193             if o is not None:
194                 L.append(o)
195         return L
196
197
198 class KeyedRef(ref):
199     """Specialized reference that includes a key corresponding to the value.
200
201     This is used in the WeakValueDictionary to avoid having to create
202     a function object for each key stored in the mapping.  A shared
203     callback object can use the 'key' attribute of a KeyedRef instead
204     of getting a reference to the key from an enclosing scope.
205
206     """
207
208     __slots__ = "key",
209
210     def __new__(type, ob, callback, key):
211         self = ref.__new__(type, ob, callback)
212         self.key = key
213         return self
214
215     def __init__(self, ob, callback, key):
216         super(KeyedRef,  self).__init__(ob, callback)
217
218
219 class WeakKeyDictionary(UserDict.UserDict):
220     """ Mapping class that references keys weakly.
221
222     Entries in the dictionary will be discarded when there is no
223     longer a strong reference to the key. This can be used to
224     associate additional data with an object owned by other parts of
225     an application without adding attributes to those objects. This
226     can be especially useful with objects that override attribute
227     accesses.
228     """
229
230     def __init__(self, dict=None):
231         self.data = {}
232         def remove(k, selfref=ref(self)):
233             self = selfref()
234             if self is not None:
235                 del self.data[k]
236         self._remove = remove
237         if dict is not None: self.update(dict)
238
239     def __delitem__(self, key):
240         del self.data[ref(key)]
241
242     def __getitem__(self, key):
243         return self.data[ref(key)]
244
245     def __repr__(self):
246         return "<WeakKeyDictionary at %s>" % id(self)
247
248     def __setitem__(self, key, value):
249         self.data[ref(key, self._remove)] = value
250
251     def copy(self):
252         new = WeakKeyDictionary()
253         for key, value in self.data.items():
254             o = key()
255             if o is not None:
256                 new[o] = value
257         return new
258
259     def get(self, key, default=None):
260         return self.data.get(ref(key),default)
261
262     def has_key(self, key):
263         try:
264             wr = ref(key)
265         except TypeError:
266             return 0
267         return wr in self.data
268
269     def __contains__(self, key):
270         try:
271             wr = ref(key)
272         except TypeError:
273             return 0
274         return wr in self.data
275
276     def items(self):
277         L = []
278         for key, value in self.data.items():
279             o = key()
280             if o is not None:
281                 L.append((o, value))
282         return L
283
284     def iteritems(self):
285         for wr, value in self.data.iteritems():
286             key = wr()
287             if key is not None:
288                 yield key, value
289
290     def iterkeyrefs(self):
291         """Return an iterator that yields the weak references to the keys.
292
293         The references are not guaranteed to be 'live' at the time
294         they are used, so the result of calling the references needs
295         to be checked before being used.  This can be used to avoid
296         creating references that will cause the garbage collector to
297         keep the keys around longer than needed.
298
299         """
300         return self.data.iterkeys()
301
302     def iterkeys(self):
303         for wr in self.data.iterkeys():
304             obj = wr()
305             if obj is not None:
306                 yield obj
307
308     def __iter__(self):
309         return self.iterkeys()
310
311     def itervalues(self):
312         return self.data.itervalues()
313
314     def keyrefs(self):
315         """Return a list of 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.keys()
325
326     def keys(self):
327         L = []
328         for wr in self.data.keys():
329             o = wr()
330             if o is not None:
331                 L.append(o)
332         return L
333
334     def popitem(self):
335         while 1:
336             key, value = self.data.popitem()
337             o = key()
338             if o is not None:
339                 return o, value
340
341     def pop(self, key, *args):
342         return self.data.pop(ref(key), *args)
343
344     def setdefault(self, key, default=None):
345         return self.data.setdefault(ref(key, self._remove),default)
346
347     def update(self, dict=None, **kwargs):
348         d = self.data
349         if dict is not None:
350             if not hasattr(dict, "items"):
351                 dict = type({})(dict)
352             for key, value in dict.items():
353                 d[ref(key, self._remove)] = value
354         if len(kwargs):
355             self.update(kwargs)