mirror of
				https://github.com/python/cpython.git
				synced 2025-10-30 21:21:22 +00:00 
			
		
		
		
	Minor bugs in the __index__ code (PEP 357), with tests.
This commit is contained in:
		
							parent
							
								
									4ef3a23a35
								
							
						
					
					
						commit
						314861c568
					
				
					 3 changed files with 100 additions and 132 deletions
				
			
		|  | @ -10,82 +10,13 @@ class newstyle(object): | |||
|     def __index__(self): | ||||
|         return self.ind | ||||
| 
 | ||||
| class ListTestCase(unittest.TestCase): | ||||
| class BaseTestCase(unittest.TestCase): | ||||
|     def setUp(self): | ||||
|         self.seq = [0,10,20,30,40,50] | ||||
|         self.o = oldstyle() | ||||
|         self.n = newstyle() | ||||
|         self.o2 = oldstyle() | ||||
|         self.n2 = newstyle() | ||||
| 
 | ||||
|     def test_basic(self): | ||||
|         self.o.ind = -2 | ||||
|         self.n.ind = 2 | ||||
|         assert(self.seq[self.n] == 20) | ||||
|         assert(self.seq[self.o] == 40) | ||||
|         assert(operator.index(self.o) == -2) | ||||
|         assert(operator.index(self.n) == 2) | ||||
| 
 | ||||
|     def test_error(self): | ||||
|         self.o.ind = 'dumb' | ||||
|         self.n.ind = 'bad' | ||||
|         myfunc = lambda x, obj: obj.seq[x] | ||||
|         self.failUnlessRaises(TypeError, operator.index, self.o) | ||||
|         self.failUnlessRaises(TypeError, operator.index, self.n) | ||||
|         self.failUnlessRaises(TypeError, myfunc, self.o, self) | ||||
|         self.failUnlessRaises(TypeError, myfunc, self.n, self) | ||||
| 
 | ||||
|     def test_slice(self): | ||||
|         self.o.ind = 1 | ||||
|         self.o2.ind = 3 | ||||
|         self.n.ind = 2 | ||||
|         self.n2.ind = 4 | ||||
|         assert(self.seq[self.o:self.o2] == self.seq[1:3]) | ||||
|         assert(self.seq[self.n:self.n2] == self.seq[2:4]) | ||||
| 
 | ||||
| class TupleTestCase(unittest.TestCase): | ||||
|     def setUp(self): | ||||
|         self.seq = (0,10,20,30,40,50) | ||||
|         self.o = oldstyle() | ||||
|         self.n = newstyle() | ||||
|         self.o2 = oldstyle() | ||||
|         self.n2 = newstyle() | ||||
| 
 | ||||
| 
 | ||||
|     def test_basic(self): | ||||
|         self.o.ind = -2 | ||||
|         self.n.ind = 2 | ||||
|         assert(self.seq[self.n] == 20) | ||||
|         assert(self.seq[self.o] == 40) | ||||
|         assert(operator.index(self.o) == -2) | ||||
|         assert(operator.index(self.n) == 2) | ||||
| 
 | ||||
|     def test_error(self): | ||||
|         self.o.ind = 'dumb' | ||||
|         self.n.ind = 'bad' | ||||
|         myfunc = lambda x, obj: obj.seq[x] | ||||
|         self.failUnlessRaises(TypeError, operator.index, self.o) | ||||
|         self.failUnlessRaises(TypeError, operator.index, self.n) | ||||
|         self.failUnlessRaises(TypeError, myfunc, self.o, self) | ||||
|         self.failUnlessRaises(TypeError, myfunc, self.n, self) | ||||
| 
 | ||||
|     def test_slice(self): | ||||
|         self.o.ind = 1 | ||||
|         self.o2.ind = 3 | ||||
|         self.n.ind = 2 | ||||
|         self.n2.ind = 4 | ||||
|         assert(self.seq[self.o:self.o2] == self.seq[1:3]) | ||||
|         assert(self.seq[self.n:self.n2] == self.seq[2:4]) | ||||
| 
 | ||||
