1
2
3
4
5
6 try:
7 from UserDict import DictMixin
8 except ImportError:
9 from collections import MutableMapping as DictMixin
13
14 """
15 An ordered dictionary that can have multiple values for each key.
16 Adds the methods getall, getone, mixed and extend and add to the normal
17 dictionary interface.
18 """
19
21 if len(args) > 1:
22 raise TypeError("MultiDict can only be called with one positional argument")
23 if args:
24 if isinstance(args[0], MultiDict):
25 items = args[0]._items
26 elif hasattr(args[0], 'iteritems'):
27 items = list(args[0].iteritems())
28 elif hasattr(args[0], 'items'):
29 items = args[0].items()
30 else:
31 items = list(args[0])
32 self._items = items
33 else:
34 self._items = []
35 if kw:
36 self._items.extend(kw.iteritems())
37
38 @classmethod
40 """
41 Create a dict from a cgi.FieldStorage instance
42 """
43 obj = cls()
44
45 for field in fs.list or ():
46 if field.filename:
47 obj.add(field.name, field)
48 else:
49 obj.add(field.name, field.value)
50 return obj
51
53 for k, v in reversed(self._items):
54 if k == key:
55 return v
56 raise KeyError(key)
57
59 try:
60 del self[key]
61 except KeyError:
62 pass
63 self._items.append((key, value))
64
65 - def add(self, key, value):
66 """
67 Add the key and value, not overwriting any previous value.
68 """
69 self._items.append((key, value))
70
72 """
73 Return a list of all values matching the key (may be an empty list)
74 """
75 return [v for k, v in self._items if k == key]
76
77 - def iget(self, key):
78 """like get but case insensitive """
79 lkey = key.lower()
80 for k, v in self._items:
81 if k.lower() == lkey:
82 return v
83 return None
84
86 """
87 Get one value matching the key, raising a KeyError if multiple
88 values were found.
89 """
90 v = self.getall(key)
91 if not v:
92 raise KeyError('Key not found: %r' % key)
93 if len(v) > 1:
94 raise KeyError('Multiple values match %r: %r' % (key, v))
95 return v[0]
96
98 """
99 Returns a dictionary where the values are either single
100 values, or a list of values when a key/value appears more than
101 once in this dictionary. This is similar to the kind of
102 dictionary often used to represent the variables in a web
103 request.
104 """
105 result = {}
106 multi = {}
107 for key, value in self.iteritems():
108 if key in result:
109
110
111 if key in multi:
112 result[key].append(value)
113 else:
114 result[key] = [result[key], value]
115 multi[key] = None
116 else:
117 result[key] = value
118 return result
119
121 """
122 Returns a dictionary where each key is associated with a list of values.
123 """
124 r = {}
125 for key, val in self.iteritems():
126 r.setdefault(key, []).append(val)
127 return r
128
130 items = self._items
131 found = False
132 for i in range(len(items)-1, -1, -1):
133 if items[i][0] == key:
134 del items[i]
135 found = True
136 if not found:
137 raise KeyError(key)
138
140 for k, v in self._items:
141 if k == key:
142 return True
143 return False
144
145 has_key = __contains__
146
149
151 return self.__class__(self)
152
154 for k, v in self._items:
155 if key == k:
156 return v
157 self._items.append((key, default))
158 return default
159
160 - def pop(self, key, *args):
161 if len(args) > 1:
162 raise TypeError, "pop expected at most 2 arguments, got "\
163 + repr(1 + len(args))
164 for i in range(len(self._items)):
165 if self._items[i][0] == key:
166 v = self._items[i][1]
167 del self._items[i]
168 return v
169 if args:
170 return args[0]
171 else:
172 raise KeyError(key)
173
174 - def ipop(self, key, *args):
175 """ like pop but case insensitive """
176 if len(args) > 1:
177 raise TypeError, "pop expected at most 2 arguments, got "\
178 + repr(1 + len(args))
179
180 lkey = key.lower()
181 for i, item in enumerate(self._items):
182 if item[0].lower() == lkey:
183 v = self._items[i][1]
184 del self._items[i]
185 return v
186 if args:
187 return args[0]
188 else:
189 raise KeyError(key)
190
192 return self._items.pop()
193
194 - def extend(self, other=None, **kwargs):
195 if other is None:
196 pass
197 elif hasattr(other, 'items'):
198 self._items.extend(other.items())
199 elif hasattr(other, 'keys'):
200 for k in other.keys():
201 self._items.append((k, other[k]))
202 else:
203 for k, v in other:
204 self._items.append((k, v))
205 if kwargs:
206 self.update(kwargs)
207
209 items = ', '.join(['(%r, %r)' % v for v in self.iteritems()])
210 return '%s([%s])' % (self.__class__.__name__, items)
211
213 return len(self._items)
214
215
216
217
218
220 return [k for k, v in self._items]
221
223 for k, v in self._items:
224 yield k
225
226 __iter__ = iterkeys
227
229 return self._items[:]
230
232 return iter(self._items)
233
235 return [v for k, v in self._items]
236
238 for k, v in self._items:
239 yield v
240