From dac72c63d20983a35ab5e6a22feb17d4b7e37c9c Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Fri, 9 Jun 2023 21:12:56 +0200 Subject: [PATCH 1/7] disable deepcopy on PyObject #757 --- src/PyCall.jl | 8 ++++++++ test/runtests.jl | 13 +++++++++++++ 2 files changed, 21 insertions(+) diff --git a/src/PyCall.jl b/src/PyCall.jl index 0c155fef..8e5617a8 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -979,6 +979,14 @@ include("serialize.jl") include("pyinit.jl") +function Base.deepcopy_internal(obj::PyObject, stackdict::Base.IdDict) + msg = """ + Deepcopy is disabled on PyObject. See + https://github.com/JuliaPy/PyCall.jl/issues/757 + """ + error(msg) +end + ######################################################################### include("precompile.jl") diff --git a/test/runtests.jl b/test/runtests.jl index 2e5c915a..84439073 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -620,6 +620,18 @@ const PyInt = pyversion < v"3" ? Int : Clonglong @test_throws ArgumentError float(pybuiltin("type")) end +@testset "deepcopy #757" begin + struct S757; a; b; end + obj = py"[1,2,3]"o + @test obj isa PyObject + @test_throws ErrorException deepcopy(obj) + @test_throws ErrorException deepcopy([obj]) + @test_throws ErrorException deepcopy(S757([obj], 2)) + GC.gc() + pyimport("gc").collect() + @test collect(obj) == [1,2,3] +end + ###################################################################### #@pydef tests: type declarations need to happen at top level @@ -855,3 +867,4 @@ end @test_throws PyCall.PyError a.a = 0 @test_throws KeyError a.a = 1 end + From 3d6004777387a740654a52588a8fdb1fdc9e2717 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 10 Jun 2023 19:33:21 +0200 Subject: [PATCH 2/7] Update src/PyCall.jl Co-authored-by: Steven G. Johnson --- src/PyCall.jl | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/PyCall.jl b/src/PyCall.jl index 8e5617a8..dad35100 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -979,12 +979,12 @@ include("serialize.jl") include("pyinit.jl") +const _deepcopy = PyNULL() + function Base.deepcopy_internal(obj::PyObject, stackdict::Base.IdDict) - msg = """ - Deepcopy is disabled on PyObject. See - https://github.com/JuliaPy/PyCall.jl/issues/757 - """ - error(msg) + haskey(stackdict, obj) && return stackdict[obj] + ispynull(_deepcopy) && copy!(_deepcopy, pyimport("copy")["deepcopy"]) + return pycall(_deepcopy, PyObject, obj) end ######################################################################### From f9139a690180372d94c32cd68ebdba06744d83f4 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 10 Jun 2023 19:47:53 +0200 Subject: [PATCH 3/7] fix deepcopy and add tests --- src/PyCall.jl | 4 +++- test/runtests.jl | 36 +++++++++++++++++++++++++++--------- 2 files changed, 30 insertions(+), 10 deletions(-) diff --git a/src/PyCall.jl b/src/PyCall.jl index dad35100..182abb13 100644 --- a/src/PyCall.jl +++ b/src/PyCall.jl @@ -984,7 +984,9 @@ const _deepcopy = PyNULL() function Base.deepcopy_internal(obj::PyObject, stackdict::Base.IdDict) haskey(stackdict, obj) && return stackdict[obj] ispynull(_deepcopy) && copy!(_deepcopy, pyimport("copy")["deepcopy"]) - return pycall(_deepcopy, PyObject, obj) + ret = pycall(_deepcopy, PyObject, obj) + stackdict[obj] = ret + ret end ######################################################################### diff --git a/test/runtests.jl b/test/runtests.jl index 84439073..24a3a905 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -621,15 +621,33 @@ const PyInt = pyversion < v"3" ? Int : Clonglong end @testset "deepcopy #757" begin - struct S757; a; b; end - obj = py"[1,2,3]"o - @test obj isa PyObject - @test_throws ErrorException deepcopy(obj) - @test_throws ErrorException deepcopy([obj]) - @test_throws ErrorException deepcopy(S757([obj], 2)) - GC.gc() - pyimport("gc").collect() - @test collect(obj) == [1,2,3] + obj = py""" + class C757: + def __init__(self, a, b): + self.a = a + self.b = b + """ + obj = py"C757(C757(1,2), C757(3,4))"o + obj2 = deepcopy(obj) + @test obj.a.a == obj2.a.a + @test obj.a.b == obj2.a.b + @test obj.b.a == obj2.b.a + @test obj.b.b == obj2.b.b + obj.a = 3 + @test obj.a == 3 + @test obj2.a.a == 1 + @test obj2.a.b == 2 + + struct S;a;b;end + + c = py"C757(1,2)" + obj = S(c, c) + obj2 = deepcopy(obj) + @test obj.a === obj.b + @test obj2.a === obj2.b + obj.a.a = 4 + @test obj.a.a == 4 + @test obj2.a.a == 1 end ###################################################################### From 7ef2c93aa432ac902a1313f307d2d74363cc848d Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Sat, 10 Jun 2023 19:49:32 +0200 Subject: [PATCH 4/7] add another deepcopy test --- test/runtests.jl | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/test/runtests.jl b/test/runtests.jl index 24a3a905..170ef47c 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -621,6 +621,14 @@ const PyInt = pyversion < v"3" ? Int : Clonglong end @testset "deepcopy #757" begin + l = py"[1,2,3]"o + l2 = deepcopy(l) + @test l == l2 + l2.append(4) + @test l != l2 + @test collect(l2) == [1,2,3,4] + @test collect(l) == [1,2,3] + obj = py""" class C757: def __init__(self, a, b): From f33b006262dd337e1e98f636857283effc4b58cd Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Tue, 13 Jun 2023 10:03:45 +0200 Subject: [PATCH 5/7] v1.95.2 --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index 54ae595e..eb427dba 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "PyCall" uuid = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" authors = ["Steven G. Johnson ", "Yichao Yu ", "Takafumi Arakaki ", "Simon Kornblith ", "Páll Haraldsson ", "Jon Malmaud ", "Jake Bolewski ", "Keno Fischer ", "Joel Mason ", "Jameson Nash ", "The JuliaPy development team"] -version = "1.95.1" +version = "1.95.2" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From 41084f540f556e3277cab48b94b828e086d27822 Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Wed, 21 Jun 2023 08:34:09 -0400 Subject: [PATCH 6/7] Update Project.toml --- Project.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Project.toml b/Project.toml index eb427dba..3c736fc2 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "PyCall" uuid = "438e738f-606a-5dbb-bf0a-cddfbfd45ab0" authors = ["Steven G. Johnson ", "Yichao Yu ", "Takafumi Arakaki ", "Simon Kornblith ", "Páll Haraldsson ", "Jon Malmaud ", "Jake Bolewski ", "Keno Fischer ", "Joel Mason ", "Jameson Nash ", "The JuliaPy development team"] -version = "1.95.2" +version = "1.96" [deps] Conda = "8f4d0f93-b110-5947-807f-2305c1781a2d" From 96963cb88fb8489b85e9ca6d84e47974cce20b3d Mon Sep 17 00:00:00 2001 From: "Steven G. Johnson" Date: Wed, 21 Jun 2023 08:37:59 -0400 Subject: [PATCH 7/7] Update test/runtests.jl --- test/runtests.jl | 1 + 1 file changed, 1 insertion(+) diff --git a/test/runtests.jl b/test/runtests.jl index 170ef47c..b718ee23 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -637,6 +637,7 @@ end """ obj = py"C757(C757(1,2), C757(3,4))"o obj2 = deepcopy(obj) + @test PyPtr(obj) != PyPtr(obj2) # make sure a new Python object is created @test obj.a.a == obj2.a.a @test obj.a.b == obj2.a.b @test obj.b.a == obj2.b.a