Accessing Config Values¶
Once the config object is created, the primary way to access values in the config is via the pull()
(while you can update individual values using push()
). Optionally, you can provide a default value to be returned if the query is not found. If no default value is provided, a SearchFailed
error is raised (which is subclass of KeyError
). Additionally, the pulls()
method allows you to provide any number of fallback queries.
Note
_
and -
are interchangeable in config keys
When reading (aka pulling) arguments from the config, if an argument is not found in the current branch and the query is not hidden (i.e. it does not begin with _
), it will automatically defer to the higher branches (aka parent branch) as well, which allows users to define more or less “global” arguments depending on how deep the node containing the argument actually is. Although this behavior can be changed using the ask_parents
key in the config settings.
For example, given the config object that is loaded from the this yaml file (registered as myconfig
):
favorites:
games: [Innovation, Triumph and Tragedy, Inis, Nations]
language: Python
activity: <>games.0
wallpaper:
color: red
jacket:
size: 30
nights: 2
trip:
- location: London
nights: 3
- location: Berlin
- location: Moscow
nights: 4
app:
price: 1.99
color: <>wallpaper.color
When this yaml file is loaded (e.g. config = fig.create_config('myconfig')
), we could use it like so:
assert config.pull('favorites.language') == 'Python'
assert config.pull('favorites.0') == 'Innvoation'
assert config.pull('app.color') == 'red'
assert config.pull('favorites.activity') == 'Innovation'
assert config.pull('trip.0.location') == 'London'
assert config.pull('trip.1.nights', 4) == 2
assert config.pull('app.publisher', 'unknown') == 'unknown' # default
assert config.pulls('jacket.color', 'wallpaper.color') == 'red'
assert config.pulls('jacket.price', 'price', 'total_cost', default='too much') == 'too much'
While this example should give you a sense for what kind of features the config system offers, a more comprehensive list of how queries in the config are resolved and the values are processed.
See the feature slide B5.
Queries¶
In addition to the behavior described above, the keys (or indices) in a config branch have the following features (where {}
refers to any value):
'_{}'
- hidden query - is not visible to child branches when they defer to parentspush()
/pull()
'{1}.{2}'
- deep query - equivalent to['{1}']['{2}']
push()
'{1}.{2}'
where'{1}'
is missing - deep push - automatically creates a new branch'{1}'
in config and then pushes'{2}'
to that new branch
Values¶
The values of arguments also have a few special features worth noting:
'<>{}'
- local alias - defer to value of{}
starting search for the key here'<o>{}'
- (advanced feature) origin alias - defer to value of{}
starting search at origin (this only makes a difference when chaining aliases, origin refers to the branch wherepull()
was called)'_x_'
- remove key if encountered (during update) - remove corresponding key it it appears in the config being updated__x__
- cut deferring chain of key - behaves as though this key didn’t exist (and doesn’t defer to parent)
Currently there are no escape sequences, so any values starting with <>
or <o>
will be treated as aliases and values that are _x_
or __x__
will not be processed as regular strings. However, if necessary, you can easily implement a component to escape these values using the automatic object instantiation, like so:
@fig.autocomponent('escaped-str')
def escape_str(value):
return value
cfg = fig.create_config(special={'_type': 'escaped-str', 'value':'<>some-value'})
assert cfg.pull('special') == '<>some-value'