Skip to content

Commit c12d6d7

Browse files
jw3126stevengj
andauthored
disable deepcopy on PyObject #757 (#1039)
* disable deepcopy on PyObject #757 * Update src/PyCall.jl Co-authored-by: Steven G. Johnson <[email protected]> * fix deepcopy and add tests * add another deepcopy test * v1.95.2 * Update Project.toml * Update test/runtests.jl --------- Co-authored-by: Steven G. Johnson <[email protected]>
1 parent b5da159 commit c12d6d7

File tree

3 files changed

+51
-1
lines changed

3 files changed

+51
-1
lines changed

Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "PyCall"
22
uuid = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0"
33
authors = ["Steven G. Johnson <[email protected]>", "Yichao Yu <[email protected]>", "Takafumi Arakaki <[email protected]>", "Simon Kornblith <[email protected]>", "Páll Haraldsson <[email protected]>", "Jon Malmaud <[email protected]>", "Jake Bolewski <[email protected]>", "Keno Fischer <[email protected]>", "Joel Mason <[email protected]>", "Jameson Nash <[email protected]>", "The JuliaPy development team"]
4-
version = "1.95.2"
4+
version = "1.96.0"
55

66
[deps]
77
Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d"

src/PyCall.jl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -979,6 +979,16 @@ include("serialize.jl")
979979

980980
include("pyinit.jl")
981981

982+
const _deepcopy = PyNULL()
983+
984+
function Base.deepcopy_internal(obj::PyObject, stackdict::Base.IdDict)
985+
haskey(stackdict, obj) && return stackdict[obj]
986+
ispynull(_deepcopy) && copy!(_deepcopy, pyimport("copy")["deepcopy"])
987+
ret = pycall(_deepcopy, PyObject, obj)
988+
stackdict[obj] = ret
989+
ret
990+
end
991+
982992
#########################################################################
983993

984994
include("precompile.jl")

test/runtests.jl

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,45 @@ const PyInt = pyversion < v"3" ? Int : Clonglong
620620
@test_throws ArgumentError float(pybuiltin("type"))
621621
end
622622

623+
@testset "deepcopy #757" begin
624+
l = py"[1,2,3]"o
625+
l2 = deepcopy(l)
626+
@test l == l2
627+
l2.append(4)
628+
@test l != l2
629+
@test collect(l2) == [1,2,3,4]
630+
@test collect(l) == [1,2,3]
631+
632+
obj = py"""
633+
class C757:
634+
def __init__(self, a, b):
635+
self.a = a
636+
self.b = b
637+
"""
638+
obj = py"C757(C757(1,2), C757(3,4))"o
639+
obj2 = deepcopy(obj)
640+
@test PyPtr(obj) != PyPtr(obj2) # make sure a new Python object is created
641+
@test obj.a.a == obj2.a.a
642+
@test obj.a.b == obj2.a.b
643+
@test obj.b.a == obj2.b.a
644+
@test obj.b.b == obj2.b.b
645+
obj.a = 3
646+
@test obj.a == 3
647+
@test obj2.a.a == 1
648+
@test obj2.a.b == 2
649+
650+
struct S;a;b;end
651+
652+
c = py"C757(1,2)"
653+
obj = S(c, c)
654+
obj2 = deepcopy(obj)
655+
@test obj.a === obj.b
656+
@test obj2.a === obj2.b
657+
obj.a.a = 4
658+
@test obj.a.a == 4
659+
@test obj2.a.a == 1
660+
end
661+
623662
######################################################################
624663
#@pydef tests: type declarations need to happen at top level
625664

@@ -855,3 +894,4 @@ end
855894
@test_throws PyCall.PyError a.a = 0
856895
@test_throws KeyError a.a = 1
857896
end
897+

0 commit comments

Comments
 (0)