Skip to content

Commit 2a37e56

Browse files
committed
Work on multidict
1 parent d1e2a43 commit 2a37e56

File tree

1 file changed

+60
-67
lines changed

1 file changed

+60
-67
lines changed

aiohttp/multidict.py

Lines changed: 60 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import pprint
22
from itertools import chain
3-
from collections import OrderedDict, abc
3+
from collections import abc
44

55
_marker = object()
66

@@ -17,7 +17,7 @@ def __init__(self, *args, **kwargs):
1717
if len(args) > 1:
1818
raise TypeError("MultiDict takes at most 2 positional "
1919
"arguments ({} given)".format(len(args) + 1))
20-
self._items = OrderedDict()
20+
self._items = []
2121
if args:
2222
if hasattr(args[0], 'items'):
2323
args = list(args[0].items())
@@ -27,18 +27,7 @@ def __init__(self, *args, **kwargs):
2727
self._fill(chain(args, kwargs.items()))
2828

2929
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)
4231

4332
def getall(self, key, default=_marker):
4433
"""Returns all values stored at key as a tuple.
@@ -53,8 +42,16 @@ def getall(self, key, default=_marker):
5342
raise KeyError(key)
5443

5544
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]
5855

5956
# extra methods #
6057

@@ -66,14 +63,20 @@ def copy(self):
6663
# Mapping interface #
6764

6865
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)
7070

7171
def __iter__(self):
7272
return iter(self._items)
7373

7474
def __len__(self):
7575
return len(self._items)
7676

77+
def keys(self, *, getall=False):
78+
return _KeysView(self._items, getall=getall)
79+
7780
def items(self, *, getall=False):
7881
return _ItemsView(self._items, getall=getall)
7982

@@ -88,7 +91,10 @@ def __eq__(self, other):
8891
return dict(self.items()) == dict(other.items())
8992

9093
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
9298

9399
def __repr__(self):
94100
return '<{}>\n{}'.format(
@@ -118,20 +124,16 @@ def getall(self, key, default=_marker):
118124
return super().getall(key.upper(), default)
119125

120126
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)
126128

127129
def getone(self, key):
128130
return self._items[key.upper()][0]
129131

130132
def __getitem__(self, key):
131-
return self._items[key.upper()][0]
133+
return super().__getitem__(key.upper())
132134

133135
def __contains__(self, key):
134-
return key.upper() in self._items
136+
return super().__contains__(key.upper())
135137

136138

137139
class BaseMutableMultiDict(abc.MutableMapping):
@@ -148,11 +150,10 @@ def getall(self, key, default=_marker):
148150
return result
149151

150152
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))
156157

157158
def extend(self, *args, **kwargs):
158159
"""Extends current MutableMultiDict with more values.
@@ -181,10 +182,21 @@ def clear(self):
181182
# MutableMapping interface #
182183

183184
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))
185190

186191
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)
188200

189201
def pop(self, key, default=None):
190202
"""Method not allowed."""
@@ -214,56 +226,37 @@ def add(self, key, value):
214226
super().add(key.upper(), value)
215227

216228
def __setitem__(self, key, value):
217-
self._items[key.upper()] = [value]
229+
super().__setitem__(key.upper(), value)
218230

219231
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
221241

222242

223243
class _ItemsView(abc.ItemsView):
224244

225-
def __init__(self, mapping, *, getall=False):
226-
super().__init__(mapping)
245+
def __init__(self, items, *, getall=False):
246+
super().__init__(items)
227247
self._getall = getall
228248

229249
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
240252

241253
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
248255

249256

250257
class _ValuesView(abc.KeysView):
251258

252259
def __init__(self, mapping, *, getall=False):
253260
super().__init__(mapping)
254261
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

Comments
 (0)