Jinja templatingΒΆ

Any string value returned from your config will be run through a Jinja2 template resolver before being returned. Any missing variables in the templates will be looked up in the config using the current context.

config = SettingsManager({
        "basic": "Var {{someval}}",
        "someval": "default",
        "task": {"someval": "override"}
}, {"task"})

config.basic == "Var default"
with config.context("task"):
        config.basic == "Var override"

This could allow you to be more flexible when merging data from multiple sources such as default, org, and user level config files. You can even add custom filters to the environment such as

config = SettingsManager({
        "myval": "{{ (1, 3) | add_two_numbers }}"
})
config.add_filter("add_two_numbers", lambda tup: tup[0] + tup[1])
config.myval == "4"

There are two variables name and id that can be pulled directly from the context. For example -

class Schema(ElementSchema)
        myval: str

config = SettingsManager([{
        "myval": "my name is {{ name }}"
}], [Schema])
with config.context(".myname"):
        config.myval == "my name is myname"
# or
config.schema(name="myname") == "my name is myname"

There is also the ability to refer directly to the config object, allowing you to pull values from other contexts, or from the parent context. This is especially useful to compose values-

class Tag(ElementSchema):
        val: str

class Child(ElementSchema):
        val: str

config = SettingsManager(
        [{
                "tag.mytag": {
                        "val": "{{ config.with_context('.other').val }}",
                        "child": {"val": "{{config.parent().val + what"}
                },
                ".other": {"val": "40"}
        }],
        [Tag, Child],
)
assert config.tag(name="mytag").val == "40"
with config.context("tag.mytag child"):
        # notice they are both string values...
        assert config.val == "40what"