blob: 30574efcb5ef13f591144cf0b4b36a640ee53806 [file] [log] [blame]
Fred Drake41deb1e2001-02-01 05:27:45 +00001"""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
8import UserDict
9
10from _weakref import \
11 getweakrefcount, \
12 getweakrefs, \
13 ref, \
14 proxy, \
15 ReferenceError, \
16 CallableProxyType, \
17 ProxyType, \
18 ReferenceType
19
20ProxyTypes = (ProxyType, CallableProxyType)
21
22
Martin v. Löwis5e163332001-02-27 18:36:56 +000023def mapping(dict=None,weakkeys=0):
24 if weakkeys:
25 return WeakKeyDictionary(dict)
26 else:
27 return WeakValueDictionary(dict)
Fred Drake41deb1e2001-02-01 05:27:45 +000028
29
Martin v. Löwis5e163332001-02-27 18:36:56 +000030class WeakValueDictionary(UserDict.UserDict):
Fred Drake41deb1e2001-02-01 05:27:45 +000031
32 # We inherit the constructor without worrying about the input
33 # dictionary; since it uses our .update() method, we get the right
Fred Drake9d2c85d2001-03-01 03:06:03 +000034 # checks (if the other dictionary is a WeakValueDictionary,
35 # objects are unwrapped on the way out, and we always wrap on the
36 # way in).
Fred Drake41deb1e2001-02-01 05:27:45 +000037
38 def __getitem__(self, key):
39 o = self.data.get(key)()
40 if o is None:
41 raise KeyError, key
42 else:
43 return o
44
45 def __repr__(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000046 return "<WeakValueDictionary at %s>" % id(self)
Fred Drake41deb1e2001-02-01 05:27:45 +000047
48 def __setitem__(self, key, value):
49 def remove(o, data=self.data, key=key):
50 del data[key]
51 self.data[key] = ref(value, remove)
52
53 def copy(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000054 new = WeakValueDictionary()
Fred Drake41deb1e2001-02-01 05:27:45 +000055 for key, ref in self.data.items():
56 o = ref()
57 if o is not None:
58 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +000059 return new
Fred Drake41deb1e2001-02-01 05:27:45 +000060
61 def get(self, key, default):
62 try:
63 ref = self.data[key]
64 except KeyError:
65 return default
66 else:
67 o = ref()
68 if o is None:
69 # This should only happen
70 return default
71 else:
72 return o
73
74 def items(self):
Fred Drake312a5dc2001-02-02 15:13:24 +000075 L = []
76 for key, ref in self.data.items():
Fred Drake41deb1e2001-02-01 05:27:45 +000077 o = ref()
78 if o is not None:
Fred Drake312a5dc2001-02-02 15:13:24 +000079 L.append((key, o))
Fred Drake41deb1e2001-02-01 05:27:45 +000080 return L
81
82 def popitem(self):
83 while 1:
84 key, ref = self.data.popitem()
85 o = ref()
86 if o is not None:
87 return key, o
88
89 def setdefault(self, key, default):
90 try:
91 ref = self.data[key]
92 except KeyError:
93 def remove(o, data=self.data, key=key):
94 del data[key]
95 ref = ref(default, remove)
96 self.data[key] = ref
97 return default
98 else:
99 return ref()
100
101 def update(self, dict):
102 d = self.data
103 L = []
104 for key, o in dict.items():
105 def remove(o, data=d, key=key):
106 del data[key]
107 L.append(key, ref(o, remove))
108 for key, r in L:
109 d[key] = r
110
111 def values(self):
112 L = []
113 for ref in self.data.values():
114 o = ref()
115 if o is not None:
116 L.append(o)
117 return L
118
119
Martin v. Löwis5e163332001-02-27 18:36:56 +0000120class WeakKeyDictionary(UserDict.UserDict):
121
122 def __init__(self, dict=None):
123 self.data = {}
124 if dict is not None: self.update(dict)
125 def remove(k, data=self.data):
126 del data[k]
127 self._remove = remove
128
129 def __getitem__(self, key):
130 return self.data[ref(key)]
131
132 def __repr__(self):
133 return "<WeakKeyDictionary at %s>" % id(self)
134
135 def __setitem__(self, key, value):
136 self.data[ref(key, self._remove)] = value
137
138 def copy(self):
139 new = WeakKeyDictionary()
140 for key, value in self.data.items():
141 o = key()
142 if o is not None:
143 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000144 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000145
146 def get(self, key, default):
147 return self.data.get(ref(key),default)
148
149 def items(self):
150 L = []
151 for key, value in self.data.items():
152 o = key()
153 if o is not None:
154 L.append((o, value))
155 return L
156
157 def popitem(self):
158 while 1:
159 key, value = self.data.popitem()
160 o = key()
161 if o is not None:
162 return o, value
163
164 def setdefault(self, key, default):
165 return self.data.setdefault(ref(key, self._remove),default)
166
167 def update(self, dict):
168 d = self.data
169 L = []
170 for key, value in dict.items():
171 L.append(ref(key, self._remove), value)
172 for key, r in L:
173 d[key] = r
174
Fred Drake41deb1e2001-02-01 05:27:45 +0000175# no longer needed
176del UserDict