Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Reverted parts of 937328 and fixed MultiDict for py3k.

MultiDict now behaves exactly like a dict.
  • Loading branch information...
commit 431262129bf32b1b29353d55dc1c0b29d35cfdf8 1 parent 238a6bd
Marcel Hellkamp authored June 03, 2011
57  bottle.py
@@ -63,8 +63,10 @@
63 63
         except ImportError: # pragma: no cover
64 64
             json_dumps = None
65 65
 
  66
+py3k = sys.version_info >= (3,0,0)
66 67
 NCTextIOWrapper = None
67  
-if sys.version_info >= (3,0,0): # pragma: no cover
  68
+
  69
+if py3k: # pragma: no cover
68 70
     # See Request.POST
69 71
     from io import BytesIO
70 72
     def touni(x, enc='utf8', err='strict'):
@@ -88,7 +90,7 @@ def tob(data, enc='utf8'):
88 90
     return data.encode(enc) if isinstance(data, unicode) else bytes(data)
89 91
 
90 92
 # Convert strings and unicode to native strings
91  
-if sys.version_info >= (3,0,0):
  93
+if  py3k:
92 94
     tonat = touni
93 95
 else:
94 96
     tonat = tob
@@ -1004,18 +1006,19 @@ def __init__(self):
1004 1006
 
1005 1007
     def set_code(self, code):
1006 1008
         self._code, self._status = int(code), '%d %s' % (code, HTTP_CODES[code])
