Thomas Wouters added the comment:

Added tests (by duplicating any slicing operations in the test suite
with extended slice syntax, to force the use of slice-objects ;)

_____________________________________
Tracker <[EMAIL PROTECTED]>
<http://bugs.python.org/issue1617699>
_____________________________________
Index: Lib/ctypes/test/test_cast.py
===================================================================
--- Lib/ctypes/test/test_cast.py	(revision 57617)
+++ Lib/ctypes/test/test_cast.py	(working copy)
@@ -50,12 +50,16 @@
     def test_other(self):
         p = cast((c_int * 4)(1, 2, 3, 4), POINTER(c_int))
         self.failUnlessEqual(p[:4], [1,2, 3, 4])
+        self.failUnlessEqual(p[:4:], [1,2, 3, 4])
         c_int()
         self.failUnlessEqual(p[:4], [1, 2, 3, 4])
+        self.failUnlessEqual(p[:4:], [1, 2, 3, 4])
         p[2] = 96
         self.failUnlessEqual(p[:4], [1, 2, 96, 4])
+        self.failUnlessEqual(p[:4:], [1, 2, 96, 4])
         c_int()
         self.failUnlessEqual(p[:4], [1, 2, 96, 4])
+        self.failUnlessEqual(p[:4:], [1, 2, 96, 4])
 
     def test_char_p(self):
         # This didn't work: bad argument to internal function
Index: Lib/ctypes/test/test_buffers.py
===================================================================
--- Lib/ctypes/test/test_buffers.py	(revision 57617)
+++ Lib/ctypes/test/test_buffers.py	(working copy)
@@ -15,6 +15,7 @@
         self.failUnless(type(b[0]) is str)
         self.failUnlessEqual(b[0], "a")
         self.failUnlessEqual(b[:], "abc\0")
+        self.failUnlessEqual(b[::], "abc\0")
 
     def test_string_conversion(self):
         b = create_string_buffer(u"abc")
@@ -23,6 +24,7 @@
         self.failUnless(type(b[0]) is str)
         self.failUnlessEqual(b[0], "a")
         self.failUnlessEqual(b[:], "abc\0")
+        self.failUnlessEqual(b[::], "abc\0")
 
     try:
         c_wchar
@@ -41,6 +43,7 @@
             self.failUnless(type(b[0]) is unicode)
             self.failUnlessEqual(b[0], u"a")
             self.failUnlessEqual(b[:], "abc\0")
+            self.failUnlessEqual(b[::], "abc\0")
 
         def test_unicode_conversion(self):
             b = create_unicode_buffer("abc")
@@ -49,6 +52,7 @@
             self.failUnless(type(b[0]) is unicode)
             self.failUnlessEqual(b[0], u"a")
             self.failUnlessEqual(b[:], "abc\0")
+            self.failUnlessEqual(b[::], "abc\0")
 
 if __name__ == "__main__":
     unittest.main()
Index: Lib/ctypes/test/test_arrays.py
===================================================================
--- Lib/ctypes/test/test_arrays.py	(revision 57617)
+++ Lib/ctypes/test/test_arrays.py	(working copy)
@@ -95,6 +95,7 @@
         p = create_string_buffer("foo")
         sz = (c_char * 3).from_address(addressof(p))
         self.failUnlessEqual(sz[:], "foo")
+        self.failUnlessEqual(sz[::], "foo")
         self.failUnlessEqual(sz.value, "foo")
 
     try:
@@ -106,6 +107,7 @@
             p = create_unicode_buffer("foo")
             sz = (c_wchar * 3).from_address(addressof(p))
             self.failUnlessEqual(sz[:], "foo")
+            self.failUnlessEqual(sz[::], "foo")
             self.failUnlessEqual(sz.value, "foo")
 
 if __name__ == '__main__':
Index: Lib/ctypes/test/test_structures.py
===================================================================
--- Lib/ctypes/test/test_structures.py	(revision 57617)
+++ Lib/ctypes/test/test_structures.py	(working copy)
@@ -236,7 +236,9 @@
 
         # can use tuple to initialize array (but not list!)
         self.failUnlessEqual(SomeInts((1, 2)).a[:], [1, 2, 0, 0])
+        self.failUnlessEqual(SomeInts((1, 2)).a[::], [1, 2, 0, 0])
         self.failUnlessEqual(SomeInts((1, 2, 3, 4)).a[:], [1, 2, 3, 4])
