A hierarchical configuration using string keys, with benefits:
Indexing:
- indexable with dot separated hierarchical keys (e.g., "group.key");
- default value can be passed to indexing with
default = <value>; - if key does not exist, returns default value instead of throwing
KeyError; - default value defaults to
nothing.
Property access:
- groups and keys can be accessed via properties (e.g.,
config.group.key); - read/write support.
The library also supports unfolding via the unfold function, producing the
Cartesian combination of all list values, see details below. Hence
the name GridConfigs.jl (i.e., a rectangular grid of configuration values).
Assume you have a TOML configuration file called config.toml:
[a]
x = 1
y = 2.0
[b]
foo = "foo"
bar = true
[c.x]
one = [1, 2, 3]
two = [4, 5, 6]
[c.y]
i = 1.0
j = 2.0
[d]
baz = ["alpha", "bravo"]You can parse this into a GridConfig using the following command:
julia> ]add https://github.com/cursorinsight/GridConfigs.jl
julia> using GridConfigs, TOML; config = GridConfig("config.toml", TOML)
GridConfig with 9 entries:
a.x = 1
a.y = 2.0
b.bar = true
b.foo = "foo"
c.x.one = [1, 2, 3]
c.x.two = [4, 5, 6]
c.y.i = 1.0
c.y.j = 2.0
d.baz = ["alpha", "bravo"]To access entries in the config, you can use either indexing with string keys or using property access. Note:
- the use of hierarchical keys (e.g., "x.one");
- accessing a non-existent key returns
nothing;
julia> config["a"]
GridConfig with 2 entries:
x = 1
y = 2.0
julia> config.a.x
1
julia> config.missing |> typeof
NothingYou can also specify a default value to return instead of nothing for
non-existent keys (works with indexing syntax only):
julia> config["a.y", default="gotcha!"]
2.0
julia> config["missing", default="gotcha!"]
"gotcha!"Both indexing and property access can be used to update entries in the config:
julia> config["a.x"] += 3
4
julia> config.a.y += 1.5
3.5
julia> sum(values(config.a))
7.5As demonstrated by the last call, GridConfig also supports the standard
keys, values and pairs functions:
julia> keys(config.a)
2-element Vector{String}:
"x"
"y"
julia> pairs(config["b"]) |> collect
2-element Vector{Pair{String}}:
"bar" => true
"foo" => "foo"List values can be unfolded: from a single config containing lists of values, a list of configs containing scalar values can be produced:
julia> config.c
GridConfig with 4 entries:
x.one = [1, 2, 3]
x.two = [4, 5, 6]
y.i = 1.0
y.j = 2.0
julia> unfold(config.c, "x.one")
3-element Vector{GridConfig}:
GridConfig with 4 entries:
x.one = 1
x.two = [4, 5, 6]
y.i = 1.0
y.j = 2.0
GridConfig with 4 entries:
x.one = 2
x.two = [4, 5, 6]
y.i = 1.0
y.j = 2.0
GridConfig with 4 entries:
x.one = 3
x.two = [4, 5, 6]
y.i = 1.0
y.j = 2.0When multiple list values are unfolded in a single step, every possible combination of the scalar values is produced:
julia> unfold(config.c, "x.one", "x.two")
9-element Vector{GridConfig}:
GridConfig with 4 entries:
x.one = 1
x.two = 4
y.i = 1.0
y.j = 2.0
GridConfig with 4 entries:
x.one = 1
x.two = 5
y.i = 1.0
y.j = 2.0
GridConfig with 4 entries:
x.one = 1
x.two = 6
y.i = 1.0
y.j = 2.0
GridConfig with 4 entries:
x.one = 2
x.two = 4
y.i = 1.0
y.j = 2.0
GridConfig with 4 entries:
x.one = 2
x.two = 5
y.i = 1.0
y.j = 2.0
GridConfig with 4 entries:
x.one = 2
x.two = 6
y.i = 1.0
y.j = 2.0
GridConfig with 4 entries:
x.one = 3
x.two = 4
y.i = 1.0
y.j = 2.0
GridConfig with 4 entries:
x.one = 3
x.two = 5
y.i = 1.0
y.j = 2.0
GridConfig with 4 entries:
x.one = 3
x.two = 6
y.i = 1.0
y.j = 2.0If you specify the name of a group, all list values within that group are
unfolded. If you specify colon (:), everything is unfolded:
julia> unfold(config.c, "x.one", "x.two") ==
unfold(config.c, "x") ==
unfold(config.c, :)
true
julia> unfold(config, "c") |> length
9
julia unfold(config, :) |> length
18In addition to TOML, GridConfigs.jl also supports YAML and JSON files. All you
have to do is import the appropriate library and pass the module in the second
argument of the GridConfig constructor:
julia> using GridConfig, JSON; json_config = GridConfig("config.json", JSON)
julia> using GridConfig, YAML; yaml_config = GridConfig("config.yml", YAML)