bpo-20186: Convert tuple object implementation to Argument Clinic. (#614)

This commit is contained in:
Serhiy Storchaka 2017-03-19 08:47:58 +02:00 committed by GitHub
parent 5c643a028e
commit 0b5615926a
2 changed files with 179 additions and 49 deletions

View File

@ -0,0 +1,102 @@
/*[clinic input]
preserve
[clinic start generated code]*/
PyDoc_STRVAR(tuple_index__doc__,
"index($self, value, start=0, stop=sys.maxsize, /)\n"
"--\n"
"\n"
"Return first index of value.\n"
"\n"
"Raises ValueError if the value is not present.");
#define TUPLE_INDEX_METHODDEF \
{"index", (PyCFunction)tuple_index, METH_FASTCALL, tuple_index__doc__},
static PyObject *
tuple_index_impl(PyTupleObject *self, PyObject *value, Py_ssize_t start,
Py_ssize_t stop);
static PyObject *
tuple_index(PyTupleObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames)
{
PyObject *return_value = NULL;
PyObject *value;
Py_ssize_t start = 0;
Py_ssize_t stop = PY_SSIZE_T_MAX;
if (!_PyArg_ParseStack(args, nargs, "O|O&O&:index",
&value, _PyEval_SliceIndex, &start, _PyEval_SliceIndex, &stop)) {
goto exit;
}
if (!_PyArg_NoStackKeywords("index", kwnames)) {
goto exit;
}
return_value = tuple_index_impl(self, value, start, stop);
exit:
return return_value;
}
PyDoc_STRVAR(tuple_count__doc__,
"count($self, value, /)\n"
"--\n"
"\n"
"Return number of occurrences of value.");
#define TUPLE_COUNT_METHODDEF \
{"count", (PyCFunction)tuple_count, METH_O, tuple_count__doc__},
PyDoc_STRVAR(tuple_new__doc__,
"tuple(iterable=(), /)\n"
"--\n"
"\n"
"Built-in immutable sequence.\n"
"\n"
"If no argument is given, the constructor returns an empty tuple.\n"
"If iterable is specified the tuple is initialized from iterable\'s items.\n"
"\n"
"If the argument is a tuple, the return value is the same object.");
static PyObject *
tuple_new_impl(PyTypeObject *type, PyObject *iterable);
static PyObject *
tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwargs)
{
PyObject *return_value = NULL;
PyObject *iterable = NULL;
if ((type == &PyTuple_Type) &&
!_PyArg_NoKeywords("tuple", kwargs)) {
goto exit;
}
if (!PyArg_UnpackTuple(args, "tuple",
0, 1,
&iterable)) {
goto exit;
}
return_value = tuple_new_impl(type, iterable);
exit:
return return_value;
}
PyDoc_STRVAR(tuple___getnewargs____doc__,
"__getnewargs__($self, /)\n"
"--\n"
"\n");
#define TUPLE___GETNEWARGS___METHODDEF \
{"__getnewargs__", (PyCFunction)tuple___getnewargs__, METH_NOARGS, tuple___getnewargs____doc__},
static PyObject *
tuple___getnewargs___impl(PyTupleObject *self);
static PyObject *
tuple___getnewargs__(PyTupleObject *self, PyObject *Py_UNUSED(ignored))
{
return tuple___getnewargs___impl(self);
}
/*[clinic end generated code: output=561a3654411d2225 input=a9049054013a1b77]*/

View File

