1b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org) 2b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php 3b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport cgi 4b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport copy 5b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport six 6b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport sys 7b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 8b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craiktry: 9b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # Python 3 10b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik from collections import MutableMapping as DictMixin 11b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikexcept ImportError: 12b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # Python 2 13b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik from UserDict import DictMixin 14b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 15b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass MultiDict(DictMixin): 16b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 17b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 18b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik An ordered dictionary that can have multiple values for each key. 19b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Adds the methods getall, getone, mixed, and add to the normal 20b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik dictionary interface. 21b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 22b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 23b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __init__(self, *args, **kw): 24b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if len(args) > 1: 25b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise TypeError( 26b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik "MultiDict can only be called with one positional argument") 27b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if args: 28b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if hasattr(args[0], 'iteritems'): 29b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = args[0].iteritems() 30b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik elif hasattr(args[0], 'items'): 31b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = args[0].items() 32b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 33b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = args[0] 34b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items = list(items) 35b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 36b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items = [] 37b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.extend(six.iteritems(kw)) 38b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 39b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __getitem__(self, key): 40b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in self._items: 41b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if k == key: 42b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return v 43b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError(repr(key)) 44b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 45b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __setitem__(self, key, value): 46b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik try: 47b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik del self[key] 48b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik except KeyError: 49b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik pass 50b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.append((key, value)) 51b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 52b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def add(self, key, value): 53b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 54b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Add the key and value, not overwriting any previous value. 55b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 56b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.append((key, value)) 57b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 58b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def getall(self, key): 59b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 60b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Return a list of all values matching the key (may be an empty list) 61b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 62b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = [] 63b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in self._items: 64b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if type(key) == type(k) and key == k: 65b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result.append(v) 66b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return result 67b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 68b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def getone(self, key): 69b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 70b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Get one value matching the key, raising a KeyError if multiple 71b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik values were found. 72b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 73b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik v = self.getall(key) 74b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if not v: 75b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError('Key not found: %r' % key) 76b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if len(v) > 1: 77b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError('Multiple values match %r: %r' % (key, v)) 78b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return v[0] 79b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 80b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def mixed(self): 81b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 82b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Returns a dictionary where the values are either single 83b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik values, or a list of values when a key/value appears more than 84b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik once in this dictionary. This is similar to the kind of 85b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik dictionary often used to represent the variables in a web 86b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik request. 87b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 88b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = {} 89b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik multi = {} 90b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for key, value in self._items: 91b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if key in result: 92b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # We do this to not clobber any lists that are 93b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # *actual* values in this dictionary: 94b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if key in multi: 95b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result[key].append(value) 96b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 97b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result[key] = [result[key], value] 98b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik multi[key] = None 99b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 100b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result[key] = value 101b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return result 102b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 103b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def dict_of_lists(self): 104b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 105b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Returns a dictionary where each key is associated with a 106b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik list of values. 107b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 108b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = {} 109b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for key, value in self._items: 110b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if key in result: 111b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result[key].append(value) 112b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 113b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result[key] = [value] 114b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return result 115b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 116b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __delitem__(self, key): 117b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = self._items 118b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik found = False 119b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for i in range(len(items)-1, -1, -1): 120b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if type(items[i][0]) == type(key) and items[i][0] == key: 121b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik del items[i] 122b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik found = True 123b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if not found: 124b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError(repr(key)) 125b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 126b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __contains__(self, key): 127b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in self._items: 128b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if type(k) == type(key) and k == key: 129b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return True 130b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return False 131b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 132b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik has_key = __contains__ 133b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 134b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def clear(self): 135b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items = [] 136b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 137b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def copy(self): 138b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return MultiDict(self) 139b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 140b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def setdefault(self, key, default=None): 141b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in self._items: 142b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if key == k: 143b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return v 144b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.append((key, default)) 145b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return default 146b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 147b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def pop(self, key, *args): 148b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if len(args) > 1: 149b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise TypeError("pop expected at most 2 arguments, got " 150b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik + repr(1 + len(args))) 151b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for i in range(len(self._items)): 152b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if type(self._items[i][0]) == type(key) and self._items[i][0] == key: 153b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik v = self._items[i][1] 154b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik del self._items[i] 155b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return v 156b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if args: 157b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return args[0] 158b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 159b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError(repr(key)) 160b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 161b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def popitem(self): 162b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self._items.pop() 163b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 164b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def update(self, other=None, **kwargs): 165b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if other is None: 166b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik pass 167b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik elif hasattr(other, 'items'): 168b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.extend(other.items()) 169b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik elif hasattr(other, 'keys'): 170b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k in other.keys(): 171b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.append((k, other[k])) 172b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 173b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in other: 174b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.append((k, v)) 175b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if kwargs: 176b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.update(kwargs) 177b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 178b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __repr__(self): 179b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = ', '.join(['(%r, %r)' % v for v in self._items]) 180b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return '%s([%s])' % (self.__class__.__name__, items) 181b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 182b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __len__(self): 183b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return len(self._items) 184b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 185b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ## 186b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ## All the iteration: 187b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ## 188b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 189b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def keys(self): 190b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [k for k, v in self._items] 191b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 192b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def iterkeys(self): 193b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in self._items: 194b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik yield k 195b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 196b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik __iter__ = iterkeys 197b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 198b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def items(self): 199b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self._items[:] 200b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 201b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def iteritems(self): 202b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return iter(self._items) 203b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 204b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def values(self): 205b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [v for k, v in self._items] 206b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 207b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def itervalues(self): 208b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in self._items: 209b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik yield v 210b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 211b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass UnicodeMultiDict(DictMixin): 212b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 213b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik A MultiDict wrapper that decodes returned values to unicode on the 214b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik fly. Decoding is not applied to assigned values. 215b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 216b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik The key/value contents are assumed to be ``str``/``strs`` or 217b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ``str``/``FieldStorages`` (as is returned by the ``paste.request.parse_`` 218b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik functions). 219b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 220b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Can optionally also decode keys when the ``decode_keys`` argument is 221b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik True. 222b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 223b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ``FieldStorage`` instances are cloned, and the clone's ``filename`` 224b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik variable is decoded. Its ``name`` variable is decoded when ``decode_keys`` 225b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik is enabled. 226b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 227b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 228b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __init__(self, multi=None, encoding=None, errors='strict', 229b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik decode_keys=False): 230b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.multi = multi 231b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if encoding is None: 232b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik encoding = sys.getdefaultencoding() 233b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.encoding = encoding 234b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.errors = errors 235b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.decode_keys = decode_keys 236b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if self.decode_keys: 237b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = self.multi._items 238b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for index, item in enumerate(items): 239b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key, value = item 240b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = self._encode_key(key) 241b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items[index] = (key, value) 242b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 243b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def _encode_key(self, key): 244b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if self.decode_keys: 245b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik try: 246b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = key.encode(self.encoding, self.errors) 247b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik except AttributeError: 248b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik pass 249b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return key 250b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 251b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def _decode_key(self, key): 252b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if self.decode_keys: 253b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik try: 254b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = key.decode(self.encoding, self.errors) 255b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik except AttributeError: 256b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik pass 257b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return key 258b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 259b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def _decode_value(self, value): 260b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 261b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Decode the specified value to unicode. Assumes value is a ``str`` or 262b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik `FieldStorage`` object. 263b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 264b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ``FieldStorage`` objects are specially handled. 265b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 266b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if isinstance(value, cgi.FieldStorage): 267b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # decode FieldStorage's field name and filename 268b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value = copy.copy(value) 269b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if self.decode_keys and isinstance(value.name, six.binary_type): 270b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value.name = value.name.decode(self.encoding, self.errors) 271b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if six.PY2: 272b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value.filename = value.filename.decode(self.encoding, self.errors) 273b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 274b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik try: 275b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value = value.decode(self.encoding, self.errors) 276b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik except AttributeError: 277b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik pass 278b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return value 279b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 280b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __getitem__(self, key): 281b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = self._encode_key(key) 282b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self._decode_value(self.multi.__getitem__(key)) 283b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 284b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __setitem__(self, key, value): 285b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = self._encode_key(key) 286b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.multi.__setitem__(key, value) 287b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 288b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def add(self, key, value): 289b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 290b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Add the key and value, not overwriting any previous value. 291b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 292b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = self._encode_key(key) 293b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.multi.add(key, value) 294b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 295b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def getall(self, key): 296b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 297b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Return a list of all values matching the key (may be an empty list) 298b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 299b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = self._encode_key(key) 300b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [self._decode_value(v) for v in self.multi.getall(key)] 301b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 302b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def getone(self, key): 303b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 304b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Get one value matching the key, raising a KeyError if multiple 305b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik values were found. 306b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 307b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = self._encode_key(key) 308b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self._decode_value(self.multi.getone(key)) 309b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 310b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def mixed(self): 311b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 312b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Returns a dictionary where the values are either single 313b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik values, or a list of values when a key/value appears more than 314b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik once in this dictionary. This is similar to the kind of 315b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik dictionary often used to represent the variables in a web 316b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik request. 317b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 318b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik unicode_mixed = {} 319b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for key, value in six.iteritems(self.multi.mixed()): 320b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if isinstance(value, list): 321b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value = [self._decode_value(value) for value in value] 322b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 323b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value = self._decode_value(value) 324b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik unicode_mixed[self._decode_key(key)] = value 325b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return unicode_mixed 326b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 327b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def dict_of_lists(self): 328b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 329b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Returns a dictionary where each key is associated with a 330b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik list of values. 331b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 332b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik unicode_dict = {} 333b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for key, value in six.iteritems(self.multi.dict_of_lists()): 334b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value = [self._decode_value(value) for value in value] 335b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik unicode_dict[self._decode_key(key)] = value 336b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return unicode_dict 337b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 338b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __delitem__(self, key): 339b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = self._encode_key(key) 340b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.multi.__delitem__(key) 341b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 342b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __contains__(self, key): 343b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = self._encode_key(key) 344b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self.multi.__contains__(key) 345b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 346b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik has_key = __contains__ 347b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 348b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def clear(self): 349b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.multi.clear() 350b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 351b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def copy(self): 352b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return UnicodeMultiDict(self.multi.copy(), self.encoding, self.errors, 353b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik decode_keys=self.decode_keys) 354b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 355b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def setdefault(self, key, default=None): 356b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = self._encode_key(key) 357b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self._decode_value(self.multi.setdefault(key, default)) 358b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 359b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def pop(self, key, *args): 360b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik key = self._encode_key(key) 361b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self._decode_value(self.multi.pop(key, *args)) 362b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 363b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def popitem(self): 364b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik k, v = self.multi.popitem() 365b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return (self._decode_key(k), self._decode_value(v)) 366b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 367b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __repr__(self): 368b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = ', '.join(['(%r, %r)' % v for v in self.items()]) 369b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return '%s([%s])' % (self.__class__.__name__, items) 370b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 371b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __len__(self): 372b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self.multi.__len__() 373b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 374b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ## 375b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ## All the iteration: 376b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ## 377b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 378b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def keys(self): 379b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [self._decode_key(k) for k in self.multi.iterkeys()] 380b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 381b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def iterkeys(self): 382b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k in self.multi.iterkeys(): 383b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik yield self._decode_key(k) 384b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 385b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik __iter__ = iterkeys 386b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 387b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def items(self): 388b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [(self._decode_key(k), self._decode_value(v)) for \ 389b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik k, v in six.iteritems(self.multi)] 390b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 391b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def iteritems(self): 392b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in six.iteritems(self.multi): 393b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik yield (self._decode_key(k), self._decode_value(v)) 394b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 395b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def values(self): 396b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [self._decode_value(v) for v in self.multi.itervalues()] 397b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 398b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def itervalues(self): 399b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for v in self.multi.itervalues(): 400b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik yield self._decode_value(v) 401b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 402b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik__test__ = { 403b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'general': """ 404b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik >>> d = MultiDict(a=1, b=2) 405b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik >>> d['a'] 406b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 1 407b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik >>> d.getall('c') 408b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik [] 409b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik >>> d.add('a', 2) 410b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik >>> d['a'] 411b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 1 412b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik >>> d.getall('a') 413b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik [1, 2] 414b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik >>> d['b'] = 4 415b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik >>> d.getall('b') 416b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik [4] 417b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik >>> d.keys() 418b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ['a', 'a', 'b'] 419b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik >>> d.items() 420b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik [('a', 1), ('a', 2), ('b', 4)] 421b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik >>> d.mixed() 422b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik {'a': [1, 2], 'b': 4} 423b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik >>> MultiDict([('a', 'b')], c=2) 424b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik MultiDict([('a', 'b'), ('c', 2)]) 425b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """} 426b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 427b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikif __name__ == '__main__': 428b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik import doctest 429b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik doctest.testmod() 430