+        self.failUnlessEqual(SomeInts((1, 2, 3, 4)).a[::], [1, 2, 3, 4])
         # too long
         # XXX Should raise ValueError?, not RuntimeError
         self.assertRaises(RuntimeError, SomeInts, (1, 2, 3, 4, 5))
Index: Lib/ctypes/test/test_strings.py
===================================================================
--- Lib/ctypes/test/test_strings.py	(revision 57617)
+++ Lib/ctypes/test/test_strings.py	(working copy)
@@ -121,6 +121,7 @@
     def XX_test_initialized_strings(self):
 
         self.failUnless(c_string("ab", 4).raw[:2] == "ab")
+        self.failUnless(c_string("ab", 4).raw[:2:] == "ab")
         self.failUnless(c_string("ab", 4).raw[-1] == "\000")
         self.failUnless(c_string("ab", 2).raw == "a\000")
 
Index: Lib/ctypes/test/test_memfunctions.py
===================================================================
--- Lib/ctypes/test/test_memfunctions.py	(revision 57617)
+++ Lib/ctypes/test/test_memfunctions.py	(working copy)
@@ -30,6 +30,8 @@
         self.failUnlessEqual(cast(a, c_char_p).value, "abcdef")
         self.failUnlessEqual(cast(a, POINTER(c_byte))[:7],
                              [97, 98, 99, 100, 101, 102, 0])
+        self.failUnlessEqual(cast(a, POINTER(c_byte))[:7:],
+                             [97, 98, 99, 100, 101, 102, 0])
 
     def test_string_at(self):
         s = string_at("foo bar")
Index: Lib/ctypes/test/test_unicode.py
===================================================================
--- Lib/ctypes/test/test_unicode.py	(revision 57617)
+++ Lib/ctypes/test/test_unicode.py	(working copy)
@@ -59,11 +59,13 @@
             ctypes.set_conversion_mode("ascii", "replace")
             buf = ctypes.create_unicode_buffer("abäöü")
             self.failUnlessEqual(buf[:], u"ab\uFFFD\uFFFD\uFFFD\0")
+            self.failUnlessEqual(buf[::], u"ab\uFFFD\uFFFD\uFFFD\0")
 
             ctypes.set_conversion_mode("ascii", "ignore")
             buf = ctypes.create_unicode_buffer("abäöü")
             # is that correct? not sure.  But with 'ignore', you get what you pay for..
             self.failUnlessEqual(buf[:], u"ab\0\0\0\0")
+            self.failUnlessEqual(buf[::], u"ab\0\0\0\0")
 
     import _ctypes_test
     func = ctypes.CDLL(_ctypes_test.__file__)._testfunc_p_p
@@ -105,11 +107,13 @@
             ctypes.set_conversion_mode("ascii", "replace")
             buf = ctypes.create_string_buffer(u"abäöü")
             self.failUnlessEqual(buf[:], "ab???\0")
+            self.failUnlessEqual(buf[::], "ab???\0")
 
             ctypes.set_conversion_mode("ascii", "ignore")
             buf = ctypes.create_string_buffer(u"abäöü")
             # is that correct? not sure.  But with 'ignore', you get what you pay for..
             self.failUnlessEqual(buf[:], "ab\0\0\0\0")
+            self.failUnlessEqual(buf[::], "ab\0\0\0\0")
 
 if __name__ == '__main__':
     unittest.main()
Index: Lib/ctypes/test/test_slicing.py
===================================================================
--- Lib/ctypes/test/test_slicing.py	(revision 57617)
+++ Lib/ctypes/test/test_slicing.py	(working copy)
@@ -8,13 +8,17 @@
         a = (c_int * 100)(*xrange(1100, 1200))
         b = range(1100, 1200)
         self.failUnlessEqual(a[0:2], b[0:2])
+        self.failUnlessEqual(a[0:2:], b[0:2:])
         self.failUnlessEqual(len(a), len(b))
         self.failUnlessEqual(a[5:7], b[5:7])
+        self.failUnlessEqual(a[5:7:], b[5:7:])
         self.failUnlessEqual(a[-1], b[-1])
         self.failUnlessEqual(a[:], b[:])
+        self.failUnlessEqual(a[::], b[::])
 
         a[0:5] = range(5, 10)
         self.failUnlessEqual(a[0:5], range(5, 10))
