mirror of https://github.com/python/cpython
Issue 2025: Add index() and count() methods to tuple so that it will follow
the ABC for collections.Sequence.
This commit is contained in:
parent
2f653c19f4
commit
65baa34115
|
@ -4,6 +4,7 @@ Tests common to tuple, list and UserList.UserList
|
||||||
|
|
||||||
import unittest
|
import unittest
|
||||||
from test import test_support
|
from test import test_support
|
||||||
|
import sys
|
||||||
|
|
||||||
# Various iterables
|
# Various iterables
|
||||||
# This is used for checking the constructor (here and in test_deque.py)
|
# This is used for checking the constructor (here and in test_deque.py)
|
||||||
|
@ -326,3 +327,64 @@ class CommonTest(unittest.TestCase):
|
||||||
self.assertEqual(a.__getitem__(slice(3,5)), self.type2test([]))
|
self.assertEqual(a.__getitem__(slice(3,5)), self.type2test([]))
|
||||||
self.assertRaises(ValueError, a.__getitem__, slice(0, 10, 0))
|
self.assertRaises(ValueError, a.__getitem__, slice(0, 10, 0))
|
||||||
self.assertRaises(TypeError, a.__getitem__, 'x')
|
self.assertRaises(TypeError, a.__getitem__, 'x')
|
||||||
|
|
||||||
|
def test_count(self):
|
||||||
|
a = self.type2test([0, 1, 2])*3
|
||||||
|
self.assertEqual(a.count(0), 3)
|
||||||
|
self.assertEqual(a.count(1), 3)
|
||||||
|
self.assertEqual(a.count(3), 0)
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, a.count)
|
||||||
|
|
||||||
|
class BadExc(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class BadCmp:
|
||||||
|
def __eq__(self, other):
|
||||||
|
if other == 2:
|
||||||
|
raise BadExc()
|
||||||
|
return False
|
||||||
|
|
||||||
|
self.assertRaises(BadExc, a.count, BadCmp())
|
||||||
|
|
||||||
|
def test_index(self):
|
||||||
|
u = self.type2test([0, 1])
|
||||||
|
self.assertEqual(u.index(0), 0)
|
||||||
|
self.assertEqual(u.index(1), 1)
|
||||||
|
self.assertRaises(ValueError, u.index, 2)
|
||||||
|
|
||||||
|
u = self.type2test([-2, -1, 0, 0, 1, 2])
|
||||||
|
self.assertEqual(u.count(0), 2)
|
||||||
|
self.assertEqual(u.index(0), 2)
|
||||||
|
self.assertEqual(u.index(0, 2), 2)
|
||||||
|
self.assertEqual(u.index(-2, -10), 0)
|
||||||
|
self.assertEqual(u.index(0, 3), 3)
|
||||||
|
self.assertEqual(u.index(0, 3, 4), 3)
|
||||||
|
self.assertRaises(ValueError, u.index, 2, 0, -10)
|
||||||
|
|
||||||
|
self.assertRaises(TypeError, u.index)
|
||||||
|
|
||||||
|
class BadExc(Exception):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class BadCmp:
|
||||||
|
def __eq__(self, other):
|
||||||
|
if other == 2:
|
||||||
|
raise BadExc()
|
||||||
|
return False
|
||||||
|
|
||||||
|
a = self.type2test([0, 1, 2, 3])
|
||||||
|
self.assertRaises(BadExc, a.index, BadCmp())
|
||||||
|
|
||||||
|
a = self.type2test([-2, -1, 0, 0, 1, 2])
|
||||||
|
self.assertEqual(a.index(0), 2)
|
||||||
|
self.assertEqual(a.index(0, 2), 2)
|
||||||
|
self.assertEqual(a.index(0, -4), 2)
|
||||||
|
self.assertEqual(a.index(-2, -10), 0)
|
||||||
|
self.assertEqual(a.index(0, 3), 3)
|
||||||
|
self.assertEqual(a.index(0, -3), 3)
|
||||||
|
self.assertEqual(a.index(0, 3, 4), 3)
|
||||||
|
self.assertEqual(a.index(0, -3, -2), 3)
|
||||||
|
self.assertEqual(a.index(0, -4*sys.maxsize, 4*sys.maxsize), 2)
|
||||||
|
self.assertRaises(ValueError, a.index, 0, 4*sys.maxsize,-4*sys.maxsize)
|
||||||
|
self.assertRaises(ValueError, a.index, 2, 0, -10)
|
||||||
|
|
|
@ -12,6 +12,9 @@ What's New in Python 3.0a3?
|
||||||
Core and Builtins
|
Core and Builtins
|
||||||
-----------------
|
-----------------
|
||||||
|
|
||||||
|
- Issue #2025 : Add tuple.count() and tuple.index() methods to comply with
|
||||||
|
the collections.Sequence API.
|
||||||
|
|
||||||
- Fixed multiple reinitialization of the Python interpreter. The small int
|
- Fixed multiple reinitialization of the Python interpreter. The small int
|
||||||
list in longobject.c has caused a seg fault during the third finalization.
|
list in longobject.c has caused a seg fault during the third finalization.
|
||||||
|
|
||||||
|
|
|
@ -430,6 +430,53 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)
|
||||||
return (PyObject *) np;
|
return (PyObject *) np;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
tupleindex(PyTupleObject *self, PyObject *args)
|
||||||
|
{
|
||||||
|
Py_ssize_t i, start=0, stop=Py_SIZE(self);
|
||||||
|
PyObject *v;
|
||||||
|
|
||||||
|
if (!PyArg_ParseTuple(args, "O|O&O&:index", &v,
|
||||||
|
_PyEval_SliceIndex, &start,
|
||||||
|
_PyEval_SliceIndex, &stop))
|
||||||
|
return NULL;
|
||||||
|
if (start < 0) {
|
||||||
|
start += Py_SIZE(self);
|
||||||
|
if (start < 0)
|
||||||
|
start = 0;
|
||||||
|
}
|
||||||
|
if (stop < 0) {
|
||||||
|
stop += Py_SIZE(self);
|
||||||
|
if (stop < 0)
|
||||||
|
stop = 0;
|
||||||
|
}
|
||||||
|
for (i = start; i < stop && i < Py_SIZE(self); i++) {
|
||||||
|
int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
|
||||||
|
if (cmp > 0)
|
||||||
|
return PyLong_FromSsize_t(i);
|
||||||
|
else if (cmp < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
PyErr_SetString(PyExc_ValueError, "tuple.index(x): x not in list");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static PyObject *
|
||||||
|
tuplecount(PyTupleObject *self, PyObject *v)
|
||||||
|
{
|
||||||
|
Py_ssize_t count = 0;
|
||||||
|
Py_ssize_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < Py_SIZE(self); i++) {
|
||||||
|
int cmp = PyObject_RichCompareBool(self->ob_item[i], v, Py_EQ);
|
||||||
|
if (cmp > 0)
|
||||||
|
count++;
|
||||||
|
else if (cmp < 0)
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return PyLong_FromSsize_t(count);
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
tupletraverse(PyTupleObject *o, visitproc visit, void *arg)
|
tupletraverse(PyTupleObject *o, visitproc visit, void *arg)
|
||||||
{
|
{
|
||||||
|
@ -636,8 +683,15 @@ tuple_getnewargs(PyTupleObject *v)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
PyDoc_STRVAR(index_doc,
|
||||||
|
"T.index(value, [start, [stop]]) -> integer -- return first index of value");
|
||||||
|
PyDoc_STRVAR(count_doc,
|
||||||
|
"T.count(value) -> integer -- return number of occurrences of value");
|
||||||
|
|
||||||
static PyMethodDef tuple_methods[] = {
|
static PyMethodDef tuple_methods[] = {
|
||||||
{"__getnewargs__", (PyCFunction)tuple_getnewargs, METH_NOARGS},
|
{"__getnewargs__", (PyCFunction)tuple_getnewargs, METH_NOARGS},
|
||||||
|
{"index", (PyCFunction)tupleindex, METH_VARARGS, index_doc},
|
||||||
|
{"count", (PyCFunction)tuplecount, METH_O, count_doc},
|
||||||
{NULL, NULL} /* sentinel */
|
{NULL, NULL} /* sentinel */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue