Skip to content

Commit

Permalink
Allow a schema version to declare no fields (#102)
Browse files Browse the repository at this point in the history
  • Loading branch information
ararslan committed Oct 8, 2023
1 parent 927b2ac commit af301ae
Show file tree
Hide file tree
Showing 2 changed files with 20 additions and 7 deletions.
5 changes: 2 additions & 3 deletions src/schemas.jl
Original file line number Diff line number Diff line change
Expand Up @@ -777,7 +777,7 @@ Note that this macro expects to be evaluated within top-level scope.
For more details and examples, please see `Legolas.jl/examples/tour.jl` and the
"Schema-Related Concepts/Conventions" section of the Legolas.jl documentation.
"""
macro version(record_type, declared_fields_block)
macro version(record_type, declared_fields_block=nothing)
# parse `record_type`
if record_type isa Symbol
parent_record_type = nothing
Expand All @@ -798,7 +798,6 @@ macro version(record_type, declared_fields_block)
if declared_fields_block isa Expr && declared_fields_block.head == :block && !isempty(declared_fields_block.args)
declared_field_statements = [f for f in declared_fields_block.args if !(f isa LineNumberNode)]
end
isempty(declared_field_statements) && return :(throw(SchemaVersionDeclarationError("malformed or missing field declaration(s)")))
declared_field_infos = DeclaredFieldInfo[]
for stmt in declared_field_statements
original_stmt = Base.Meta.quot(deepcopy(stmt))
Expand All @@ -817,7 +816,7 @@ macro version(record_type, declared_fields_block)
msg = string("cannot have field name which start with an underscore in `@version` declaration: ", invalid_field_names)
return :(throw(SchemaVersionDeclarationError($msg)))
end
declared_field_names_types = Expr(:tuple, (:($(f.name) = $(esc(f.type))) for f in declared_field_infos)...)
declared_field_names_types = Expr(:tuple, Expr(:parameters, (Expr(:kw, f.name, esc(f.type)) for f in declared_field_infos)...))

return quote
if !isdefined((@__MODULE__), :__legolas_schema_name_from_prefix__)
Expand Down
22 changes: 18 additions & 4 deletions test/runtests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ end
y::String = string(y[1:2])
end

@schema "test.great-grandchild" GreatGrandchild
@version GreatGrandchildV1 > GrandchildV1

@schema "test.nested" Nested
@version NestedV1 begin
gc::GrandchildV1
Expand Down Expand Up @@ -302,10 +305,12 @@ end
b::Union{Int,Missing}
end

@schema "test.empty-inside" EmptyInside

@version EmptyInsideV1

@testset "`Legolas.@version` and associated utilities for declared `Legolas.SchemaVersion`s" begin
@testset "Legolas.SchemaVersionDeclarationError" begin
@test_throws SchemaVersionDeclarationError("malformed or missing field declaration(s)") eval(:(@version(NewV1, $(Expr(:block, LineNumberNode(1, :test))))))
@test_throws SchemaVersionDeclarationError("malformed or missing field declaration(s)") @version(ChildV2, begin end)
@test_throws SchemaVersionDeclarationError("missing prior `@schema` declaration for `Unknown` in current module") @version(UnknownV1 > ChildV1, begin x end)
@test_throws SchemaVersionDeclarationError("provided record type symbol is malformed: Child") @version(Child, begin x end)
@test_throws SchemaVersionDeclarationError("provided record type symbol is malformed: Childv2") @version(Childv2, begin x end)
Expand All @@ -332,28 +337,32 @@ end

@testset "Legolas.declared" begin
@test !Legolas.declared(undeclared)
@test all(Legolas.declared, (ParentV1SchemaVersion(), ChildV1SchemaVersion(), GrandchildV1SchemaVersion()))
@test all(Legolas.declared, (ParentV1SchemaVersion(), ChildV1SchemaVersion(), GrandchildV1SchemaVersion(), GreatGrandchildV1SchemaVersion()))
end

@testset "Legolas.parent" begin
@test isnothing(Legolas.parent(undeclared))
@test isnothing(Legolas.parent(ParentV1SchemaVersion()))
@test Legolas.parent(ChildV1SchemaVersion()) == ParentV1SchemaVersion()
@test Legolas.parent(GrandchildV1SchemaVersion()) == ChildV1SchemaVersion()
@test Legolas.parent(GreatGrandchildV1SchemaVersion()) == GrandchildV1SchemaVersion()
end

@testset "Legolas.identifier" begin
@test_throws Legolas.UnknownSchemaVersionError(undeclared) Legolas.identifier(undeclared)
@test Legolas.identifier(ParentV1SchemaVersion()) == "test.parent@1"
@test Legolas.identifier(ChildV1SchemaVersion()) == "test.child@1>test.parent@1"
@test Legolas.identifier(GrandchildV1SchemaVersion()) == "test.grandchild@1>test.child@1>test.parent@1"
@test Legolas.identifier(GreatGrandchildV1SchemaVersion()) == "test.great-grandchild@1>test.grandchild@1>test.child@1>test.parent@1"
end

@testset "Legolas.declared_fields" begin
@test_throws Legolas.UnknownSchemaVersionError(undeclared) Legolas.declared_fields(undeclared)
@test Legolas.declared_fields(EmptyInsideV1SchemaVersion()) == NamedTuple()
@test Legolas.declared_fields(ParentV1SchemaVersion()) == (x=Vector, y=AbstractString)
@test Legolas.declared_fields(ChildV1SchemaVersion()) == (x=Vector, y=AbstractString, z=Any)
@test Legolas.declared_fields(GrandchildV1SchemaVersion()) == (x=Vector, y=String, z=Any, a=Int32)
@test Legolas.declared_fields(GreatGrandchildV1SchemaVersion()) == (x=Vector, y=String, z=Any, a=Int32)

# xref https://github.com/beacon-biosignals/Legolas.jl/pull/100
@test Legolas.declared_fields(ParentV1SchemaVersion()) == (@test_deprecated Legolas.required_fields(ParentV1SchemaVersion()))
Expand All @@ -366,6 +375,8 @@ end
@test_throws Legolas.UnknownSchemaVersionError(undeclared) Legolas.complies_with(Tables.Schema((:a, :b), (Int, Int)), undeclared)
@test_throws Legolas.UnknownSchemaVersionError(undeclared) Legolas.find_violation(Tables.Schema((:a, :b), (Int, Int)), undeclared)

@test Legolas.complies_with(Tables.Schema((), ()), EmptyInsideV1SchemaVersion())

# Note that many of the basic properties of `find_violation`/`complies_with`/`validate`
# are unit-tested in `examples/tour.jl`; thus, we focus here on testing that these
# functions work as expected w.r.t. schema extension in particular.
Expand All @@ -389,7 +400,8 @@ end

# Multiple missing field violations
t = Tables.Schema((:a, :z), (Int32, Any))
for (s, id) in ((GrandchildV1SchemaVersion(), "test.grandchild@1"),
for (s, id) in ((GreatGrandchildV1SchemaVersion(), "test.great-grandchild@1"),
(GrandchildV1SchemaVersion(), "test.grandchild@1"),
(ChildV1SchemaVersion(), "test.child@1"),
(ParentV1SchemaVersion(), "test.parent@1"))
msg = """
Expand Down Expand Up @@ -449,6 +461,7 @@ end
@test Legolas.declaration(ChildV1SchemaVersion()) == ("test.child@1>test.parent@1" => [DeclaredFieldInfo(:z, :Any, false, :(z::Any = z))])
@test Legolas.declaration(GrandchildV1SchemaVersion()) == ("test.grandchild@1>test.child@1" => [DeclaredFieldInfo(:a, :Int32, false, :(a::Int32 = round(Int32, a))),
DeclaredFieldInfo(:y, :String, false, :(y::String = string(y[1:2])))])
@test Legolas.declaration(GreatGrandchildV1SchemaVersion()) == ("test.great-grandchild@1>test.grandchild@1" => DeclaredFieldInfo[])
@test Legolas.DeclaredFieldInfo === Legolas.RequiredFieldInfo # xref https://github.com/beacon-biosignals/Legolas.jl/pull/100
end

Expand All @@ -457,6 +470,7 @@ end
@test Legolas.record_type(ParentV1SchemaVersion()) == ParentV1
@test Legolas.record_type(ChildV1SchemaVersion()) == ChildV1
@test Legolas.record_type(GrandchildV1SchemaVersion()) == GrandchildV1
@test Legolas.record_type(GreatGrandchildV1SchemaVersion()) == GreatGrandchildV1
end

r0 = (x=[42], y="foo", z=:three, a=1.3)
Expand Down

2 comments on commit af301ae

@ararslan
Copy link
Member Author

Choose a reason for hiding this comment

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

@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/93178

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 v0.5.15 -m "<description of version>" af301ae4870c62bb398a01da27af40d8218ae030
git push origin v0.5.15

Please sign in to comment.