""" Tests for stuff in django.utils.datastructures. """ import copy import pickle from django.test import SimpleTestCase from django.utils.datastructures import (DictWrapper, ImmutableList, MultiValueDict, MultiValueDictKeyError, MergeDict, SortedDict) from django.utils import six class SortedDictTests(SimpleTestCase): def setUp(self): self.d1 = SortedDict() self.d1[7] = 'seven' self.d1[1] = 'one' self.d1[9] = 'nine' self.d2 = SortedDict() self.d2[1] = 'one' self.d2[9] = 'nine' self.d2[0] = 'nil' self.d2[7] = 'seven' def test_basic_methods(self): self.assertEqual(list(six.iterkeys(self.d1)), [7, 1, 9]) self.assertEqual(list(six.itervalues(self.d1)), ['seven', 'one', 'nine']) self.assertEqual(list(six.iteritems(self.d1)), [(7, 'seven'), (1, 'one'), (9, 'nine')]) def test_overwrite_ordering(self): """ Overwriting an item keeps its place. """ self.d1[1] = 'ONE' self.assertEqual(list(six.itervalues(self.d1)), ['seven', 'ONE', 'nine']) def test_append_items(self): """ New items go to the end. """ self.d1[0] = 'nil' self.assertEqual(list(six.iterkeys(self.d1)), [7, 1, 9, 0]) def test_delete_and_insert(self): """ Deleting an item, then inserting the same key again will place it at the end. """ del self.d2[7] self.assertEqual(list(six.iterkeys(self.d2)), [1, 9, 0]) self.d2[7] = 'lucky number 7' self.assertEqual(list(six.iterkeys(self.d2)), [1, 9, 0, 7]) if six.PY2: def test_change_keys(self): """ Changing the keys won't do anything, it's only a copy of the keys dict. This test doesn't make sense under Python 3 because keys is an iterator. """ k = self.d2.keys() k.remove(9) self.assertEqual(self.d2.keys(), [1, 9, 0, 7]) def test_init_keys(self): """ Initialising a SortedDict with two keys will just take the first one. A real dict will actually take the second value so we will too, but we'll keep the ordering from the first key found. """ tuples = ((2, 'two'), (1, 'one'), (2, 'second-two')) d = SortedDict(tuples) self.assertEqual(list(six.iterkeys(d)), [2, 1]) real_dict = dict(tuples) self.assertEqual(sorted(six.itervalues(real_dict)), ['one', 'second-two']) # Here the order of SortedDict values *is* what we are testing self.assertEqual(list(six.itervalues(d)), ['second-two', 'one']) def test_overwrite(self): self.d1[1] = 'not one' self.assertEqual(self.d1[1], 'not one') self.assertEqual(list(six.iterkeys(self.d1)), list(six.iterkeys(self.d1.copy()))) def test_append(self): self.d1[13] = 'thirteen' self.assertEqual( repr(self.d1), "{7: 'seven', 1: 'one', 9: 'nine', 13: 'thirteen'}" ) def test_pop(self): self.assertEqual(self.d1.pop(1, 'missing'), 'one') self.assertEqual(self.d1.pop(1, 'missing'), 'missing') # We don't know which item will be popped in popitem(), so we'll # just check that the number of keys has decreased. l = len(self.d1) self.d1.popitem() self.assertEqual(l - len(self.d1), 1) def test_dict_equality(self): d = SortedDict((i, i) for i in range(3)) self.assertEqual(d, {0: 0, 1: 1, 2: 2}) def test_tuple_init(self): d = SortedDict(((1, "one"), (0, "zero"), (2, "two"))) self.assertEqual(repr(d), "{1: 'one', 0: 'zero', 2: 'two'}") def test_pickle(self): self.assertEqual( pickle.loads(pickle.dumps(self.d1, 2)), {7: 'seven', 1: 'one', 9: 'nine'} ) def test_copy(self): orig = SortedDict(((1, "one"), (0, "zero"), (2, "two"))) copied = copy.copy(orig) self.assertEqual(list(six.iterkeys(orig)), [1, 0, 2]) self.assertEqual(list(six.iterkeys(copied)), [1, 0, 2]) def test_clear(self): self.d1.clear() self.assertEqual(self.d1, {}) self.assertEqual(self.d1.keyOrder, []) def test_reversed(self): self.assertEqual(list(self.d1), [7, 1, 9]) self.assertEqual(list(self.d2), [1, 9, 0, 7]) self.assertEqual(list(reversed(self.d1)), [9, 1, 7]) self.assertEqual(list(reversed(self.d2)), [7, 0, 9, 1]) class MergeDictTests(SimpleTestCase): def test_simple_mergedict(self): d1 = {'chris':'cool', 'camri':'cute', 'cotton':'adorable', 'tulip':'snuggable', 'twoofme':'firstone'} d2 = {'chris2':'cool2', 'camri2':'cute2', 'cotton2':'adorable2', 'tulip2':'snuggable2'} d3 = {'chris3':'cool3', 'camri3':'cute3', 'cotton3':'adorable3', 'tulip3':'snuggable3'} d4 = {'twoofme': 'secondone'} md = MergeDict(d1, d2, d3) self.assertEqual(md['chris'], 'cool') self.assertEqual(md['camri'], 'cute') self.assertEqual(md['twoofme'], 'firstone') md2 = md.copy() self.assertEqual(md2['chris'], 'cool') def test_mergedict_merges_multivaluedict(self): """ MergeDict can merge MultiValueDicts """ multi1 = MultiValueDict({'key1': ['value1'], 'key2': ['value2', 'value3']}) multi2 = MultiValueDict({'key2': ['value4'], 'key4': ['value5', 'value6']}) mm = MergeDict(multi1, multi2) # Although 'key2' appears in both dictionaries, # only the first value is used. self.assertEqual(mm.getlist('key2'), ['value2', 'value3']) self.assertEqual(mm.getlist('key4'), ['value5', 'value6']) self.assertEqual(mm.getlist('undefined'), []) self.assertEqual(sorted(six.iterkeys(mm)), ['key1', 'key2', 'key4']) self.assertEqual(len(list(six.itervalues(mm))), 3) self.assertTrue('value1' in six.itervalues(mm)) self.assertEqual(sorted(six.iteritems(mm), key=lambda k: k[0]), [('key1', 'value1'), ('key2', 'value3'), ('key4', 'value6')]) self.assertEqual([(k,mm.getlist(k)) for k in sorted(mm)], [('key1', ['value1']), ('key2', ['value2', 'value3']), ('key4', ['value5', 'value6'])]) def test_bool_casting(self): empty = MergeDict({}, {}, {}) not_empty = MergeDict({}, {}, {"key": "value"}) self.assertFalse(empty) self.assertTrue(not_empty) def test_key_error(self): """ Test that the message of KeyError contains the missing key name. """ d1 = MergeDict({'key1': 42}) with six.assertRaisesRegex(self, KeyError, 'key2'): d1['key2'] class MultiValueDictTests(SimpleTestCase): def test_multivaluedict(self): d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']}) self.assertEqual(d['name'], 'Simon') self.assertEqual(d.get('name'), 'Simon') self.assertEqual(d.getlist('name'), ['Adrian', 'Simon']) self.assertEqual(sorted(list(six.iteritems(d))), [('name', 'Simon'), ('position', 'Developer')]) self.assertEqual(sorted(list(six.iterlists(d))), [('name', ['Adrian', 'Simon']), ('position', ['Developer'])]) # MultiValueDictKeyError: "Key 'lastname' not found in # " six.assertRaisesRegex(self, MultiValueDictKeyError, r'"Key \'lastname\' not found in