weakref.py revision bd7f818c508248e12f88e51198cb5e9b861dacbf
1"""Weak reference support for Python. 2 3This module is an implementation of PEP 205: 4 5http://python.sourceforge.net/peps/pep-0205.html 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 12import UserDict 13 14from _weakref import \ 15 getweakrefcount, \ 16 getweakrefs, \ 17 ref, \ 18 proxy, \ 19 ReferenceError, \ 20 CallableProxyType, \ 21 ProxyType, \ 22 ReferenceType 23 24ProxyTypes = (ProxyType, CallableProxyType) 25 26__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs", 27 "WeakKeyDictionary", "ReferenceType", "ProxyType", 28 "CallableProxyType", "ProxyTypes", "WeakValueDictionary"] 29 30 31class WeakValueDictionary(UserDict.UserDict): 32 """Mapping class that references values weakly. 33 34 Entries in the dictionary will be discarded when no strong 35 reference to the value exists anymore 36 """ 37 # We inherit the constructor without worrying about the input 38 # dictionary; since it uses our .update() method, we get the right 39 # checks (if the other dictionary is a WeakValueDictionary, 40 # objects are unwrapped on the way out, and we always wrap on the 41 # way in). 42 43 def __getitem__(self, key): 44 o = self.data.get(key)() 45 if o is None: 46 raise KeyError, key 47 else: 48 return o 49 50 def __repr__(self): 51 return "<WeakValueDictionary at %s>" % id(self) 52 53 def __setitem__(self, key, value): 54 def remove(o, data=self.data, key=key): 55 del data[key] 56 self.data[key] = ref(value, remove) 57 58 def copy(self): 59 new = WeakValueDictionary() 60 for key, wr in self.data.items(): 61 o = wr() 62 if o is not None: 63 new[key] = o 64 return new 65 66 def get(self, key, default=None): 67 try: 68 wr = self.data[key] 69 except KeyError: 70 return default 71 else: 72 o = wr() 73 if o is None: 74 # This should only happen 75 return default 76 else: 77 return o 78 79 def items(self): 80 L = [] 81 for key, wr in self.data.items(): 82 o = wr() 83 if o is not None: 84 L.append((key, o)) 85 return L 86 87 def popitem(self): 88 while 1: 89 key, wr = self.data.popitem() 90 o = wr() 91 if o is not None: 92 return key, o 93 94 def setdefault(self, key, default): 95 try: 96 wr = self.data[key] 97 except KeyError: 98 def remove(o, data=self.data, key=key): 99 del data[key] 100 self.data[key] = ref(default, remove) 101 return default 102 else: 103 return wr() 104 105 def update(self, dict): 106 d = self.data 107 for key, o in dict.items(): 108 def remove(o, data=d, key=key): 109 del data[key] 110 d[key] = ref(o, remove) 111 112 def values(self): 113 L = [] 114 for wr in self.data.values(): 115 o = wr() 116 if o is not None: 117 L.append(o) 118 return L 119 120 121class WeakKeyDictionary(UserDict.UserDict): 122 """ Mapping class that references keys weakly. 123 124 Entries in the dictionary will be discarded when there is no 125 longer a strong reference to the key. This can be used to 126 associate additional data with an object owned by other parts of 127 an application without adding attributes to those objects. This 128 can be especially useful with objects that override attribute 129 accesses. 130 """ 131 132 def __init__(self, dict=None): 133 self.data = {} 134 if dict is not None: self.update(dict) 135 def remove(k, data=self.data): 136 del data[k] 137 self._remove = remove 138 139 def __getitem__(self, key): 140 return self.data[ref(key)] 141 142 def __repr__(self): 143 return "<WeakKeyDictionary at %s>" % id(self) 144 145 def __setitem__(self, key, value): 146 self.data[ref(key, self._remove)] = value 147 148 def copy(self): 149 new = WeakKeyDictionary() 150 for key, value in self.data.items(): 151 o = key() 152 if o is not None: 153 new[o] = value 154 return new 155 156 def get(self, key, default=None): 157 return self.data.get(ref(key),default) 158 159 def has_key(self, key): 160 return self.data.has_key(ref(key)) 161 162 def items(self): 163 L = [] 164 for key, value in self.data.items(): 165 o = key() 166 if o is not None: 167 L.append((o, value)) 168 return L 169 170 def keys(self): 171 L = [] 172 for wr in self.data.keys(): 173 o = wr() 174 if o is not None: 175 L.append(o) 176 return L 177 178 def popitem(self): 179 while 1: 180 key, value = self.data.popitem() 181 o = key() 182 if o is not None: 183 return o, value 184 185 def setdefault(self, key, default): 186 return self.data.setdefault(ref(key, self._remove),default) 187 188 def update(self, dict): 189 d = self.data 190 for key, value in dict.items(): 191 d[ref(key, self._remove)] = value 192 193 194# no longer needed 195del UserDict 196