+        self.failUnlessEqual(a[0:5:], range(5, 10))
 
     def test_setslice_cint(self):
         a = (c_int * 100)(*xrange(1100, 1200))
@@ -22,17 +26,25 @@
 
         a[32:47] = range(32, 47)
         self.failUnlessEqual(a[32:47], range(32, 47))
+        a[32:47] = range(132, 147)
+        self.failUnlessEqual(a[32:47:], range(132, 147))
 
-        from operator import setslice
+        from operator import setslice, setitem
 
         # TypeError: int expected instead of str instance
         self.assertRaises(TypeError, setslice, a, 0, 5, "abcde")
+        self.assertRaises(TypeError, setitem, a, slice(0, 5), "abcde")
         # TypeError: int expected instead of str instance
         self.assertRaises(TypeError, setslice, a, 0, 5, ["a", "b", "c", "d", "e"])
+        self.assertRaises(TypeError, setitem, a, slice(0, 5),
+                          ["a", "b", "c", "d", "e"])
         # TypeError: int expected instead of float instance
         self.assertRaises(TypeError, setslice, a, 0, 5, [1, 2, 3, 4, 3.14])
+        self.assertRaises(TypeError, setitem, a, slice(0, 5),
+                          [1, 2, 3, 4, 3.14])
         # ValueError: Can only assign sequence of same size
         self.assertRaises(ValueError, setslice, a, 0, 5, range(32))
+        self.assertRaises(ValueError, setitem, a, slice(0, 5), range(32))
 
     def test_char_ptr(self):
         s = "abcdefghijklmnopqrstuvwxyz"
@@ -42,15 +54,19 @@
         dll.my_free.restype = None
         res = dll.my_strdup(s)
         self.failUnlessEqual(res[:len(s)], s)
+        self.failUnlessEqual(res[:len(s):], s)
 
         import operator
         self.assertRaises(TypeError, operator.setslice,
                           res, 0, 5, u"abcde")
+        self.assertRaises(TypeError, operator.setitem,
+                          res, slice(0, 5), u"abcde")
         dll.my_free(res)
 
         dll.my_strdup.restype = POINTER(c_byte)
         res = dll.my_strdup(s)
         self.failUnlessEqual(res[:len(s)], range(ord("a"), ord("z")+1))
+        self.failUnlessEqual(res[:len(s):], range(ord("a"), ord("z")+1))
         dll.my_free(res)
 
     def test_char_ptr_with_free(self):
@@ -80,6 +96,7 @@
 
         p = (c_char * 27)(*s)
         self.failUnlessEqual(p[:], s)
+        self.failUnlessEqual(p[::], s)
 
 
     try:
@@ -96,10 +113,13 @@
             dll.my_free.restype = None
             res = dll.my_wcsdup(s)
             self.failUnlessEqual(res[:len(s)], s)
+            self.failUnlessEqual(res[:len(s):], s)
 
             import operator
             self.assertRaises(TypeError, operator.setslice,
                               res, 0, 5, u"abcde")
+            self.assertRaises(TypeError, operator.setitem,
+                              res, slice(0, 5), u"abcde")
             dll.my_free(res)
 
             if sizeof(c_wchar) == sizeof(c_short):
@@ -112,6 +132,7 @@
                 return
             res = dll.my_wcsdup(s)
             self.failUnlessEqual(res[:len(s)-1], range(ord("a"), ord("z")+1))
+            self.failUnlessEqual(res[:len(s)-1:], range(ord("a"), ord("z")+1))
             dll.my_free(res)
 
 ################################################################
Index: Modules/_ctypes/_ctypes.c
===================================================================
--- Modules/_ctypes/_ctypes.c	(revision 57617)
+++ Modules/_ctypes/_ctypes.c	(working copy)
@@ -3768,6 +3768,74 @@
 	return (PyObject *)np;
 }
 
