diff --git a/Lib/collections/__init__.py b/Lib/collections/__init__.py --- a/Lib/collections/__init__.py +++ b/Lib/collections/__init__.py @@ -16,6 +16,8 @@ from itertools import repeat as _repeat, chain as _chain, starmap as _starmap from reprlib import recursive_repr as _recursive_repr +MutableSequence.register(deque) + ################################################################################ ### OrderedDict ################################################################################ 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 @@ -237,6 +237,15 @@ self.assertNotIn(val, d) self.assertEqual(len(d), 0) + def test_index(self): + for n in [0, 10, 100, 500]: + s = list(range(n)) + list(range(n)) + d = deque(s) + for value in s: + expected_index = s.index(value) + actual_index = d.index(value) + self.assertEqual(expected_index, actual_index) + def test_reverse(self): n = 500 # O(n**2) test, don't make this too big data = [random.random() for i in range(n)] diff --git a/Modules/_collectionsmodule.c b/Modules/_collectionsmodule.c --- a/Modules/_collectionsmodule.c +++ b/Modules/_collectionsmodule.c @@ -64,7 +64,7 @@ Py_ssize_t rightindex; /* in range(BLOCKLEN) */ size_t state; /* incremented whenever the indices move */ Py_ssize_t maxlen; - PyObject *weakreflist; /* List of weak references */ + PyObject *weakreflist; } dequeobject; static PyTypeObject deque_type; @@ -731,6 +731,91 @@ } static PyObject * +deque_index(dequeobject *deque, PyObject *args) +{ + Py_ssize_t i, start=0, stop=Py_SIZE(deque); + PyObject *v, *item; + block *b = deque->leftblock; + Py_ssize_t index = deque->leftindex; + size_t start_state = deque->state; + + 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) + start = 0; + } + if (stop < 0) { + stop += Py_SIZE(deque); + if (stop < 0) + stop = 0; + } + + for (i=0 ; i= start) { + int cmp; + CHECK_NOT_END(b); + item = b->data[index]; + cmp = PyObject_RichCompareBool(item, v, Py_EQ); + if (cmp > 0) + return PyLong_FromSsize_t(i); + else if (cmp < 0) + return NULL; + if (start_state != deque->state) { + PyErr_SetString(PyExc_RuntimeError, + "deque mutated during iteration"); + return NULL; + } + } + index++; + if (index == BLOCKLEN) { + b = b->rightlink; + index = 0; + } + } + PyErr_Format(PyExc_ValueError, "%R is not in deque", v); + return NULL; +} + +PyDoc_STRVAR(index_doc, +"D.index(value, [start, [stop]]) -> integer -- return first index of value.\n" +"Raises ValueError if the value is not present."); + +static PyObject * +deque_insert(dequeobject *deque, PyObject *args) +{ + Py_ssize_t index; + Py_ssize_t n=Py_SIZE(deque); + PyObject *value; + PyObject *rv; + + if (!PyArg_ParseTuple(args, "nO:insert", &index, &value)) + return NULL; + if (index >= n) + return deque_append(deque, value); + if (index <= -n || index == 0) + return deque_appendleft(deque, value); + if (_deque_rotate(deque, -index)) + return NULL; + if (index < 0) + rv = deque_append(deque, value); + else + rv = deque_appendleft(deque, value); + if (rv == NULL) + return NULL; + Py_DECREF(rv); + if (_deque_rotate(deque, index)) + return NULL; + Py_RETURN_NONE; +} + +PyDoc_STRVAR(insert_doc, +"D.insert(index, object) -- insert object before index"); + +static PyObject * deque_remove(dequeobject *deque, PyObject *value) { Py_ssize_t i, n=Py_SIZE(deque); @@ -1176,12 +1261,18 @@ METH_NOARGS, clear_doc}, {"__copy__", (PyCFunction)deque_copy, METH_NOARGS, copy_doc}, + {"copy", (PyCFunction)deque_copy, + METH_NOARGS, copy_doc}, {"count", (PyCFunction)deque_count, - METH_O, count_doc}, + METH_O, count_doc}, {"extend", (PyCFunction)deque_extend, METH_O, extend_doc}, {"extendleft", (PyCFunction)deque_extendleft, METH_O, extendleft_doc}, + {"index", (PyCFunction)deque_index, + METH_VARARGS, index_doc}, + {"insert", (PyCFunction)deque_insert, + METH_VARARGS, insert_doc}, {"pop", (PyCFunction)deque_pop, METH_NOARGS, pop_doc}, {"popleft", (PyCFunction)deque_popleft,