diff --git a/Cython/Compiler/Builtin.py b/Cython/Compiler/Builtin.py index 1116d6edd4cf3aece8b4638ca58e26e639603e0b..f48e9e31411bb960f5d635f8609fcc4175bbbf3a 100644 --- a/Cython/Compiler/Builtin.py +++ b/Cython/Compiler/Builtin.py @@ -287,6 +287,8 @@ builtin_types_table = [ BuiltinMethod("reverse", "T", "r", "PyList_Reverse"), BuiltinMethod("append", "TO", "r", "__Pyx_PyList_Append", utility_code=UtilityCode.load("ListAppend", "Optimize.c")), + BuiltinMethod("extend", "TO", "r", "__Pyx_PyList_Extend", + utility_code=UtilityCode.load("ListExtend", "Optimize.c")), ]), ("dict", "PyDict_Type", [BuiltinMethod("__contains__", "TO", "b", "PyDict_Contains"), diff --git a/Cython/Utility/Optimize.c b/Cython/Utility/Optimize.c index 7b2ae077f1224d98d66eff991574629aca9c2ede..4a8a935e00043dded9483c06356ae9272dcbd31b 100644 --- a/Cython/Utility/Optimize.c +++ b/Cython/Utility/Optimize.c @@ -52,6 +52,20 @@ static CYTHON_INLINE int __Pyx_ListComp_Append(PyObject* list, PyObject* x) { #define __Pyx_ListComp_Append(L,x) PyList_Append(L,x) #endif +//////////////////// ListExtend.proto //////////////////// + +static CYTHON_INLINE int __Pyx_PyList_Extend(PyObject* L, PyObject* v) { +#if CYTHON_COMPILING_IN_CPYTHON + PyObject* none = _PyList_Extend((PyListObject*)L, v); + if (unlikely(!none)) + return -1; + Py_DECREF(none); + return 0; +#else + return PyList_SetSlice(L, PY_SSIZE_T_MAX, PY_SSIZE_T_MAX, v); +#endif +} + /////////////// pop.proto /////////////// static CYTHON_INLINE PyObject* __Pyx_PyObject_Pop(PyObject* L); /*proto*/ diff --git a/tests/run/list.pyx b/tests/run/list.pyx index 55bd4c97096d7c4947ba97a7e492ac8323c5591f..02fdc09bd2471943da0ec12c3845eb5054768576 100644 --- a/tests/run/list.pyx +++ b/tests/run/list.pyx @@ -104,10 +104,43 @@ def test_list_pop_all(): """ cdef list l1 l1 = [1,2] + i = 0 try: l1.pop() + i = 1 l1.pop(-1) + i = 2 l1.pop(0) + i = 3 except IndexError: - return True + return i == 2 return False + +def test_list_extend(): + """ + >>> test_list_extend() + [1, 2, 3, 4, 5, 6] + """ + cdef list l = [1,2,3] + l.extend([]) + l.extend(()) + l.extend(set()) + assert l == [1,2,3] + assert len(l) == 3 + l.extend([4,5,6]) + return l + +def test_none_list_extend(list l): + """ + >>> test_none_list_extend([]) + [1, 2, 3] + >>> test_none_list_extend([0, 0, 0]) + [0, 0, 0, 1, 2, 3] + >>> test_none_list_extend(None) + 123 + """ + try: + l.extend([1,2,3]) + except AttributeError: + return 123 + return l