c 20082009 aryeh leib taurog http www aryehleib com modified from original contribution by aryeh leib taurog which was released under the new bsd license this would work self list self mytypeitems but then we wouldn t be testing length parameter tests base class listmixin by comparing a list clone which is a listmixin subclass with a real python list c 2008 2009 aryeh leib taurog http www aryehleib com modified from original contribution by aryeh leib taurog which was released under the new bsd license this would work self _list self _mytype items but then we wouldn t be testing length parameter tests base class listmixin by comparing a list clone which is a listmixin subclass with a real python list set index d i get index d i del index d i
import unittest

from django.contrib.gis.geos.mutable_list import ListMixin


class UserListA(ListMixin):
    _mytype = tuple

    def __init__(self, i_list, *args, **kwargs):
        self._list = self._mytype(i_list)
        super().__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):
        
        
        
        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):
    

    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 [*range(-1 - self.limit, 0), *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])
                        with self.assertRaises(ValueError):
                            setfcn(ul, i, j, k, sliceLen + 1)
                        if sliceLen > 2:
                            with 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 [*range(-Len - 1, 0), *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 [*range(-Len - 1, 0), *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 [*range(-Len - 1, 0), *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):
            with self.assertRaises(IndexError):  
                setfcn(ul, i)
            with self.assertRaises(IndexError):  
                getfcn(ul, i)
            with self.assertRaises(IndexError):  
                delfcn(ul, 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)

        with self.assertRaises(IndexError):
            popfcn(ul, self.limit)
        with 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)

        with self.assertRaises(ValueError):
            indexfcn(ul, 40)
        with self.assertRaises(ValueError):
            removefcn(ul, 40)

    def test07_allowed_types(self):
        "Type-restricted list"
        pl, ul = self.lists_of_len()
        ul._allowed = int
        ul[1] = 50
        ul[:2] = [60, 70, 80]

        def setfcn(x, i, v):
            x[i] = v

        with self.assertRaises(TypeError):
            setfcn(ul, 2, "hello")
        with self.assertRaises(TypeError):
            setfcn(ul, slice(0, 3, 2), ("hello", "goodbye"))

    def test08_min_length(self):
        "Length limits"
        pl, ul = self.lists_of_len(5)
        ul._minlength = 3

        def delfcn(x, i):
            del x[:i]

        def setfcn(x, i):
            x[:i] = []

        for i in range(len(ul) - ul._minlength + 1, len(ul)):
            with self.assertRaises(ValueError):
                delfcn(ul, i)
            with self.assertRaises(ValueError):
                setfcn(ul, i)
        del ul[: len(ul) - ul._minlength]

        ul._maxlength = 4
        for i in range(0, ul._maxlength - len(ul)):
            ul.append(i)
        with 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

        with 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):
            with self.assertRaises(IndexError):
                ul._checkindex(i)

    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")

        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