Skip to content

Commit 04a0fe8

Browse files
authored
[mypyc] Add and implement primitive list.copy() (#18771)
Closes mypyc/mypyc#1092
1 parent 5c87e97 commit 04a0fe8

File tree

6 files changed

+86
-0
lines changed

6 files changed

+86
-0
lines changed

mypyc/lib-rt/CPy.h

+1
Original file line numberDiff line numberDiff line change
@@ -665,6 +665,7 @@ CPyTagged CPyList_Index(PyObject *list, PyObject *obj);
665665
PyObject *CPySequence_Multiply(PyObject *seq, CPyTagged t_size);
666666
PyObject *CPySequence_RMultiply(CPyTagged t_size, PyObject *seq);
667667
PyObject *CPyList_GetSlice(PyObject *obj, CPyTagged start, CPyTagged end);
668+
PyObject *CPyList_Copy(PyObject *list);
668669
int CPySequence_Check(PyObject *obj);
669670

670671

mypyc/lib-rt/list_ops.c

+14
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,20 @@ PyObject *CPyList_Build(Py_ssize_t len, ...) {
2929
return res;
3030
}
3131

32+
PyObject *CPyList_Copy(PyObject *list) {
33+
if(PyList_CheckExact(list)) {
34+
return PyList_GetSlice(list, 0, PyList_GET_SIZE(list));
35+
}
36+
_Py_IDENTIFIER(copy);
37+
38+
PyObject *name = _PyUnicode_FromId(&PyId_copy);
39+
if (name == NULL) {
40+
return NULL;
41+
}
42+
return PyObject_CallMethodNoArgs(list, name);
43+
}
44+
45+
3246
PyObject *CPyList_GetItemUnsafe(PyObject *list, CPyTagged index) {
3347
Py_ssize_t n = CPyTagged_ShortAsSsize_t(index);
3448
PyObject *result = PyList_GET_ITEM(list, n);

mypyc/primitives/list_ops.py

+9
Original file line numberDiff line numberDiff line change
@@ -262,6 +262,15 @@
262262
error_kind=ERR_MAGIC,
263263
)
264264

265+
# list.copy()
266+
method_op(
267+
name="copy",
268+
arg_types=[list_rprimitive],
269+
return_type=list_rprimitive,
270+
c_function_name="CPyList_Copy",
271+
error_kind=ERR_MAGIC,
272+
)
273+
265274
# list * int
266275
binary_op(
267276
name="*",

mypyc/test-data/fixtures/ir.py

+1
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ def sort(self) -> None: pass
233233
def reverse(self) -> None: pass
234234
def remove(self, o: _T) -> None: pass
235235
def index(self, o: _T) -> int: pass
236+
def copy(self) -> List[_T]: pass
236237

237238
class dict(Mapping[_K, _V]):
238239
@overload

mypyc/test-data/irbuild-lists.test

+12
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,18 @@ L0:
182182
r1 = r0 << 1
183183
return r1
184184

185+
[case testListCopy]
186+
from typing import List
187+
from typing import Any
188+
def f(a: List[Any]) -> List[Any]:
189+
return a.copy()
190+
[out]
191+
def f(a):
192+
a, r0 :: list
193+
L0:
194+
r0 = CPyList_Copy(a)
195+
return r0
196+
185197
[case testListAppend]
186198
from typing import List
187199
def f(a: List[int], x: int) -> None:

mypyc/test-data/run-lists.test

+49
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,55 @@ print(2, a)
5151
1 [-1, 5]
5252
2 [340282366920938463463374607431768211461, -170141183460469231731687303715884105736]
5353

54+
[case testListCopy]
55+
from typing import List
56+
from copysubclass import subc
57+
58+
def test_list_copy() -> None:
59+
l1 = [1, 2, 3, -4, 5]
60+
l2 = l1.copy()
61+
assert l1.copy() == l1
62+
assert l1.copy() == l2
63+
assert l1 == l2
64+
assert l1.copy() == l2.copy()
65+
l1 = l2.copy()
66+
assert l1 == l2
67+
assert l1.copy() == l2
68+
assert l1 == [1, 2, 3, -4, 5]
69+
l2 = [1, 2, -3]
70+
l1 = []
71+
assert l1.copy() == []
72+
assert l2.copy() != l1
73+
assert l2 == l2.copy()
74+
l1 = l2
75+
assert l1.copy().copy() == l2.copy().copy().copy()
76+
assert l1.copy() == l2.copy()
77+
l1 == [1, 2, -3].copy()
78+
assert l1 == l2
79+
l2 = [1, 2, 3].copy()
80+
assert l2 != l1
81+
l1 = [1, 2, 3]
82+
assert l1.copy() == l2.copy()
83+
l3 = [1, 2 , 3, "abcdef"]
84+
assert l3 == l3.copy()
85+
l4 = ["abc", 5, 10]
86+
l4 = l3.copy()
87+
assert l4 == l3
88+
#subclass testing
89+
l5: subc = subc([1, 2, 3])
90+
l6 = l5.copy()
91+
assert l6 == l5
92+
l6 = [1, 2, "3", 4, 5]
93+
l5 = subc([1,2,"3",4,5])
94+
assert l5.copy() == l6.copy()
95+
l6 = l5.copy()
96+
assert l5 == l6
97+
98+
[file copysubclass.py]
99+
from typing import Any
100+
class subc(list[Any]):
101+
pass
102+
54103
[case testSieve]
55104
from typing import List
56105

0 commit comments

Comments
 (0)