test_datastructures.py 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  1. """
  2. Tests for stuff in django.utils.datastructures.
  3. """
  4. import copy
  5. from django.test import SimpleTestCase
  6. from django.utils.datastructures import (
  7. CaseInsensitiveMapping, DictWrapper, ImmutableList, MultiValueDict,
  8. MultiValueDictKeyError, OrderedSet,
  9. )
  10. class OrderedSetTests(SimpleTestCase):
  11. def test_bool(self):
  12. # Refs #23664
  13. s = OrderedSet()
  14. self.assertFalse(s)
  15. s.add(1)
  16. self.assertTrue(s)
  17. def test_len(self):
  18. s = OrderedSet()
  19. self.assertEqual(len(s), 0)
  20. s.add(1)
  21. s.add(2)
  22. s.add(2)
  23. self.assertEqual(len(s), 2)
  24. class MultiValueDictTests(SimpleTestCase):
  25. def test_multivaluedict(self):
  26. d = MultiValueDict({'name': ['Adrian', 'Simon'], 'position': ['Developer']})
  27. self.assertEqual(d['name'], 'Simon')
  28. self.assertEqual(d.get('name'), 'Simon')
  29. self.assertEqual(d.getlist('name'), ['Adrian', 'Simon'])
  30. self.assertEqual(
  31. sorted(d.items()),
  32. [('name', 'Simon'), ('position', 'Developer')]
  33. )
  34. self.assertEqual(
  35. sorted(d.lists()),
  36. [('name', ['Adrian', 'Simon']), ('position', ['Developer'])]
  37. )
  38. with self.assertRaises(MultiValueDictKeyError) as cm:
  39. d.__getitem__('lastname')
  40. self.assertEqual(str(cm.exception), "'lastname'")
  41. self.assertIsNone(d.get('lastname'))
  42. self.assertEqual(d.get('lastname', 'nonexistent'), 'nonexistent')
  43. self.assertEqual(d.getlist('lastname'), [])
  44. self.assertEqual(d.getlist('doesnotexist', ['Adrian', 'Simon']), ['Adrian', 'Simon'])
  45. d.setlist('lastname', ['Holovaty', 'Willison'])
  46. self.assertEqual(d.getlist('lastname'), ['Holovaty', 'Willison'])
  47. self.assertEqual(sorted(d.values()), ['Developer', 'Simon', 'Willison'])
  48. def test_appendlist(self):
  49. d = MultiValueDict()
  50. d.appendlist('name', 'Adrian')
  51. d.appendlist('name', 'Simon')
  52. self.assertEqual(d.getlist('name'), ['Adrian', 'Simon'])
  53. def test_copy(self):
  54. for copy_func in [copy.copy, lambda d: d.copy()]:
  55. d1 = MultiValueDict({
  56. "developers": ["Carl", "Fred"]
  57. })
  58. self.assertEqual(d1["developers"], "Fred")
  59. d2 = copy_func(d1)
  60. d2.update({"developers": "Groucho"})
  61. self.assertEqual(d2["developers"], "Groucho")
  62. self.assertEqual(d1["developers"], "Fred")
  63. d1 = MultiValueDict({
  64. "key": [[]]
  65. })
  66. self.assertEqual(d1["key"], [])
  67. d2 = copy_func(d1)
  68. d2["key"].append("Penguin")
  69. self.assertEqual(d1["key"], ["Penguin"])
  70. self.assertEqual(d2["key"], ["Penguin"])
  71. def test_dict_translation(self):
  72. mvd = MultiValueDict({
  73. 'devs': ['Bob', 'Joe'],
  74. 'pm': ['Rory'],
  75. })
  76. d = mvd.dict()
  77. self.assertEqual(sorted(d), sorted(mvd))
  78. for key in mvd:
  79. self.assertEqual(d[key], mvd[key])
  80. self.assertEqual({}, MultiValueDict().dict())
  81. def test_getlist_doesnt_mutate(self):
  82. x = MultiValueDict({'a': ['1', '2'], 'b': ['3']})
  83. values = x.getlist('a')
  84. values += x.getlist('b')
  85. self.assertEqual(x.getlist('a'), ['1', '2'])
  86. def test_internal_getlist_does_mutate(self):
  87. x = MultiValueDict({'a': ['1', '2'], 'b': ['3']})
  88. values = x._getlist('a')
  89. values += x._getlist('b')
  90. self.assertEqual(x._getlist('a'), ['1', '2', '3'])
  91. def test_getlist_default(self):
  92. x = MultiValueDict({'a': [1]})
  93. MISSING = object()
  94. values = x.getlist('b', default=MISSING)
  95. self.assertIs(values, MISSING)
  96. def test_getlist_none_empty_values(self):
  97. x = MultiValueDict({'a': None, 'b': []})
  98. self.assertIsNone(x.getlist('a'))
  99. self.assertEqual(x.getlist('b'), [])
  100. class ImmutableListTests(SimpleTestCase):
  101. def test_sort(self):
  102. d = ImmutableList(range(10))
  103. # AttributeError: ImmutableList object is immutable.
  104. with self.assertRaisesMessage(AttributeError, 'ImmutableList object is immutable.'):
  105. d.sort()
  106. self.assertEqual(repr(d), '(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)')
  107. def test_custom_warning(self):
  108. d = ImmutableList(range(10), warning="Object is immutable!")
  109. self.assertEqual(d[1], 1)
  110. # AttributeError: Object is immutable!
  111. with self.assertRaisesMessage(AttributeError, 'Object is immutable!'):
  112. d.__setitem__(1, 'test')
  113. class DictWrapperTests(SimpleTestCase):
  114. def test_dictwrapper(self):
  115. def f(x):
  116. return "*%s" % x
  117. d = DictWrapper({'a': 'a'}, f, 'xx_')
  118. self.assertEqual(
  119. "Normal: %(a)s. Modified: %(xx_a)s" % d,
  120. 'Normal: a. Modified: *a'
  121. )
  122. class CaseInsensitiveMappingTests(SimpleTestCase):
  123. def setUp(self):
  124. self.dict1 = CaseInsensitiveMapping({
  125. 'Accept': 'application/json',
  126. 'content-type': 'text/html',
  127. })
  128. def test_create_with_invalid_values(self):
  129. msg = 'dictionary update sequence element #1 has length 4; 2 is required'
  130. with self.assertRaisesMessage(ValueError, msg):
  131. CaseInsensitiveMapping([('Key1', 'Val1'), 'Key2'])
  132. def test_create_with_invalid_key(self):
  133. msg = 'Element key 1 invalid, only strings are allowed'
  134. with self.assertRaisesMessage(ValueError, msg):
  135. CaseInsensitiveMapping([(1, '2')])
  136. def test_list(self):
  137. self.assertEqual(sorted(list(self.dict1)), sorted(['Accept', 'content-type']))
  138. def test_dict(self):
  139. self.assertEqual(dict(self.dict1), {'Accept': 'application/json', 'content-type': 'text/html'})
  140. def test_repr(self):
  141. dict1 = CaseInsensitiveMapping({'Accept': 'application/json'})
  142. dict2 = CaseInsensitiveMapping({'content-type': 'text/html'})
  143. self.assertEqual(repr(dict1), repr({'Accept': 'application/json'}))
  144. self.assertEqual(repr(dict2), repr({'content-type': 'text/html'}))
  145. def test_str(self):
  146. dict1 = CaseInsensitiveMapping({'Accept': 'application/json'})
  147. dict2 = CaseInsensitiveMapping({'content-type': 'text/html'})
  148. self.assertEqual(str(dict1), str({'Accept': 'application/json'}))
  149. self.assertEqual(str(dict2), str({'content-type': 'text/html'}))
  150. def test_equal(self):
  151. self.assertEqual(self.dict1, {'Accept': 'application/json', 'content-type': 'text/html'})
  152. self.assertNotEqual(self.dict1, {'accept': 'application/jso', 'Content-Type': 'text/html'})
  153. self.assertNotEqual(self.dict1, 'string')
  154. def test_items(self):
  155. other = {'Accept': 'application/json', 'content-type': 'text/html'}
  156. self.assertEqual(sorted(self.dict1.items()), sorted(other.items()))
  157. def test_copy(self):
  158. copy = self.dict1.copy()
  159. self.assertIs(copy, self.dict1)
  160. self.assertEqual(copy, self.dict1)
  161. def test_getitem(self):
  162. self.assertEqual(self.dict1['Accept'], 'application/json')
  163. self.assertEqual(self.dict1['accept'], 'application/json')
  164. self.assertEqual(self.dict1['aCCept'], 'application/json')
  165. self.assertEqual(self.dict1['content-type'], 'text/html')
  166. self.assertEqual(self.dict1['Content-Type'], 'text/html')
  167. self.assertEqual(self.dict1['Content-type'], 'text/html')
  168. def test_in(self):
  169. self.assertIn('Accept', self.dict1)
  170. self.assertIn('accept', self.dict1)
  171. self.assertIn('aCCept', self.dict1)
  172. self.assertIn('content-type', self.dict1)
  173. self.assertIn('Content-Type', self.dict1)
  174. def test_del(self):
  175. self.assertIn('Accept', self.dict1)
  176. msg = "'CaseInsensitiveMapping' object does not support item deletion"
  177. with self.assertRaisesMessage(TypeError, msg):
  178. del self.dict1['Accept']
  179. self.assertIn('Accept', self.dict1)
  180. def test_set(self):
  181. self.assertEqual(len(self.dict1), 2)
  182. msg = "'CaseInsensitiveMapping' object does not support item assignment"
  183. with self.assertRaisesMessage(TypeError, msg):
  184. self.dict1['New Key'] = 1
  185. self.assertEqual(len(self.dict1), 2)