/tests/regressiontests/utils/datastructures.py
Python | 277 lines | 242 code | 28 blank | 7 comment | 3 complexity | 97b124e0f7a79276db8668a56b834910 MD5 | raw file
1""" 2Tests for stuff in django.utils.datastructures. 3""" 4import pickle 5import unittest 6 7from django.utils.copycompat import copy 8from django.utils.datastructures import * 9 10 11class DatastructuresTestCase(unittest.TestCase): 12 def assertRaisesErrorWithMessage(self, error, message, callable, 13 *args, **kwargs): 14 self.assertRaises(error, callable, *args, **kwargs) 15 try: 16 callable(*args, **kwargs) 17 except error, e: 18 self.assertEqual(message, str(e)) 19 20 21class SortedDictTests(DatastructuresTestCase): 22 def setUp(self): 23 self.d1 = SortedDict() 24 self.d1[7] = 'seven' 25 self.d1[1] = 'one' 26 self.d1[9] = 'nine' 27 28 self.d2 = SortedDict() 29 self.d2[1] = 'one' 30 self.d2[9] = 'nine' 31 self.d2[0] = 'nil' 32 self.d2[7] = 'seven' 33 34 def test_basic_methods(self): 35 self.assertEqual(self.d1.keys(), [7, 1, 9]) 36 self.assertEqual(self.d1.values(), ['seven', 'one', 'nine']) 37 self.assertEqual(self.d1.items(), [(7, 'seven'), (1, 'one'), (9, 'nine')]) 38 39 def test_overwrite_ordering(self): 40 """ Overwriting an item keeps it's place. """ 41 self.d1[1] = 'ONE' 42 self.assertEqual(self.d1.values(), ['seven', 'ONE', 'nine']) 43 44 def test_append_items(self): 45 """ New items go to the end. """ 46 self.d1[0] = 'nil' 47 self.assertEqual(self.d1.keys(), [7, 1, 9, 0]) 48 49 def test_delete_and_insert(self): 50 """ 51 Deleting an item, then inserting the same key again will place it 52 at the end. 53 """ 54 del self.d2[7] 55 self.assertEqual(self.d2.keys(), [1, 9, 0]) 56 self.d2[7] = 'lucky number 7' 57 self.assertEqual(self.d2.keys(), [1, 9, 0, 7]) 58 59 def test_change_keys(self): 60 """ 61 Changing the keys won't do anything, it's only a copy of the 62 keys dict. 63 """ 64 k = self.d2.keys() 65 k.remove(9) 66 self.assertEqual(self.d2.keys(), [1, 9, 0, 7]) 67 68 def test_init_keys(self): 69 """ 70 Initialising a SortedDict with two keys will just take the first one. 71 72 A real dict will actually take the second value so we will too, but 73 we'll keep the ordering from the first key found. 74 """ 75 tuples = ((2, 'two'), (1, 'one'), (2, 'second-two')) 76 d = SortedDict(tuples) 77 78 self.assertEqual(d.keys(), [2, 1]) 79 80 real_dict = dict(tuples) 81 self.assertEqual(sorted(real_dict.values()), ['one', 'second-two']) 82 83 # Here the order of SortedDict values *is* what we are testing 84 self.assertEqual(d.values(), ['second-two', 'one']) 85 86 def test_overwrite(self): 87 self.d1[1] = 'not one' 88 self.assertEqual(self.d1[1], 'not one') 89 self.assertEqual(self.d1.keys(), self.d1.copy().keys()) 90 91 def test_append(self): 92 self.d1[13] = 'thirteen' 93 self.assertEqual( 94 repr(self.d1), 95 "{7: 'seven', 1: 'one', 9: 'nine', 13: 'thirteen'}" 96 ) 97 98 def test_pop(self): 99 self.assertEqual(self.d1.pop(1, 'missing'), 'one') 100 self.assertEqual(self.d1.pop(1, 'missing'), 'missing') 101 102 # We don't know which item will be popped in popitem(), so we'll 103 # just check that the number of keys has decreased. 104 l = len(self.d1) 105 self.d1.popitem() 106 self.assertEqual(l - len(self.d1), 1) 107 108 def test_dict_equality(self): 109 d = SortedDict((i, i) for i in xrange(3)) 110 self.assertEqual(d, {0: 0, 1: 1, 2: 2}) 111 112 def test_tuple_init(self): 113 d = SortedDict(((1, "one"), (0, "zero"), (2, "two"))) 114 self.assertEqual(repr(d), "{1: 'one', 0: 'zero', 2: 'two'}") 115 116 def test_pickle(self): 117 self.assertEqual( 118 pickle.loads(pickle.dumps(self.d1, 2)), 119 {7: 'seven', 1: 'one', 9: 'nine'} 120 ) 121 122 def test_clear(self): 123 self.d1.clear() 124 self.assertEqual(self.d1, {}) 125 self.assertEqual(self.d1.keyOrder, []) 126 127class MergeDictTests(DatastructuresTestCase): 128 129 def test_simple_mergedict(self): 130 d1 = {'chris':'cool', 'camri':'cute', 'cotton':'adorable', 131 'tulip':'snuggable', 'twoofme':'firstone'} 132 133 d2 = {'chris2':'cool2', 'camri2':'cute2', 'cotton2':'adorable2', 134 'tulip2':'snuggable2'} 135 136 d3 = {'chris3':'cool3', 'camri3':'cute3', 'cotton3':'adorable3', 137 'tulip3':'snuggable3'} 138 139 d4 = {'twoofme': 'secondone'} 140 141 md = MergeDict(d1, d2, d3) 142 143 self.assertEqual(md['chris'], 'cool') 144 self.assertEqual(md['camri'], 'cute') 145 self.assertEqual(md['twoofme'], 'firstone') 146 147 md2 = md.copy() 148 self.assertEqual(md2['chris'], 'cool') 149 150 def test_mergedict_merges_multivaluedict(self): 151 """ MergeDict can merge MultiValueDicts """ 152 153 multi1 = MultiValueDict({'key1': ['value1'], 154 'key2': ['value2', 'value3']}) 155 156 multi2 = MultiValueDict({'key2': ['value4'], 157 'key4': ['value5', 'value6']}) 158 159 mm = MergeDict(multi1, multi2) 160 161 # Although 'key2' appears in both dictionaries, 162 # only the first value is used. 163 self.assertEqual(mm.getlist('key2'), ['value2', 'value3']) 164 self.assertEqual(mm.getlist('key4'), ['value5', 'value6']) 165 self.assertEqual(mm.getlist('undefined'), []) 166 167 self.assertEqual(sorted(mm.keys()), ['key1', 'key2', 'key4']) 168 self.assertEqual(len(mm.values()), 3) 169 170 self.assertTrue('value1' in mm.values()) 171 172 self.assertEqual(sorted(mm.items(), key=lambda k: k[0]), 173 [('key1', 'value1'), ('key2', 'value3'), 174 ('key4', 'value6')]) 175 176 self.assertEqual([(k,mm.getlist(k)) for k in sorted(mm)], 177 [('key1', ['value1']), 178 ('key2', ['value2', 'value3']), 179 ('key4', ['value5', 'value6'])]) 180 181class MultiValueDictTests(DatastructuresTestCase): 182 183 def test_multivaluedict(self): 184 d = MultiValueDict({'name': ['Adrian', 'Simon'], 185 'position': ['Developer']}) 186 187 self.assertEqual(d['name'], 'Simon') 188 self.assertEqual(d.get('name'), 'Simon') 189 self.assertEqual(d.getlist('name'), ['Adrian', 'Simon']) 190 self.assertEqual(list(d.iteritems()), 191 [('position', 'Developer'), ('name', 'Simon')]) 192 193 self.assertEqual(list(d.iterlists()), 194 [('position', ['Developer']), 195 ('name', ['Adrian', 'Simon'])]) 196 197 # MultiValueDictKeyError: "Key 'lastname' not found in 198 # <MultiValueDict: {'position': ['Developer'], 199 # 'name': ['Adrian', 'Simon']}>" 200 self.assertRaisesErrorWithMessage(MultiValueDictKeyError, 201 '"Key \'lastname\' not found in <MultiValueDict: {\'position\':'\ 202 ' [\'Developer\'], \'name\': [\'Adrian\', \'Simon\']}>"', 203 d.__getitem__, 'lastname') 204 205 self.assertEqual(d.get('lastname'), None) 206 self.assertEqual(d.get('lastname', 'nonexistent'), 'nonexistent') 207 self.assertEqual(d.getlist('lastname'), []) 208 209 d.setlist('lastname', ['Holovaty', 'Willison']) 210 self.assertEqual(d.getlist('lastname'), ['Holovaty', 'Willison']) 211 self.assertEqual(d.values(), ['Developer', 'Simon', 'Willison']) 212 self.assertEqual(list(d.itervalues()), 213 ['Developer', 'Simon', 'Willison']) 214 215 def test_copy(self): 216 for copy_func in [copy, lambda d: d.copy()]: 217 d1 = MultiValueDict({ 218 "developers": ["Carl", "Fred"] 219 }) 220 self.assertEqual(d1["developers"], "Fred") 221 d2 = copy_func(d1) 222 d2.update({"developers": "Groucho"}) 223 self.assertEqual(d2["developers"], "Groucho") 224 self.assertEqual(d1["developers"], "Fred") 225 226 d1 = MultiValueDict({ 227 "key": [[]] 228 }) 229 self.assertEqual(d1["key"], []) 230 d2 = copy_func(d1) 231 d2["key"].append("Penguin") 232 self.assertEqual(d1["key"], ["Penguin"]) 233 self.assertEqual(d2["key"], ["Penguin"]) 234 235 236class DotExpandedDictTests(DatastructuresTestCase): 237 238 def test_dotexpandeddict(self): 239 240 d = DotExpandedDict({'person.1.firstname': ['Simon'], 241 'person.1.lastname': ['Willison'], 242 'person.2.firstname': ['Adrian'], 243 'person.2.lastname': ['Holovaty']}) 244 245 self.assertEqual(d['person']['1']['lastname'], ['Willison']) 246 self.assertEqual(d['person']['2']['lastname'], ['Holovaty']) 247 self.assertEqual(d['person']['2']['firstname'], ['Adrian']) 248 249 250class ImmutableListTests(DatastructuresTestCase): 251 252 def test_sort(self): 253 d = ImmutableList(range(10)) 254 255 # AttributeError: ImmutableList object is immutable. 256 self.assertRaisesErrorWithMessage(AttributeError, 257 'ImmutableList object is immutable.', d.sort) 258 259 self.assertEqual(repr(d), '(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)') 260 261 def test_custom_warning(self): 262 d = ImmutableList(range(10), warning="Object is immutable!") 263 264 self.assertEqual(d[1], 1) 265 266 # AttributeError: Object is immutable! 267 self.assertRaisesErrorWithMessage(AttributeError, 268 'Object is immutable!', d.__setitem__, 1, 'test') 269 270 271class DictWrapperTests(DatastructuresTestCase): 272 273 def test_dictwrapper(self): 274 f = lambda x: "*%s" % x 275 d = DictWrapper({'a': 'a'}, f, 'xx_') 276 self.assertEqual("Normal: %(a)s. Modified: %(xx_a)s" % d, 277 'Normal: a. Modified: *a')