+static PyObject *
+Array_subscript(PyObject *_self, PyObject *item)
+{
+	CDataObject *self = (CDataObject *)_self;
+
+	if (PyIndex_Check(item)) {
+		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+		
+		if (i == -1 && PyErr_Occurred())
+			return NULL;
+		if (i < 0)
+			i += self->b_length;
+		return Array_item(_self, i);
+	}
+	else if PySlice_Check(item) {
+		StgDictObject *stgdict, *itemdict;
+		PyObject *proto;
+		PyListObject *np;
+		Py_ssize_t start, stop, step, slicelen, i;
+		
+		if (PySlice_GetIndicesEx((PySliceObject *)item,
+					 self->b_length, &start, &stop,
+					 &step, &slicelen) < 0) {
+			return NULL;
+		}
+		if (step != 1) {
+			PyErr_Format(PyExc_TypeError, "slice-steps other "
+				"than 1 not supported (%zd given)", step);
+			return NULL;
+		}
+		
+		stgdict = PyObject_stgdict((PyObject *)self);
+		assert(stgdict); /* Cannot be NULL for array object instances */
+		proto = stgdict->proto;
+		itemdict = PyType_stgdict(proto);
+		assert(itemdict); /* proto is the item type of the array, a
+				     ctypes type, so this cannot be NULL */
+
+		if (itemdict->getfunc == getentry("c")->getfunc) {
+			char *ptr = (char *)self->b_ptr;
+			return PyString_FromStringAndSize(ptr + start,
+							  slicelen);
+#ifdef CTYPES_UNICODE
+		} else if (itemdict->getfunc == getentry("u")->getfunc) {
+			wchar_t *ptr = (wchar_t *)self->b_ptr;
+			return PyUnicode_FromWideChar(ptr + start,
+						      slicelen);
+#endif
+		}
+
+		np = (PyListObject *) PyList_New(slicelen);
+		if (np == NULL)
+			return NULL;
+
+		for (i = 0; i < slicelen; i++) {
+			PyObject *v = Array_item(_self, i+start);
+			PyList_SET_ITEM(np, i, v);
+		}
+		return (PyObject *)np;
+	}
+	else {
+		PyErr_SetString(PyExc_TypeError, 
+				"indices must be integers");
+		return NULL;
+	}
+
+}
+
 static int
 Array_ass_item(PyObject *_self, Py_ssize_t index, PyObject *value)
 {
@@ -3839,6 +3907,69 @@
 	return 0;
 }
 
+static int
+Array_ass_subscript(PyObject *_self, PyObject *item, PyObject *value)
+{
+	CDataObject *self = (CDataObject *)_self;
+	
+	if (value == NULL) {
+		PyErr_SetString(PyExc_TypeError,
+				"Array does not support item deletion");
+		return -1;
+	}
+
+	if (PyIndex_Check(item)) {
+		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+		
+		if (i == -1 && PyErr_Occurred())
+			return -1;
+		if (i < 0)
+			i += self->b_length;
+		return Array_ass_item(_self, i, value);
+	}
+	else if (PySlice_Check(item)) {
+		Py_ssize_t start, stop, step, slicelen, otherlen, i;
+		
+		if (PySlice_GetIndicesEx((PySliceObject *)item,
+					 self->b_length, &start, &stop,
+					 &step, &slicelen) < 0) {
+			return -1;
+		}
+		/* XXX(twouters) fix this */
+		if (step != 1) {
+			PyErr_Format(PyExc_TypeError, "slice-steps other "
+				"than 1 not supported (%zd given)", step);
+			return -1;
+		}
+		if ((step < 0 && start < stop) ||
+		    (step > 0 && start > stop))
+			stop = start;
+
+		otherlen = PySequence_Length(value);
+		if (otherlen != slicelen) {
+			PyErr_SetString(PyExc_ValueError,
+				"Can only assign sequence of same size");
+			return -1;
+		}
+		for (i = 0; i < otherlen; i++) {
+			PyObject *item = PySequence_GetItem(value, i);
+			int result;
+			if (item == NULL)
+				return -1;
+			result = Array_ass_item(_self, i+start, item);
+			Py_DECREF(item);
+			if (result == -1)
+				return -1;
+		}
+		return 0;
+	}
+	else {
+		PyErr_SetString(PyExc_TypeError,
+				"indices must be integer");
+		return -1;
+	}
+}
+
 static Py_ssize_t
 Array_length(PyObject *_self)
 {
@@ -3860,6 +3991,12 @@
 	0,					/* sq_inplace_repeat; */
 };
 
+static PyMappingMethods Array_as_mapping = {
+	Array_length,
+	Array_subscript,
+	Array_ass_subscript,
+};
+
 PyTypeObject Array_Type = {
 	PyVarObject_HEAD_INIT(NULL, 0)
 	"_ctypes.Array",
@@ -3873,7 +4010,7 @@
 	0,					/* tp_repr */
 	0,					/* tp_as_number */
 	&Array_as_sequence,			/* tp_as_sequence */
-	0,					/* tp_as_mapping */
+	&Array_as_mapping,			/* tp_as_mapping */
 	0,					/* tp_hash */
 	0,					/* tp_call */
 	0,					/* tp_str */
@@ -4359,6 +4496,94 @@
 	return (PyObject *)np;
 }
 
