From cd24e541fd90ab54d2ee12ddd6ccd229be9a5f1e Mon Sep 17 00:00:00 2001 From: Alexander Plavin Date: Mon, 17 Jul 2023 19:38:28 +0300 Subject: [PATCH] support non-tuple propertynames (#79) --- Project.toml | 2 +- src/ConstructionBase.jl | 19 ++++++++++++------- test/runtests.jl | 9 +++++++++ 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Project.toml b/Project.toml index a641d69..ed3f011 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "ConstructionBase" uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9" authors = ["Takafumi Arakaki", "Rafael Schouten", "Jan Weidner"] -version = "1.5.2" +version = "1.5.3" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" diff --git a/src/ConstructionBase.jl b/src/ConstructionBase.jl index 6174be0..0be68fb 100644 --- a/src/ConstructionBase.jl +++ b/src/ConstructionBase.jl @@ -82,15 +82,20 @@ else end end -# names are consecutive integers: return tuple -# names are symbols: return namedtuple -# names are empty (object has no properties): also return namedtuple, for backwards compat and generally makes more sense +# dispatch on eltype(names) to select Tuple vs NamedTuple +@inline tuple_or_ntuple(names, vals) = tuple_or_ntuple(eltype(names), names, vals) +# if names are empty (object has no properties): return namedtuple, for backwards compat and generally makes more sense than tuple @inline tuple_or_ntuple(names::Tuple{}, vals::Tuple) = NamedTuple{names}(vals) -@inline tuple_or_ntuple(names::Tuple{Vararg{Symbol}}, vals::Tuple) = NamedTuple{names}(vals) -@inline function tuple_or_ntuple(names::Tuple{Vararg{Int}}, vals::Tuple) - @assert names === ntuple(identity, length(names)) - vals + +# names are consecutive integers: return tuple +@inline function tuple_or_ntuple(::Type{Int}, names, vals) + @assert Tuple(names) == ntuple(identity, length(names)) + Tuple(vals) end +# names are symbols: return namedtuple +@inline tuple_or_ntuple(::Type{Symbol}, names, vals) = NamedTuple{Tuple(names)}(vals) +# otherwise: throw an error +tuple_or_ntuple(::Type, names, vals) = error("Only Int and Symbol propertynames are supported") if VERSION >= v"1.7" function getproperties(obj) diff --git a/test/runtests.jl b/test/runtests.jl index 0bd249a..c31ae24 100644 --- a/test/runtests.jl +++ b/test/runtests.jl @@ -319,6 +319,15 @@ if VERSION >= v"1.7" @test getproperties(SProp((1, 2))) === ("pi1", "pi2") # what should it return? @test_broken getproperties(SProp(("a", "b"))) + + @test_throws ErrorException getproperties(SProp((1, :a))) + end + + @testset "propertynames can be a vector" begin + @test getproperties(SProp([:a, :b])) === (a="psa", b="psb") + @test getproperties(SProp(Symbol[])) === (;) + @test getproperties(SProp([1, 2])) === ("pi1", "pi2") + @test getproperties(SProp(Int[])) === () end end