Skip to content

Commit

Permalink
Merge pull request #60 from aplavin/master
Browse files Browse the repository at this point in the history
use properties, not fields
  • Loading branch information
jw3126 authored Jun 28, 2022
2 parents dec3c28 + 16ba039 commit 9fa5044
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 9 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
name = "ConstructionBase"
uuid = "187b0558-2788-49d3-abe0-74a17ed4e7c9"
authors = ["Takafumi Arakaki", "Rafael Schouten", "Jan Weidner"]
version = "1.3.0"
version = "1.3.1"

[deps]
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
Expand Down
33 changes: 25 additions & 8 deletions src/ConstructionBase.jl
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,31 @@ end

getproperties(o::NamedTuple) = o
getproperties(o::Tuple) = o
@generated function getproperties(obj)
fnames = fieldnames(obj)
fvals = map(fnames) do fname
Expr(:call, :getproperty, :obj, QuoteNode(fname))
if VERSION >= v"1.7"
function getproperties(obj)
fnames = propertynames(obj)
NamedTuple{fnames}(getproperty.(Ref(obj), fnames))
end
else
@generated function getproperties(obj)
if which(propertynames, Tuple{obj}).sig != Tuple{typeof(propertynames), Any}
# custom propertynames defined for this type
return quote
msg = """
Different fieldnames and propertynames are only supported on Julia v1.7+.
For older julia versions, consider overloading
`ConstructionBase.getproperties(obj::$(typeof(obj))`.
See also https://github.com/JuliaObjects/ConstructionBase.jl/pull/60.
"""
error(msg)
end
end
fnames = fieldnames(obj)
fvals = map(fnames) do fname
:(obj.$fname)
end
:(NamedTuple{$fnames}(($(fvals...),)))
end
fvals = Expr(:tuple, fvals...)
:(NamedTuple{$fnames}($fvals))
end

################################################################################
Expand Down Expand Up @@ -86,9 +104,8 @@ function validate_setproperties_result(
end
@noinline function validate_setproperties_result(nt_new, nt_old, obj, patch)
O = typeof(obj)
P = typeof(patch)
msg = """
Failed to assign properties $(fieldnames(P)) to object with fields $(fieldnames(O)).
Failed to assign properties $(propertynames(patch)) to object with properties $(propertynames(obj)).
You may want to overload
ConstructionBase.setproperties(obj::$O, patch::NamedTuple)
ConstructionBase.getproperties(obj::$O)
Expand Down
24 changes: 24 additions & 0 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,30 @@ end
end
end

# example of a struct with different fields and properties
struct FieldProps{NT <: NamedTuple{(:a, :b)}}
components::NT
end

Base.propertynames(obj::FieldProps) = (:a, :b)
Base.getproperty(obj::FieldProps, name::Symbol) = getproperty(getfield(obj, :components), name)
ConstructionBase.constructorof(::Type{<:FieldProps}) = (a, b) -> FieldProps((a=a, b=b))

@testset "use properties, not fields" begin
x = FieldProps((a=1, b=:b))
if VERSION >= v"1.7"
@test getproperties(x) == (a=1, b=:b)
@test setproperties(x, a="aaa") == FieldProps((a="aaa", b=:b))
VERSION >= v"1.8-dev" ?
(@test_throws "Failed to assign properties (:c,) to object with properties (:a, :b)" setproperties(x, c=0)) :
(@test_throws ArgumentError setproperties(x, c=0))
else
@test_throws ErrorException getproperties(x)
@test_throws ErrorException setproperties(x, a="aaa")
@test_throws ErrorException setproperties(x, c=0)
end
end

function funny_numbers(::Type{Tuple}, n)::Tuple
types = [
Int128, Int16, Int32, Int64, Int8,
Expand Down

2 comments on commit 9fa5044

@jw3126
Copy link
Member Author

@jw3126 jw3126 commented on 9fa5044 Jun 28, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@JuliaRegistrator register()

@JuliaRegistrator
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Registration pull request created: JuliaRegistries/General/63246

After the above pull request is merged, it is recommended that a tag is created on this repository for the registered package version.

This will be done automatically if the Julia TagBot GitHub Action is installed, or can be done manually through the github interface, or via:

git tag -a v1.3.1 -m "<description of version>" 9fa5044d27f98d7e247c937ffd871240a8d6adac
git push origin v1.3.1

Please sign in to comment.