+static PyObject *
+Pointer_subscript(PyObject *_self, PyObject *item)
+{
+	CDataObject *self = (CDataObject *)_self;
+	if (PyIndex_Check(item)) {
+		Py_ssize_t i = PyNumber_AsSsize_t(item, PyExc_IndexError);
+		if (i == -1 && PyErr_Occurred())
+			return NULL;
+		return Pointer_item(_self, i);
+	}
+	else if (PySlice_Check(item)) {
+		/* Since pointers have no length, we cannot use any
+		   of the PySlice API functions, and have to fiddle
+		   with the attributes directly */
+		PySliceObject *slice = (PySliceObject *)item;
+		Py_ssize_t start, stop;
+		PyListObject *np;
+		StgDictObject *stgdict, *itemdict;
+		PyObject *proto;
+		Py_ssize_t i, len;
+
+		if (slice->step != Py_None) {
+			Py_ssize_t step = PyNumber_AsSsize_t(slice->step,
+							PyExc_IndexError);
+			if (step == -1 && PyErr_Occurred())
+				return NULL;
+			if (step != 1) {
+				PyErr_Format(PyExc_TypeError,
+					     "unsupported step size %zd",
+					     step);
+				return NULL;
+			}
+		}
+		if (slice->start == Py_None)
+			start = 0;
+		else {
+			start = PyNumber_AsSsize_t(slice->start,
+						   PyExc_IndexError);
+			if (start == -1 && PyErr_Occurred())
+				return NULL;
+			if (start < 0)
+				start = 0;
+		}
+		if (slice->stop == Py_None)
+			stop = PY_SSIZE_T_MAX;
+		else {
+			stop = PyNumber_AsSsize_t(slice->stop,
+						  PyExc_IndexError);
+			if (stop == -1 && PyErr_Occurred())
+				return NULL;
+		}
+		if (stop < start)
+			stop = start;
+		len = stop - start;
+
+		stgdict = PyObject_stgdict((PyObject *)self);
+		assert(stgdict); /* Cannot be NULL fr pointer instances */
+		proto = stgdict->proto;
+		assert(proto);
+		itemdict = PyType_stgdict(proto);
+		assert(itemdict);
+		if (itemdict->getfunc == getentry("c")->getfunc) {
+			char *ptr = *(char **)self->b_ptr;
+			return PyString_FromStringAndSize(ptr + start, len);
+#ifdef CTYPES_UNICODE
+		} else if (itemdict->getfunc == getentry("u")->getfunc) {
+			wchar_t *ptr = *(wchar_t **)self->b_ptr;
+			return PyUnicode_FromWideChar(ptr + start, len);
+#endif
+		}
+
+		np = (PyListObject *) PyList_New(len);
+		if (np == NULL)
+			return NULL;
+
+		for (i = 0; i < len; i++) {
+			PyObject *v = Pointer_item(_self, i+start);
+			PyList_SET_ITEM(np, i, v);
+		}
+		return (PyObject *)np;
+	}
+	else {
+		PyErr_SetString(PyExc_TypeError,
+				"Pointer indices must be integer");
+		return NULL;
+	}
+}
+
 static PySequenceMethods Pointer_as_sequence = {
 	0,					/* inquiry sq_length; */
 	0,					/* binaryfunc sq_concat; */
@@ -4373,6 +4598,11 @@
 	0,					/* intargfunc sq_inplace_repeat; */
 };
 
+static PyMappingMethods Pointer_as_mapping = {
+	0,
+	Pointer_subscript,
+};
+
 static int
 Pointer_nonzero(CDataObject *self)
 {
@@ -4406,7 +4636,7 @@
 	0,					/* tp_repr */
 	&Pointer_as_number,			/* tp_as_number */
 	&Pointer_as_sequence,			/* tp_as_sequence */
-	0,					/* tp_as_mapping */
+	&Pointer_as_mapping,			/* tp_as_mapping */
 	0,					/* tp_hash */
 	0,					/* tp_call */
 	0,					/* tp_str */
_______________________________________________
Python-bugs-list mailing list 
Unsubscribe: 
http://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to