1007  
-    code = property(lambda self: self._code or 200, set_code, None,
  1009
+    status_code = property(lambda self: self._code or 200, set_code, None,
1008 1010
         ''' The response status code as an integer (default: 200). ''')
1009 1011
     del set_code
1010 1012
 
1011 1013
     def set_status(self, value):
1012 1014
         self._code, self._status = int(value[:3]), value
1013  
-    status = property(lambda self: self._status or '200 OK', set_status, None,
  1015
+    status_line = property(lambda self: self._status or '200 OK', set_status, None,
1014 1016
         ''' The response status line as a string (default: '200 OK'). ''')
1015 1017
     del set_status
1016 1018
 
1017 1019
     # Make stuff backwards compatible...
1018  
-    status, status_line, status_code = code, status, code
  1020
+    status = status_code # will change to status_line in 0.11
  1021
+    #code   = status_code # Added in 0.11
1019 1022
 
1020 1023
     def bind(self):
1021 1024
         ''' Reset to factory defaults. '''
@@ -1043,7 +1046,7 @@ def wsgiheader(self):
1043 1046
             self.headers.filter(('allow', 'content-encoding', 'content-language',
1044 1047
                       'content-length', 'content-md5', 'content-range',
1045 1048
                       'content-type', 'last-modified')) # + c-location, expires?
1046  
-        return list(self.headers.iteritems())
  1049
+        return list(self.headers.iterallitems())
1047 1050
     headerlist = property(wsgiheader)
1048 1051
 
1049 1052
     content_type = HeaderProperty('Content-Type')
@@ -1273,7 +1276,10 @@ def load_module(self, fullname):
1273 1276
 
1274 1277
 
1275 1278
 class MultiDict(DictMixin):
1276  
-    """ A dict that stores multiple values per key. """
  1279
+    """ This dict stores multiple values per key, but behaves exactly like a normal
  1280
+        dict in that it returns only the newest value for any given key. There are
  1281
+        special methods available to access the full list of values.
  1282
+    """
1277 1283
 
1278 1284
     def __init__(self, *a, **k):
1279 1285
         self.dict = dict((k, [v]) for k, v in dict(*a, **k).iteritems())
@@ -1283,28 +1289,39 @@ def __contains__(self, key): return key in self.dict
1283 1289
     def __delitem__(self, key): del self.dict[key]
1284 1290
     def __getitem__(self, key): return self.dict[key][-1]
1285 1291
     def __setitem__(self, key, value): self.append(key, value)
1286  
-    def keys(self): return self.dict.keys()
1287  
-    def items(self): return list(self.iteritems())
1288  
-
1289  
-    def iteritems(self):
1290  
-        ''' Iterate over all (key, value) tuples for each value of each key.'''
  1292
+    def iterkeys(self): return self.dict.iterkeys()
  1293
+    def itervalues(self): return (v[-1] for v in self.dict.itervalues())
  1294
+    def iteritems(self): return ((k, v[-1]) for (k, v) in self.dict.iteritems())
  1295
+    def iterallitems(self):
1291 1296
         for key, values in self.dict.iteritems():
1292 1297
             for value in values:
1293 1298
                 yield key, value
1294 1299
 
1295  
-    def iterallitems(self):
1296  
-        depr('Iterating over all items is now the default for MultiDict.iteritems()')
1297  
-        return self.iteritems()
1298  
-
1299  
-    def append(self, key, value): self.dict.setdefault(key, []).append(value)
1300  
-    def replace(self, key, value): self.dict[key] = [value]
1301  
-    def getall(self, key): return self.dict.get(key) or []
  1300
+    # 2to3 is not able to fix these automatically.
  1301
+    keys     = iterkeys     if py3k else lambda self: list(self.iterkeys())
  1302
+    values   = itervalues   if py3k else lambda self: list(self.itervalues())
  1303
+    items    = iteritems    if py3k else lambda self: list(self.iteritems())
  1304
+    allitems = iterallitems if py3k else lambda self: list(self.iterallitems())
1302 1305
 
1303 1306
     def get(self, key, default=None, index=-1):
  1307
+        ''' Return the current value for a key. The third `index` parameter
  1308
+            defaults to -1 (last value). '''
1304 1309
         if key in self.dict or default is KeyError:
1305 1310
             return self.dict[key][index]
1306 1311
         return default
1307 1312
 
  1313
+    def append(self, key, value):
  1314
+        ''' Add a new value to the list of values for this key. '''
  1315
+        self.dict.setdefault(key, []).append(value)
  1316
+
  1317
+    def replace(self, key, value):
  1318
+        ''' Replace the list of values with a single value. '''
  1319
+        self.dict[key] = [value]
  1320
+
  1321
+    def getall(self, key):
  1322
+        ''' Return a (possibly empty) list of values for a key. '''
  1323
+        return self.dict.get(key) or []
  1324
+
1308 1325
 
1309 1326
 def _hkey(s):
1310 1327
     return s.title().replace('_','-')
@@ -1324,7 +1341,7 @@ def append(self, key, value):
1324 1341
     def replace(self, key, value): self.dict[_hkey(key)] = [str(value)]
1325 1342
     def getall(self, key): return self.dict.get(_hkey(key)) or []
1326 1343
     def get(self, key, default=None, index=-1):
1327  
-        return super(HeaderDict, self).get(_hkey(key), default, index)
  1344
+        return MultiDict.get(self, _hkey(key), default, index)
1328 1345
     def filter(self, names):
1329 1346
         for name in map(_hkey, names):
1330 1347
             if name in self.dict:
2  test/test_mdict.py 100644 → 100755
@@ -10,6 +10,8 @@ def test_isadict(self):
10 10
         d['k2'], m['k2'] = 'v2', 'v2'
11 11
         self.assertEqual(d.keys(), m.keys())
12 12
         self.assertEqual(d.values(), m.values())
  13
+        self.assertEqual(list(d.iterkeys()), list(m.iterkeys()))
  14
+        self.assertEqual(list(d.itervalues()), list(m.itervalues()))
13 15
         self.assertEqual(d.get('key'), m.get('key'))
14 16
         self.assertEqual(d.get('cay'), m.get('cay'))
15 17
         self.assertEqual(list(iter(d)), list(iter(m)))

0 notes on commit 4312621

Please sign in to comment.
Something went wrong with that request. Please try again.