| class StringTestCase(unittest.TestCase): | ||||
|     def setUp(self): | ||||
|         self.seq = "this is a test" | ||||
|         self.o = oldstyle() | ||||
|         self.n = newstyle() | ||||
|         self.o2 = oldstyle() | ||||
|         self.n2 = newstyle() | ||||
| 
 | ||||
| 
 | ||||
|     def test_basic(self): | ||||
|         self.o.ind = -2 | ||||
|         self.n.ind = 2 | ||||
|  | @ -111,40 +42,86 @@ def test_slice(self): | |||
|         assert(self.seq[self.o:self.o2] == self.seq[1:3]) | ||||
|         assert(self.seq[self.n:self.n2] == self.seq[2:4]) | ||||
| 
 | ||||
|     def test_repeat(self): | ||||
|         self.o.ind = 3 | ||||
|         self.n.ind = 2 | ||||
|         assert(self.seq * self.o == self.seq * 3) | ||||
|         assert(self.seq * self.n == self.seq * 2) | ||||
|         assert(self.o * self.seq == self.seq * 3) | ||||
|         assert(self.n * self.seq == self.seq * 2) | ||||
| 
 | ||||
| class UnicodeTestCase(unittest.TestCase): | ||||
|     def setUp(self): | ||||
|         self.seq = u"this is a test" | ||||
|         self.o = oldstyle() | ||||
|         self.n = newstyle() | ||||
|         self.o2 = oldstyle() | ||||
|         self.n2 = newstyle() | ||||
|     def test_wrappers(self): | ||||
|         n = self.n | ||||
|         n.ind = 5 | ||||
|         assert n.__index__() == 5 | ||||
|         assert 6 .__index__() == 6 | ||||
|         assert -7L.__index__() == -7 | ||||
|         assert self.seq.__getitem__(n) == self.seq[5] | ||||
|         assert self.seq.__mul__(n) == self.seq * 5 | ||||
|         assert self.seq.__rmul__(n) == self.seq * 5 | ||||
| 
 | ||||
|     def test_infinite_recusion(self): | ||||
|         class Trap1(int): | ||||
|             def __index__(self): | ||||
|                 return self | ||||
|         class Trap2(long): | ||||
|             def __index__(self): | ||||
|                 return self | ||||
|         self.failUnlessRaises(TypeError, operator.getitem, self.seq, Trap1()) | ||||
|         self.failUnlessRaises(TypeError, operator.getitem, self.seq, Trap2()) | ||||
| 
 | ||||
| 
 | ||||
|     def test_basic(self): | ||||
| class ListTestCase(BaseTestCase): | ||||
|     seq = [0,10,20,30,40,50] | ||||
| 
 | ||||
|     def test_setdelitem(self): | ||||
|         self.o.ind = -2 | ||||
|         self.n.ind = 2 | ||||
|         assert(self.seq[self.n] == self.seq[2]) | ||||
|         assert(self.seq[self.o] == self.seq[-2]) | ||||
|         assert(operator.index(self.o) == -2) | ||||
|         assert(operator.index(self.n) == 2) | ||||
|         lst = list('ab!cdefghi!j') | ||||
|         del lst[self.o] | ||||
|         del lst[self.n] | ||||
|         lst[self.o] = 'X' | ||||
|         lst[self.n] = 'Y' | ||||
|         assert lst == list('abYdefghXj') | ||||
| 
 | ||||
|     def test_error(self): | ||||
|         self.o.ind = 'dumb' | ||||
|         self.n.ind = 'bad' | ||||
|         myfunc = lambda x, obj: obj.seq[x] | ||||
|         self.failUnlessRaises(TypeError, operator.index, self.o) | ||||
|         self.failUnlessRaises(TypeError, operator.index, self.n) | ||||
|         self.failUnlessRaises(TypeError, myfunc, self.o, self) | ||||
|         self.failUnlessRaises(TypeError, myfunc, self.n, self) | ||||
|         lst = [5, 6, 7, 8, 9, 10, 11] | ||||
|         lst.__setitem__(self.n, "here") | ||||
|         assert lst == [5, 6, "here", 8, 9, 10, 11] | ||||
|         lst.__delitem__(self.n) | ||||
|         assert lst == [5, 6, 8, 9, 10, 11] | ||||
| 
 | ||||
