Ticket #736: mvd.patch
File mvd.patch, 13.5 KB (added by , 19 years ago) |
---|
-
django/utils/httpwrappers.py
1 1 from Cookie import SimpleCookie 2 2 from pprint import pformat 3 3 from urllib import urlencode 4 from django.utils import datastructures4 from django.utils.datastructures import MultiValueDict 5 5 6 6 class HttpRequest(object): # needs to be new-style class because subclasses define "property"s 7 7 "A basic HTTP request" … … 33 33 raw_message = '\r\n'.join(['%s:%s' % pair for pair in header_dict.items()]) 34 34 raw_message += '\r\n\r\n' + post_data 35 35 msg = email.message_from_string(raw_message) 36 POST = datastructures.MultiValueDict()37 FILES = datastructures.MultiValueDict()36 POST = MultiValueDict() 37 FILES = MultiValueDict() 38 38 for submessage in msg.get_payload(): 39 39 if isinstance(submessage, email.Message.Message): 40 40 name_dict = parse_header(submessage['Content-Disposition'])[1] … … 57 57 POST.appendlist(name_dict['name'], submessage.get_payload()) 58 58 return POST, FILES 59 59 60 class QueryDict(datastructures.MultiValueDict): 60 try: 61 from mod_python.util import parse_qsl 62 except ImportError: 63 from cgi import parse_qsl 64 class QueryDict(MultiValueDict): 61 65 """A specialized MultiValueDict that takes a query string when initialized. 62 66 This is immutable unless you create a copy of it.""" 63 67 def __init__(self, query_string): 64 try: 65 from mod_python.util import parse_qsl 66 except ImportError: 67 from cgi import parse_qsl 68 if not query_string: 69 self.data = {} 70 self._keys = [] 71 else: 72 self.data = {} 73 self._keys = [] 74 for name, value in parse_qsl(query_string, True): # keep_blank_values=True 75 if name in self.data: 76 self.data[name].append(value) 77 else: 78 self.data[name] = [value] 79 if name not in self._keys: 80 self._keys.append(name) 68 MultiValueDict.__init__(self) 69 self._mutable = True 70 for key, value in parse_qsl(query_string, True): # keep_blank_values=True 71 self.appendlist(key, value) 81 72 self._mutable = False 82 73 83 def _ _setitem__(self, key, value):74 def _assert_mutable(self): 84 75 if not self._mutable: 85 76 raise AttributeError, "This QueryDict instance is immutable" 86 else:87 self.data[key] = [value]88 if not key in self._keys:89 self._keys.append(key)90 77 78 def _setitem_if_mutable(self, key, value): 79 self._assert_mutable() 80 MultiValueDict.__setitem__(self, key, value) 81 __setitem__ = _setitem_if_mutable 82 91 83 def setlist(self, key, list_): 92 if not self._mutable: 93 raise AttributeError, "This QueryDict instance is immutable" 94 else: 95 self.data[key] = list_ 96 if not key in self._keys: 97 self._keys.append(key) 84 self._assert_mutable() 85 MultiValueDict.setlist(self, key, list_) 98 86 87 def appendlist(self, key, value): 88 self._assert_mutable() 89 MultiValueDict.appendlist(self, key, value) 90 91 def update(self, other_dict): 92 self._assert_mutable() 93 MultiValueDict.update(self, other_dict) 94 95 def pop(self, key): 96 self._assert_mutable() 97 return MultiValueDict.pop(self, key) 98 99 def popitem(self): 100 self._assert_mutable() 101 return MultiValueDict.popitem(self) 102 103 def clear(self): 104 self._assert_mutable() 105 MultiValueDict.clear(self) 106 107 def setdefault(self, *args): 108 self._assert_mutable() 109 return MultiValueDict.setdefault(self, *args) 110 99 111 def copy(self): 100 "Returns a mutable copy of this object" 101 cp = datastructures.MultiValueDict.copy(self) 112 """Returns a mutable copy of this object. Our special __setitem__ 113 must be disabled for copying machinery.""" 114 QueryDict.__setitem__ = dict.__setitem__ 115 import copy 116 cp = copy.deepcopy(self) 117 QueryDict.__setitem__ = QueryDict._setitem_if_mutable 102 118 cp._mutable = True 103 119 return cp 104 120 105 def assert_synchronized(self):106 assert(len(self._keys) == len(self.data.keys())), \107 "QueryDict data structure is out of sync: %s %s" % (str(self._keys), str(self.data))108 109 121 def items(self): 110 "Respect order preserved by self._keys" 111 self.assert_synchronized() 112 items = [] 113 for key in self._keys: 114 if key in self.data: 115 items.append((key, self.data[key][0])) 116 return items 122 return self.lists() 117 123 118 def keys(self):119 self.assert_synchronized()120 return self._keys121 122 124 def urlencode(self): 123 125 output = [] 124 for k, list_ in self. data.items():126 for k, list_ in self.items(): 125 127 output.extend([urlencode({k: v}) for v in list_]) 126 128 return '&'.join(output) 127 129 -
django/utils/datastructures.py
43 43 class MultiValueDictKeyError(KeyError): 44 44 pass 45 45 46 class MultiValueDict :46 class MultiValueDict(dict): 47 47 """ 48 A dictionary-like class customized to deal withmultiple values for the same key.48 A subclass of dictionary customized to handle multiple values for the same key. 49 49 50 50 >>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']}) 51 51 >>> d['name'] … … 60 60 which returns a list for every key, even though most Web forms submit 61 61 single name-value pairs. 62 62 """ 63 def __init__(self, key_to_list_mapping= None):64 self.data = key_to_list_mapping or {}63 def __init__(self, key_to_list_mapping=()): 64 dict.__init__(self, key_to_list_mapping) 65 65 66 def __repr__(self):67 return repr(self.data)68 69 66 def __getitem__(self, key): 70 " Returns the data value for this key; raises KeyError if not found"71 if self.data.has_key(key):72 73 return self.data[key][-1] # in case of duplicates, use last value ([-1])74 75 67 """Returns the last data value for this key or [] if empty list; raises KeyError 68 if key not found.""" 69 try: 70 return dict.__getitem__(self, key)[-1] 71 except IndexError: 72 return [] 76 73 raise MultiValueDictKeyError, "Key '%s' not found in MultiValueDict %s" % (key, self.data) 77 74 78 def __setitem__(self, key, value): 79 self.data[key] = [value] 75 def _setitem_list(self, key, value): 76 "Items are assigned to a list." 77 dict.__setitem__(self, key, [value]) 78 __setitem__ = _setitem_list 80 79 81 def __len__(self): 82 return len(self.data) 83 84 def get(self, key, default): 85 "Returns the default value if the requested data doesn't exist" 80 def get(self, key, *args): 81 "Returns the default value if the requested data doesn't exist." 86 82 try: 87 val = self[key] 88 except (KeyError, IndexError): 89 return default 90 if val == []: 91 return default 92 return val 83 return self[key] 84 except KeyError: 85 if args: 86 return args[0] 87 raise 93 88 94 def getlist(self, key): 95 "Returns an empty list if the requested data doesn't exist" 89 def getlist(self, key, *args): 90 """Returns an empty list, or a user-specified default, if the requested data 91 doesn't exist.""" 96 92 try: 97 return self.data[key]93 return dict.__getitem__(self, key) 98 94 except KeyError: 95 if args: 96 return args[0] 99 97 return [] 100 98 101 99 def setlist(self, key, list_): 102 self.data[key] = list_ 100 "Set the list associated with a key." 101 dict.__setitem__(self, key, list_) 103 102 104 def appendlist(self, key, item): 105 "Appends an item to the internal list associated with key" 106 try: 107 self.data[key].append(item) 108 except KeyError: 109 self.data[key] = [item] 103 def appendlist(self, key, value): 104 "Appends an item to the internal list associated with key." 105 x = self.setdefault(key, []) 106 x.append(value) 110 107 111 def has_key(self, key):112 return self.data.has_key(key)113 114 108 def items(self): 115 # we don't just return self.data.items() here, because we want to use116 # self.__getitem__() to access the values as *strings*, not lists117 return [(key, self[key]) for key in self. data.keys()]109 """Returns a list of (key, value) pairs, where value is the last item in 110 the list associated with the key.""" 111 return [(key, self[key]) for key in self.keys()] 118 112 119 def keys(self): 120 return self.data.keys() 113 def lists(self): 114 "Returns a list of (key, list) pairs." 115 return dict.items(self) 121 116 122 def update(self, other_dict): 123 if isinstance(other_dict, MultiValueDict): 124 for key, value_list in other_dict.data.items(): 125 self.data.setdefault(key, []).extend(value_list) 126 elif type(other_dict) == type({}): 127 for key, value in other_dict.items(): 128 self.data.setdefault(key, []).append(value) 129 else: 130 raise ValueError, "MultiValueDict.update() takes either a MultiValueDict or dictionary" 117 def values(self): 118 "Returns a list of the last value on every key list." 119 return [self[key] for key in self.keys()] 131 120 132 121 def copy(self): 133 "Returns a copy of this object" 122 """Returns a copy of this object. Our special __setitem__ 123 must be disabled for copying machinery.""" 134 124 import copy 125 MultiValueDict.__setitem__ = dict.__setitem__ 135 126 cp = copy.deepcopy(self) 127 MultiValueDict.__setitem__ = MultiValueDict._setitem_list 136 128 return cp 137 129 130 def update(self, other_dict): 131 "Update extends rather than replaces existing key lists." 132 if isinstance(other_dict, MultiValueDict): 133 for key, value_list in other_dict.lists(): 134 self.setdefault(key, []).extend(value_list) 135 else: 136 try: 137 for key, value in other_dict.items(): 138 self.setdefault(key, []).append(value) 139 except TypeError: 140 raise ValueError, "MultiValueDict.update() takes either a MultiValueDict or dictionary" 141 138 142 class DotExpandedDict(dict): 139 143 """ 140 144 A special dictionary constructor that takes a dictionary in which the keys -
tests/othertests/datastructures.py
1 """ 2 >>> d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']}) 3 >>> d['name'] 4 'Simon' 5 >>> d.get('name') 6 'Simon' 7 >>> d.get('nonkey') 8 Traceback (most recent call last): 9 ... 10 KeyError: 'nonkey' 11 >>> d.get('nonkey', 'nonexistent') 12 'nonexistent' 13 >>> d.items() 14 [('position', 'Developer'), ('name', 'Simon')] 15 >>> d.values() 16 ['Developer', 'Simon'] 17 >>> d.lists() 18 [('position', ['Developer']), ('name', ['Adrian', 'Simon'])] 19 >>> d.appendlist('name', 'Wilson') 20 >>> d.getlist('name') 21 ['Adrian', 'Simon', 'Wilson'] 22 >>> d.getlist('nonkey') 23 [] 24 >>> d.getlist('nonkey', 'nonexistent') 25 'nonexistent' 26 >>> d.setlist('lastname', ['Holovaty', 'Willison']) 27 >>> d.getlist('lastname') 28 ['Holovaty', 'Willison'] 29 >>> d.update({'name':'Jacob'}) 30 >>> d.getlist('name') 31 ['Adrian', 'Simon', 'Wilson', 'Jacob'] 32 >>> dc = d.copy() 33 >>> d is dc 34 False 35 >>> d == dc 36 True 37 38 >>> qd = QueryDict('a=1&b=2&b=3') 39 >>> qd.urlencode() 40 'a=1&b=2&b=3' 41 >>> qd['a'] 42 '1' 43 >>> qd.keys() 44 ['a', 'b'] 45 >>> qd.items() 46 [('a', ['1']), ('b', ['2', '3'])] 47 >>> qd.values() 48 ['1', '3'] 49 >>> qd['a'] = 2 50 Traceback (most recent call last): 51 ... 52 AttributeError: This QueryDict instance is immutable 53 >>> qd.setlist('a', [2]) 54 Traceback (most recent call last): 55 ... 56 AttributeError: This QueryDict instance is immutable 57 >>> qd.appendlist('a', 2) 58 Traceback (most recent call last): 59 ... 60 AttributeError: This QueryDict instance is immutable 61 >>> qd.pop('a') 62 Traceback (most recent call last): 63 ... 64 AttributeError: This QueryDict instance is immutable 65 >>> qd.popitem() 66 Traceback (most recent call last): 67 ... 68 AttributeError: This QueryDict instance is immutable 69 >>> qd.update({'a':'2'}) 70 Traceback (most recent call last): 71 ... 72 AttributeError: This QueryDict instance is immutable 73 >>> qd.setdefault('a', 2) 74 Traceback (most recent call last): 75 ... 76 AttributeError: This QueryDict instance is immutable 77 >>> qd.clear() 78 Traceback (most recent call last): 79 ... 80 AttributeError: This QueryDict instance is immutable 81 >>> qdc = qd.copy() 82 >>> qd is qdc 83 False 84 >>> qd == qdc 85 True 86 >>> qdc.setlist('a', [1, 2]) 87 >>> qdc['a'] 88 2 89 >>> qdc.appendlist('a', 3) 90 >>> qdc.pop('a') 91 [1, 2, 3] 92 >>> qdc.clear() 93 >>> qdc.setdefault('a', ['1']) 94 ['1'] 95 >>> qdc.update({'a':'2', 'b':'3'}) 96 >>> qdc 97 {'a': ['1', '2'], 'b': ['3']} 98 """ 99 100 from django.utils.datastructures import MultiValueDict 101 from django.utils.httpwrappers import QueryDict 102 103 if __name__ == '__main__': 104 import doctest 105 doctest.testmod()