From fdd42c481edba4261f861fc1dfe24bbd79b5a17a Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Sat, 11 Mar 2017 09:19:20 +0200 Subject: [PATCH] bpo-20185: Convert list object implementation to Argument Clinic. (#542) --- Lib/idlelib/idle_test/test_calltips.py | 8 +- Objects/clinic/listobject.c.h | 300 ++++++++++++++++++++ Objects/listobject.c | 373 +++++++++++++++---------- 3 files changed, 527 insertions(+), 154 deletions(-) create mode 100644 Objects/clinic/listobject.c.h diff --git a/Lib/idlelib/idle_test/test_calltips.py b/Lib/idlelib/idle_test/test_calltips.py index 0b11602ca9..29b9f06faf 100644 --- a/Lib/idlelib/idle_test/test_calltips.py +++ b/Lib/idlelib/idle_test/test_calltips.py @@ -58,7 +58,7 @@ class Get_signatureTest(unittest.TestCase): 'Create and return a new object. See help(type) for accurate signature.') gtest(list.__init__, 'Initialize self. See help(type(self)) for accurate signature.') - append_doc = "L.append(object) -> None -- append object to end" + append_doc = "Append object to the end of the list." gtest(list.append, append_doc) gtest([].append, append_doc) gtest(List.append, append_doc) @@ -81,9 +81,9 @@ class Get_signatureTest(unittest.TestCase): def test_multiline_docstring(self): # Test fewer lines than max. - self.assertEqual(signature(list), - "list() -> new empty list\n" - "list(iterable) -> new list initialized from iterable's items") + self.assertEqual(signature(range), + "range(stop) -> range object\n" + "range(start, stop[, step]) -> range object") # Test max lines self.assertEqual(signature(bytes), '''\ diff --git a/Objects/clinic/listobject.c.h b/Objects/clinic/listobject.c.h new file mode 100644 index 0000000000..eeb932a240 --- /dev/null +++ b/Objects/clinic/listobject.c.h @@ -0,0 +1,300 @@ +/*[clinic input] +preserve +[clinic start generated code]*/ + +PyDoc_STRVAR(list_insert__doc__, +"insert($self, index, object, /)\n" +"--\n" +"\n" +"Insert object before index."); + +#define LIST_INSERT_METHODDEF \ + {"insert", (PyCFunction)list_insert, METH_FASTCALL, list_insert__doc__}, + +static PyObject * +list_insert_impl(PyListObject *self, Py_ssize_t index, PyObject *object); + +static PyObject * +list_insert(PyListObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + Py_ssize_t index; + PyObject *object; + + if (!_PyArg_ParseStack(args, nargs, "nO:insert", + &index, &object)) { + goto exit; + } + + if (!_PyArg_NoStackKeywords("insert", kwnames)) { + goto exit; + } + return_value = list_insert_impl(self, index, object); + +exit: + return return_value; +} + +PyDoc_STRVAR(list_clear__doc__, +"clear($self, /)\n" +"--\n" +"\n" +"Remove all items from list."); + +#define LIST_CLEAR_METHODDEF \ + {"clear", (PyCFunction)list_clear, METH_NOARGS, list_clear__doc__}, + +static PyObject * +list_clear_impl(PyListObject *self); + +static PyObject * +list_clear(PyListObject *self, PyObject *Py_UNUSED(ignored)) +{ + return list_clear_impl(self); +} + +PyDoc_STRVAR(list_copy__doc__, +"copy($self, /)\n" +"--\n" +"\n" +"Return a shallow copy of the list."); + +#define LIST_COPY_METHODDEF \ + {"copy", (PyCFunction)list_copy, METH_NOARGS, list_copy__doc__}, + +static PyObject * +list_copy_impl(PyListObject *self); + +static PyObject * +list_copy(PyListObject *self, PyObject *Py_UNUSED(ignored)) +{ + return list_copy_impl(self); +} + +PyDoc_STRVAR(list_append__doc__, +"append($self, object, /)\n" +"--\n" +"\n" +"Append object to the end of the list."); + +#define LIST_APPEND_METHODDEF \ + {"append", (PyCFunction)list_append, METH_O, list_append__doc__}, + +PyDoc_STRVAR(list_extend__doc__, +"extend($self, iterable, /)\n" +"--\n" +"\n" +"Extend list by appending elements from the iterable."); + +#define LIST_EXTEND_METHODDEF \ + {"extend", (PyCFunction)list_extend, METH_O, list_extend__doc__}, + +PyDoc_STRVAR(list_pop__doc__, +"pop($self, index=-1, /)\n" +"--\n" +"\n" +"Remove and return item at index (default last).\n" +"\n" +"Raises IndexError if list is empty or index is out of range."); + +#define LIST_POP_METHODDEF \ + {"pop", (PyCFunction)list_pop, METH_FASTCALL, list_pop__doc__}, + +static PyObject * +list_pop_impl(PyListObject *self, Py_ssize_t index); + +static PyObject * +list_pop(PyListObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + Py_ssize_t index = -1; + + if (!_PyArg_ParseStack(args, nargs, "|n:pop", + &index)) { + goto exit; + } + + if (!_PyArg_NoStackKeywords("pop", kwnames)) { + goto exit; + } + return_value = list_pop_impl(self, index); + +exit: + return return_value; +} + +PyDoc_STRVAR(list_sort__doc__, +"sort($self, /, *, key=None, reverse=False)\n" +"--\n" +"\n" +"Stable sort *IN PLACE*."); + +#define LIST_SORT_METHODDEF \ + {"sort", (PyCFunction)list_sort, METH_FASTCALL, list_sort__doc__}, + +static PyObject * +list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse); + +static PyObject * +list_sort(PyListObject *self, PyObject **args, Py_ssize_t nargs, PyObject *kwnames) +{ + PyObject *return_value = NULL; + static const char * const _keywords[] = {"key", "reverse", NULL}; + static _PyArg_Parser _parser = {"|$Oi:sort", _keywords, 0}; + PyObject *keyfunc = Py_None; + int reverse = 0; + + if (!_PyArg_ParseStackAndKeywords(args, nargs, kwnames, &_parser, + &keyfunc, &reverse)) { + goto exit; + } + return_value = list_sort_impl(self, keyfunc, reverse); + +exit: + return return_value; +} + +PyDoc_STRVAR(list_reverse__doc__, +"reverse($self, /)\n" +"--\n" +"\n" +"Reverse *IN PLACE*."); + +#define LIST_REVERSE_METHODDEF \ + {"reverse", (PyCFunction)list_reverse, METH_NOARGS, list_reverse__doc__}, + +static PyObject * +list_reverse_impl(PyListObject *self); + +static PyObject * +list_reverse(PyListObject *self, PyObject *Py_UNUSED(ignored)) +{ + return list_reverse_impl(self); +} + +PyDoc_STRVAR(list_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 LIST_INDEX_METHODDEF \ + {"index", (PyCFunction)list_index, METH_FASTCALL, list_index__doc__}, + +static PyObject * +list_index_impl(PyListObject *self, PyObject *value, Py_ssize_t start, + Py_ssize_t stop); + +static PyObject * +list_index(PyListObject *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 = list_index_impl(self, value, start, stop); + +exit: + return return_value; +} + +PyDoc_STRVAR(list_count__doc__, +"count($self, value, /)\n" +"--\n" +"\n" +"Return number of occurrences of value."); + +#define LIST_COUNT_METHODDEF \ + {"count", (PyCFunction)list_count, METH_O, list_count__doc__}, + +PyDoc_STRVAR(list_remove__doc__, +"remove($self, value, /)\n" +"--\n" +"\n" +"Remove first occurrence of value.\n" +"\n" +"Raises ValueError if the value is not present."); + +#define LIST_REMOVE_METHODDEF \ + {"remove", (PyCFunction)list_remove, METH_O, list_remove__doc__}, + +PyDoc_STRVAR(list___init____doc__, +"list(iterable=(), /)\n" +"--\n" +"\n" +"Built-in mutable sequence.\n" +"\n" +"If no argument is given, the constructor creates a new empty list.\n" +"The argument must be an iterable if specified."); + +static int +list___init___impl(PyListObject *self, PyObject *iterable); + +static int +list___init__(PyObject *self, PyObject *args, PyObject *kwargs) +{ + int return_value = -1; + PyObject *iterable = NULL; + + if ((Py_TYPE(self) == &PyList_Type) && + !_PyArg_NoKeywords("list", kwargs)) { + goto exit; + } + if (!PyArg_UnpackTuple(args, "list", + 0, 1, + &iterable)) { + goto exit; + } + return_value = list___init___impl((PyListObject *)self, iterable); + +exit: + return return_value; +} + +PyDoc_STRVAR(list___sizeof____doc__, +"__sizeof__($self, /)\n" +"--\n" +"\n" +"Return the size of the list in memory, in bytes."); + +#define LIST___SIZEOF___METHODDEF \ + {"__sizeof__", (PyCFunction)list___sizeof__, METH_NOARGS, list___sizeof____doc__}, + +static PyObject * +list___sizeof___impl(PyListObject *self); + +static PyObject * +list___sizeof__(PyListObject *self, PyObject *Py_UNUSED(ignored)) +{ + return list___sizeof___impl(self); +} + +PyDoc_STRVAR(list___reversed____doc__, +"__reversed__($self, /)\n" +"--\n" +"\n" +"Return a reverse iterator over the list."); + +#define LIST___REVERSED___METHODDEF \ + {"__reversed__", (PyCFunction)list___reversed__, METH_NOARGS, list___reversed____doc__}, + +static PyObject * +list___reversed___impl(PyListObject *self); + +static PyObject * +list___reversed__(PyListObject *self, PyObject *Py_UNUSED(ignored)) +{ + return list___reversed___impl(self); +} +/*[clinic end generated code: output=2a3b75efcf858ed5 input=a9049054013a1b77]*/ diff --git a/Objects/listobject.c b/Objects/listobject.c index 473bd20874..b0e58bf283 100644 --- a/Objects/listobject.c +++ b/Objects/listobject.c @@ -9,6 +9,13 @@ #include /* For size_t */ #endif +/*[clinic input] +class list "PyListObject *" "&PyList_Type" +[clinic start generated code]*/ +/*[clinic end generated code: output=da39a3ee5e6b4b0d input=f9b222678f9f71e0]*/ + +#include "clinic/listobject.c.h" + /* Ensure ob_item has room for at least newsize elements, and set * ob_size to newsize. If newsize > ob_size on entry, the content * of the new slots at exit is undefined heap trash; it's the caller's @@ -542,7 +549,7 @@ list_repeat(PyListObject *a, Py_ssize_t n) } static int -list_clear(PyListObject *a) +_list_clear(PyListObject *a) { Py_ssize_t i; PyObject **item = a->ob_item; @@ -624,7 +631,7 @@ list_ass_slice(PyListObject *a, Py_ssize_t ilow, Py_ssize_t ihigh, PyObject *v) d = n - norig; if (Py_SIZE(a) + d == 0) { Py_XDECREF(v_as_SF); - return list_clear(a); + return _list_clear(a); } item = a->ob_item; /* recycle the items that we are about to remove */ @@ -700,7 +707,7 @@ list_inplace_repeat(PyListObject *self, Py_ssize_t n) } if (n < 1) { - (void)list_clear(self); + (void)_list_clear(self); Py_INCREF(self); return (PyObject *)self; } @@ -740,45 +747,86 @@ list_ass_item(PyListObject *a, Py_ssize_t i, PyObject *v) return 0; } +/*[clinic input] +list.insert + + index: Py_ssize_t + object: object + / + +Insert object before index. +[clinic start generated code]*/ + static PyObject * -listinsert(PyListObject *self, PyObject *args) +list_insert_impl(PyListObject *self, Py_ssize_t index, PyObject *object) +/*[clinic end generated code: output=7f35e32f60c8cb78 input=858514cf894c7eab]*/ { - Py_ssize_t i; - PyObject *v; - if (!PyArg_ParseTuple(args, "nO:insert", &i, &v)) - return NULL; - if (ins1(self, i, v) == 0) + if (ins1(self, index, object) == 0) Py_RETURN_NONE; return NULL; } +/*[clinic input] +list.clear + +Remove all items from list. +[clinic start generated code]*/ + static PyObject * -listclear(PyListObject *self) +list_clear_impl(PyListObject *self) +/*[clinic end generated code: output=67a1896c01f74362 input=ca3c1646856742f6]*/ { - list_clear(self); + _list_clear(self); Py_RETURN_NONE; } +/*[clinic input] +list.copy + +Return a shallow copy of the list. +[clinic start generated code]*/ + static PyObject * -listcopy(PyListObject *self) +list_copy_impl(PyListObject *self) +/*[clinic end generated code: output=ec6b72d6209d418e input=6453ab159e84771f]*/ { return list_slice(self, 0, Py_SIZE(self)); } +/*[clinic input] +list.append + + object: object + / + +Append object to the end of the list. +[clinic start generated code]*/ + static PyObject * -listappend(PyListObject *self, PyObject *v) +list_append(PyListObject *self, PyObject *object) +/*[clinic end generated code: output=7c096003a29c0eae input=43a3fe48a7066e91]*/ { - if (app1(self, v) == 0) + if (app1(self, object) == 0) Py_RETURN_NONE; return NULL; } +/*[clinic input] +list.extend + + iterable: object + / + +Extend list by appending elements from the iterable. +[clinic start generated code]*/ + static PyObject * -listextend(PyListObject *self, PyObject *b) +list_extend(PyListObject *self, PyObject *iterable) +/*[clinic end generated code: output=630fb3bca0c8e789 input=9ec5ba3a81be3a4d]*/ { PyObject *it; /* iter(v) */ Py_ssize_t m; /* size of self */ - Py_ssize_t n; /* guess for size of b */ + Py_ssize_t n; /* guess for size of iterable */ Py_ssize_t mn; /* m + n */ Py_ssize_t i; PyObject *(*iternext)(PyObject *); @@ -787,15 +835,16 @@ listextend(PyListObject *self, PyObject *b) 1) lists and tuples which can use PySequence_Fast ops 2) extending self to self requires making a copy first */ - if (PyList_CheckExact(b) || PyTuple_CheckExact(b) || (PyObject *)self == b) { + if (PyList_CheckExact(iterable) || PyTuple_CheckExact(iterable) || + (PyObject *)self == iterable) { PyObject **src, **dest; - b = PySequence_Fast(b, "argument must be iterable"); - if (!b) + iterable = PySequence_Fast(iterable, "argument must be iterable"); + if (!iterable) return NULL; - n = PySequence_Fast_GET_SIZE(b); + n = PySequence_Fast_GET_SIZE(iterable); if (n == 0) { - /* short circuit when b is empty */ - Py_DECREF(b); + /* short circuit when iterable is empty */ + Py_DECREF(iterable); Py_RETURN_NONE; } m = Py_SIZE(self); @@ -803,33 +852,33 @@ listextend(PyListObject *self, PyObject *b) an overflow on any relevant platform */ assert(m < PY_SSIZE_T_MAX - n); if (list_resize(self, m + n) < 0) { - Py_DECREF(b); + Py_DECREF(iterable); return NULL; } - /* note that we may still have self == b here for the + /* note that we may still have self == iterable here for the * situation a.extend(a), but the following code works * in that case too. Just make sure to resize self * before calling PySequence_Fast_ITEMS. */ - /* populate the end of self with b's items */ - src = PySequence_Fast_ITEMS(b); + /* populate the end of self with iterable's items */ + src = PySequence_Fast_ITEMS(iterable); dest = self->ob_item + m; for (i = 0; i < n; i++) { PyObject *o = src[i]; Py_INCREF(o); dest[i] = o; } - Py_DECREF(b); + Py_DECREF(iterable); Py_RETURN_NONE; } - it = PyObject_GetIter(b); + it = PyObject_GetIter(iterable); if (it == NULL) return NULL; iternext = *it->ob_type->tp_iternext; /* Guess a result list size. */ - n = PyObject_LengthHint(b, 8); + n = PyObject_LengthHint(iterable, 8); if (n < 0) { Py_DECREF(it); return NULL; @@ -890,9 +939,9 @@ listextend(PyListObject *self, PyObject *b) } PyObject * -_PyList_Extend(PyListObject *self, PyObject *b) +_PyList_Extend(PyListObject *self, PyObject *iterable) { - return listextend(self, b); + return list_extend(self, iterable); } static PyObject * @@ -900,7 +949,7 @@ list_inplace_concat(PyListObject *self, PyObject *other) { PyObject *result; - result = listextend(self, other); + result = list_extend(self, other); if (result == NULL) return result; Py_DECREF(result); @@ -908,29 +957,37 @@ list_inplace_concat(PyListObject *self, PyObject *other) return (PyObject *)self; } +/*[clinic input] +list.pop + + index: Py_ssize_t = -1 + / + +Remove and return item at index (default last). + +Raises IndexError if list is empty or index is out of range. +[clinic start generated code]*/ + static PyObject * -listpop(PyListObject *self, PyObject *args) +list_pop_impl(PyListObject *self, Py_ssize_t index) +/*[clinic end generated code: output=6bd69dcb3f17eca8 input=b83675976f329e6f]*/ { - Py_ssize_t i = -1; PyObject *v; int status; - if (!PyArg_ParseTuple(args, "|n:pop", &i)) - return NULL; - if (Py_SIZE(self) == 0) { /* Special-case most common failure cause */ PyErr_SetString(PyExc_IndexError, "pop from empty list"); return NULL; } - if (i < 0) - i += Py_SIZE(self); - if (i < 0 || i >= Py_SIZE(self)) { + if (index < 0) + index += Py_SIZE(self); + if (index < 0 || index >= Py_SIZE(self)) { PyErr_SetString(PyExc_IndexError, "pop index out of range"); return NULL; } - v = self->ob_item[i]; - if (i == Py_SIZE(self) - 1) { + v = self->ob_item[index]; + if (index == Py_SIZE(self) - 1) { status = list_resize(self, Py_SIZE(self) - 1); if (status >= 0) return v; /* and v now owns the reference the list had */ @@ -938,7 +995,7 @@ listpop(PyListObject *self, PyObject *args) return NULL; } Py_INCREF(v); - status = list_ass_slice(self, i, i+1, (PyObject *)NULL); + status = list_ass_slice(self, index, index+1, (PyObject *)NULL); if (status < 0) { Py_DECREF(v); return NULL; @@ -1906,8 +1963,19 @@ reverse_sortslice(sortslice *s, Py_ssize_t n) * list will be some permutation of its input state (nothing is lost or * duplicated). */ +/*[clinic input] +list.sort + + * + key as keyfunc: object = None + reverse: int(c_default="0") = False + +Stable sort *IN PLACE*. +[clinic start generated code]*/ + static PyObject * -listsort_impl(PyListObject *self, PyObject *keyfunc, int reverse) +list_sort_impl(PyListObject *self, PyObject *keyfunc, int reverse) +/*[clinic end generated code: output=57b9f9c5e23fbe42 input=5029c13c9209d86a]*/ { MergeState ms; Py_ssize_t nremaining; @@ -1921,7 +1989,7 @@ listsort_impl(PyListObject *self, PyObject *keyfunc, int reverse) PyObject **keys; assert(self != NULL); - assert (PyList_Check(self)); + assert(PyList_Check(self)); if (keyfunc == Py_None) keyfunc = NULL; @@ -2057,7 +2125,7 @@ keyfunc_fail: self->ob_item = saved_ob_item; self->allocated = saved_allocated; if (final_ob_item != NULL) { - /* we cannot use list_clear() for this because it does not + /* we cannot use _list_clear() for this because it does not guarantee that the list is really empty when it returns */ while (--i >= 0) { Py_XDECREF(final_ob_item[i]); @@ -2070,19 +2138,6 @@ keyfunc_fail: #undef IFLT #undef ISLT -static PyObject * -listsort(PyListObject *self, PyObject *args, PyObject *kwds) -{ - static char *kwlist[] = {"key", "reverse", 0}; - PyObject *keyfunc = NULL; - int reverse = 0; - - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|$Oi:sort", - kwlist, &keyfunc, &reverse)) - return NULL; - return listsort_impl(self, keyfunc, reverse); -} - int PyList_Sort(PyObject *v) { @@ -2090,15 +2145,22 @@ PyList_Sort(PyObject *v) PyErr_BadInternalCall(); return -1; } - v = listsort_impl((PyListObject *)v, NULL, 0); + v = list_sort_impl((PyListObject *)v, NULL, 0); if (v == NULL) return -1; Py_DECREF(v); return 0; } +/*[clinic input] +list.reverse + +Reverse *IN PLACE*. +[clinic start generated code]*/ + static PyObject * -listreverse(PyListObject *self) +list_reverse_impl(PyListObject *self) +/*[clinic end generated code: output=482544fc451abea9 input=eefd4c3ae1bc9887]*/ { if (Py_SIZE(self) > 1) reverse_slice(self->ob_item, self->ob_item + Py_SIZE(self)); @@ -2144,16 +2206,26 @@ PyList_AsTuple(PyObject *v) return w; } +/*[clinic input] +list.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 * -listindex(PyListObject *self, PyObject *args) +list_index_impl(PyListObject *self, PyObject *value, Py_ssize_t start, + Py_ssize_t stop) +/*[clinic end generated code: output=ec51b88787e4e481 input=70b7247e398a6999]*/ { - 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) @@ -2165,24 +2237,34 @@ listindex(PyListObject *self, PyObject *args) stop = 0; } for (i = start; i < stop && 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) return PyLong_FromSsize_t(i); else if (cmp < 0) return NULL; } - PyErr_Format(PyExc_ValueError, "%R is not in list", v); + PyErr_Format(PyExc_ValueError, "%R is not in list", value); return NULL; } +/*[clinic input] +list.count + + value: object + / + +Return number of occurrences of value. +[clinic start generated code]*/ + static PyObject * -listcount(PyListObject *self, PyObject *v) +list_count(PyListObject *self, PyObject *value) +/*[clinic end generated code: output=b1f5d284205ae714 input=3bdc3a5e6f749565]*/ { 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) @@ -2191,13 +2273,25 @@ listcount(PyListObject *self, PyObject *v) return PyLong_FromSsize_t(count); } +/*[clinic input] +list.remove + + value: object + / + +Remove first occurrence of value. + +Raises ValueError if the value is not present. +[clinic start generated code]*/ + static PyObject * -listremove(PyListObject *self, PyObject *v) +list_remove(PyListObject *self, PyObject *value) +/*[clinic end generated code: output=f087e1951a5e30d1 input=2dc2ba5bb2fb1f82]*/ { 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) { if (list_ass_slice(self, i, i+1, (PyObject *)NULL) == 0) @@ -2289,16 +2383,22 @@ list_richcompare(PyObject *v, PyObject *w, int op) return PyObject_RichCompare(vl->ob_item[i], wl->ob_item[i], op); } -static int -list_init(PyListObject *self, PyObject *args, PyObject *kw) -{ - PyObject *arg = NULL; +/*[clinic input] +list.__init__ - if (!_PyArg_NoKeywords("list()", kw)) - return -1; - if (!PyArg_UnpackTuple(args, "list", 0, 1, &arg)) - return -1; + iterable: object(c_default="NULL") = () + / + +Built-in mutable sequence. + +If no argument is given, the constructor creates a new empty list. +The argument must be an iterable if specified. +[clinic start generated code]*/ +static int +list___init___impl(PyListObject *self, PyObject *iterable) +/*[clinic end generated code: output=0f3c21379d01de48 input=b3f3fe7206af8f6b]*/ +{ /* Verify list invariants established by PyType_GenericAlloc() */ assert(0 <= Py_SIZE(self)); assert(Py_SIZE(self) <= self->allocated || self->allocated == -1); @@ -2307,10 +2407,10 @@ list_init(PyListObject *self, PyObject *args, PyObject *kw) /* Empty previous contents */ if (self->ob_item != NULL) { - (void)list_clear(self); + (void)_list_clear(self); } - if (arg != NULL) { - PyObject *rv = listextend(self, arg); + if (iterable != NULL) { + PyObject *rv = list_extend(self, iterable); if (rv == NULL) return -1; Py_DECREF(rv); @@ -2318,8 +2418,15 @@ list_init(PyListObject *self, PyObject *args, PyObject *kw) return 0; } +/*[clinic input] +list.__sizeof__ + +Return the size of the list in memory, in bytes. +[clinic start generated code]*/ + static PyObject * -list_sizeof(PyListObject *self) +list___sizeof___impl(PyListObject *self) +/*[clinic end generated code: output=3417541f95f9a53e input=b8030a5d5ce8a187]*/ { Py_ssize_t res; @@ -2328,57 +2435,23 @@ list_sizeof(PyListObject *self) } static PyObject *list_iter(PyObject *seq); -static PyObject *list_reversed(PyListObject* seq, PyObject* unused); - -PyDoc_STRVAR(getitem_doc, -"x.__getitem__(y) <==> x[y]"); -PyDoc_STRVAR(reversed_doc, -"L.__reversed__() -- return a reverse iterator over the list"); -PyDoc_STRVAR(sizeof_doc, -"L.__sizeof__() -- size of L in memory, in bytes"); -PyDoc_STRVAR(clear_doc, -"L.clear() -> None -- remove all items from L"); -PyDoc_STRVAR(copy_doc, -"L.copy() -> list -- a shallow copy of L"); -PyDoc_STRVAR(append_doc, -"L.append(object) -> None -- append object to end"); -PyDoc_STRVAR(extend_doc, -"L.extend(iterable) -> None -- extend list by appending elements from the iterable"); -PyDoc_STRVAR(insert_doc, -"L.insert(index, object) -- insert object before index"); -PyDoc_STRVAR(pop_doc, -"L.pop([index]) -> item -- remove and return item at index (default last).\n" -"Raises IndexError if list is empty or index is out of range."); -PyDoc_STRVAR(remove_doc, -"L.remove(value) -> None -- remove first occurrence of value.\n" -"Raises ValueError if the value is not present."); -PyDoc_STRVAR(index_doc, -"L.index(value, [start, [stop]]) -> integer -- return first index of value.\n" -"Raises ValueError if the value is not present."); -PyDoc_STRVAR(count_doc, -"L.count(value) -> integer -- return number of occurrences of value"); -PyDoc_STRVAR(reverse_doc, -"L.reverse() -- reverse *IN PLACE*"); -PyDoc_STRVAR(sort_doc, -"L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*"); - static PyObject *list_subscript(PyListObject*, PyObject*); static PyMethodDef list_methods[] = { - {"__getitem__", (PyCFunction)list_subscript, METH_O|METH_COEXIST, getitem_doc}, - {"__reversed__",(PyCFunction)list_reversed, METH_NOARGS, reversed_doc}, - {"__sizeof__", (PyCFunction)list_sizeof, METH_NOARGS, sizeof_doc}, - {"clear", (PyCFunction)listclear, METH_NOARGS, clear_doc}, - {"copy", (PyCFunction)listcopy, METH_NOARGS, copy_doc}, - {"append", (PyCFunction)listappend, METH_O, append_doc}, - {"insert", (PyCFunction)listinsert, METH_VARARGS, insert_doc}, - {"extend", (PyCFunction)listextend, METH_O, extend_doc}, - {"pop", (PyCFunction)listpop, METH_VARARGS, pop_doc}, - {"remove", (PyCFunction)listremove, METH_O, remove_doc}, - {"index", (PyCFunction)listindex, METH_VARARGS, index_doc}, - {"count", (PyCFunction)listcount, METH_O, count_doc}, - {"reverse", (PyCFunction)listreverse, METH_NOARGS, reverse_doc}, - {"sort", (PyCFunction)listsort, METH_VARARGS | METH_KEYWORDS, sort_doc}, + {"__getitem__", (PyCFunction)list_subscript, METH_O|METH_COEXIST, "x.__getitem__(y) <==> x[y]"}, + LIST___REVERSED___METHODDEF + LIST___SIZEOF___METHODDEF + LIST_CLEAR_METHODDEF + LIST_COPY_METHODDEF + LIST_APPEND_METHODDEF + LIST_INSERT_METHODDEF + LIST_EXTEND_METHODDEF + LIST_POP_METHODDEF + LIST_REMOVE_METHODDEF + LIST_INDEX_METHODDEF + LIST_COUNT_METHODDEF + LIST_REVERSE_METHODDEF + LIST_SORT_METHODDEF {NULL, NULL} /* sentinel */ }; @@ -2395,10 +2468,6 @@ static PySequenceMethods list_as_sequence = { (ssizeargfunc)list_inplace_repeat, /* sq_inplace_repeat */ }; -PyDoc_STRVAR(list_doc, -"list() -> new empty list\n" -"list(iterable) -> new list initialized from iterable's items"); - static PyObject * list_subscript(PyListObject* self, PyObject* item) { @@ -2640,10 +2709,10 @@ PyTypeObject PyList_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LIST_SUBCLASS, /* tp_flags */ - list_doc, /* tp_doc */ + Py_TPFLAGS_BASETYPE | Py_TPFLAGS_LIST_SUBCLASS, /* tp_flags */ + list___init____doc__, /* tp_doc */ (traverseproc)list_traverse, /* tp_traverse */ - (inquiry)list_clear, /* tp_clear */ + (inquiry)_list_clear, /* tp_clear */ list_richcompare, /* tp_richcompare */ 0, /* tp_weaklistoffset */ list_iter, /* tp_iter */ @@ -2656,13 +2725,12 @@ PyTypeObject PyList_Type = { 0, /* tp_descr_get */ 0, /* tp_descr_set */ 0, /* tp_dictoffset */ - (initproc)list_init, /* tp_init */ + (initproc)list___init__, /* tp_init */ PyType_GenericAlloc, /* tp_alloc */ PyType_GenericNew, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; - /*********************** List Iterator **************************/ typedef struct { @@ -2671,7 +2739,6 @@ typedef struct { PyListObject *it_seq; /* Set to NULL when iterator is exhausted */ } listiterobject; -static PyObject *list_iter(PyObject *); static void listiter_dealloc(listiterobject *); static int listiter_traverse(listiterobject *, visitproc, void *); static PyObject *listiter_next(listiterobject *); @@ -2825,7 +2892,6 @@ typedef struct { PyListObject *it_seq; /* Set to NULL when iterator is exhausted */ } listreviterobject; -static PyObject *list_reversed(PyListObject *, PyObject *); static void listreviter_dealloc(listreviterobject *); static int listreviter_traverse(listreviterobject *, visitproc, void *); static PyObject *listreviter_next(listreviterobject *); @@ -2873,18 +2939,25 @@ PyTypeObject PyListRevIter_Type = { 0, }; +/*[clinic input] +list.__reversed__ + +Return a reverse iterator over the list. +[clinic start generated code]*/ + static PyObject * -list_reversed(PyListObject *seq, PyObject *unused) +list___reversed___impl(PyListObject *self) +/*[clinic end generated code: output=b166f073208c888c input=eadb6e17f8a6a280]*/ { listreviterobject *it; it = PyObject_GC_New(listreviterobject, &PyListRevIter_Type); if (it == NULL) return NULL; - assert(PyList_Check(seq)); - it->it_index = PyList_GET_SIZE(seq) - 1; - Py_INCREF(seq); - it->it_seq = seq; + assert(PyList_Check(self)); + it->it_index = PyList_GET_SIZE(self) - 1; + Py_INCREF(self); + it->it_seq = self; PyObject_GC_Track(it); return (PyObject *)it; } -- 2.40.0