350 lines
6.7 KiB
Markdown
350 lines
6.7 KiB
Markdown
# Browse the Config
|
||
|
||
## Getting the options
|
||
|
||
Create a simple Config:
|
||
|
||
```python
|
||
from asyncio import run
|
||
from tiramisu import Config
|
||
from tiramisu import StrOption, OptionDescription
|
||
|
||
# let's declare some options
|
||
var1 = StrOption('var1', 'first option')
|
||
# an option with a default value
|
||
var2 = StrOption('var2', 'second option', 'value')
|
||
# let's create a group of options
|
||
od1 = OptionDescription('od1', 'first OD', [var1, var2])
|
||
|
||
# let's create another group of options
|
||
rootod = OptionDescription('rootod', '', [od1])
|
||
|
||
async def main():
|
||
# let's create the config
|
||
cfg = await Config(rootod)
|
||
# the api is read only
|
||
await cfg.property.read_only()
|
||
# the read_write api is available
|
||
await cfg.property.read_write()
|
||
return cfg
|
||
|
||
cfg = run(main())
|
||
```
|
||
|
||
We retrieve by path an option named "var1" and then we retrieve its name and its docstring:
|
||
|
||
```python
|
||
async def main():
|
||
print(await cfg.option('od1.var1').option.name())
|
||
print(await cfg.option('od1.var1').option.doc())
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
var1
|
||
first option
|
||
```
|
||
|
||
## Accessing the values of the options
|
||
|
||
Let's browse the configuration structure and option values.
|
||
|
||
You have getters as a "get" method on option objects:
|
||
|
||
1. getting all the options
|
||
|
||
```python
|
||
async def main():
|
||
print(await cfg.value.dict())
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
{'var1': None, 'var2': 'value'}
|
||
```
|
||
|
||
2. getting the "od1" option description
|
||
|
||
```python
|
||
async def main():
|
||
print(await cfg.option('od1').value.dict())
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
{'od1.var1': None, 'od1.var2': 'value'}
|
||
```
|
||
|
||
3. getting the var1 option's value
|
||
|
||
```python
|
||
async def main():
|
||
print(await cfg.option('od1.var1').value.get())
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
None
|
||
```
|
||
|
||
4. getting the var2 option's default value
|
||
|
||
```python
|
||
async def main():
|
||
print(await cfg.option('od1.var2').value.get())
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
value
|
||
```
|
||
|
||
5. trying to get a non existent option's value
|
||
|
||
```python
|
||
async def main():
|
||
try:
|
||
await cfg.option('od1.idontexist').value.get()
|
||
except AttributeError as err:
|
||
print(str(err))
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
unknown option "idontexist" in optiondescription "first OD"
|
||
```
|
||
|
||
## Setting the value of an option
|
||
|
||
An important part of the setting's configuration consists of setting the
|
||
value's option.
|
||
|
||
You have setters as a "set" method on option objects.
|
||
|
||
And if you wanna come back to a default value, use the "reset()" method.
|
||
|
||
1. changing the "od1.var1" value
|
||
|
||
```python
|
||
async def main():
|
||
await cfg.option('od1.var1').value.set('éééé')
|
||
print(await cfg.option('od1.var1').value.get())
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
éééé
|
||
```
|
||
|
||
2. carefull to the type of the value to be set
|
||
|
||
```python
|
||
async def main():
|
||
try:
|
||
await cfg.option('od1.var1').value.set(23454)
|
||
except ValueError as err:
|
||
print(str(err))
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
"23454" is an invalid string for "first option"
|
||
```
|
||
|
||
3. let's come back to the default value
|
||
|
||
```python
|
||
async def main():
|
||
await cfg.option('od1.var2').value.reset()
|
||
print(await cfg.option('od1.var2').value.get())
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
value
|
||
```
|
||
|
||
> **_Important_** If the config is "read only", setting an option's value isn't allowed, see [property](property.md).
|
||
|
||
Let's make the protocol of accessing a Config's option explicit
|
||
(because explicit is better than implicit):
|
||
|
||
1. If the option has not been declared, an "Error" is raised,
|
||
2. If an option is declared, but neither a value nor a default value has
|
||
been set, the returned value is "None",
|
||
3. If an option is declared and a default value has been set, but no value
|
||
has been set, the returned value is the default value of the option,
|
||
|
||
4. If an option is declared, and a value has been set, the returned value is
|
||
the value of the option.
|
||
|
||
But there are special exceptions. We will see later on that an option can be a
|
||
mandatory option. A mandatory option is an option that must have a value
|
||
defined.
|
||
|
||
Searching for an option
|
||
~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||
|
||
In an application, knowing the path of an option is not always feasible.
|
||
That's why a tree of options can easily be searched with the "find()" method.
|
||
|
||
```python
|
||
from asyncio import run
|
||
from tiramisu import Config
|
||
from tiramisu import OptionDescription, StrOption
|
||
from tiramisu.setting import undefined
|
||
|
||
var1 = StrOption('var1', '')
|
||
var2 = StrOption('var2', '')
|
||
var3 = StrOption('var3', '')
|
||
od1 = OptionDescription('od1', '', [var1, var2, var3])
|
||
var4 = StrOption('var4', '')
|
||
var5 = StrOption('var5', '')
|
||
var6 = StrOption('var6', '')
|
||
var7 = StrOption('var1', '', 'value')
|
||
od2 = OptionDescription('od2', '', [var4, var5, var6, var7])
|
||
rootod = OptionDescription('rootod', '', [od1, od2])
|
||
```
|
||
|
||
Let's find an option by it's name
|
||
|
||
And let's find first an option by it's name
|
||
|
||
The search can be performed in a subtree
|
||
|
||
```python
|
||
async def main():
|
||
cfg = await Config(rootod)
|
||
print(await cfg.option.find(name='var1'))
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
[<tiramisu.api.TiramisuOption object at 0x7f490a530f98>, <tiramisu.api.TiramisuOption object at 0x7f490a530748>]
|
||
```
|
||
|
||
If the option name is unique, the search can be stopped once one matched option has been found:
|
||
|
||
```python
|
||
async def main():
|
||
cfg = await Config(rootod)
|
||
print(await cfg.option.find(name='var1', first=True))
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
<tiramisu.api.TiramisuOption object at 0x7ff27fc93c70>
|
||
```
|
||
|
||
Search object behaves like a cfg object, for example:
|
||
|
||
```python
|
||
async def main():
|
||
cfg = await Config(rootod)
|
||
option = await cfg.option.find(name='var1', first=True)
|
||
print(await option.option.name())
|
||
print(await option.option.doc())
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
var1
|
||
var1
|
||
```
|
||
|
||
Search can be made with various criteria:
|
||
|
||
```python
|
||
async def main():
|
||
cfg = await Config(rootod)
|
||
await cfg.option.find(name='var3', value=undefined)
|
||
await cfg.option.find(name='var3', type=StrOption)
|
||
|
||
run(main())
|
||
```
|
||
|
||
The find method can be used in subconfigs:
|
||
|
||
```python
|
||
async def main():
|
||
cfg = await Config(rootod)
|
||
print(await cfg.option('od2').find('var1'))
|
||
|
||
run(main())
|
||
```
|
||
|
||
## The "dict" flattening utility
|
||
|
||
In a config or a subconfig, you can print a dict-like representation
|
||
|
||
In a "fullpath" or a "flatten" way
|
||
|
||
- get the "od1" option description:
|
||
|
||
```python
|
||
async def main():
|
||
cfg = await Config(rootod)
|
||
print(await cfg.option('od1').value.dict(fullpath=True))
|
||
|
||
run(main())
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
{'od1.var1': None, 'od1.var2': None, 'od1.var3': None}
|
||
```
|
||
|
||
```python
|
||
async def main():
|
||
cfg = await Config(rootod)
|
||
print(await cfg.option('od1').value.dict(fullpath=False))
|
||
|
||
run(main())
|
||
>>> print(cfg.option('od1').value.dict(fullpath=True))
|
||
```
|
||
|
||
returns:
|
||
|
||
```
|
||
{'var1': None, 'var2': None, 'var3': None}
|
||
```
|
||
|
||
> **_NOTE_** be carefull with this "flatten" parameter, because we can just loose some options if there are same name (some option can be overriden).
|
||
|