blob: b6b45282d06582ca7d9cbf49ede1967a1a2b7741 [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
Fred Drake9a9d2192001-04-10 19:11:23 +000022__all__ = ["ref", "proxy", "getweakrefcount", "getweakrefs",
Skip Montanaro40fc1602001-03-01 04:27:19 +000023 "WeakKeyDictionary", "ReferenceType", "ProxyType",
24 "CallableProxyType", "ProxyTypes", "WeakValueDictionary"]
Fred Drake41deb1e2001-02-01 05:27:45 +000025
Martin v. Löwis5e163332001-02-27 18:36:56 +000026class WeakValueDictionary(UserDict.UserDict):
Fred Drake41deb1e2001-02-01 05:27:45 +000027
28 # We inherit the constructor without worrying about the input
29 # dictionary; since it uses our .update() method, we get the right
Fred Drake9d2c85d2001-03-01 03:06:03 +000030 # checks (if the other dictionary is a WeakValueDictionary,
31 # objects are unwrapped on the way out, and we always wrap on the
32 # way in).
Fred Drake41deb1e2001-02-01 05:27:45 +000033
34 def __getitem__(self, key):
35 o = self.data.get(key)()
36 if o is None:
37 raise KeyError, key
38 else:
39 return o
40
41 def __repr__(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000042 return "<WeakValueDictionary at %s>" % id(self)
Fred Drake41deb1e2001-02-01 05:27:45 +000043
44 def __setitem__(self, key, value):
45 def remove(o, data=self.data, key=key):
46 del data[key]
47 self.data[key] = ref(value, remove)
48
49 def copy(self):
Fred Drake9d2c85d2001-03-01 03:06:03 +000050 new = WeakValueDictionary()
Fred Drake41deb1e2001-02-01 05:27:45 +000051 for key, ref in self.data.items():
52 o = ref()
53 if o is not None:
54 new[key] = o
Fred Drake9d2c85d2001-03-01 03:06:03 +000055 return new
Fred Drake41deb1e2001-02-01 05:27:45 +000056
Fred Drake1d9e4b72001-04-16 17:34:48 +000057 def get(self, key, default=None):
Fred Drake41deb1e2001-02-01 05:27:45 +000058 try:
59 ref = self.data[key]
60 except KeyError:
61 return default
62 else:
63 o = ref()
64 if o is None:
65 # This should only happen
66 return default
67 else:
68 return o
69
70 def items(self):
Fred Drake312a5dc2001-02-02 15:13:24 +000071 L = []
72 for key, ref in self.data.items():
Fred Drake41deb1e2001-02-01 05:27:45 +000073 o = ref()
74 if o is not None:
Fred Drake312a5dc2001-02-02 15:13:24 +000075 L.append((key, o))
Fred Drake41deb1e2001-02-01 05:27:45 +000076 return L
77
78 def popitem(self):
79 while 1:
80 key, ref = self.data.popitem()
81 o = ref()
82 if o is not None:
83 return key, o
84
85 def setdefault(self, key, default):
86 try:
87 ref = self.data[key]
88 except KeyError:
89 def remove(o, data=self.data, key=key):
90 del data[key]
91 ref = ref(default, remove)
92 self.data[key] = ref
93 return default
94 else:
95 return ref()
96
97 def update(self, dict):
98 d = self.data
99 L = []
100 for key, o in dict.items():
101 def remove(o, data=d, key=key):
102 del data[key]
Fred Drake1d9e4b72001-04-16 17:34:48 +0000103 L.append((key, ref(o, remove)))
Fred Drake41deb1e2001-02-01 05:27:45 +0000104 for key, r in L:
105 d[key] = r
106
107 def values(self):
108 L = []
109 for ref in self.data.values():
110 o = ref()
111 if o is not None:
112 L.append(o)
113 return L
114
115
Martin v. Löwis5e163332001-02-27 18:36:56 +0000116class WeakKeyDictionary(UserDict.UserDict):
117
118 def __init__(self, dict=None):
119 self.data = {}
120 if dict is not None: self.update(dict)
121 def remove(k, data=self.data):
122 del data[k]
123 self._remove = remove
124
125 def __getitem__(self, key):
126 return self.data[ref(key)]
127
128 def __repr__(self):
129 return "<WeakKeyDictionary at %s>" % id(self)
130
131 def __setitem__(self, key, value):
132 self.data[ref(key, self._remove)] = value
133
134 def copy(self):
135 new = WeakKeyDictionary()
136 for key, value in self.data.items():
137 o = key()
138 if o is not None:
139 new[o] = value
Fred Drake9d2c85d2001-03-01 03:06:03 +0000140 return new
Martin v. Löwis5e163332001-02-27 18:36:56 +0000141
Fred Drake1d9e4b72001-04-16 17:34:48 +0000142 def get(self, key, default=None):
Martin v. Löwis5e163332001-02-27 18:36:56 +0000143 return self.data.get(ref(key),default)
144
Fred Drake1d9e4b72001-04-16 17:34:48 +0000145 def has_key(self, key):
146 return self.data.has_key(ref(key))
147
Martin v. Löwis5e163332001-02-27 18:36:56 +0000148 def items(self):
149 L = []
150 for key, value in self.data.items():
151 o = key()
152 if o is not None:
153 L.append((o, value))
154 return L
155
Fred Drake1d9e4b72001-04-16 17:34:48 +0000156 def keys(self):
157 L = []
158 for ref in self.data.keys():
159 o = ref()
160 if o is not None:
161 L.append(o)
162 return L
163
Martin v. Löwis5e163332001-02-27 18:36:56 +0000164 def popitem(self):
165 while 1:
166 key, value = self.data.popitem()
167 o = key()
168 if o is not None:
169 return o, value
170
171 def setdefault(self, key, default):
172 return self.data.setdefault(ref(key, self._remove),default)
173
174 def update(self, dict):
175 d = self.data
176 L = []
177 for key, value in dict.items():
Fred Drake1d9e4b72001-04-16 17:34:48 +0000178 L.append((ref(key, self._remove), value))
Martin v. Löwis5e163332001-02-27 18:36:56 +0000179 for key, r in L:
180 d[key] = r
181
Fred Drake41deb1e2001-02-01 05:27:45 +0000182# no longer needed
183del UserDict