test_mutable_list.py 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425
  1. # Copyright (c) 2008-2009 Aryeh Leib Taurog, http://www.aryehleib.com
  2. # All rights reserved.
  3. #
  4. # Modified from original contribution by Aryeh Leib Taurog, which was
  5. # released under the New BSD license.
  6. import unittest
  7. from django.contrib.gis.geos.mutable_list import ListMixin
  8. from django.utils import six
  9. class UserListA(ListMixin):
  10. _mytype = tuple
  11. def __init__(self, i_list, *args, **kwargs):
  12. self._list = self._mytype(i_list)
  13. super(UserListA, self).__init__(*args, **kwargs)
  14. def __len__(self):
  15. return len(self._list)
  16. def __str__(self):
  17. return str(self._list)
  18. def __repr__(self):
  19. return repr(self._list)
  20. def _set_list(self, length, items):
  21. # this would work:
  22. # self._list = self._mytype(items)
  23. # but then we wouldn't be testing length parameter
  24. itemList = ['x'] * length
  25. for i, v in enumerate(items):
  26. itemList[i] = v
  27. self._list = self._mytype(itemList)
  28. def _get_single_external(self, index):
  29. return self._list[index]
  30. class UserListB(UserListA):
  31. _mytype = list
  32. def _set_single(self, index, value):
  33. self._list[index] = value
  34. def nextRange(length):
  35. nextRange.start += 100
  36. return range(nextRange.start, nextRange.start + length)
  37. nextRange.start = 0
  38. class ListMixinTest(unittest.TestCase):
  39. """
  40. Tests base class ListMixin by comparing a list clone which is
  41. a ListMixin subclass with a real Python list.
  42. """
  43. limit = 3
  44. listType = UserListA
  45. def lists_of_len(self, length=None):
  46. if length is None:
  47. length = self.limit
  48. pl = list(range(length))
  49. return pl, self.listType(pl)
  50. def limits_plus(self, b):
  51. return range(-self.limit - b, self.limit + b)
  52. def step_range(self):
  53. return list(range(-1 - self.limit, 0)) + list(range(1, 1 + self.limit))
  54. def test01_getslice(self):
  55. 'Slice retrieval'
  56. pl, ul = self.lists_of_len()
  57. for i in self.limits_plus(1):
  58. self.assertEqual(pl[i:], ul[i:], 'slice [%d:]' % (i))
  59. self.assertEqual(pl[:i], ul[:i], 'slice [:%d]' % (i))
  60. for j in self.limits_plus(1):
  61. self.assertEqual(pl[i:j], ul[i:j], 'slice [%d:%d]' % (i, j))
  62. for k in self.step_range():
  63. self.assertEqual(pl[i:j:k], ul[i:j:k], 'slice [%d:%d:%d]' % (i, j, k))
  64. for k in self.step_range():
  65. self.assertEqual(pl[i::k], ul[i::k], 'slice [%d::%d]' % (i, k))
  66. self.assertEqual(pl[:i:k], ul[:i:k], 'slice [:%d:%d]' % (i, k))
  67. for k in self.step_range():
  68. self.assertEqual(pl[::k], ul[::k], 'slice [::%d]' % (k))
  69. def test02_setslice(self):
  70. 'Slice assignment'
  71. def setfcn(x, i, j, k, L):
  72. x[i:j:k] = range(L)
  73. pl, ul = self.lists_of_len()
  74. for slen in range(self.limit + 1):
  75. ssl = nextRange(slen)
  76. ul[:] = ssl
  77. pl[:] = ssl
  78. self.assertEqual(pl, ul[:], 'set slice [:]')
  79. for i in self.limits_plus(1):
  80. ssl = nextRange(slen)
  81. ul[i:] = ssl
  82. pl[i:] = ssl
  83. self.assertEqual(pl, ul[:], 'set slice [%d:]' % (i))
  84. ssl = nextRange(slen)
  85. ul[:i] = ssl
  86. pl[:i] = ssl
  87. self.assertEqual(pl, ul[:], 'set slice [:%d]' % (i))
  88. for j in self.limits_plus(1):
  89. ssl = nextRange(slen)
  90. ul[i:j] = ssl
  91. pl[i:j] = ssl
  92. self.assertEqual(pl, ul[:], 'set slice [%d:%d]' % (i, j))
  93. for k in self.step_range():
  94. ssl = nextRange(len(ul[i:j:k]))
  95. ul[i:j:k] = ssl
  96. pl[i:j:k] = ssl
  97. self.assertEqual(pl, ul[:], 'set slice [%d:%d:%d]' % (i, j, k))
  98. sliceLen = len(ul[i:j:k])
  99. self.assertRaises(ValueError, setfcn, ul, i, j, k, sliceLen + 1)
  100. if sliceLen > 2:
  101. self.assertRaises(ValueError, setfcn, ul, i, j, k, sliceLen - 1)
  102. for k in self.step_range():
  103. ssl = nextRange(len(ul[i::k]))
  104. ul[i::k] = ssl
  105. pl[i::k] = ssl
  106. self.assertEqual(pl, ul[:], 'set slice [%d::%d]' % (i, k))
  107. ssl = nextRange(len(ul[:i:k]))
  108. ul[:i:k] = ssl
  109. pl[:i:k] = ssl
  110. self.assertEqual(pl, ul[:], 'set slice [:%d:%d]' % (i, k))
  111. for k in self.step_range():
  112. ssl = nextRange(len(ul[::k]))
  113. ul[::k] = ssl
  114. pl[::k] = ssl
  115. self.assertEqual(pl, ul[:], 'set slice [::%d]' % (k))
  116. def test03_delslice(self):
  117. 'Delete slice'
  118. for Len in range(self.limit):
  119. pl, ul = self.lists_of_len(Len)
  120. del pl[:]
  121. del ul[:]
  122. self.assertEqual(pl[:], ul[:], 'del slice [:]')
  123. for i in range(-Len - 1, Len + 1):
  124. pl, ul = self.lists_of_len(Len)
  125. del pl[i:]
  126. del ul[i:]
  127. self.assertEqual(pl[:], ul[:], 'del slice [%d:]' % (i))
  128. pl, ul = self.lists_of_len(Len)
  129. del pl[:i]
  130. del ul[:i]
  131. self.assertEqual(pl[:], ul[:], 'del slice [:%d]' % (i))
  132. for j in range(-Len - 1, Len + 1):
  133. pl, ul = self.lists_of_len(Len)
  134. del pl[i:j]
  135. del ul[i:j]
  136. self.assertEqual(pl[:], ul[:], 'del slice [%d:%d]' % (i, j))
  137. for k in list(range(-Len - 1, 0)) + list(range(1, Len)):
  138. pl, ul = self.lists_of_len(Len)
  139. del pl[i:j:k]
  140. del ul[i:j:k]
  141. self.assertEqual(pl[:], ul[:], 'del slice [%d:%d:%d]' % (i, j, k))
  142. for k in list(range(-Len - 1, 0)) + list(range(1, Len)):
  143. pl, ul = self.lists_of_len(Len)
  144. del pl[:i:k]
  145. del ul[:i:k]
  146. self.assertEqual(pl[:], ul[:], 'del slice [:%d:%d]' % (i, k))
  147. pl, ul = self.lists_of_len(Len)
  148. del pl[i::k]
  149. del ul[i::k]
  150. self.assertEqual(pl[:], ul[:], 'del slice [%d::%d]' % (i, k))
  151. for k in list(range(-Len - 1, 0)) + list(range(1, Len)):
  152. pl, ul = self.lists_of_len(Len)
  153. del pl[::k]
  154. del ul[::k]
  155. self.assertEqual(pl[:], ul[:], 'del slice [::%d]' % (k))
  156. def test04_get_set_del_single(self):
  157. 'Get/set/delete single item'
  158. pl, ul = self.lists_of_len()
  159. for i in self.limits_plus(0):
  160. self.assertEqual(pl[i], ul[i], 'get single item [%d]' % i)
  161. for i in self.limits_plus(0):
  162. pl, ul = self.lists_of_len()
  163. pl[i] = 100
  164. ul[i] = 100
  165. self.assertEqual(pl[:], ul[:], 'set single item [%d]' % i)
  166. for i in self.limits_plus(0):
  167. pl, ul = self.lists_of_len()
  168. del pl[i]
  169. del ul[i]
  170. self.assertEqual(pl[:], ul[:], 'del single item [%d]' % i)
  171. def test05_out_of_range_exceptions(self):
  172. 'Out of range exceptions'
  173. def setfcn(x, i):
  174. x[i] = 20
  175. def getfcn(x, i):
  176. return x[i]
  177. def delfcn(x, i):
  178. del x[i]
  179. pl, ul = self.lists_of_len()
  180. for i in (-1 - self.limit, self.limit):
  181. self.assertRaises(IndexError, setfcn, ul, i) # 'set index %d' % i)
  182. self.assertRaises(IndexError, getfcn, ul, i) # 'get index %d' % i)
  183. self.assertRaises(IndexError, delfcn, ul, i) # 'del index %d' % i)
  184. def test06_list_methods(self):
  185. 'List methods'
  186. pl, ul = self.lists_of_len()
  187. pl.append(40)
  188. ul.append(40)
  189. self.assertEqual(pl[:], ul[:], 'append')
  190. pl.extend(range(50, 55))
  191. ul.extend(range(50, 55))
  192. self.assertEqual(pl[:], ul[:], 'extend')
  193. pl.reverse()
  194. ul.reverse()
  195. self.assertEqual(pl[:], ul[:], 'reverse')
  196. for i in self.limits_plus(1):
  197. pl, ul = self.lists_of_len()
  198. pl.insert(i, 50)
  199. ul.insert(i, 50)
  200. self.assertEqual(pl[:], ul[:], 'insert at %d' % i)
  201. for i in self.limits_plus(0):
  202. pl, ul = self.lists_of_len()
  203. self.assertEqual(pl.pop(i), ul.pop(i), 'popped value at %d' % i)
  204. self.assertEqual(pl[:], ul[:], 'after pop at %d' % i)
  205. pl, ul = self.lists_of_len()
  206. self.assertEqual(pl.pop(), ul.pop(i), 'popped value')
  207. self.assertEqual(pl[:], ul[:], 'after pop')
  208. pl, ul = self.lists_of_len()
  209. def popfcn(x, i):
  210. x.pop(i)
  211. self.assertRaises(IndexError, popfcn, ul, self.limit)
  212. self.assertRaises(IndexError, popfcn, ul, -1 - self.limit)
  213. pl, ul = self.lists_of_len()
  214. for val in range(self.limit):
  215. self.assertEqual(pl.index(val), ul.index(val), 'index of %d' % val)
  216. for val in self.limits_plus(2):
  217. self.assertEqual(pl.count(val), ul.count(val), 'count %d' % val)
  218. for val in range(self.limit):
  219. pl, ul = self.lists_of_len()
  220. pl.remove(val)
  221. ul.remove(val)
  222. self.assertEqual(pl[:], ul[:], 'after remove val %d' % val)
  223. def indexfcn(x, v):
  224. return x.index(v)
  225. def removefcn(x, v):
  226. return x.remove(v)
  227. self.assertRaises(ValueError, indexfcn, ul, 40)
  228. self.assertRaises(ValueError, removefcn, ul, 40)
  229. def test07_allowed_types(self):
  230. 'Type-restricted list'
  231. pl, ul = self.lists_of_len()
  232. ul._allowed = six.integer_types
  233. ul[1] = 50
  234. ul[:2] = [60, 70, 80]
  235. def setfcn(x, i, v):
  236. x[i] = v
  237. self.assertRaises(TypeError, setfcn, ul, 2, 'hello')
  238. self.assertRaises(TypeError, setfcn, ul, slice(0, 3, 2), ('hello', 'goodbye'))
  239. def test08_min_length(self):
  240. 'Length limits'
  241. pl, ul = self.lists_of_len()
  242. ul._minlength = 1
  243. def delfcn(x, i):
  244. del x[:i]
  245. def setfcn(x, i):
  246. x[:i] = []
  247. for i in range(self.limit - ul._minlength + 1, self.limit + 1):
  248. self.assertRaises(ValueError, delfcn, ul, i)
  249. self.assertRaises(ValueError, setfcn, ul, i)
  250. del ul[:ul._minlength]
  251. ul._maxlength = 4
  252. for i in range(0, ul._maxlength - len(ul)):
  253. ul.append(i)
  254. self.assertRaises(ValueError, ul.append, 10)
  255. def test09_iterable_check(self):
  256. 'Error on assigning non-iterable to slice'
  257. pl, ul = self.lists_of_len(self.limit + 1)
  258. def setfcn(x, i, v):
  259. x[i] = v
  260. self.assertRaises(TypeError, setfcn, ul, slice(0, 3, 2), 2)
  261. def test10_checkindex(self):
  262. 'Index check'
  263. pl, ul = self.lists_of_len()
  264. for i in self.limits_plus(0):
  265. if i < 0:
  266. self.assertEqual(ul._checkindex(i), i + self.limit, '_checkindex(neg index)')
  267. else:
  268. self.assertEqual(ul._checkindex(i), i, '_checkindex(pos index)')
  269. for i in (-self.limit - 1, self.limit):
  270. self.assertRaises(IndexError, ul._checkindex, i)
  271. ul._IndexError = TypeError
  272. self.assertRaises(TypeError, ul._checkindex, -self.limit - 1)
  273. def test_11_sorting(self):
  274. 'Sorting'
  275. pl, ul = self.lists_of_len()
  276. pl.insert(0, pl.pop())
  277. ul.insert(0, ul.pop())
  278. pl.sort()
  279. ul.sort()
  280. self.assertEqual(pl[:], ul[:], 'sort')
  281. mid = pl[len(pl) // 2]
  282. pl.sort(key=lambda x: (mid - x) ** 2)
  283. ul.sort(key=lambda x: (mid - x) ** 2)
  284. self.assertEqual(pl[:], ul[:], 'sort w/ key')
  285. pl.insert(0, pl.pop())
  286. ul.insert(0, ul.pop())
  287. pl.sort(reverse=True)
  288. ul.sort(reverse=True)
  289. self.assertEqual(pl[:], ul[:], 'sort w/ reverse')
  290. mid = pl[len(pl) // 2]
  291. pl.sort(key=lambda x: (mid - x) ** 2)
  292. ul.sort(key=lambda x: (mid - x) ** 2)
  293. self.assertEqual(pl[:], ul[:], 'sort w/ key')
  294. def test_12_arithmetic(self):
  295. 'Arithmetic'
  296. pl, ul = self.lists_of_len()
  297. al = list(range(10, 14))
  298. self.assertEqual(list(pl + al), list(ul + al), 'add')
  299. self.assertEqual(type(ul), type(ul + al), 'type of add result')
  300. self.assertEqual(list(al + pl), list(al + ul), 'radd')
  301. self.assertEqual(type(al), type(al + ul), 'type of radd result')
  302. objid = id(ul)
  303. pl += al
  304. ul += al
  305. self.assertEqual(pl[:], ul[:], 'in-place add')
  306. self.assertEqual(objid, id(ul), 'in-place add id')
  307. for n in (-1, 0, 1, 3):
  308. pl, ul = self.lists_of_len()
  309. self.assertEqual(list(pl * n), list(ul * n), 'mul by %d' % n)
  310. self.assertEqual(type(ul), type(ul * n), 'type of mul by %d result' % n)
  311. self.assertEqual(list(n * pl), list(n * ul), 'rmul by %d' % n)
  312. self.assertEqual(type(ul), type(n * ul), 'type of rmul by %d result' % n)
  313. objid = id(ul)
  314. pl *= n
  315. ul *= n
  316. self.assertEqual(pl[:], ul[:], 'in-place mul by %d' % n)
  317. self.assertEqual(objid, id(ul), 'in-place mul by %d id' % n)
  318. pl, ul = self.lists_of_len()
  319. self.assertEqual(pl, ul, 'cmp for equal')
  320. self.assertNotEqual(ul, pl + [2], 'cmp for not equal')
  321. self.assertGreaterEqual(pl, ul, 'cmp for gte self')
  322. self.assertLessEqual(pl, ul, 'cmp for lte self')
  323. self.assertGreaterEqual(ul, pl, 'cmp for self gte')
  324. self.assertLessEqual(ul, pl, 'cmp for self lte')
  325. self.assertGreater(pl + [5], ul, 'cmp')
  326. self.assertGreaterEqual(pl + [5], ul, 'cmp')
  327. self.assertLess(pl, ul + [2], 'cmp')
  328. self.assertLessEqual(pl, ul + [2], 'cmp')
  329. self.assertGreater(ul + [5], pl, 'cmp')
  330. self.assertGreaterEqual(ul + [5], pl, 'cmp')
  331. self.assertLess(ul, pl + [2], 'cmp')
  332. self.assertLessEqual(ul, pl + [2], 'cmp')
  333. # Also works with a custom IndexError
  334. ul_longer = ul + [2]
  335. ul_longer._IndexError = TypeError
  336. ul._IndexError = TypeError
  337. self.assertNotEqual(ul_longer, pl)
  338. self.assertGreater(ul_longer, ul)
  339. pl[1] = 20
  340. self.assertGreater(pl, ul, 'cmp for gt self')
  341. self.assertLess(ul, pl, 'cmp for self lt')
  342. pl[1] = -20
  343. self.assertLess(pl, ul, 'cmp for lt self')
  344. self.assertGreater(ul, pl, 'cmp for gt self')
  345. class ListMixinTestSingle(ListMixinTest):
  346. listType = UserListB