123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425 |
- # Copyright (c) 2008-2009 Aryeh Leib Taurog, http://www.aryehleib.com
- # All rights reserved.
- #
- # Modified from original contribution by Aryeh Leib Taurog, which was
- # released under the New BSD license.
- import unittest
- from django.contrib.gis.geos.mutable_list import ListMixin
- from django.utils import six
- class UserListA(ListMixin):
- _mytype = tuple
- def __init__(self, i_list, *args, **kwargs):
- self._list = self._mytype(i_list)
- super(UserListA, self).__init__(*args, **kwargs)
- def __len__(self):
- return len(self._list)
- def __str__(self):
- return str(self._list)
- def __repr__(self):
- return repr(self._list)
- def _set_list(self, length, items):
- # this would work:
- # self._list = self._mytype(items)
- # but then we wouldn't be testing length parameter
- itemList = ['x'] * length
- for i, v in enumerate(items):
- itemList[i] = v
- self._list = self._mytype(itemList)
- def _get_single_external(self, index):
- return self._list[index]
- class UserListB(UserListA):
- _mytype = list
- def _set_single(self, index, value):
- self._list[index] = value
- def nextRange(length):
- nextRange.start += 100
- return range(nextRange.start, nextRange.start + length)
- nextRange.start = 0
- class ListMixinTest(unittest.TestCase):
- """
- Tests base class ListMixin by comparing a list clone which is
- a ListMixin subclass with a real Python list.
- """
- limit = 3
- listType = UserListA
- def lists_of_len(self, length=None):
- if length is None:
- length = self.limit
- pl = list(range(length))
- return pl, self.listType(pl)
- def limits_plus(self, b):
- return range(-self.limit - b, self.limit + b)
- def step_range(self):
- return list(range(-1 - self.limit, 0)) + list(range(1, 1 + self.limit))
- def test01_getslice(self):
- 'Slice retrieval'
- pl, ul = self.lists_of_len()
- for i in self.limits_plus(1):
- self.assertEqual(pl[i:], ul[i:], 'slice [%d:]' % (i))
- self.assertEqual(pl[:i], ul[:i], 'slice [:%d]' % (i))
- for j in self.limits_plus(1):
- self.assertEqual(pl[i:j], ul[i:j], 'slice [%d:%d]' % (i, j))
- for k in self.step_range():
- self.assertEqual(pl[i:j:k], ul[i:j:k], 'slice [%d:%d:%d]' % (i, j, k))
- for k in self.step_range():
- self.assertEqual(pl[i::k], ul[i::k], 'slice [%d::%d]' % (i, k))
- self.assertEqual(pl[:i:k], ul[:i:k], 'slice [:%d:%d]' % (i, k))
- for k in self.step_range():
- self.assertEqual(pl[::k], ul[::k], 'slice [::%d]' % (k))
- def test02_setslice(self):
- 'Slice assignment'
- def setfcn(x, i, j, k, L):
- x[i:j:k] = range(L)
- pl, ul = self.lists_of_len()
- for slen in range(self.limit + 1):
- ssl = nextRange(slen)
- ul[:] = ssl
- pl[:] = ssl
- self.assertEqual(pl, ul[:], 'set slice [:]')
- for i in self.limits_plus(1):
- ssl = nextRange(slen)
- ul[i:] = ssl
- pl[i:] = ssl
- self.assertEqual(pl, ul[:], 'set slice [%d:]' % (i))
- ssl = nextRange(slen)
- ul[:i] = ssl
- pl[:i] = ssl
- self.assertEqual(pl, ul[:], 'set slice [:%d]' % (i))
- for j in self.limits_plus(1):
- ssl = nextRange(slen)
- ul[i:j] = ssl
- pl[i:j] = ssl
- self.assertEqual(pl, ul[:], 'set slice [%d:%d]' % (i, j))
- for k in self.step_range():
- ssl = nextRange(len(ul[i:j:k]))
- ul[i:j:k] = ssl
- pl[i:j:k] = ssl
- self.assertEqual(pl, ul[:], 'set slice [%d:%d:%d]' % (i, j, k))
- sliceLen = len(ul[i:j:k])
- self.assertRaises(ValueError, setfcn, ul, i, j, k, sliceLen + 1)
- if sliceLen > 2:
- self.assertRaises(ValueError, setfcn, ul, i, j, k, sliceLen - 1)
- for k in self.step_range():
- ssl = nextRange(len(ul[i::k]))
- ul[i::k] = ssl
- pl[i::k] = ssl
- self.assertEqual(pl, ul[:], 'set slice [%d::%d]' % (i, k))
- ssl = nextRange(len(ul[:i:k]))
- ul[:i:k] = ssl
- pl[:i:k] = ssl
- self.assertEqual(pl, ul[:], 'set slice [:%d:%d]' % (i, k))
- for k in self.step_range():
- ssl = nextRange(len(ul[::k]))
- ul[::k] = ssl
- pl[::k] = ssl
- self.assertEqual(pl, ul[:], 'set slice [::%d]' % (k))
- def test03_delslice(self):
- 'Delete slice'
- for Len in range(self.limit):
- pl, ul = self.lists_of_len(Len)
- del pl[:]
- del ul[:]
- self.assertEqual(pl[:], ul[:], 'del slice [:]')
- for i in range(-Len - 1, Len + 1):
- pl, ul = self.lists_of_len(Len)
- del pl[i:]
- del ul[i:]
- self.assertEqual(pl[:], ul[:], 'del slice [%d:]' % (i))
- pl, ul = self.lists_of_len(Len)
- del pl[:i]
- del ul[:i]
- self.assertEqual(pl[:], ul[:], 'del slice [:%d]' % (i))
- for j in range(-Len - 1, Len + 1):
- pl, ul = self.lists_of_len(Len)
- del pl[i:j]
- del ul[i:j]
- self.assertEqual(pl[:], ul[:], 'del slice [%d:%d]' % (i, j))
- for k in list(range(-Len - 1, 0)) + list(range(1, Len)):
- pl, ul = self.lists_of_len(Len)
- del pl[i:j:k]
- del ul[i:j:k]
- self.assertEqual(pl[:], ul[:], 'del slice [%d:%d:%d]' % (i, j, k))
- for k in list(range(-Len - 1, 0)) + list(range(1, Len)):
- pl, ul = self.lists_of_len(Len)
- del pl[:i:k]
- del ul[:i:k]
- self.assertEqual(pl[:], ul[:], 'del slice [:%d:%d]' % (i, k))
- pl, ul = self.lists_of_len(Len)
- del pl[i::k]
- del ul[i::k]
- self.assertEqual(pl[:], ul[:], 'del slice [%d::%d]' % (i, k))
- for k in list(range(-Len - 1, 0)) + list(range(1, Len)):
- pl, ul = self.lists_of_len(Len)
- del pl[::k]
- del ul[::k]
- self.assertEqual(pl[:], ul[:], 'del slice [::%d]' % (k))
- def test04_get_set_del_single(self):
- 'Get/set/delete single item'
- pl, ul = self.lists_of_len()
- for i in self.limits_plus(0):
- self.assertEqual(pl[i], ul[i], 'get single item [%d]' % i)
- for i in self.limits_plus(0):
- pl, ul = self.lists_of_len()
- pl[i] = 100
- ul[i] = 100
- self.assertEqual(pl[:], ul[:], 'set single item [%d]' % i)
- for i in self.limits_plus(0):
- pl, ul = self.lists_of_len()
- del pl[i]
- del ul[i]
- self.assertEqual(pl[:], ul[:], 'del single item [%d]' % i)
- def test05_out_of_range_exceptions(self):
- 'Out of range exceptions'
- def setfcn(x, i):
- x[i] = 20
- def getfcn(x, i):
- return x[i]
- def delfcn(x, i):
- del x[i]
- pl, ul = self.lists_of_len()
- for i in (-1 - self.limit, self.limit):
- self.assertRaises(IndexError, setfcn, ul, i) # 'set index %d' % i)
- self.assertRaises(IndexError, getfcn, ul, i) # 'get index %d' % i)
- self.assertRaises(IndexError, delfcn, ul, i) # 'del index %d' % i)
- def test06_list_methods(self):
- 'List methods'
- pl, ul = self.lists_of_len()
- pl.append(40)
- ul.append(40)
- self.assertEqual(pl[:], ul[:], 'append')
- pl.extend(range(50, 55))
- ul.extend(range(50, 55))
- self.assertEqual(pl[:], ul[:], 'extend')
- pl.reverse()
- ul.reverse()
- self.assertEqual(pl[:], ul[:], 'reverse')
- for i in self.limits_plus(1):
- pl, ul = self.lists_of_len()
- pl.insert(i, 50)
- ul.insert(i, 50)
- self.assertEqual(pl[:], ul[:], 'insert at %d' % i)
- for i in self.limits_plus(0):
- pl, ul = self.lists_of_len()
- self.assertEqual(pl.pop(i), ul.pop(i), 'popped value at %d' % i)
- self.assertEqual(pl[:], ul[:], 'after pop at %d' % i)
- pl, ul = self.lists_of_len()
- self.assertEqual(pl.pop(), ul.pop(i), 'popped value')
- self.assertEqual(pl[:], ul[:], 'after pop')
- pl, ul = self.lists_of_len()
- def popfcn(x, i):
- x.pop(i)
- self.assertRaises(IndexError, popfcn, ul, self.limit)
- self.assertRaises(IndexError, popfcn, ul, -1 - self.limit)
- pl, ul = self.lists_of_len()
- for val in range(self.limit):
- self.assertEqual(pl.index(val), ul.index(val), 'index of %d' % val)
- for val in self.limits_plus(2):
- self.assertEqual(pl.count(val), ul.count(val), 'count %d' % val)
- for val in range(self.limit):
- pl, ul = self.lists_of_len()
- pl.remove(val)
- ul.remove(val)
- self.assertEqual(pl[:], ul[:], 'after remove val %d' % val)
- def indexfcn(x, v):
- return x.index(v)
- def removefcn(x, v):
- return x.remove(v)
- self.assertRaises(ValueError, indexfcn, ul, 40)
- self.assertRaises(ValueError, removefcn, ul, 40)
- def test07_allowed_types(self):
- 'Type-restricted list'
- pl, ul = self.lists_of_len()
- ul._allowed = six.integer_types
- ul[1] = 50
- ul[:2] = [60, 70, 80]
- def setfcn(x, i, v):
- x[i] = v
- self.assertRaises(TypeError, setfcn, ul, 2, 'hello')
- self.assertRaises(TypeError, setfcn, ul, slice(0, 3, 2), ('hello', 'goodbye'))
- def test08_min_length(self):
- 'Length limits'
- pl, ul = self.lists_of_len()
- ul._minlength = 1
- def delfcn(x, i):
- del x[:i]
- def setfcn(x, i):
- x[:i] = []
- for i in range(self.limit - ul._minlength + 1, self.limit + 1):
- self.assertRaises(ValueError, delfcn, ul, i)
- self.assertRaises(ValueError, setfcn, ul, i)
- del ul[:ul._minlength]
- ul._maxlength = 4
- for i in range(0, ul._maxlength - len(ul)):
- ul.append(i)
- self.assertRaises(ValueError, ul.append, 10)
- def test09_iterable_check(self):
- 'Error on assigning non-iterable to slice'
- pl, ul = self.lists_of_len(self.limit + 1)
- def setfcn(x, i, v):
- x[i] = v
- self.assertRaises(TypeError, setfcn, ul, slice(0, 3, 2), 2)
- def test10_checkindex(self):
- 'Index check'
- pl, ul = self.lists_of_len()
- for i in self.limits_plus(0):
- if i < 0:
- self.assertEqual(ul._checkindex(i), i + self.limit, '_checkindex(neg index)')
- else:
- self.assertEqual(ul._checkindex(i), i, '_checkindex(pos index)')
- for i in (-self.limit - 1, self.limit):
- self.assertRaises(IndexError, ul._checkindex, i)
- ul._IndexError = TypeError
- self.assertRaises(TypeError, ul._checkindex, -self.limit - 1)
- def test_11_sorting(self):
- 'Sorting'
- pl, ul = self.lists_of_len()
- pl.insert(0, pl.pop())
- ul.insert(0, ul.pop())
- pl.sort()
- ul.sort()
- self.assertEqual(pl[:], ul[:], 'sort')
- mid = pl[len(pl) // 2]
- pl.sort(key=lambda x: (mid - x) ** 2)
- ul.sort(key=lambda x: (mid - x) ** 2)
- self.assertEqual(pl[:], ul[:], 'sort w/ key')
- pl.insert(0, pl.pop())
- ul.insert(0, ul.pop())
- pl.sort(reverse=True)
- ul.sort(reverse=True)
- self.assertEqual(pl[:], ul[:], 'sort w/ reverse')
- mid = pl[len(pl) // 2]
- pl.sort(key=lambda x: (mid - x) ** 2)
- ul.sort(key=lambda x: (mid - x) ** 2)
- self.assertEqual(pl[:], ul[:], 'sort w/ key')
- def test_12_arithmetic(self):
- 'Arithmetic'
- pl, ul = self.lists_of_len()
- al = list(range(10, 14))
- self.assertEqual(list(pl + al), list(ul + al), 'add')
- self.assertEqual(type(ul), type(ul + al), 'type of add result')
- self.assertEqual(list(al + pl), list(al + ul), 'radd')
- self.assertEqual(type(al), type(al + ul), 'type of radd result')
- objid = id(ul)
- pl += al
- ul += al
- self.assertEqual(pl[:], ul[:], 'in-place add')
- self.assertEqual(objid, id(ul), 'in-place add id')
- for n in (-1, 0, 1, 3):
- pl, ul = self.lists_of_len()
- self.assertEqual(list(pl * n), list(ul * n), 'mul by %d' % n)
- self.assertEqual(type(ul), type(ul * n), 'type of mul by %d result' % n)
- self.assertEqual(list(n * pl), list(n * ul), 'rmul by %d' % n)
- self.assertEqual(type(ul), type(n * ul), 'type of rmul by %d result' % n)
- objid = id(ul)
- pl *= n
- ul *= n
- self.assertEqual(pl[:], ul[:], 'in-place mul by %d' % n)
- self.assertEqual(objid, id(ul), 'in-place mul by %d id' % n)
- pl, ul = self.lists_of_len()
- self.assertEqual(pl, ul, 'cmp for equal')
- self.assertNotEqual(ul, pl + [2], 'cmp for not equal')
- self.assertGreaterEqual(pl, ul, 'cmp for gte self')
- self.assertLessEqual(pl, ul, 'cmp for lte self')
- self.assertGreaterEqual(ul, pl, 'cmp for self gte')
- self.assertLessEqual(ul, pl, 'cmp for self lte')
- self.assertGreater(pl + [5], ul, 'cmp')
- self.assertGreaterEqual(pl + [5], ul, 'cmp')
- self.assertLess(pl, ul + [2], 'cmp')
- self.assertLessEqual(pl, ul + [2], 'cmp')
- self.assertGreater(ul + [5], pl, 'cmp')
- self.assertGreaterEqual(ul + [5], pl, 'cmp')
- self.assertLess(ul, pl + [2], 'cmp')
- self.assertLessEqual(ul, pl + [2], 'cmp')
- # Also works with a custom IndexError
- ul_longer = ul + [2]
- ul_longer._IndexError = TypeError
- ul._IndexError = TypeError
- self.assertNotEqual(ul_longer, pl)
- self.assertGreater(ul_longer, ul)
- pl[1] = 20
- self.assertGreater(pl, ul, 'cmp for gt self')
- self.assertLess(ul, pl, 'cmp for self lt')
- pl[1] = -20
- self.assertLess(pl, ul, 'cmp for lt self')
- self.assertGreater(ul, pl, 'cmp for gt self')
- class ListMixinTestSingle(ListMixinTest):
- listType = UserListB
|