static int pyjlist_set_subscript(PyObject* self, PyObject* item, PyObject* value) { if (PyInt_Check(item)) { long i = (long) PyInt_AS_LONG(item); if (i < 0) { i += (long) PyObject_Size(self); } return pyjlist_setitem(self, (Py_ssize_t) i, value); } else if (PyLong_Check(item)) { long i = PyLong_AsLong(item); if (i == -1 && PyErr_Occurred()) { return -1; } if (i < 0) { i += (long) PyObject_Size(self); } return pyjlist_setitem(self, (Py_ssize_t) i, value); } else if (PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; #if PY_MAJOR_VERSION >= 3 if (PySlice_GetIndicesEx(item, PyObject_Size(self), &start, &stop, &step, &slicelength) < 0) { // error will already be set return -1; } #else /* * This silences a compile warning on PySlice_GetIndicesEx by casting * item. Python fixed the method signature in 3.2 to take item as a * PyObject* */ if (PySlice_GetIndicesEx((PySliceObject *) item, PyObject_Size(self), &start, &stop, &step, &slicelength) < 0) { // error will already be set return -1; } #endif if (slicelength <= 0) { return 0; } else if (step != 1) { PyErr_SetString(PyExc_TypeError, "pyjlist slices must have step of 1"); return -1; } else { return pyjlist_setslice(self, start, stop, value); } } else { PyErr_SetString(PyExc_TypeError, "list indices must be integers, longs, or slices"); return -1; } }
/* * Method for setting slices with the [int:int] operator on pyjlist. For * example, o[i1:i2] = v where v is a sequence. */ static int pyjlist_setslice(PyObject *o, Py_ssize_t i1, Py_ssize_t i2, PyObject *v) { Py_ssize_t oSize; Py_ssize_t vSize; Py_ssize_t diff; Py_ssize_t i, vi; if (!PySequence_Check(v)) { PyErr_Format(PyExc_TypeError, "PyJList can only slice assign a sequence"); return -1; } oSize = PySequence_Size(o); vSize = PySequence_Size(v); if (i1 < 0) { i1 = 0; } if (i2 > oSize) { i2 = oSize; } if (i1 >= i2) { PyErr_Format(PyExc_IndexError, "invalid slice indices: %i:%i", (int) i1, (int) i2); return -1; } diff = i2 - i1; if (diff != vSize) { /* * TODO: Python lists support slice assignment of a different length, * but that gets complicated, so not planning on supporting it until * requested. For inspiration look at python's listobject.c's * list_ass_slice(). */ PyErr_Format(PyExc_IndexError, "PyJList only supports assigning a sequence of the same size as the slice, slice = [%i:%i], value size=%i", (int) i1, (int) i2, (int) vSize); return -1; } vi = 0; for (i = i1; i < i2; i++) { PyObject *vVal = PySequence_GetItem(v, vi); if (pyjlist_setitem(o, i, vVal) == -1) { /* * TODO This is not transactional if it fails partially through. * Not sure how to make that safe short of making a copy of o * and then replacing o's underlying jobject on success. That * would slow it down though.... */ Py_DECREF(vVal); return -1; } Py_DECREF(vVal); vi++; } return 0; }
static int pyjlist_set_subscript(PyObject* self, PyObject* item, PyObject* value) { if(PyInt_Check(item)) { long i = PyInt_AS_LONG(item); if (i < 0) i += (long) PyObject_Size(self); return pyjlist_setitem(self, (Py_ssize_t) i, value); } else if(PyLong_Check(item)) { long i = PyLong_AsLong(item); if (i == -1 && PyErr_Occurred()) return -1; if (i < 0) i += (long) PyObject_Size(self); return pyjlist_setitem(self, (Py_ssize_t) i, value); } else if(PySlice_Check(item)) { Py_ssize_t start, stop, step, slicelength; /* * ignore compile warning on the next line, they fixed the * method signature in python 3.2 */ if(PySlice_GetIndicesEx(item, PyObject_Size(self), &start, &stop, &step, &slicelength) < 0) { // error will already be set return -1; } if(slicelength <= 0) { return 0; } else if(step != 1) { PyErr_SetString(PyExc_TypeError, "pyjlist slices must have step of 1"); return -1; } else { return pyjlist_setslice(self, start, stop, value); } } else { PyErr_SetString(PyExc_TypeError, "list indices must be integers, longs, or slices"); return -1; } }