|     def test_slice(self): | ||||
|         self.o.ind = 1 | ||||
|         self.o2.ind = 3 | ||||
|         self.n.ind = 2 | ||||
|         self.n2.ind = 4 | ||||
|         assert(self.seq[self.o:self.o2] == self.seq[1:3]) | ||||
|         assert(self.seq[self.n:self.n2] == self.seq[2:4]) | ||||
|     def test_inplace_repeat(self): | ||||
|         self.o.ind = 2 | ||||
|         self.n.ind = 3 | ||||
|         lst = [6, 4] | ||||
|         lst *= self.o | ||||
|         assert lst == [6, 4, 6, 4] | ||||
|         lst *= self.n | ||||
|         assert lst == [6, 4, 6, 4] * 3 | ||||
| 
 | ||||
|         lst = [5, 6, 7, 8, 9, 11] | ||||
|         l2 = lst.__imul__(self.n) | ||||
|         assert l2 is lst | ||||
|         assert lst == [5, 6, 7, 8, 9, 11] * 3 | ||||
| 
 | ||||
| 
 | ||||
| class TupleTestCase(BaseTestCase): | ||||
|     seq = (0,10,20,30,40,50) | ||||
| 
 | ||||
| class StringTestCase(BaseTestCase): | ||||
|     seq = "this is a test" | ||||
| 
 | ||||
| class UnicodeTestCase(BaseTestCase): | ||||
|     seq = u"this is a test" | ||||
| 
 | ||||
| 
 | ||||
| class XRangeTestCase(unittest.TestCase): | ||||
| 
 | ||||
|     def test_xrange(self): | ||||
|         n = newstyle() | ||||
|         n.ind = 5 | ||||
|         assert xrange(1, 20)[n] == 6 | ||||
|         assert xrange(1, 20).__getitem__(n) == 6 | ||||
| 
 | ||||
| 
 | ||||
| def test_main(): | ||||
|  | @ -152,7 +129,8 @@ def test_main(): | |||
|         ListTestCase, | ||||
|         TupleTestCase, | ||||
|         StringTestCase, | ||||
|         UnicodeTestCase | ||||
|         UnicodeTestCase, | ||||
|         XRangeTestCase, | ||||
|     ) | ||||
| 
 | ||||
| if __name__ == "__main__": | ||||
|  |  | |||
|  | @ -942,8 +942,9 @@ PyNumber_Index(PyObject *item) | |||
| 		value = nb->nb_index(item); | ||||
| 	} | ||||
| 	else { | ||||
| 		PyErr_SetString(PyExc_IndexError,  | ||||
| 				"object cannot be interpreted as an index"); | ||||
| 		PyErr_Format(PyExc_TypeError, | ||||
| 			     "'%.200s' object cannot be interpreted " | ||||
| 			     "as an index", item->ob_type->tp_name); | ||||
| 	} | ||||
| 	return value; | ||||
| } | ||||
|  |  | |||
|  | @ -3542,12 +3542,16 @@ wrap_unaryfunc(PyObject *self, PyObject *args, void *wrapped) | |||
| } | ||||
| 
 | ||||
