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