1b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# (c) 2005 Ian Bicking and contributors; written for Paste 2b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# (http://pythonpaste.org) Licensed under the MIT license: 3b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# http://www.opensource.org/licenses/mit-license.php 4b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik""" 5b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris CraikGives a multi-value dictionary object (MultiDict) plus several wrappers 6b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik""" 7b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfrom collections import MutableMapping 8b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 9b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport binascii 10b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikimport warnings 11b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 12b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikfrom webob.compat import ( 13b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik PY3, 14b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik iteritems_, 15b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik itervalues_, 16b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik url_encode, 17b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ) 18b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 19b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik__all__ = ['MultiDict', 'NestedMultiDict', 'NoVars', 'GetDict'] 20b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 21b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass MultiDict(MutableMapping): 22b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 23b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik An ordered dictionary that can have multiple values for each key. 24b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Adds the methods getall, getone, mixed and extend and add to the normal 25b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik dictionary interface. 26b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 27b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 28b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __init__(self, *args, **kw): 29b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if len(args) > 1: 30b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise TypeError("MultiDict can only be called with one positional " 31b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik "argument") 32b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if args: 33b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if hasattr(args[0], 'iteritems'): 34b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = list(args[0].iteritems()) 35b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik elif hasattr(args[0], 'items'): 36b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = list(args[0].items()) 37b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 38b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = list(args[0]) 39b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items = items 40b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 41b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items = [] 42b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if kw: 43b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.extend(kw.items()) 44b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 45b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik @classmethod 46b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def view_list(cls, lst): 47b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 48b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Create a dict that is a view on the given list 49b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 50b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if not isinstance(lst, list): 51b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise TypeError( 52b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik "%s.view_list(obj) takes only actual list objects, not %r" 53b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik % (cls.__name__, lst)) 54b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik obj = cls() 55b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik obj._items = lst 56b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return obj 57b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 58b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik @classmethod 59b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def from_fieldstorage(cls, fs): 60b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 61b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Create a dict from a cgi.FieldStorage instance 62b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 63b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik obj = cls() 64b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # fs.list can be None when there's nothing to parse 65b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for field in fs.list or (): 66b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik charset = field.type_options.get('charset', 'utf8') 67b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik transfer_encoding = field.headers.get('Content-Transfer-Encoding', None) 68b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik supported_transfer_encoding = { 69b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'base64' : binascii.a2b_base64, 70b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 'quoted-printable' : binascii.a2b_qp 71b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik } 72b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if PY3: # pragma: no cover 73b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if charset == 'utf8': 74b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik decode = lambda b: b 75b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 76b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik decode = lambda b: b.encode('utf8').decode(charset) 77b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 78b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik decode = lambda b: b.decode(charset) 79b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if field.filename: 80b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik field.filename = decode(field.filename) 81b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik obj.add(field.name, field) 82b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 83b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value = field.value 84b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if transfer_encoding in supported_transfer_encoding: 85b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if PY3: # pragma: no cover 86b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # binascii accepts bytes 87b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value = value.encode('utf8') 88b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value = supported_transfer_encoding[transfer_encoding](value) 89b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if PY3: # pragma: no cover 90b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # binascii returns bytes 91b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value = value.decode('utf8') 92b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik obj.add(field.name, decode(value)) 93b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return obj 94b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 95b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __getitem__(self, key): 96b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in reversed(self._items): 97b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if k == key: 98b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return v 99b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError(key) 100b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 101b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __setitem__(self, key, value): 102b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik try: 103b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik del self[key] 104b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik except KeyError: 105b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik pass 106b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.append((key, value)) 107b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 108b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def add(self, key, value): 109b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 110b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Add the key and value, not overwriting any previous value. 111b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 112b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.append((key, value)) 113b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 114b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def getall(self, key): 115b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 116b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Return a list of all values matching the key (may be an empty list) 117b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 118b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [v for k, v in self._items if k == key] 119b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 120b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def getone(self, key): 121b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 122b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Get one value matching the key, raising a KeyError if multiple 123b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik values were found. 124b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 125b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik v = self.getall(key) 126b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if not v: 127b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError('Key not found: %r' % key) 128b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if len(v) > 1: 129b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError('Multiple values match %r: %r' % (key, v)) 130b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return v[0] 131b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 132b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def mixed(self): 133b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 134b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Returns a dictionary where the values are either single 135b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik values, or a list of values when a key/value appears more than 136b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik once in this dictionary. This is similar to the kind of 137b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik dictionary often used to represent the variables in a web 138b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik request. 139b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 140b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = {} 141b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik multi = {} 142b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for key, value in self.items(): 143b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if key in result: 144b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # We do this to not clobber any lists that are 145b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # *actual* values in this dictionary: 146b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if key in multi: 147b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result[key].append(value) 148b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 149b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result[key] = [result[key], value] 150b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik multi[key] = None 151b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 152b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result[key] = value 153b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return result 154b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 155b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def dict_of_lists(self): 156b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 157b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Returns a dictionary where each key is associated with a list of values. 158b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 159b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik r = {} 160b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for key, val in self.items(): 161b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik r.setdefault(key, []).append(val) 162b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return r 163b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 164b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __delitem__(self, key): 165b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = self._items 166b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik found = False 167b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for i in range(len(items)-1, -1, -1): 168b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if items[i][0] == key: 169b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik del items[i] 170b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik found = True 171b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if not found: 172b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError(key) 173b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 174b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __contains__(self, key): 175b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in self._items: 176b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if k == key: 177b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return True 178b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return False 179b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 180b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik has_key = __contains__ 181b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 182b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def clear(self): 183b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik del self._items[:] 184b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 185b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def copy(self): 186b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self.__class__(self) 187b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 188b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def setdefault(self, key, default=None): 189b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in self._items: 190b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if key == k: 191b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return v 192b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.append((key, default)) 193b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return default 194b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 195b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def pop(self, key, *args): 196b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if len(args) > 1: 197b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise TypeError("pop expected at most 2 arguments, got %s" 198b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik % repr(1 + len(args))) 199b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for i in range(len(self._items)): 200b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if self._items[i][0] == key: 201b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik v = self._items[i][1] 202b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik del self._items[i] 203b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return v 204b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if args: 205b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return args[0] 206b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 207b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError(key) 208b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 209b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def popitem(self): 210b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self._items.pop() 211b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 212b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def update(self, *args, **kw): 213b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if args: 214b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik lst = args[0] 215b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if len(lst) != len(dict(lst)): 216b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # this does not catch the cases where we overwrite existing 217b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # keys, but those would produce too many warning 218b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik msg = ("Behavior of MultiDict.update() has changed " 219b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik "and overwrites duplicate keys. Consider using .extend()" 220b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ) 221b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik warnings.warn(msg, UserWarning, stacklevel=2) 222b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik MutableMapping.update(self, *args, **kw) 223b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 224b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def extend(self, other=None, **kwargs): 225b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if other is None: 226b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik pass 227b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik elif hasattr(other, 'items'): 228b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.extend(other.items()) 229b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik elif hasattr(other, 'keys'): 230b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k in other.keys(): 231b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.append((k, other[k])) 232b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 233b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in other: 234b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self._items.append((k, v)) 235b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if kwargs: 236b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.update(kwargs) 237b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 238b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __repr__(self): 239b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = map('(%r, %r)'.__mod__, _hide_passwd(self.items())) 240b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return '%s([%s])' % (self.__class__.__name__, ', '.join(items)) 241b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 242b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __len__(self): 243b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return len(self._items) 244b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 245b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ## 246b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ## All the iteration: 247b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ## 248b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 249b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def iterkeys(self): 250b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in self._items: 251b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik yield k 252b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if PY3: # pragma: no cover 253b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik keys = iterkeys 254b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 255b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def keys(self): 256b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [k for k, v in self._items] 257b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 258b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik __iter__ = iterkeys 259b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 260b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def iteritems(self): 261b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return iter(self._items) 262b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 263b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if PY3: # pragma: no cover 264b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = iteritems 265b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 266b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def items(self): 267b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self._items[:] 268b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 269b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def itervalues(self): 270b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in self._items: 271b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik yield v 272b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 273b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if PY3: # pragma: no cover 274b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik values = itervalues 275b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 276b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def values(self): 277b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [v for k, v in self._items] 278b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 279b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik_dummy = object() 280b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 281b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass GetDict(MultiDict): 282b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# def __init__(self, data, tracker, encoding, errors): 283b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# d = lambda b: b.decode(encoding, errors) 284b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik# data = [(d(k), d(v)) for k,v in data] 285b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __init__(self, data, env): 286b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.env = env 287b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik MultiDict.__init__(self, data) 288b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def on_change(self): 289b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik e = lambda t: t.encode('utf8') 290b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik data = [(e(k), e(v)) for k,v in self.items()] 291b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik qs = url_encode(data) 292b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.env['QUERY_STRING'] = qs 293b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.env['webob._parsed_query_vars'] = (self, qs) 294b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __setitem__(self, key, value): 295b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik MultiDict.__setitem__(self, key, value) 296b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.on_change() 297b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def add(self, key, value): 298b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik MultiDict.add(self, key, value) 299b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.on_change() 300b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __delitem__(self, key): 301b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik MultiDict.__delitem__(self, key) 302b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.on_change() 303b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def clear(self): 304b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik MultiDict.clear(self) 305b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.on_change() 306b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def setdefault(self, key, default=None): 307b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = MultiDict.setdefault(self, key, default) 308b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.on_change() 309b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return result 310b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def pop(self, key, *args): 311b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = MultiDict.pop(self, key, *args) 312b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.on_change() 313b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return result 314b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def popitem(self): 315b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = MultiDict.popitem(self) 316b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.on_change() 317b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return result 318b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def update(self, *args, **kwargs): 319b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik MultiDict.update(self, *args, **kwargs) 320b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.on_change() 321b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def extend(self, *args, **kwargs): 322b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik MultiDict.extend(self, *args, **kwargs) 323b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.on_change() 324b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __repr__(self): 325b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = map('(%r, %r)'.__mod__, _hide_passwd(self.items())) 326b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # TODO: GET -> GetDict 327b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return 'GET([%s])' % (', '.join(items)) 328b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def copy(self): 329b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # Copies shouldn't be tracked 330b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return MultiDict(self) 331b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 332b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass NestedMultiDict(MultiDict): 333b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 334b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Wraps several MultiDict objects, treating it as one large MultiDict 335b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 336b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 337b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __init__(self, *dicts): 338b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.dicts = dicts 339b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 340b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __getitem__(self, key): 341b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for d in self.dicts: 342b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik value = d.get(key, _dummy) 343b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if value is not _dummy: 344b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return value 345b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError(key) 346b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 347b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def _readonly(self, *args, **kw): 348b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError("NestedMultiDict objects are read-only") 349b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik __setitem__ = _readonly 350b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik add = _readonly 351b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik __delitem__ = _readonly 352b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik clear = _readonly 353b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik setdefault = _readonly 354b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik pop = _readonly 355b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik popitem = _readonly 356b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik update = _readonly 357b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 358b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def getall(self, key): 359b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result = [] 360b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for d in self.dicts: 361b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik result.extend(d.getall(key)) 362b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return result 363b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 364b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # Inherited: 365b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # getone 366b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # mixed 367b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik # dict_of_lists 368b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 369b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def copy(self): 370b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return MultiDict(self) 371b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 372b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __contains__(self, key): 373b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for d in self.dicts: 374b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if key in d: 375b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return True 376b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return False 377b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 378b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik has_key = __contains__ 379b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 380b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __len__(self): 381b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik v = 0 382b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for d in self.dicts: 383b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik v += len(d) 384b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return v 385b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 386b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __nonzero__(self): 387b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for d in self.dicts: 388b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if d: 389b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return True 390b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return False 391b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 392b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def iteritems(self): 393b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for d in self.dicts: 394b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for item in iteritems_(d): 395b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik yield item 396b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if PY3: # pragma: no cover 397b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = iteritems 398b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 399b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def items(self): 400b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return list(self.iteritems()) 401b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 402b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def itervalues(self): 403b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for d in self.dicts: 404b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for value in itervalues_(d): 405b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik yield value 406b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if PY3: # pragma: no cover 407b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik values = itervalues 408b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 409b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def values(self): 410b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return list(self.itervalues()) 411b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 412b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __iter__(self): 413b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for d in self.dicts: 414b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for key in d: 415b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik yield key 416b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 417b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik iterkeys = __iter__ 418b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 419b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if PY3: # pragma: no cover 420b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik keys = iterkeys 421b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 422b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def keys(self): 423b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return list(self.iterkeys()) 424b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 425b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikclass NoVars(object): 426b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 427b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik Represents no variables; used when no variables 428b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik are applicable. 429b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 430b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik This is read-only 431b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik """ 432b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 433b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __init__(self, reason=None): 434b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.reason = reason or 'N/A' 435b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 436b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __getitem__(self, key): 437b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError("No key %r: %s" % (key, self.reason)) 438b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 439b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __setitem__(self, *args, **kw): 440b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError("Cannot add variables: %s" % self.reason) 441b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 442b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik add = __setitem__ 443b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik setdefault = __setitem__ 444b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik update = __setitem__ 445b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 446b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __delitem__(self, *args, **kw): 447b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik raise KeyError("No keys to delete: %s" % self.reason) 448b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik clear = __delitem__ 449b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik pop = __delitem__ 450b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik popitem = __delitem__ 451b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 452b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def get(self, key, default=None): 453b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return default 454b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 455b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def getall(self, key): 456b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [] 457b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 458b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def getone(self, key): 459b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self[key] 460b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 461b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def mixed(self): 462b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return {} 463b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik dict_of_lists = mixed 464b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 465b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __contains__(self, key): 466b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return False 467b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik has_key = __contains__ 468b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 469b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def copy(self): 470b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return self 471b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 472b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __repr__(self): 473b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return '<%s: %s>' % (self.__class__.__name__, 474b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik self.reason) 475b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 476b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __len__(self): 477b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return 0 478b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 479b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def __cmp__(self, other): 480b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return cmp({}, other) 481b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 482b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def iterkeys(self): 483b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return iter([]) 484b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 485b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if PY3: # pragma: no cover 486b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik keys = iterkeys 487b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = iterkeys 488b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik values = iterkeys 489b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 490b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik def keys(self): 491b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik return [] 492b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik items = keys 493b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik values = keys 494b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik itervalues = iterkeys 495b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik iteritems = iterkeys 496b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 497b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik __iter__ = iterkeys 498b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik 499b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craikdef _hide_passwd(items): 500b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik for k, v in items: 501b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik if ('password' in k 502b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik or 'passwd' in k 503b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik or 'pwd' in k 504b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik ): 505b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik yield k, '******' 506b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik else: 507b2cbf1594f8d6e4ba32d384cf379f62a74ed7654Chris Craik yield k, v 508