| static PyObject * | ||||
| wrap_ssizeargfunc(PyObject *self, PyObject *args, void *wrapped) | ||||
| wrap_indexargfunc(PyObject *self, PyObject *args, void *wrapped) | ||||
| { | ||||
| 	ssizeargfunc func = (ssizeargfunc)wrapped; | ||||
| 	PyObject* o; | ||||
| 	Py_ssize_t i; | ||||
| 
 | ||||
| 	if (!PyArg_ParseTuple(args, "n", &i)) | ||||
| 	if (!PyArg_UnpackTuple(args, "", 1, 1, &o)) | ||||
| 		return NULL; | ||||
| 	i = PyNumber_Index(o); | ||||
| 	if (i == -1 && PyErr_Occurred()) | ||||
| 		return NULL; | ||||
| 	return (*func)(self, i); | ||||
| } | ||||
|  | @ -3557,7 +3561,7 @@ getindex(PyObject *self, PyObject *arg) | |||
| { | ||||
| 	Py_ssize_t i; | ||||
| 
 | ||||
| 	i = PyInt_AsSsize_t(arg); | ||||
| 	i = PyNumber_Index(arg); | ||||
| 	if (i == -1 && PyErr_Occurred()) | ||||
| 		return -1; | ||||
| 	if (i < 0) { | ||||
|  | @ -4366,26 +4370,14 @@ slot_nb_nonzero(PyObject *self) | |||
| static Py_ssize_t  | ||||
| slot_nb_index(PyObject *self) | ||||
| { | ||||
| 	PyObject *func, *args; | ||||
| 	static PyObject *index_str; | ||||
| 	Py_ssize_t result = -1; | ||||
| 	PyObject *temp = call_method(self, "__index__", &index_str, "()"); | ||||
| 	Py_ssize_t result; | ||||
| 
 | ||||
| 	func = lookup_maybe(self, "__index__", &index_str); | ||||
| 	if (func == NULL) { | ||||
| 		if (!PyErr_Occurred()) { | ||||
| 			PyErr_SetString(PyExc_TypeError,  | ||||
| 				"object cannot be interpreted as an index"); | ||||
| 		} | ||||
| 	if (temp == NULL) | ||||
| 		return -1; | ||||
|  	} | ||||
| 	args = PyTuple_New(0); | ||||
| 	if (args != NULL) { | ||||
| 		PyObject *temp = PyObject_Call(func, args, NULL); | ||||
| 		Py_DECREF(args); | ||||
| 		if (temp != NULL) { | ||||
| 			if (PyInt_Check(temp) || PyLong_Check(temp)) { | ||||
| 				result = | ||||
|                                   temp->ob_type->tp_as_number->nb_index(temp); | ||||
| 	if (PyInt_CheckExact(temp) || PyLong_CheckExact(temp)) { | ||||
| 		result = temp->ob_type->tp_as_number->nb_index(temp); | ||||
| 	} | ||||
| 	else { | ||||
| 		PyErr_SetString(PyExc_TypeError,  | ||||
|  | @ -4393,9 +4385,6 @@ slot_nb_index(PyObject *self) | |||
| 		result = -1; | ||||
| 	} | ||||
| 	Py_DECREF(temp); | ||||
| 		} | ||||
| 	} | ||||
| 	Py_DECREF(func); | ||||
| 	return result; | ||||
| } | ||||
| 
 | ||||
|  | @ -5026,9 +5015,9 @@ static slotdef slotdefs[] = { | |||
| 	   test_descr.notimplemented() */ | ||||
| 	SQSLOT("__add__", sq_concat, NULL, wrap_binaryfunc, | ||||
|           "x.__add__(y) <==> x+y"), | ||||
| 	SQSLOT("__mul__", sq_repeat, NULL, wrap_ssizeargfunc, | ||||
| 	SQSLOT("__mul__", sq_repeat, NULL, wrap_indexargfunc, | ||||
|           "x.__mul__(n) <==> x*n"), | ||||
| 	SQSLOT("__rmul__", sq_repeat, NULL, wrap_ssizeargfunc, | ||||
| 	SQSLOT("__rmul__", sq_repeat, NULL, wrap_indexargfunc, | ||||
|           "x.__rmul__(n) <==> n*x"), | ||||
| 	SQSLOT("__getitem__", sq_item, slot_sq_item, wrap_sq_item, | ||||
| 	       "x.__getitem__(y) <==> x[y]"), | ||||
|  | @ -5054,7 +5043,7 @@ static slotdef slotdefs[] = { | |||
| 	SQSLOT("__iadd__", sq_inplace_concat, NULL, | ||||
|           wrap_binaryfunc, "x.__iadd__(y) <==> x+=y"), | ||||
| 	SQSLOT("__imul__", sq_inplace_repeat, NULL, | ||||
|           wrap_ssizeargfunc, "x.__imul__(y) <==> x*=y"), | ||||
|           wrap_indexargfunc, "x.__imul__(y) <==> x*=y"), | ||||
| 
 | ||||
| 	MPSLOT("__len__", mp_length, slot_mp_length, wrap_lenfunc, | ||||
| 	       "x.__len__() <==> len(x)"), | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Armin Rigo
						Armin Rigo