blob: a5a2d1d183eaa51c85add844f3205fe2de90b5aa [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
Skip Montanaro40fc1602001-03-01 04:27:19 +000022__all__ = ["ref", "mapping", "proxy", "getweakrefcount", "getweakrefs",
23 "WeakKeyDictionary", "ReferenceType", "ProxyType",
24 "CallableProxyType", "ProxyTypes", "WeakValueDictionary"]
Fred Drake41deb1e2001-02-01 05:27:45 +000025
Martin v. Löwis5e163332001-02-27 18:36:56 +000026def mapping(dict=None,weakkeys=0):
27 if weakkeys:
28 return WeakKeyDictionary(dict)
29 else:
30 return WeakValueDictionary(dict)
Fred Drake41deb1e2001-02-01 05:27:45 +000031
32
Martin v. Löwis5e163332001-02-27 18:36:56 +000033class WeakValueDictionary(UserDict.UserDict):
Fred Drake41deb1e2001-02-01 05:27:45 +000034
35 # We inherit the constructor without worrying about the input
36 # dictionary; since it uses our .update() method, we get the right
Fred Drake9d2c85d2001-03-01 03:06:03 +000037 # checks (if the other dictionary is a WeakValueDictionary,
38 # objects are unwrapped on the way out, and we always wrap on the
39 # way in).
Fred Drake41deb1e2001-02-01 05:27:45 +000040
41 def __getitem__(self, key):
42 o = self.data.get(key)()
43 if o is None:
44 raise KeyError, key
45 else:
46 return o
47
48 def __repr__(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000049 return "<WeakValueDictionary at %s>" % id(self)
Fred Drake41deb1e2001-02-01 05:27:45 +000050
51 def __setitem__(self, key, value):
52 def remove(o, data=self.data, key=key):
53 del data[key]
54 self.data[key] = ref(value, remove)
55
56 def copy(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000057 new = WeakValueDictionary()
Fred Drake41deb1e2001-02-01 05:27:45 +000058 for key, ref in self.data.items():
59 o = ref()
60 if o is not None:
61 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +000062 return new
Fred Drake41deb1e2001-02-01 05:27:45 +000063
64 def get(self, key, default):
65 try:
66 ref = self.data[key]
67 except KeyError:
68 return default
69 else:
70 o = ref()
71 if o is None:
72 # This should only happen
73 return default
74 else:
75 return o
76
77 def items(self):
Fred Drake312a5dc2001-02-02 15:13:24 +000078 L = []
79 for key, ref in self.data.items():
Fred Drake41deb1e2001-02-01 05:27:45 +000080 o = ref()
81 if o is not None:
Fred Drake312a5dc2001-02-02 15:13:24 +000082 L.append((key, o))
Fred Drake41deb1e2001-02-01 05:27:45 +000083 return L
84
85 def popitem(self):
86 while 1:
87 key, ref = self.data.popitem()
88 o = ref()
89 if o is not None:
90 return key, o
91
92 def setdefault(self, key, default):
93 try:
94 ref = self.data[key]
95 except KeyError:
96 def remove(o, data=self.data, key=key):
97 del data[key]
98 ref = ref(default, remove)
99 self.data[key] = ref
100 return default
101 else:
102 return ref()
103
104 def update(self, dict):
105 d = self.data
106 L = []
107 for key, o in dict.items():
108 def remove(o, data=d, key=key):
109 del data[key]
110 L.append(key, ref(o, remove))
111 for key, r in L:
112 d[key] = r
113
114 def values(self):
115 L = []
116 for ref in self.data.values():
117 o = ref()
118 if o is not None:
119 L.append(o)
120 return L
121
122
Martin v. Löwis5e163332001-02-27 18:36:56 +0000123class WeakKeyDictionary(UserDict.UserDict):
124
125 def __init__(self, dict=None):
126 self.data = {}
127 if dict is not None: self.update(dict)
128 def remove(k, data=self.data):
129 del data[k]
130 self._remove = remove
131
132 def __getitem__(self, key):
133 return self.data[ref(key)]
134
135 def __repr__(self):
136 return "<WeakKeyDictionary at %s>" % id(self)
137
138 def __setitem__(self, key, value):
139 self.data[ref(key, self._remove)] = value
140
141 def copy(self):
142 new = WeakKeyDictionary()
143 for key, value in self.data.items():
144 o = key()
145 if o is not None:
146 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000147 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000148
149 def get(self, key, default):
150 return self.data.get(ref(key),default)
151
152 def items(self):
153 L = []
154 for key, value in self.data.items():
155 o = key()
156 if o is not None:
157 L.append((o, value))
158 return L
159
160 def popitem(self):
161 while 1:
162 key, value = self.data.popitem()
163 o = key()
164 if o is not None:
165 return o, value
166
167 def setdefault(self, key, default):
168 return self.data.setdefault(ref(key, self._remove),default)
169
170 def update(self, dict):
171 d = self.data
172 L = []
173 for key, value in dict.items():
174 L.append(ref(key, self._remove), value)
175 for key, r in L:
176 d[key] = r
177
Fred Drake41deb1e2001-02-01 05:27:45 +0000178# no longer needed
179del UserDict