diff --git a/Lib/test/test_deque.py b/Lib/test/test_deque.py --- a/Lib/test/test_deque.py +++ b/Lib/test/test_deque.py @@ -503,7 +503,7 @@ for match in (True, False): d = deque(['ab']) d.extend([MutateCmp(d, match), 'c']) - self.assertRaises(IndexError, d.remove, 'c') + self.assertRaises((IndexError, RuntimeError), d.remove, 'c') self.assertEqual(d, deque()) def test_repr(self): diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -1039,19 +1039,17 @@ return Py_SIZE(deque); } -static PyObject * -deque_index(dequeobject *deque, PyObject *args) +Py_ssize_t +deque_index_internal(dequeobject *deque, PyObject *value, + Py_ssize_t start, Py_ssize_t stop) { - Py_ssize_t i, start=0, stop=Py_SIZE(deque); - PyObject *v, *item; + Py_ssize_t i; + PyObject *item; block *b = deque->leftblock; Py_ssize_t index = deque->leftindex; size_t start_state = deque->state; + int cmp; - if (!PyArg_ParseTuple(args, "O|O&O&:index", &v, - _PyEval_SliceIndex, &start, - _PyEval_SliceIndex, &stop)) - return NULL; if (start < 0) { start += Py_SIZE(deque); if (start < 0) @@ -1067,18 +1065,17 @@ for (i=0 ; i= start) { - int cmp; CHECK_NOT_END(b); item = b->data[index]; - cmp = PyObject_RichCompareBool(item, v, Py_EQ); + cmp = PyObject_RichCompareBool(item, value, Py_EQ); if (cmp > 0) - return PyLong_FromSsize_t(i); + return i; else if (cmp < 0) - return NULL; + return -1; if (start_state != deque->state) { PyErr_SetString(PyExc_RuntimeError, "deque mutated during iteration"); - return NULL; + return -1; } } index++; @@ -1087,8 +1084,24 @@ index = 0; } } - PyErr_Format(PyExc_ValueError, "%R is not in deque", v); - return NULL; + PyErr_Format(PyExc_ValueError, "%R is not in deque", value); + return -1; +} + +static PyObject * +deque_index(dequeobject *deque, PyObject *args) +{ + Py_ssize_t i, start=0, stop=Py_SIZE(deque); + PyObject *value; + + if (!PyArg_ParseTuple(args, "O|O&O&:index", &value, + _PyEval_SliceIndex, &start, + _PyEval_SliceIndex, &stop)) + return NULL; + i = deque_index_internal(deque, value, start, stop); + if (i < 0) + return NULL; + return PyLong_FromSsize_t(i); } PyDoc_STRVAR(index_doc, @@ -1134,36 +1147,26 @@ PyDoc_STRVAR(insert_doc, "D.insert(index, object) -- insert object before index"); +static int deque_del_item(dequeobject *, Py_ssize_t); + static PyObject * deque_remove(dequeobject *deque, PyObject *value) { - Py_ssize_t i, n=Py_SIZE(deque); + Py_ssize_t i; + size_t start_state = deque->state; + int rv; - for (i=0 ; ileftblock->data[deque->leftindex]; - int cmp = PyObject_RichCompareBool(item, value, Py_EQ); - - if (Py_SIZE(deque) != n) { - PyErr_SetString(PyExc_IndexError, - "deque mutated during remove()."); - return NULL; - } - if (cmp > 0) { - PyObject *tgt = deque_popleft(deque, NULL); - assert (tgt != NULL); - if (_deque_rotate(deque, i)) - return NULL; - Py_DECREF(tgt); - Py_RETURN_NONE; - } - else if (cmp < 0) { - _deque_rotate(deque, i); - return NULL; - } - _deque_rotate(deque, -1); + i = deque_index_internal(deque, value, 0, Py_SIZE(deque)); + if (i < 0) + return NULL; + if (start_state != deque->state) { + PyErr_SetString(PyExc_RuntimeError, "deque mutated during remove"); + return NULL; } - PyErr_SetString(PyExc_ValueError, "deque.remove(x): x not in deque"); - return NULL; + rv = deque_del_item(deque, i); + if (rv < 0) + return NULL; + Py_RETURN_NONE; } PyDoc_STRVAR(remove_doc,