Skip to content

Allow system level metadata information #3892

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 4 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 28 additions & 1 deletion src/systems/model_parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@ function _model_macro(mod, fullname::Union{Expr, Symbol}, expr, isconnector)
dict = Dict{Symbol, Any}(
:defaults => Dict{Symbol, Any}(),
:kwargs => Dict{Symbol, Dict}(),
:structural_parameters => Dict{Symbol, Dict}()
:structural_parameters => Dict{Symbol, Dict}(),
:metadata => Dict{Symbol, Any}()
)
comps = Union{Symbol, Expr}[]
ext = []
Expand Down Expand Up @@ -127,6 +128,7 @@ function _model_macro(mod, fullname::Union{Expr, Symbol}, expr, isconnector)

consolidate = get(dict, :consolidate, default_consolidate)
description = get(dict, :description, "")
model_meta = get(dict, :metadata, Dict{Symbol, Any}())

@inline pop_structure_dict!.(
Ref(dict), [:defaults, :kwargs, :structural_parameters])
Expand All @@ -145,6 +147,14 @@ function _model_macro(mod, fullname::Union{Expr, Symbol}, expr, isconnector)
isconnector && push!(exprs.args,
:($Setfield.@set!(var"#___sys___".connector_type=$connector_type(var"#___sys___"))))

meta_exprs = quote
for (k, v) in $model_meta
var"#___sys___" = setmetadata(var"#___sys___", $get_var($mod, k), v)
end
end
push!(exprs.args, meta_exprs)
push!(exprs.args, :(var"#___sys___"))

f = if length(where_types) == 0
:($(Symbol(:__, name, :__))(; name, $(kwargs...)) = $exprs)
else
Expand Down Expand Up @@ -678,6 +688,8 @@ function parse_model!(exprs, comps, ext, eqs, icon, vs, ps, sps, c_evts, d_evts,
parse_costs!(costs, dict, body)
elseif mname == Symbol("@consolidate")
parse_consolidate!(body, dict)
elseif mname == Symbol("@metadata")
parse_metadata_block!(body, dict, mod)
else
error("$mname is not handled.")
end
Expand Down Expand Up @@ -1254,6 +1266,21 @@ function parse_description!(body, dict)
end
end

function parse_metadata_block!(body, dict, mod)
Base.remove_linenums!(body)
for arg in body.args
MLStyle.@match arg begin
Expr(:(=), a, b) => begin
dict[:metadata][a] = get_var(mod, b)
end
Expr(:call, :(=>), a, b) => begin
dict[:metadata][a] = get_var(mod, b)
end
_ => error("Invalid metadata entry: $arg. Expected key = value or key => value format.")
end
end
end

### Parsing Components:

function component_args!(a, b, varexpr, kwargs; index_name = nothing)
Expand Down
38 changes: 38 additions & 0 deletions test/model_parsing.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1045,3 +1045,41 @@ end
@test Example.structure[:constraints] == ["(EvalAt(0.3))(x) ~ 3", "y ≲ 4"]
@test Example.structure[:costs] == ["x + y", "(EvalAt(1))(y) ^ 2"]
end

@testset "Model Level Metadata" begin
struct Author end
struct MyVersion end
struct License end
struct Category end
struct Tags end

@mtkmodel TestMetadataModel begin
@metadata begin
Author = "Test Author"
MyVersion = "1.0.0"
License = "MIT"
Category => "example"
Tags = ["test", "demo", "metadata"]
end

@parameters begin
k = 1.0, [description = "Gain parameter"]
end

@variables begin
x(t), [description = "State variable"]
y(t), [description = "Output variable"]
end

@equations begin
D(x) ~ -k * x
y ~ x
end
end
@named test_model = TestMetadataModel()

struct UnknownMetaKey end
@test ModelingToolkit.getmetadata(test_model, Author, nothing) == "Test Author"
@test ModelingToolkit.getmetadata(test_model, MyVersion, nothing) == "1.0.0"
@test ModelingToolkit.getmetadata(test_model, UnknownMetaKey, nothing) === nothing
end
Loading