1
1
import pprint
2
2
from itertools import chain
3
- from collections import OrderedDict , abc
3
+ from collections import abc
4
4
5
5
_marker = object ()
6
6
@@ -17,7 +17,7 @@ def __init__(self, *args, **kwargs):
17
17
if len (args ) > 1 :
18
18
raise TypeError ("MultiDict takes at most 2 positional "
19
19
"arguments ({} given)" .format (len (args ) + 1 ))
20
- self ._items = OrderedDict ()
20
+ self ._items = []
21
21
if args :
22
22
if hasattr (args [0 ], 'items' ):
23
23
args = list (args [0 ].items ())
@@ -27,18 +27,7 @@ def __init__(self, *args, **kwargs):
27
27
self ._fill (chain (args , kwargs .items ()))
28
28
29
29
def _fill (self , ipairs ):
30
- for key , value in ipairs :
31
- if key in self ._items :
32
- self ._items [key ].append (value )
33
- else :
34
- self ._items [key ] = [value ]
35
-
36
- def get (self , key , default = None ):
37
- """Return first value stored at key."""
38
- if key in self ._items and self ._items [key ]:
39
- return self ._items [key ][0 ]
40
- else :
41
- return default
30
+ self ._items .extend (ipairs )
42
31
43
32
def getall (self , key , default = _marker ):
44
33
"""Returns all values stored at key as a tuple.
@@ -53,8 +42,16 @@ def getall(self, key, default=_marker):
53
42
raise KeyError (key )
54
43
55
44
def getone (self , key ):
56
- """Return first value stored at key."""
57
- return self ._items [key ][0 ]
45
+ """
46
+ Get one value matching the key, raising a KeyError if multiple
47
+ values were found.
48
+ """
49
+ v = self .getall (key )
50
+ if not v :
51
+ raise KeyError ('Key not found: %r' % key )
52
+ if len (v ) > 1 :
53
+ raise KeyError ('Multiple values match %r: %r' % (key , v ))
54
+ return v [0 ]
58
55
59
56
# extra methods #
60
57
@@ -66,14 +63,20 @@ def copy(self):
66
63
# Mapping interface #
67
64
68
65
def __getitem__ (self , key ):
69
- return self ._items [key ][0 ]
66
+ for k , v in reversed (self ._items ):
67
+ if k == key :
68
+ return v
69
+ raise KeyError (key )
70
70
71
71
def __iter__ (self ):
72
72
return iter (self ._items )
73
73
74
74
def __len__ (self ):
75
75
return len (self ._items )
76
76
77
+ def keys (self , * , getall = False ):
78
+ return _KeysView (self ._items , getall = getall )
79
+
77
80
def items (self , * , getall = False ):
78
81
return _ItemsView (self ._items , getall = getall )
79
82
@@ -88,7 +91,10 @@ def __eq__(self, other):
88
91
return dict (self .items ()) == dict (other .items ())
89
92
90
93
def __contains__ (self , key ):
91
- return key in self ._items
94
+ for k , v in self ._items :
95
+ if k == key :
96
+ return True
97
+ return False
92
98
93
99
def __repr__ (self ):
94
100
return '<{}>\n {}' .format (
@@ -118,20 +124,16 @@ def getall(self, key, default=_marker):
118
124
return super ().getall (key .upper (), default )
119
125
120
126
def get (self , key , default = None ):
121
- key = key .upper ()
122
- if key in self ._items and self ._items [key ]:
123
- return self ._items [key ][0 ]
124
- else :
125
- return default
127
+ return self .get (key .upper (), default )
126
128
127
129
def getone (self , key ):
128
130
return self ._items [key .upper ()][0 ]
129
131
130
132
def __getitem__ (self , key ):
131
- return self . _items [ key .upper ()][ 0 ]
133
+ return super (). __getitem__ ( key .upper ())
132
134
133
135
def __contains__ (self , key ):
134
- return key .upper () in self . _items
136
+ return super (). __contains__ ( key .upper ())
135
137
136
138
137
139
class BaseMutableMultiDict (abc .MutableMapping ):
@@ -148,11 +150,10 @@ def getall(self, key, default=_marker):
148
150
return result
149
151
150
152
def add (self , key , value ):
151
- """Adds value to a key."""
152
- if key in self ._items :
153
- self ._items [key ].append (value )
154
- else :
155
- self ._items [key ] = [value ]
153
+ """
154
+ Add the key and value, not overwriting any previous value.
155
+ """
156
+ self ._items .append ((key , value ))
156
157
157
158
def extend (self , * args , ** kwargs ):
158
159
"""Extends current MutableMultiDict with more values.
@@ -181,10 +182,21 @@ def clear(self):
181
182
# MutableMapping interface #
182
183
183
184
def __setitem__ (self , key , value ):
184
- self ._items [key ] = [value ]
185
+ try :
186
+ del self [key ]
187
+ except KeyError :
188
+ pass
189
+ self ._items .append ((key , value ))
185
190
186
191
def __delitem__ (self , key ):
187
- del self ._items [key ]
192
+ items = self ._items
193
+ found = False
194
+ for i in range (len (items )- 1 , - 1 , - 1 ):
195
+ if items [i ][0 ] == key :
196
+ del items [i ]
197
+ found = True
198
+ if not found :
199
+ raise KeyError (key )
188
200
189
201
def pop (self , key , default = None ):
190
202
"""Method not allowed."""
@@ -214,56 +226,37 @@ def add(self, key, value):
214
226
super ().add (key .upper (), value )
215
227
216
228
def __setitem__ (self , key , value ):
217
- self . _items [ key .upper ()] = [ value ]
229
+ super (). __setitem__ ( key .upper (), value )
218
230
219
231
def __delitem__ (self , key ):
220
- del self ._items [key .upper ()]
232
+ super ().__delitem__ (key .upper ())
233
+
234
+
235
+ class _KeysView (abc .ItemsView ):
236
+
237
+ def __init__ (self , items , * , getall = False ):
238
+ super ().__init__ (items )
239
+ self ._getall = getall
240
+ # TBD
221
241
222
242
223
243
class _ItemsView (abc .ItemsView ):
224
244
225
- def __init__ (self , mapping , * , getall = False ):
226
- super ().__init__ (mapping )
245
+ def __init__ (self , items , * , getall = False ):
246
+ super ().__init__ (items )
227
247
self ._getall = getall
228
248
229
249
def __contains__ (self , item ):
230
- key , value = item
231
- try :
232
- values = self ._mapping [key ]
233
- except KeyError :
234
- return False
235
- else :
236
- if self ._getall :
237
- return value in values
238
- else :
239
- return value == values [0 ]
250
+ # TBD
251
+ pass
240
252
241
253
def __iter__ (self ):
242
- for key , values in self ._mapping .items ():
243
- if self ._getall :
244
- for value in values :
245
- yield key , value
246
- else :
247
- yield key , values [0 ]
254
+ pass
248
255
249
256
250
257
class _ValuesView (abc .KeysView ):
251
258
252
259
def __init__ (self , mapping , * , getall = False ):
253
260
super ().__init__ (mapping )
254
261
self ._getall = getall
255
-
256
- def __contains__ (self , value ):
257
- for values in self ._mapping .values ():
258
- if self ._getall and value in values :
259
- return True
260
- elif value == values [0 ]:
261
- return True
262
- return False
263
-
264
- def __iter__ (self ):
265
- for values in self ._mapping .values ():
266
- if self ._getall :
267
- yield from iter (values )
268
- else :
269
- yield values [0 ]
262
+ # TBD
0 commit comments