Skip to content

Commit e99c560

Browse files
authored
Check optional sections in TOML file (#546)
* Check optional `logging` and `time` settings in TOML file
1 parent b8383d8 commit e99c560

File tree

4 files changed

+41
-10
lines changed

4 files changed

+41
-10
lines changed

Diff for: src/io.jl

+38-6
Original file line numberDiff line numberDiff line change
@@ -27,20 +27,34 @@ end
2727
"""
2828
Config(path::AbstractString)
2929
Config(dict::AbstractDict)
30-
Config(dict::Dict{String,Any}, path::Union{String,Nothing})
3130
3231
Struct that contains the parsed TOML configuration, as well as a reference to the TOML path,
33-
if it exists. It behaves largely like a distionary, but it overloads `getproperty` and
32+
if it exists. It behaves largely like a dictionary, but it overloads `getproperty` and
3433
`setproperty` to support syntax like `config.model.reinit = false`.
3534
"""
3635
struct Config
3736
dict::Dict{String, Any} # nested key value mapping of all settings
3837
path::Union{String, Nothing} # path to the TOML file, or nothing
3938
end
4039

41-
Config(path::AbstractString) = Config(TOML.parsefile(path), path)
40+
function Config(path::AbstractString)
41+
config = Config(TOML.parsefile(path), path)
42+
config = optional_keys(config)
43+
check_config_states(config)
44+
return config
45+
end
4246
Config(dict::AbstractDict) = Config(dict, nothing)
4347

48+
"Add optional TOML keys `logging` and `time` to `config` (if not present in TOML file)"
49+
function optional_keys(config::Config)
50+
if !haskey(config, "logging")
51+
config.logging = Dict{String, Any}()
52+
elseif !haskey(config, "time")
53+
config.time = Dict{String, Any}()
54+
end
55+
return config
56+
end
57+
4458
# allows using getproperty, e.g. config.input.time instead of config["input"]["time"]
4559
function Base.getproperty(config::Config, f::Symbol)
4660
dict = Dict(config)
@@ -950,8 +964,8 @@ function prepare_writer(
950964
end
951965

952966
# create a separate state output netCDF that will hold the last timestep of all states
953-
# but only if config.state.path_output and config.state.variables have been set
954-
if check_config_states(config, "path_output")
967+
# but only if config.state.path_output has been set
968+
if haskey(config, "state") && haskey(config.state, "path_output")
955969
state_ncnames = check_states(config)
956970
state_map = out_map(state_ncnames, modelmap)
957971
nc_state_path = output_path(config, config.state.path_output)
@@ -1645,7 +1659,7 @@ function get_index_dimension(var, config::Config, dim_value)::Int
16451659
return index
16461660
end
16471661

1648-
"Check state settings in `config` object (parsed TOML file)"
1662+
"Check if state TOML keys are set in `config` object (parsed TOML file)"
16491663
function check_config_states(config::Config, path::AbstractString)
16501664
state_settings =
16511665
haskey(config, "state") &&
@@ -1654,6 +1668,24 @@ function check_config_states(config::Config, path::AbstractString)
16541668
return state_settings
16551669
end
16561670

1671+
"""
1672+
Check if required state settings in `config` object (parsed TOML file) are set for reading
1673+
or writing states.
1674+
"""
1675+
function check_config_states(config::Config)
1676+
reinit = get(config.model, "reinit", true)::Bool
1677+
if !reinit
1678+
state_settings = check_config_states(config, "path_input")
1679+
state_settings ||
1680+
error("The state section for reading states in the TOML file is incomplete")
1681+
elseif haskey(config, "state") && haskey(config.state, "path_output")
1682+
state_settings = check_config_states(config, "path_output")
1683+
state_settings ||
1684+
error("The state section for writing states in the TOML file is incomplete")
1685+
end
1686+
return nothing
1687+
end
1688+
16571689
"""
16581690
Check output settings for file description (e.g. file format and data type), file path and
16591691
TOML `key`(e.g. containing variable name) in `config` object (parsed TOML file).

Diff for: src/sbm_model.jl

-2
Original file line numberDiff line numberDiff line change
@@ -471,8 +471,6 @@ function set_states!(model::AbstractModel{<:Union{SbmModel, SbmGwfModel}})
471471

472472
# read and set states in model object if reinit=false
473473
if reinit == false
474-
state_settings = check_config_states(config, "path_input")
475-
state_settings || error("The state section in the TOML file is incomplete")
476474
nriv = length(network.river.indices)
477475
instate_path = input_path(config, config.state.path_input)
478476
@info "Set initial conditions from state file `$instate_path`."

Diff for: src/sediment_model.jl

-2
Original file line numberDiff line numberDiff line change
@@ -126,8 +126,6 @@ function set_states!(model::AbstractModel{<:SedimentModel})
126126
(; config) = model
127127
reinit = get(config.model, "reinit", true)::Bool
128128
if reinit == false
129-
state_settings = check_config_states(config, "path_input")
130-
state_settings || error("The state section in the TOML file is incomplete")
131129
instate_path = input_path(config, config.state.path_input)
132130
@info "Set initial conditions from state file `$instate_path`."
133131
set_states!(instate_path, model; type = Float)

Diff for: test/run_sbm_gwf.jl

+3
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,9 @@ end
8181

8282
Wflow.close_files(model; delete_output = false)
8383

84+
# test complete run including logging entry TOML file (not set)
85+
Wflow.run(tomlpath; silent = true)
86+
8487
# test local-inertial option for river flow routing
8588
tomlpath = joinpath(@__DIR__, "sbm_gwf_config.toml")
8689
config = Wflow.Config(tomlpath)

0 commit comments

Comments
 (0)