Fixed bug in time-to-midnight calculation.
[python.git] / Lib / weakref.py
blob09bd0bee24d6feadfcc080c5d6f214b7f882541d
1 """Weak reference support for Python.
3 This module is an implementation of PEP 205:
5 http://python.sourceforge.net/peps/pep-0205.html
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 import UserDict
14 from _weakref import (
15 getweakrefcount,
16 getweakrefs,
17 ref,
18 proxy,
19 CallableProxyType,
20 ProxyType,
21 ReferenceType)
23 from exceptions import ReferenceError
26 ProxyTypes = (ProxyType, CallableProxyType)
28 __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
29 "WeakKeyDictionary", "ReferenceType", "ProxyType",
30 "CallableProxyType", "ProxyTypes", "WeakValueDictionary"]
33 class WeakValueDictionary(UserDict.UserDict):
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 UserDict.UserDict.__init__(self, *args, **kw)
53 def __getitem__(self, key):
54 o = self.data[key]()
55 if o is None:
56 raise KeyError, key
57 else:
58 return o
60 def __contains__(self, key):
61 try:
62 o = self.data[key]()
63 except KeyError:
64 return False
65 return o is not None
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
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 iteritems(self):
110 for wr in self.data.itervalues():
111 value = wr()
112 if value is not None:
113 yield wr.key, value
115 def iterkeys(self):
116 return self.data.iterkeys()
118 def __iter__(self):
119 return self.data.iterkeys()
121 def itervalues(self):
122 for wr in self.data.itervalues():
123 obj = wr()
124 if obj is not None:
125 yield obj
127 def popitem(self):
128 while 1:
129 key, wr = self.data.popitem()
130 o = wr()
131 if o is not None:
132 return key, o
134 def pop(self, key, *args):
135 try:
136 o = self.data.pop(key)()
137 except KeyError:
138 if args:
139 return args[0]
140 raise
141 if o is None:
142 raise KeyError, key
143 else:
144 return o
146 def setdefault(self, key, default=None):
147 try:
148 wr = self.data[key]
149 except KeyError:
150 self.data[key] = KeyedRef(default, self._remove, key)
151 return default
152 else:
153 return wr()
155 def update(self, dict=None, **kwargs):
156 d = self.data
157 if dict is not None:
158 if not hasattr(dict, "items"):
159 dict = type({})(dict)
160 for key, o in dict.items():
161 d[key] = KeyedRef(o, self._remove, key)
162 if len(kwargs):
163 self.update(kwargs)
165 def values(self):
166 L = []
167 for wr in self.data.values():
168 o = wr()
169 if o is not None:
170 L.append(o)
171 return L
174 class KeyedRef(ref):
175 """Specialized reference that includes a key corresponding to the value.
177 This is used in the WeakValueDictionary to avoid having to create
178 a function object for each key stored in the mapping. A shared
179 callback object can use the 'key' attribute of a KeyedRef instead
180 of getting a reference to the key from an enclosing scope.
184 __slots__ = "key",
186 def __new__(type, ob, callback, key):
187 self = ref.__new__(type, ob, callback)
188 self.key = key
189 return self
191 def __init__(self, ob, callback, key):
192 super(KeyedRef, self).__init__(ob, callback)
195 class WeakKeyDictionary(UserDict.UserDict):
196 """ Mapping class that references keys weakly.
198 Entries in the dictionary will be discarded when there is no
199 longer a strong reference to the key. This can be used to
200 associate additional data with an object owned by other parts of
201 an application without adding attributes to those objects. This
202 can be especially useful with objects that override attribute
203 accesses.
206 def __init__(self, dict=None):
207 self.data = {}
208 def remove(k, selfref=ref(self)):
209 self = selfref()
210 if self is not None:
211 del self.data[k]
212 self._remove = remove
213 if dict is not None: self.update(dict)
215 def __delitem__(self, key):
216 del self.data[ref(key)]
218 def __getitem__(self, key):
219 return self.data[ref(key)]
221 def __repr__(self):
222 return "<WeakKeyDictionary at %s>" % id(self)
224 def __setitem__(self, key, value):
225 self.data[ref(key, self._remove)] = value
227 def copy(self):
228 new = WeakKeyDictionary()
229 for key, value in self.data.items():
230 o = key()
231 if o is not None:
232 new[o] = value
233 return new
235 def get(self, key, default=None):
236 return self.data.get(ref(key),default)
238 def has_key(self, key):
239 try:
240 wr = ref(key)
241 except TypeError:
242 return 0
243 return wr in self.data
245 def __contains__(self, key):
246 try:
247 wr = ref(key)
248 except TypeError:
249 return 0
250 return wr in self.data
252 def items(self):
253 L = []
254 for key, value in self.data.items():
255 o = key()
256 if o is not None:
257 L.append((o, value))
258 return L
260 def iteritems(self):
261 for wr, value in self.data.iteritems():
262 key = wr()
263 if key is not None:
264 yield key, value
266 def iterkeys(self):
267 for wr in self.data.iterkeys():
268 obj = wr()
269 if obj is not None:
270 yield obj
272 def __iter__(self):
273 return self.iterkeys()
275 def itervalues(self):
276 return self.data.itervalues()
278 def keys(self):
279 L = []
280 for wr in self.data.keys():
281 o = wr()
282 if o is not None:
283 L.append(o)
284 return L
286 def popitem(self):
287 while 1:
288 key, value = self.data.popitem()
289 o = key()
290 if o is not None:
291 return o, value
293 def pop(self, key, *args):
294 return self.data.pop(ref(key), *args)
296 def setdefault(self, key, default=None):
297 return self.data.setdefault(ref(key, self._remove),default)
299 def update(self, dict=None, **kwargs):
300 d = self.data
301 if dict is not None:
302 if not hasattr(dict, "items"):
303 dict = type({})(dict)
304 for key, value in dict.items():
305 d[ref(key, self._remove)] = value
306 if len(kwargs):
307 self.update(kwargs)