test_mutable_list.py 14 KB

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