From 90fa8fe3c2cd874db78a5972e8b3574006a2ae15 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Wed, 2 Oct 2019 17:53:44 +0200 Subject: [PATCH 1/3] Improve setproperties error message --- src/ConstructionBase.jl | 34 ++++++++++++++++++++++++---------- 1 file changed, 24 insertions(+), 10 deletions(-) diff --git a/src/ConstructionBase.jl b/src/ConstructionBase.jl index 5aefdad..f4605c6 100644 --- a/src/ConstructionBase.jl +++ b/src/ConstructionBase.jl @@ -53,18 +53,32 @@ function setproperties(obj; kw...) end @generated function setproperties(obj, patch::NamedTuple) - assert_hasfields(obj, fieldnames(patch)) - args = map(fieldnames(obj)) do fn - if fn in fieldnames(patch) - :(patch.$fn) - else - :(obj.$fn) + if issubset(fieldnames(patch), fieldnames(obj)) + args = map(fieldnames(obj)) do fn + if fn in fieldnames(patch) + :(patch.$fn) + else + :(obj.$fn) + end end + return Expr(:block, + Expr(:meta, :inline), + Expr(:call,:(constructorof($obj)), args...) + ) + else + :(setproperties_unknown_field_error(obj, patch)) end - Expr(:block, - Expr(:meta, :inline), - Expr(:call,:(constructorof($obj)), args...) - ) +end + +function setproperties_unknown_field_error(obj, patch) + O = typeof(obj) + P = typeof(patch) + msg = """ + Failed to assign properties $(fieldnames(P)) to object with fields $(fieldnames(O)). + You may want to overload + ConstructionBase.setproperties(obj::$O, patch::NamedTuple) + """ + throw(ArgumentError(msg)) end From 2a004c1399992cfbde90d8204e7806fadb82832b Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Wed, 2 Oct 2019 17:56:23 +0200 Subject: [PATCH 2/3] remove assert_hasfields --- src/ConstructionBase.jl | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/ConstructionBase.jl b/src/ConstructionBase.jl index f4605c6..3f4a788 100644 --- a/src/ConstructionBase.jl +++ b/src/ConstructionBase.jl @@ -39,15 +39,6 @@ struct NamedTupleConstructor{names} end end end -function assert_hasfields(T, fnames) - for fname in fnames - if !(fname in fieldnames(T)) - msg = "$T has no field $fname" - throw(ArgumentError(msg)) - end - end -end - function setproperties(obj; kw...) setproperties(obj, (;kw...)) end From 9515d4a2109bb954fed7b5da6a15275325901fb2 Mon Sep 17 00:00:00 2001 From: Jan Weidner Date: Thu, 3 Oct 2019 14:26:11 +0200 Subject: [PATCH 3/3] test setproperties error messages --- test/runtests.jl | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/test/runtests.jl b/test/runtests.jl index 42e3dfb..24bc7bb 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -24,8 +24,18 @@ end @test setproperties(o, (a=2, b=3.0)) === AB(2,3.0) @test setproperties(o, a=2, b=3.0) === AB(2,3.0) - @test_throws ArgumentError setproperties(o, (a=2, c=3.0)) - @test_throws ArgumentError setproperties(o, a=2, c=3.0) + res = @test_throws ArgumentError setproperties(o, (a=2, this_field_does_not_exist=3.0)) + msg = sprint(showerror, res.value) + @test occursin("this_field_does_not_exist", msg) + @test occursin("overload", msg) + @test occursin("ConstructionBase.setproperties", msg) + + res = @test_throws ArgumentError setproperties(o, a=2, this_field_does_not_exist=3.0) + msg = sprint(showerror, res.value) + @test occursin("this_field_does_not_exist", msg) + @test occursin("overload", msg) + @test occursin("ConstructionBase.setproperties", msg) + @test setproperties(Empty(), NamedTuple()) === Empty() @test setproperties(Empty()) === Empty()