Accessing Config values

The Data Context

Once the data is loaded, it can be accessed anywhere in your application by just accessing the attribute on your config object.

var = config.my_var

Whenever you access a value on the config object, it searches through all of the rulesets that is has for the specified key. It then uses its current_context to pick the one that is a match with the highest specificity. In the above example, there is no context, so it searches with “” as the selector string. You can use config.context(selector) as a context manager to get deeper values-

with config.context("task.default_task environment"):
        assert config.setting_a == "inner"

The context works like the nested tree of an html structure. the model

with config.context("el.myclass"):
        config.the_value
        with config.context("child"):
                config.the_value
                with config.context("par#inner"):
                        config.the_value

would have the same effect as an html structure of

<el class="myclass">
        the_value
        <child>
                the_value
                <par id=inner>
                        the_value
                </par>
        </child>
</el>

if you had a ruleset like

the_value: 0
el:
        the_value: 1
child:
        the_value: 2
par:
        the_value: 3
.myclass:
        the_value: 4
#inner:
        the_value: 5
.myclass #inner:
        the_value: 6
el child:
        the_value: 7

The output would be - 4 - 7 - 6

Using Schemas

Schemas let you enforce structure on rules- what attributes are actually valid for any particular element type. We have seen how to define them, lets see how you can use them.

class Task(ElementSchema):
        taskval: str

config = SettingsManager([data], [Task])
print(config.task().someval)

Each ElementSchema has a _name_ associated with it. When you access that name on the SettingsManager object, it will create an instance of the Schema for you. Basically, it will push the element onto the search context so that any values you lookup will come from that element. You can pass extra context as well using the name and identifier arguments-

with config.context("parent"):
        config.task(identifier="mytask").someval

In this case, someval would be looked up with the context “parent task#mytask”. Schema objects aren’t context managers, they keep a closure of the context when they were created, so this

with config.context("parent"):
        task = config.task(identifier="mytask")
val  = task.someval

would work the same way as the previous example. Schema objects also provides a convenience method load() which will return a dictionary of all of the resolved properties that are defined on the schema. Its the equivalent of

data = {key: getattr(task, key) for key in Task.__props__}

Debugging

It can be hard to figure out the problem if the program doesn’t find a key you expect. To get better info, set the logging level to DEBUG, or if your app doesn’t use logging, set the environment variable SETTINGS_LOGGER=DEBUG