0001 """Weak reference support for Python. 0002 0003 This module is an implementation of PEP 205: 0004 0005 http://python.sourceforge.net/peps/pep-0205.html 0006 """ 0007 0008 # Naming convention: Variables named "wr" are weak reference objects; 0009 # they are called this instead of "ref" to avoid name collisions with 0010 # the module-global ref() function imported from _weakref. 0011 0012 import UserDict 0013 0014 from _weakref import ( 0015 getweakrefcount, 0016 getweakrefs, 0017 ref, 0018 proxy, 0019 CallableProxyType, 0020 ProxyType, 0021 ReferenceType) 0022 0023 from exceptions import ReferenceError 0024 0025 0026 ProxyTypes = (ProxyType, CallableProxyType) 0027 0028 __all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs", 0029 "WeakKeyDictionary", "ReferenceType", "ProxyType", 0030 "CallableProxyType", "ProxyTypes", "WeakValueDictionary"] 0031 0032 0033 class WeakValueDictionary(UserDict.UserDict): 0034 """Mapping class that references values weakly. 0035 0036 Entries in the dictionary will be discarded when no strong 0037 reference to the value exists anymore 0038 """ 0039 # We inherit the constructor without worrying about the input 0040 # dictionary; since it uses our .update() method, we get the right 0041 # checks (if the other dictionary is a WeakValueDictionary, 0042 # objects are unwrapped on the way out, and we always wrap on the 0043 # way in). 0044 0045 def __init__(self, *args, **kw): 0046 UserDict.UserDict.__init__(self, *args, **kw) 0047 def remove(wr, selfref=ref(self)): 0048 self = selfref() 0049 if self is not None: 0050 del self.data[wr.key] 0051 self._remove = remove 0052 0053 def __getitem__(self, key): 0054 o = self.data[key]() 0055 if o is None: 0056 raise KeyError, key 0057 else: 0058 return o 0059 0060 def __contains__(self, key): 0061 try: 0062 o = self.data[key]() 0063 except KeyError: 0064 return False 0065 return o is not None 0066 0067 def has_key(self, key): 0068 try: 0069 o = self.data[key]() 0070 except KeyError: 0071 return False 0072 return o is not None 0073 0074 def __repr__(self): 0075 return "<WeakValueDictionary at %s>" % id(self) 0076 0077 def __setitem__(self, key, value): 0078 self.data[key] = KeyedRef(value, self._remove, key) 0079 0080 def copy(self): 0081 new = WeakValueDictionary() 0082 for key, wr in self.data.items(): 0083 o = wr() 0084 if o is not None: 0085 new[key] = o 0086 return new 0087 0088 def get(self, key, default=None): 0089 try: 0090 wr = self.data[key] 0091 except KeyError: 0092 return default 0093 else: 0094 o = wr() 0095 if o is None: 0096 # This should only happen 0097 return default 0098 else: 0099 return o 0100 0101 def items(self): 0102 L = [] 0103 for key, wr in self.data.items(): 0104 o = wr() 0105 if o is not None: 0106 L.append((key, o)) 0107 return L 0108 0109 def iteritems(self): 0110 for wr in self.data.itervalues(): 0111 value = wr() 0112 if value is not None: 0113 yield wr.key, value 0114 0115 def iterkeys(self): 0116 return self.data.iterkeys() 0117 0118 def __iter__(self): 0119 return self.data.iterkeys() 0120 0121 def itervalues(self): 0122 for wr in self.data.itervalues(): 0123 obj = wr() 0124 if obj is not None: 0125 yield obj 0126 0127 def popitem(self): 0128 while 1: 0129 key, wr = self.data.popitem() 0130 o = wr() 0131 if o is not None: 0132 return key, o 0133 0134 def pop(self, key, *args): 0135 try: 0136 o = self.data.pop(key)() 0137 except KeyError: 0138 if args: 0139 return args[0] 0140 raise 0141 if o is None: 0142 raise KeyError, key 0143 else: 0144 return o 0145 0146 def setdefault(self, key, default=None): 0147 try: 0148 wr = self.data[key] 0149 except KeyError: 0150 self.data[key] = KeyedRef(default, self._remove, key) 0151 return default 0152 else: 0153 return wr() 0154 0155 def update(self, dict=None, **kwargs): 0156 d = self.data 0157 if dict is not None: 0158 if not hasattr(dict, "items"): 0159 dict = type({})(dict) 0160 for key, o in dict.items(): 0161 d[key] = KeyedRef(o, self._remove, key) 0162 if len(kwargs): 0163 self.update(kwargs) 0164 0165 def values(self): 0166 L = [] 0167 for wr in self.data.values(): 0168 o = wr() 0169 if o is not None: 0170 L.append(o) 0171 return L 0172 0173 0174 class KeyedRef(ref): 0175 """Specialized reference that includes a key corresponding to the value. 0176 0177 This is used in the WeakValueDictionary to avoid having to create 0178 a function object for each key stored in the mapping. A shared 0179 callback object can use the 'key' attribute of a KeyedRef instead 0180 of getting a reference to the key from an enclosing scope. 0181 0182 """ 0183 0184 __slots__ = "key", 0185 0186 def __new__(type, ob, callback, key): 0187 self = ref.__new__(type, ob, callback) 0188 self.key = key 0189 return self 0190 0191 def __init__(self, ob, callback, key): 0192 super(KeyedRef, self).__init__(ob, callback) 0193 0194 0195 class WeakKeyDictionary(UserDict.UserDict): 0196 """ Mapping class that references keys weakly. 0197 0198 Entries in the dictionary will be discarded when there is no 0199 longer a strong reference to the key. This can be used to 0200 associate additional data with an object owned by other parts of 0201 an application without adding attributes to those objects. This 0202 can be especially useful with objects that override attribute 0203 accesses. 0204 """ 0205 0206 def __init__(self, dict=None): 0207 self.data = {} 0208 def remove(k, selfref=ref(self)): 0209 self = selfref() 0210 if self is not None: 0211 del self.data[k] 0212 self._remove = remove 0213 if dict is not None: self.update(dict) 0214 0215 def __delitem__(self, key): 0216 del self.data[ref(key)] 0217 0218 def __getitem__(self, key): 0219 return self.data[ref(key)] 0220 0221 def __repr__(self): 0222 return "<WeakKeyDictionary at %s>" % id(self) 0223 0224 def __setitem__(self, key, value): 0225 self.data[ref(key, self._remove)] = value 0226 0227 def copy(self): 0228 new = WeakKeyDictionary() 0229 for key, value in self.data.items(): 0230 o = key() 0231 if o is not None: 0232 new[o] = value 0233 return new 0234 0235 def get(self, key, default=None): 0236 return self.data.get(ref(key),default) 0237 0238 def has_key(self, key): 0239 try: 0240 wr = ref(key) 0241 except TypeError: 0242 return 0 0243 return wr in self.data 0244 0245 def __contains__(self, key): 0246 try: 0247 wr = ref(key) 0248 except TypeError: 0249 return 0 0250 return wr in self.data 0251 0252 def items(self): 0253 L = [] 0254 for key, value in self.data.items(): 0255 o = key() 0256 if o is not None: 0257 L.append((o, value)) 0258 return L 0259 0260 def iteritems(self): 0261 for wr, value in self.data.iteritems(): 0262 key = wr() 0263 if key is not None: 0264 yield key, value 0265 0266 def iterkeys(self): 0267 for wr in self.data.iterkeys(): 0268 obj = wr() 0269 if obj is not None: 0270 yield obj 0271 0272 def __iter__(self): 0273 return self.iterkeys() 0274 0275 def itervalues(self): 0276 return self.data.itervalues() 0277 0278 def keys(self): 0279 L = [] 0280 for wr in self.data.keys(): 0281 o = wr() 0282 if o is not None: 0283 L.append(o) 0284 return L 0285 0286 def popitem(self): 0287 while 1: 0288 key, value = self.data.popitem() 0289 o = key() 0290 if o is not None: 0291 return o, value 0292 0293 def pop(self, key, *args): 0294 return self.data.pop(ref(key), *args) 0295 0296 def setdefault(self, key, default=None): 0297 return self.data.setdefault(ref(key, self._remove),default) 0298 0299 def update(self, dict=None, **kwargs): 0300 d = self.data 0301 if dict is not None: 0302 if not hasattr(dict, "items"): 0303 dict = type({})(dict) 0304 for key, value in dict.items(): 0305 d[ref(key, self._remove)] = value 0306 if len(kwargs): 0307 self.update(kwargs) 0308
Generated by PyXR 0.9.4