Skip to content

Commit bb0d5a8

Browse files
committed
pythongh-111138: Add PyList_Extend() and PyList_Clear() functions
* Split list_extend() into two sub-functions: list_extend_fast() and list_extend_iter(). * list_inplace_concat() no longer has to call Py_DECREF() on the list_extend() result, since list_extend() now returns an int.
1 parent 804575b commit bb0d5a8

File tree

8 files changed

+262
-118
lines changed

8 files changed

+262
-118
lines changed

Doc/c-api/list.rst

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,17 @@ List Objects
5151
``len(list)`` on a list object.
5252
5353
54+
.. c:function:: int PyList_Clear(PyObject *list)
55+
56+
Remove all items from *list*. Similar to:
57+
``PyList_SetSlice(L, 0, PY_SSIZE_T_MAX, NULL)``.
58+
59+
Raise an exception and return ``-1`` if *list* is not a :class:`list`
60+
object. Return 0 on success.
61+
62+
.. versionadded:: 3.13
63+
64+
5465
.. c:function:: Py_ssize_t PyList_GET_SIZE(PyObject *list)
5566
5667
Similar to :c:func:`PyList_Size`, but without error checking.
@@ -112,6 +123,17 @@ List Objects
112123
to ``list.append(item)``.
113124
114125
126+
.. c:function:: int PyList_Extend(PyObject *self, PyObject *iterable)
127+
128+
Extend *list* with the contents of *iterable*. Similar to:
129+
``PyList_SetSlice(L, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, iterable)``.
130+
131+
Raise an exception and return ``-1`` if *list* is not a :class:`list`
132+
object. Return 0 on success.
133+
134+
.. versionadded:: 3.13
135+
136+
115137
.. c:function:: PyObject* PyList_GetSlice(PyObject *list, Py_ssize_t low, Py_ssize_t high)
116138
117139
Return a list of the objects in *list* containing the objects *between* *low*

Doc/whatsnew/3.13.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,6 +1156,10 @@ New Features
11561156
:c:func:`PyErr_WriteUnraisable`, but allow to customize the warning mesage.
11571157
(Contributed by Serhiy Storchaka in :gh:`108082`.)
11581158

1159+
* Add :c:func:`PyList_Extend` and :c:func:`PyList_Clear` functions: similar to
1160+
Python ``list.extend()`` and ``list.clear()`` methods.
1161+
(Contributed by Victor Stinner in :gh:`111138`.)
1162+
11591163

11601164
Porting to Python 3.13
11611165
----------------------

Include/listobject.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ PyAPI_FUNC(int) PyList_Append(PyObject *, PyObject *);
3535

3636
PyAPI_FUNC(PyObject *) PyList_GetSlice(PyObject *, Py_ssize_t, Py_ssize_t);
3737
PyAPI_FUNC(int) PyList_SetSlice(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *);
38+
PyAPI_FUNC(int) PyList_Extend(PyObject *self, PyObject *iterable);
39+
PyAPI_FUNC(int) PyList_Clear(PyObject *self);
3840

3941
PyAPI_FUNC(int) PyList_Sort(PyObject *);
4042
PyAPI_FUNC(int) PyList_Reverse(PyObject *);

Lib/test/test_capi/test_list.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -275,3 +275,39 @@ def test_list_astuple(self):
275275
self.assertRaises(SystemError, astuple, ())
276276
self.assertRaises(SystemError, astuple, object())
277277
self.assertRaises(SystemError, astuple, NULL)
278+
279+
def test_list_clear(self):
280+
# Test PyList_Clear()
281+
list_clear = _testcapi.list_clear
282+
283+
lst = [1, 2, 3]
284+
self.assertEqual(list_clear(lst), 0)
285+
self.assertEqual(lst, [])
286+
287+
lst = []
288+
self.assertEqual(list_clear(lst), 0)
289+
self.assertEqual(lst, [])
290+
291+
self.assertRaises(TypeError, list_clear, ())
292+
self.assertRaises(TypeError, list_clear, object())
293+
294+
# CRASHES list_clear(NULL)
295+
296+
def test_list_extend(self):
297+
# Test PyList_Extend()
298+
list_extend = _testcapi.list_extend
299+
300+
lst = [1]
301+
arg = [2, 3]
302+
self.assertEqual(list_extend(lst, arg), 0)
303+
self.assertEqual(lst, [1, 2, 3])
304+
305+
lst = []
306+
arg = (2, 3)
307+
self.assertEqual(list_extend(lst, arg), 0)
308+
self.assertEqual(lst, [2, 3])
309+
310+
self.assertRaises(TypeError, list_extend, [], object())
311+
312+
# CRASHES list_extend(NULL, [])
313+
# CRASHES list_extend([], NULL)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Add :c:func:`PyList_Extend` and :c:func:`PyList_Clear` functions: similar to
2+
Python ``list.extend()`` and ``list.clear()`` methods. Patch by Victor Stinner.

Modules/_testcapi/list.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,25 @@ list_astuple(PyObject* Py_UNUSED(module), PyObject *obj)
162162
}
163163

164164

165+
static PyObject *
166+
list_clear(PyObject* Py_UNUSED(module), PyObject *obj)
167+
{
168+
NULLABLE(obj);
169+
RETURN_INT(PyList_Clear(obj));
170+
}
171+
172+
173+
static PyObject *
174+
list_extend(PyObject* Py_UNUSED(module), PyObject *args)
175+
{
176+
PyObject *obj, *arg;
177+
if (!PyArg_ParseTuple(args, "OO", &obj, &arg)) {
178+
return NULL;
179+
}
180+
NULLABLE(obj);
181+
NULLABLE(arg);
182+
RETURN_INT(PyList_Extend(obj, arg));
183+
}
165184

166185

167186
static PyMethodDef test_methods[] = {
@@ -181,6 +200,8 @@ static PyMethodDef test_methods[] = {
181200
{"list_sort", list_sort, METH_O},
182201
{"list_reverse", list_reverse, METH_O},
183202
{"list_astuple", list_astuple, METH_O},
203+
{"list_clear", list_clear, METH_O},
204+
{"list_extend", list_extend, METH_VARARGS},
184205
{NULL},
185206
};
186207

Objects/clinic/listobject.c.h

Lines changed: 10 additions & 10 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)