Index: Objects/listobject.c =================================================================== --- Objects/listobject.c (revision 53047) +++ Objects/listobject.c (working copy) @@ -2475,6 +2475,9 @@ if (slicelength <= 0) { return PyList_New(0); } + else if (step == 1) { + return list_slice(self, start, stop); + } else { result = PyList_New(slicelength); if (!result) return NULL; @@ -2522,6 +2525,12 @@ if (step == 1 && ((PySliceObject*)item)->step == Py_None) return list_ass_slice(self, start, stop, value); + /* Make sure s[5:2] = [..] inserts at the right place: + before 5, not before 2. */ + if ((step < 0 && start < stop) || + (step > 0 && start > stop)) + stop = start; + if (value == NULL) { /* delete slice */ PyObject **garbage; @@ -2543,12 +2552,16 @@ return -1; } - /* drawing pictures might help - understand these for loops */ + /* drawing pictures might help understand these for + loops. Basically, we memmove the parts of the + list that are *not* part of the slice: step-1 + items for each item that is part of the slice, + and then tail end of the list that was not + covered by the slice */ for (cur = start, i = 0; cur < stop; cur += step, i++) { - Py_ssize_t lim = step; + Py_ssize_t lim = step - 1; garbage[i] = PyList_GET_ITEM(self, cur); @@ -2560,11 +2573,11 @@ self->ob_item + cur + 1, lim * sizeof(PyObject *)); } - - for (cur = start + slicelength*step + 1; - cur < self->ob_size; cur++) { - PyList_SET_ITEM(self, cur - slicelength, - PyList_GET_ITEM(self, cur)); + cur = start + slicelength*step; + if (cur < self->ob_size) { + memmove(self->ob_item + cur - slicelength, + self->ob_item + cur, + (self->ob_size - cur) * sizeof(PyObject *)); } self->ob_size -= slicelength; Index: Lib/test/list_tests.py =================================================================== --- Lib/test/list_tests.py (revision 53047) +++ Lib/test/list_tests.py (working copy) @@ -179,8 +179,10 @@ self.assertEqual(a, self.type2test(range(10))) self.assertRaises(TypeError, a.__setslice__, 0, 1, 5) + self.assertRaises(TypeError, a.__setitem__, slice(0, 1, 5)) self.assertRaises(TypeError, a.__setslice__) + self.assertRaises(TypeError, a.__setitem__) def test_delslice(self): a = self.type2test([0, 1])