diff --git a/django/contrib/gis/geos/collections.py b/django/contrib/gis/geos/collections.py index e0a616d67ee..041c3c458f2 100644 --- a/django/contrib/gis/geos/collections.py +++ b/django/contrib/gis/geos/collections.py @@ -13,7 +13,6 @@ from django.contrib.gis.geos import prototypes as capi class GeometryCollection(GEOSGeometry): _typeid = 7 - _minlength = 0 def __init__(self, *args, **kwargs): "Initializes a Geometry Collection from a sequence of Geometry objects." @@ -77,12 +76,6 @@ class GeometryCollection(GEOSGeometry): if srid: self.srid = srid capi.destroy_geom(prev_ptr) - # Because GeometryCollections need to be rebuilt upon the changing of a - # component geometry, these routines are set to their counterparts that - # rebuild the entire geometry. - _set_single = GEOSGeometry._set_single_rebuild - _assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild - @property def kml(self): "Returns the KML for this Geometry Collection." diff --git a/django/contrib/gis/geos/geometry.py b/django/contrib/gis/geos/geometry.py index 418dc10c678..e13faa090ac 100644 --- a/django/contrib/gis/geos/geometry.py +++ b/django/contrib/gis/geos/geometry.py @@ -91,6 +91,7 @@ class GEOSGeometry(GEOSBase, ListMixin): # Post-initialization setup. self._post_init(srid) + super(GEOSGeometry, self).__init__() def _post_init(self, srid): "Helper routine for performing post-initialization setup." diff --git a/django/contrib/gis/geos/mutable_list.py b/django/contrib/gis/geos/mutable_list.py index 9ed4b5c39db..fc150d5baed 100644 --- a/django/contrib/gis/geos/mutable_list.py +++ b/django/contrib/gis/geos/mutable_list.py @@ -50,7 +50,18 @@ class ListMixin(object): _maxlength = None _IndexError = IndexError - ### Special methods for Python list interface ### + ### Python initialization and list interface methods ### + + def __init__(self, *args, **kwargs): + if not hasattr(self, '_getitem_internal'): + self._getitem_internal = self._getitem_external + + if not hasattr(self, '_set_single'): + self._set_single = self._set_single_rebuild + self._assign_extended_slice = self._assign_extended_slice_rebuild + + super(ListMixin, self).__init__(*args, **kwargs) + def __getitem__(self, index): "Gets the coordinates of the point(s) at the specified index/slice." if isinstance(index, slice): @@ -128,19 +139,6 @@ class ListMixin(object): ### Private API routines unique to ListMixin ### - def __init__(self, *args, **kwargs): - if not hasattr(self, '_getitem_internal'): - self._getitem_internal = self._getitem_external - - if hasattr(self, '_set_single'): - self._canSetSingle = True - else: - self._canSetSingle = False - self._set_single = self._set_single_rebuild - self._assign_extended_slice = self._assign_extended_slice_rebuild - - super(ListMixin, self).__init__(*args, **kwargs) - def _rebuild(self, newLen, newItems): if newLen < self._minlength: raise ValueError('Must have at least %d items' % self._minlength) diff --git a/django/contrib/gis/geos/point.py b/django/contrib/gis/geos/point.py index 6ab873fe8fd..7abe7ed5927 100644 --- a/django/contrib/gis/geos/point.py +++ b/django/contrib/gis/geos/point.py @@ -52,9 +52,6 @@ class Point(GEOSGeometry): return capi.create_point(cs) - def _getitem_external(self, index): - return self._cs.getOrdinate(index, 0) - def _set_collection(self, length, items): ptr = self._create_point(length, items) if ptr: diff --git a/django/contrib/gis/geos/polygon.py b/django/contrib/gis/geos/polygon.py index 0974822712c..345f1d7652d 100644 --- a/django/contrib/gis/geos/polygon.py +++ b/django/contrib/gis/geos/polygon.py @@ -133,12 +133,6 @@ class Polygon(GEOSGeometry): def _getitem_external(self, index): return GEOSGeometry(capi.geom_clone(self._getitem_internal(index)), srid=self.srid) - # Because Polygonss need to be rebuilt upon the changing of a - # component geometry, these routines are set to their counterparts that - # rebuild the entire geometry. - _set_single = GEOSGeometry._set_single_rebuild - _assign_extended_slice = GEOSGeometry._assign_extended_slice_rebuild - #### Polygon Properties #### @property def num_interior_rings(self): diff --git a/django/contrib/gis/geos/tests/pymutable_geometries.py b/django/contrib/gis/geos/tests/pymutable_geometries.py deleted file mode 100644 index da98766820d..00000000000 --- a/django/contrib/gis/geos/tests/pymutable_geometries.py +++ /dev/null @@ -1,184 +0,0 @@ -from django.contrib.gis.geos import * -from random import random - -SEQ_LENGTH = 10 -SEQ_RANGE = (-1 * SEQ_LENGTH, SEQ_LENGTH) -SEQ_BOUNDS = (-1 * SEQ_LENGTH, -1, 0, SEQ_LENGTH - 1) -SEQ_OUT_OF_BOUNDS = (-1 * SEQ_LENGTH -1 , SEQ_LENGTH) - -def seqrange(): return xrange(*SEQ_RANGE) - -def random_coord(dim = 2, # coordinate dimensions - rng = (-50,50), # coordinate range - num_type = float, - round_coords = True): - - if round_coords: - num = lambda: num_type(round(random() * (rng[1]-rng[0]) + rng[0])) - else: - num = lambda: num_type(random() * (rng[1]-rng[0]) + rng[0]) - - return tuple( num() for axis in xrange(dim) ) - -def random_list(length = SEQ_LENGTH, ring = False, **kwargs): - result = [ random_coord(**kwargs) for index in xrange(length) ] - if ring: - result[-1] = result[0] - - return result - -random_list.single = random_coord - -def random_coll(count = SEQ_LENGTH, **kwargs): - return [ tuple(random_list(**kwargs)) for i in xrange(count) ] - -random_coll.single = random_list - -class PyMutTestGeom: - "The Test Geometry class container." - def __init__(self, geom_type, coords_fcn=random_list, subtype=tuple, **kwargs): - self.geom_type = geom_type - self.subtype = subtype - self.coords_fcn = coords_fcn - self.fcn_args = kwargs - self.coords = self.coords_fcn(**kwargs) - self.geom = self.make_geom() - - def newitem(self, **kwargs): - a = self.coords_fcn.single(**kwargs) - return self.subtype(a), tuple(a) - - @property - def tuple_coords(self): - return tuple(self.coords) - - def make_geom(self): - return self.geom_type(map(self.subtype,self.coords)) - - -def slice_geometries(ring=True): - testgeoms = [ - PyMutTestGeom(LineString), - PyMutTestGeom(MultiPoint, subtype=Point), - PyMutTestGeom(MultiLineString, coords_fcn=random_coll, subtype=LineString), - ] - if ring: - testgeoms.append(PyMutTestGeom(LinearRing, ring=True)) - - return testgeoms - -def getslice_functions(): - def gs_01(x): x[0:4], - def gs_02(x): x[5:-1], - def gs_03(x): x[6:2:-1], - def gs_04(x): x[:], - def gs_05(x): x[:3], - def gs_06(x): x[::2], - def gs_07(x): x[::-4], - def gs_08(x): x[7:7], - def gs_09(x): x[20:], - - # don't really care about ringy-ness here - return mark_ring(vars(), 'gs_') - -def delslice_functions(): - def ds_01(x): del x[0:4] - def ds_02(x): del x[5:-1] - def ds_03(x): del x[6:2:-1] - def ds_04(x): del x[:] # should this be allowed? - def ds_05(x): del x[:3] - def ds_06(x): del x[1:9:2] - def ds_07(x): del x[::-4] - def ds_08(x): del x[7:7] - def ds_09(x): del x[-7:-2] - - return mark_ring(vars(), 'ds_') - -def setslice_extended_functions(g): - a = g.coords_fcn(3, rng=(100,150)) - def maptype(x,a): - if isinstance(x, list): return a - else: return map(g.subtype, a) - - def sse_00(x): x[:3:1] = maptype(x, a) - def sse_01(x): x[0:3:1] = maptype(x, a) - def sse_02(x): x[2:5:1] = maptype(x, a) - def sse_03(x): x[-3::1] = maptype(x, a) - def sse_04(x): x[-4:-1:1] = maptype(x, a) - def sse_05(x): x[8:5:-1] = maptype(x, a) - def sse_06(x): x[-6:-9:-1] = maptype(x, a) - def sse_07(x): x[:8:3] = maptype(x, a) - def sse_08(x): x[1::3] = maptype(x, a) - def sse_09(x): x[-2::-3] = maptype(x, a) - def sse_10(x): x[7:1:-2] = maptype(x, a) - def sse_11(x): x[2:8:2] = maptype(x, a) - - return mark_ring(vars(), 'sse_') - -def setslice_simple_functions(g): - a = g.coords_fcn(3, rng=(100,150)) - def maptype(x,a): - if isinstance(x, list): return a - else: return map(g.subtype, a) - - def ss_00(x): x[:0] = maptype(x, a) - def ss_01(x): x[:1] = maptype(x, a) - def ss_02(x): x[:2] = maptype(x, a) - def ss_03(x): x[:3] = maptype(x, a) - def ss_04(x): x[-4:] = maptype(x, a) - def ss_05(x): x[-3:] = maptype(x, a) - def ss_06(x): x[-2:] = maptype(x, a) - def ss_07(x): x[-1:] = maptype(x, a) - def ss_08(x): x[5:] = maptype(x, a) - def ss_09(x): x[:] = maptype(x, a) - def ss_10(x): x[4:4] = maptype(x, a) - def ss_11(x): x[4:5] = maptype(x, a) - def ss_12(x): x[4:7] = maptype(x, a) - def ss_13(x): x[4:8] = maptype(x, a) - def ss_14(x): x[10:] = maptype(x, a) - def ss_15(x): x[20:30] = maptype(x, a) - def ss_16(x): x[-13:-8] = maptype(x, a) - def ss_17(x): x[-13:-9] = maptype(x, a) - def ss_18(x): x[-13:-10] = maptype(x, a) - def ss_19(x): x[-13:-11] = maptype(x, a) - - return mark_ring(vars(), 'ss_') - -def test_geos_functions(): - - return ( - lambda x: x.num_coords, - lambda x: x.empty, - lambda x: x.valid, - lambda x: x.simple, - lambda x: x.ring, - lambda x: x.boundary, - lambda x: x.convex_hull, - lambda x: x.extend, - lambda x: x.area, - lambda x: x.length, - ) - -def mark_ring(locals, name_pat, length=SEQ_LENGTH): - ''' - Accepts an array of functions which perform slice modifications - and labels each function as to whether or not it preserves ring-ness - ''' - func_array = [ val for name, val in locals.items() - if hasattr(val, '__call__') - and name.startswith(name_pat) ] - - for i in xrange(len(func_array)): - a = range(length) - a[-1] = a[0] - func_array[i](a) - ring = len(a) == 0 or (len(a) > 3 and a[-1] == a[0]) - func_array[i].ring = ring - - return func_array - -def getcoords(o): - if hasattr(o, 'coords'): - return o.coords - else: - return o diff --git a/django/contrib/gis/geos/tests/test_mutable_list.py b/django/contrib/gis/geos/tests/test_mutable_list.py index d4d70758c51..34b3a4c200e 100644 --- a/django/contrib/gis/geos/tests/test_mutable_list.py +++ b/django/contrib/gis/geos/tests/test_mutable_list.py @@ -1,329 +1,329 @@ -# Copyright (c) 2008-2009 Aryeh Leib Taurog, 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 - -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 __iter__(self): return iter(self._list) - - def __str__(self): return str(self._list) - - def __repr__(self): return repr(self._list) - - def _set_collection(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 _getitem_external(self, index): - return self._list[index] - - _getitem_internal = _getitem_external - _set_single = ListMixin._set_single_rebuild - _assign_extended_slice = ListMixin._assign_extended_slice_rebuild - -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 - - @classmethod - def lists_of_len(cls, length=None): - if length is None: length = cls.limit - pl = range(length) - return pl, cls.listType(pl) - - @classmethod - def limits_plus(cls, b): - return range(-cls.limit - b, cls.limit + b) - - @classmethod - def step_range(cls): - return range(-1 - cls.limit, 0) + range(1, 1 + cls.limit) - - def test01_getslice(self): - 'Testing 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): - 'Testing 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): - 'Testing 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): - 'Testing 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): - 'Testing 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): - 'Testing 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') - - 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): - 'Testing type-restricted list' - pl, ul = self.lists_of_len() - ul._allowed = (int, long) - 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): - 'Testing 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): - 'Testing 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): - 'Testing 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) - -class ListMixinTestSingle(ListMixinTest): - listType = UserListB - -def suite(): - s = unittest.TestSuite() - s.addTest(unittest.makeSuite(ListMixinTest)) - s.addTest(unittest.makeSuite(ListMixinTestSingle)) - return s - -def run(verbosity=2): - unittest.TextTestRunner(verbosity=verbosity).run(suite()) - -if __name__ == '__main__': - run() +# Copyright (c) 2008-2009 Aryeh Leib Taurog, 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 + +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 __iter__(self): return iter(self._list) + + def __str__(self): return str(self._list) + + def __repr__(self): return repr(self._list) + + def _set_collection(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 _getitem_external(self, index): + return self._list[index] + + _getitem_internal = _getitem_external + _set_single = ListMixin._set_single_rebuild + _assign_extended_slice = ListMixin._assign_extended_slice_rebuild + +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 + + @classmethod + def lists_of_len(cls, length=None): + if length is None: length = cls.limit + pl = range(length) + return pl, cls.listType(pl) + + @classmethod + def limits_plus(cls, b): + return range(-cls.limit - b, cls.limit + b) + + @classmethod + def step_range(cls): + return range(-1 - cls.limit, 0) + range(1, 1 + cls.limit) + + def test01_getslice(self): + 'Testing 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): + 'Testing 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): + 'Testing 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): + 'Testing 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): + 'Testing 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): + 'Testing 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') + + 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): + 'Testing type-restricted list' + pl, ul = self.lists_of_len() + ul._allowed = (int, long) + 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): + 'Testing 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): + 'Testing 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): + 'Testing 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) + +class ListMixinTestSingle(ListMixinTest): + listType = UserListB + +def suite(): + s = unittest.TestSuite() + s.addTest(unittest.makeSuite(ListMixinTest)) + s.addTest(unittest.makeSuite(ListMixinTestSingle)) + return s + +def run(verbosity=2): + unittest.TextTestRunner(verbosity=verbosity).run(suite()) + +if __name__ == '__main__': + run()