From 63d6be9f86277129c1d41b456fd5dda40ede6178 Mon Sep 17 00:00:00 2001 From: exertustfm <54768149+exertustfm@users.noreply.github.com> Date: Fri, 7 Mar 2025 23:39:35 -0600 Subject: [PATCH 01/10] Update list_ops.c implement CPyList_Copy() implements the primitive list.copy() method --- mypyc/lib-rt/list_ops.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mypyc/lib-rt/list_ops.c b/mypyc/lib-rt/list_ops.c index d297ece8f417..249390cc0996 100644 --- a/mypyc/lib-rt/list_ops.c +++ b/mypyc/lib-rt/list_ops.c @@ -29,6 +29,15 @@ PyObject *CPyList_Build(Py_ssize_t len, ...) { return res; } +PyObject *CPyList_Copy(PyObject *list) { + if(PyList_CheckExact(list)) { + return PyList_GetSlice(list, 0, PyList_GET_SIZE(list)); + } + _Py_IDENTIFIER(copy); + return _PyObject_CallMethodIdNoArgs(list, &PyId_copy); +} + + PyObject *CPyList_GetItemUnsafe(PyObject *list, CPyTagged index) { Py_ssize_t n = CPyTagged_ShortAsSsize_t(index); PyObject *result = PyList_GET_ITEM(list, n); From 926a277d6750822d25c06a11c7b8d6f9926b1b8e Mon Sep 17 00:00:00 2001 From: exertustfm <54768149+exertustfm@users.noreply.github.com> Date: Fri, 7 Mar 2025 23:42:18 -0600 Subject: [PATCH 02/10] Update list_ops.py added list.copy() --- mypyc/primitives/list_ops.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/mypyc/primitives/list_ops.py b/mypyc/primitives/list_ops.py index f3af17d3859e..a453e568f00f 100644 --- a/mypyc/primitives/list_ops.py +++ b/mypyc/primitives/list_ops.py @@ -262,6 +262,15 @@ error_kind=ERR_MAGIC, ) +# list.copy() +method_op( + name="copy", + arg_types=[list_rprimitive], + return_type=list_rprimitive, + c_function_name="CPyList_Copy", + error_kind=ERR_MAGIC, +) + # list * int binary_op( name="*", From d5e7bc132b23f0c929dadc137803589d91ca4c52 Mon Sep 17 00:00:00 2001 From: exertustfm <54768149+exertustfm@users.noreply.github.com> Date: Fri, 7 Mar 2025 23:45:00 -0600 Subject: [PATCH 03/10] Create check-listcopy.test creates a test for list.copy() --- test-data/unit/check-listcopy | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 test-data/unit/check-listcopy diff --git a/test-data/unit/check-listcopy b/test-data/unit/check-listcopy new file mode 100644 index 000000000000..4ac8b5bb1153 --- /dev/null +++ b/test-data/unit/check-listcopy @@ -0,0 +1,31 @@ +[case testListCopy] +[builtins fixtures/list.pyi] +def test_list_copy() -> None: + l1 = [1, 2, 3, -4, 5] + l2 = l1.copy() + assert l1.copy() == l1 + assert l1.copy() == l2 + assert l1 == l2 + assert l1.copy() == l2.copy() + l1 = l2.copy() + assert l1 == l2 + assert l1.copy() == l2 + assert l1 == [1, 2, 3, -4, 5] + l2 = [1, 2, -3] + l1 = [] + assert l1.copy() == [] + assert l2.copy() != l1 + assert l2 == l2.copy() + l1 = l2 + assert l1.copy().copy() == l2.copy().copy().copy() + assert l1.copy() == l2.copy() + l1 == [1, 2, -3].copy() + assert l1 == l2 + l2 = [1, 2, 3].copy() + assert l2 != l1 + l1 = [1, 2, 3] + assert l1.copy() == l2.copy() + l3 = ["string", 2 , 3] + assert l3 == l3.copy() + l2 = ["string", 2, 3] + assert l2 == l3.copy() From abd1a046563419fbde755e177f7661dffc65d93b Mon Sep 17 00:00:00 2001 From: exertustfm <54768149+exertustfm@users.noreply.github.com> Date: Fri, 7 Mar 2025 23:46:52 -0600 Subject: [PATCH 04/10] Update list.pyi fixture for list.copy() --- test-data/unit/fixtures/list.pyi | 1 + 1 file changed, 1 insertion(+) diff --git a/test-data/unit/fixtures/list.pyi b/test-data/unit/fixtures/list.pyi index 3dcdf18b2faa..cfece986ec5c 100644 --- a/test-data/unit/fixtures/list.pyi +++ b/test-data/unit/fixtures/list.pyi @@ -25,6 +25,7 @@ class list(Sequence[T]): def __setitem__(self, x: int, v: T) -> None: pass def append(self, x: T) -> None: pass def extend(self, x: Iterable[T]) -> None: pass + def copy(self) -> list[T]: pass class tuple(Generic[T]): pass class function: pass From f1a03bbafcc13ec3cf3c7ccbc44bb6e28e1b1928 Mon Sep 17 00:00:00 2001 From: exertustfm <54768149+exertustfm@users.noreply.github.com> Date: Fri, 7 Mar 2025 23:45:00 -0600 Subject: [PATCH 05/10] Create check-listcopy.test creates a test for list.copy() renamed for missing .test extension --- test-data/unit/check-listcopy.test | 31 ++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 test-data/unit/check-listcopy.test diff --git a/test-data/unit/check-listcopy.test b/test-data/unit/check-listcopy.test new file mode 100644 index 000000000000..4ac8b5bb1153 --- /dev/null +++ b/test-data/unit/check-listcopy.test @@ -0,0 +1,31 @@ +[case testListCopy] +[builtins fixtures/list.pyi] +def test_list_copy() -> None: + l1 = [1, 2, 3, -4, 5] + l2 = l1.copy() + assert l1.copy() == l1 + assert l1.copy() == l2 + assert l1 == l2 + assert l1.copy() == l2.copy() + l1 = l2.copy() + assert l1 == l2 + assert l1.copy() == l2 + assert l1 == [1, 2, 3, -4, 5] + l2 = [1, 2, -3] + l1 = [] + assert l1.copy() == [] + assert l2.copy() != l1 + assert l2 == l2.copy() + l1 = l2 + assert l1.copy().copy() == l2.copy().copy().copy() + assert l1.copy() == l2.copy() + l1 == [1, 2, -3].copy() + assert l1 == l2 + l2 = [1, 2, 3].copy() + assert l2 != l1 + l1 = [1, 2, 3] + assert l1.copy() == l2.copy() + l3 = ["string", 2 , 3] + assert l3 == l3.copy() + l2 = ["string", 2, 3] + assert l2 == l3.copy() From eec3dfac96094869c0d322775949f5c9a0ac1b96 Mon Sep 17 00:00:00 2001 From: exertustfm <54768149+exertustfm@users.noreply.github.com> Date: Fri, 7 Mar 2025 23:46:52 -0600 Subject: [PATCH 06/10] Update list.pyi fixture for list.copy() --- test-data/unit/fixtures/list.pyi | 1 + 1 file changed, 1 insertion(+) diff --git a/test-data/unit/fixtures/list.pyi b/test-data/unit/fixtures/list.pyi index 3dcdf18b2faa..cfece986ec5c 100644 --- a/test-data/unit/fixtures/list.pyi +++ b/test-data/unit/fixtures/list.pyi @@ -25,6 +25,7 @@ class list(Sequence[T]): def __setitem__(self, x: int, v: T) -> None: pass def append(self, x: T) -> None: pass def extend(self, x: Iterable[T]) -> None: pass + def copy(self) -> list[T]: pass class tuple(Generic[T]): pass class function: pass From 32e01302bf9475c51622c921e2b4eb9e045dc128 Mon Sep 17 00:00:00 2001 From: exertustfm Date: Sat, 8 Mar 2025 00:27:56 -0600 Subject: [PATCH 07/10] Add CPyList_Copy() in header file --- mypyc/lib-rt/CPy.h | 1 + 1 file changed, 1 insertion(+) diff --git a/mypyc/lib-rt/CPy.h b/mypyc/lib-rt/CPy.h index 1c8b59855fc7..dc81c8237527 100644 --- a/mypyc/lib-rt/CPy.h +++ b/mypyc/lib-rt/CPy.h @@ -665,6 +665,7 @@ CPyTagged CPyList_Index(PyObject *list, PyObject *obj); PyObject *CPySequence_Multiply(PyObject *seq, CPyTagged t_size); PyObject *CPySequence_RMultiply(CPyTagged t_size, PyObject *seq); PyObject *CPyList_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end); +PyObject *CPyList_Copy(PyObject *list); int CPySequence_Check(PyObject *obj); From e74aad5ef19537429671d3f7b287f758525df2a8 Mon Sep 17 00:00:00 2001 From: exertustfm Date: Sun, 9 Mar 2025 03:45:35 -0500 Subject: [PATCH 08/10] Changed method to call PyObject_CallMethodNoArgs --- mypyc/lib-rt/list_ops.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mypyc/lib-rt/list_ops.c b/mypyc/lib-rt/list_ops.c index 249390cc0996..8388e1eea73a 100644 --- a/mypyc/lib-rt/list_ops.c +++ b/mypyc/lib-rt/list_ops.c @@ -34,7 +34,12 @@ PyObject *CPyList_Copy(PyObject *list) { return PyList_GetSlice(list, 0, PyList_GET_SIZE(list)); } _Py_IDENTIFIER(copy); - return _PyObject_CallMethodIdNoArgs(list, &PyId_copy); + + PyObject *name = _PyUnicode_FromId(&PyId_copy); + if (name == NULL) { + return NULL; + } + return PyObject_CallMethodNoArgs(list, name); } From de725e01e904b8f7ab4c07f8dc1a2504e918e1ae Mon Sep 17 00:00:00 2001 From: exertustfm Date: Sat, 15 Mar 2025 02:16:47 -0500 Subject: [PATCH 09/10] Revert "Update list.pyi" This reverts commit eec3dfac96094869c0d322775949f5c9a0ac1b96. --- test-data/unit/fixtures/list.pyi | 1 - 1 file changed, 1 deletion(-) diff --git a/test-data/unit/fixtures/list.pyi b/test-data/unit/fixtures/list.pyi index cfece986ec5c..3dcdf18b2faa 100644 --- a/test-data/unit/fixtures/list.pyi +++ b/test-data/unit/fixtures/list.pyi @@ -25,7 +25,6 @@ class list(Sequence[T]): def __setitem__(self, x: int, v: T) -> None: pass def append(self, x: T) -> None: pass def extend(self, x: Iterable[T]) -> None: pass - def copy(self) -> list[T]: pass class tuple(Generic[T]): pass class function: pass From 70f35732f089622dba703606d5e1330e6ebc3646 Mon Sep 17 00:00:00 2001 From: exertustfm Date: Tue, 18 Mar 2025 08:10:19 -0500 Subject: [PATCH 10/10] Create tests for list.copy() tests and fixture for list.copy() moved to the correct locations --- mypyc/test-data/fixtures/ir.py | 1 + mypyc/test-data/irbuild-lists.test | 12 ++++++++ mypyc/test-data/run-lists.test | 49 ++++++++++++++++++++++++++++++ test-data/unit/check-listcopy | 31 ------------------- test-data/unit/check-listcopy.test | 31 ------------------- 5 files changed, 62 insertions(+), 62 deletions(-) delete mode 100644 test-data/unit/check-listcopy delete mode 100644 test-data/unit/check-listcopy.test diff --git a/mypyc/test-data/fixtures/ir.py b/mypyc/test-data/fixtures/ir.py index 38fecbc20c65..4fab88fdb3a9 100644 --- a/mypyc/test-data/fixtures/ir.py +++ b/mypyc/test-data/fixtures/ir.py @@ -231,6 +231,7 @@ def sort(self) -> None: pass def reverse(self) -> None: pass def remove(self, o: _T) -> None: pass def index(self, o: _T) -> int: pass + def copy(self) -> List[_T]: pass class dict(Mapping[_K, _V]): @overload diff --git a/mypyc/test-data/irbuild-lists.test b/mypyc/test-data/irbuild-lists.test index 56ad2d53b7eb..e2c656399821 100644 --- a/mypyc/test-data/irbuild-lists.test +++ b/mypyc/test-data/irbuild-lists.test @@ -182,6 +182,18 @@ L0: r1 = r0 << 1 return r1 +[case testListCopy] +from typing import List +from typing import Any +def f(a: List[Any]) -> List[Any]: + return a.copy() +[out] +def f(a): + a, r0 :: list +L0: + r0 = CPyList_Copy(a) + return r0 + [case testListAppend] from typing import List def f(a: List[int], x: int) -> None: diff --git a/mypyc/test-data/run-lists.test b/mypyc/test-data/run-lists.test index 84d5ee121a20..3b2721093e0f 100644 --- a/mypyc/test-data/run-lists.test +++ b/mypyc/test-data/run-lists.test @@ -51,6 +51,55 @@ print(2, a) 1 [-1, 5] 2 [340282366920938463463374607431768211461, -170141183460469231731687303715884105736] +[case testListCopy] +from typing import List +from copysubclass import subc + +def test_list_copy() -> None: + l1 = [1, 2, 3, -4, 5] + l2 = l1.copy() + assert l1.copy() == l1 + assert l1.copy() == l2 + assert l1 == l2 + assert l1.copy() == l2.copy() + l1 = l2.copy() + assert l1 == l2 + assert l1.copy() == l2 + assert l1 == [1, 2, 3, -4, 5] + l2 = [1, 2, -3] + l1 = [] + assert l1.copy() == [] + assert l2.copy() != l1 + assert l2 == l2.copy() + l1 = l2 + assert l1.copy().copy() == l2.copy().copy().copy() + assert l1.copy() == l2.copy() + l1 == [1, 2, -3].copy() + assert l1 == l2 + l2 = [1, 2, 3].copy() + assert l2 != l1 + l1 = [1, 2, 3] + assert l1.copy() == l2.copy() + l3 = [1, 2 , 3, "abcdef"] + assert l3 == l3.copy() + l4 = ["abc", 5, 10] + l4 = l3.copy() + assert l4 == l3 + #subclass testing + l5: subc = subc([1, 2, 3]) + l6 = l5.copy() + assert l6 == l5 + l6 = [1, 2, "3", 4, 5] + l5 = subc([1,2,"3",4,5]) + assert l5.copy() == l6.copy() + l6 = l5.copy() + assert l5 == l6 + +[file copysubclass.py] +from typing import Any +class subc(list[Any]): + pass + [case testSieve] from typing import List diff --git a/test-data/unit/check-listcopy b/test-data/unit/check-listcopy deleted file mode 100644 index 4ac8b5bb1153..000000000000 --- a/test-data/unit/check-listcopy +++ /dev/null @@ -1,31 +0,0 @@ -[case testListCopy] -[builtins fixtures/list.pyi] -def test_list_copy() -> None: - l1 = [1, 2, 3, -4, 5] - l2 = l1.copy() - assert l1.copy() == l1 - assert l1.copy() == l2 - assert l1 == l2 - assert l1.copy() == l2.copy() - l1 = l2.copy() - assert l1 == l2 - assert l1.copy() == l2 - assert l1 == [1, 2, 3, -4, 5] - l2 = [1, 2, -3] - l1 = [] - assert l1.copy() == [] - assert l2.copy() != l1 - assert l2 == l2.copy() - l1 = l2 - assert l1.copy().copy() == l2.copy().copy().copy() - assert l1.copy() == l2.copy() - l1 == [1, 2, -3].copy() - assert l1 == l2 - l2 = [1, 2, 3].copy() - assert l2 != l1 - l1 = [1, 2, 3] - assert l1.copy() == l2.copy() - l3 = ["string", 2 , 3] - assert l3 == l3.copy() - l2 = ["string", 2, 3] - assert l2 == l3.copy() diff --git a/test-data/unit/check-listcopy.test b/test-data/unit/check-listcopy.test deleted file mode 100644 index 4ac8b5bb1153..000000000000 --- a/test-data/unit/check-listcopy.test +++ /dev/null @@ -1,31 +0,0 @@ -[case testListCopy] -[builtins fixtures/list.pyi] -def test_list_copy() -> None: - l1 = [1, 2, 3, -4, 5] - l2 = l1.copy() - assert l1.copy() == l1 - assert l1.copy() == l2 - assert l1 == l2 - assert l1.copy() == l2.copy() - l1 = l2.copy() - assert l1 == l2 - assert l1.copy() == l2 - assert l1 == [1, 2, 3, -4, 5] - l2 = [1, 2, -3] - l1 = [] - assert l1.copy() == [] - assert l2.copy() != l1 - assert l2 == l2.copy() - l1 = l2 - assert l1.copy().copy() == l2.copy().copy().copy() - assert l1.copy() == l2.copy() - l1 == [1, 2, -3].copy() - assert l1 == l2 - l2 = [1, 2, 3].copy() - assert l2 != l1 - l1 = [1, 2, 3] - assert l1.copy() == l2.copy() - l3 = ["string", 2 , 3] - assert l3 == l3.copy() - l2 = ["string", 2, 3] - assert l2 == l3.copy()