@ -4,6 +4,13 @@
#include "Python.h"
#include "accu.h"
/*[clinic input]
class tuple "PyTupleObject *" "&PyTuple_Type"
[clinic start generated code]*/
/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f051ba3cfdf9a189]*/
#include "clinic/tupleobject.c.h"
/* Speed optimization to avoid frequent malloc/free of small tuples */
#ifndef PyTuple_MAXSAVESIZE
#define PyTuple_MAXSAVESIZE 20 /* Largest tuple to save on free list */
@ -523,16 +530,26 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)
return (PyObject *) np;
}
static PyObject *
tupleindex(PyTupleObject *self, PyObject *args)
{
Py_ssize_t i, start=0, stop=Py_SIZE(self);
PyObject *v;
/*[clinic input]
tuple.index
value: object
start: object(converter="_PyEval_SliceIndex", type="Py_ssize_t") = 0
stop: object(converter="_PyEval_SliceIndex", type="Py_ssize_t", c_default="PY_SSIZE_T_MAX") = sys.maxsize
/
Return first index of value.
Raises ValueError if the value is not present.
[clinic start generated code]*/
static PyObject *
tuple_index_impl(PyTupleObject *self, PyObject *value, Py_ssize_t start,
Py_ssize_t stop)
/*[clinic end generated code: output=07b6f9f3cb5c33eb input=28890d4bec234471]*/
{
Py_ssize_t i;
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)
@ -540,11 +557,12 @@ tupleindex(PyTupleObject *self, PyObject *args)
}
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);
else if (stop > Py_SIZE(self)) {
stop = Py_SIZE(self);
}
for (i = start; i < stop; i++) {
int cmp = PyObject_RichCompareBool(self->ob_item[i], value, Py_EQ);
if (cmp > 0)
return PyLong_FromSsize_t(i);
else if (cmp < 0)
@ -554,14 +572,24 @@ tupleindex(PyTupleObject *self, PyObject *args)
return NULL;
}
/*[clinic input]
tuple.count
value: object
/
Return number of occurrences of value.
[clinic start generated code]*/
static PyObject *
tuplecount(PyTupleObject *self, PyObject *v)
tuple_count(PyTupleObject *self, PyObject *value)
/*[clinic end generated code: output=aa927affc5a97605 input=531721aff65bd772]*/
{
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);
int cmp = PyObject_RichCompareBool(self->ob_item[i], value, Py_EQ);
if (cmp > 0)
count++;
else if (cmp < 0)
@ -650,34 +678,43 @@ tuplerichcompare(PyObject *v, PyObject *w, int op)
}
static PyObject *
tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds);
tuple_subtype_new(PyTypeObject *type, PyObject *iterable);
/*[clinic input]
@classmethod
tuple.__new__ as tuple_new
iterable: object(c_default="NULL") = ()
/
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple.
If iterable is specified the tuple is initialized from iterable's items.
If the argument is a tuple, the return value is the same object.
[clinic start generated code]*/
static PyObject *
tuple_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
tuple_new_impl(PyTypeObject *type, PyObject *iterable)
/*[clinic end generated code: output=4546d9f0d469bce7 input=86963bcde633b5a2]*/
{
PyObject *arg = NULL;
if (type != &PyTuple_Type)
return tuple_subtype_new(type, args, kwds);
if (!_PyArg_NoKeywords("tuple()", kwds))
return NULL;
if (!PyArg_UnpackTuple(args, "tuple", 0, 1, &arg))
return NULL;
return tuple_subtype_new(type, iterable);
if (arg == NULL)
if (iterable == NULL)
return PyTuple_New(0);
else
return PySequence_Tuple(arg);
return PySequence_Tuple(iterable);
}
static PyObject *
tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
tuple_subtype_new(PyTypeObject *type, PyObject *iterable)
{
PyObject *tmp, *newobj, *item;
Py_ssize_t i, n;
assert(PyType_IsSubtype(type, &PyTuple_Type));
tmp = tuple_new(&PyTuple_Type, args, kwds);
tmp = tuple_new_impl(&PyTuple_Type, iterable);
if (tmp == NULL)
return NULL;
assert(PyTuple_Check(tmp));
@ -693,12 +730,6 @@ tuple_subtype_new(PyTypeObject *type, PyObject *args, PyObject *kwds)
return newobj;
}
PyDoc_STRVAR(tuple_doc,
"tuple() -> empty tuple\n\
tuple(iterable) -> tuple initialized from iterable's items\n\
\n\
If the argument is a tuple, the return value is the same object.");
static PySequenceMethods tuple_as_sequence = {
(lenfunc)tuplelength, /* sq_length */
(binaryfunc)tupleconcat, /* sq_concat */
@ -766,24 +797,21 @@ tuplesubscript(PyTupleObject* self, PyObject* item)
}
}
static PyObject *
tuple_getnewargs(PyTupleObject *v)
{
return Py_BuildValue("(N)", tupleslice(v, 0, Py_SIZE(v)));
/*[clinic input]
tuple.__getnewargs__
[clinic start generated code]*/
static PyObject *
tuple___getnewargs___impl(PyTupleObject *self)
/*[clinic end generated code: output=25e06e3ee56027e2 input=1aeb4b286a21639a]*/
{
return Py_BuildValue("(N)", tupleslice(self, 0, Py_SIZE(self)));
}
PyDoc_STRVAR(index_doc,
"T.index(value, [start, [stop]]) -> integer -- return first index of value.\n"
"Raises ValueError if the value is not present."
);
PyDoc_STRVAR(count_doc,
"T.count(value) -> integer -- return number of occurrences of value");
static PyMethodDef tuple_methods[] = {
{"__getnewargs__", (PyCFunction)tuple_getnewargs, METH_NOARGS},
{"index", (PyCFunction)tupleindex, METH_VARARGS, index_doc},
{"count", (PyCFunction)tuplecount, METH_O, count_doc},
TUPLE___GETNEWARGS___METHODDEF
TUPLE_INDEX_METHODDEF
TUPLE_COUNT_METHODDEF
{NULL, NULL} /* sentinel */
};
@ -817,7 +845,7 @@ PyTypeObject PyTuple_Type = {
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE | Py_TPFLAGS_TUPLE_SUBCLASS, /* tp_flags */
tuple_doc, /* tp_doc */
tuple_new__doc__, /* tp_doc */
(traverseproc)tupletraverse, /* tp_traverse */
0, /* tp_clear */
tuplerichcompare, /* tp_richcompare */