Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
102 changes: 102 additions & 0 deletions Objects/clinic/tupleobject.c.h
Original file line number Diff line number Diff line change
@@ -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]*/
120 changes: 74 additions & 46 deletions Objects/tupleobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -523,28 +530,39 @@ tuplerepeat(PyTupleObject *a, Py_ssize_t n)
return (PyObject *) np;
}

/*[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 *
tupleindex(PyTupleObject *self, PyObject *args)
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, start=0, stop=Py_SIZE(self);
PyObject *v;
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)
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);
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)
Expand All @@ -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)
Expand Down Expand Up @@ -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));
Expand All @@ -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 */
Expand Down Expand Up @@ -766,24 +797,21 @@ tuplesubscript(PyTupleObject* self, PyObject* item)
}
}

/*[clinic input]
tuple.__getnewargs__
[clinic start generated code]*/

static PyObject *
tuple_getnewargs(PyTupleObject *v)
tuple___getnewargs___impl(PyTupleObject *self)
/*[clinic end generated code: output=25e06e3ee56027e2 input=1aeb4b286a21639a]*/
{
return Py_BuildValue("(N)", tupleslice(v, 0, Py_SIZE(v)));

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 */
};

Expand Down Expand Up @@ -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 */
Expand Down