351 lines
6.7 KiB
Markdown
351 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).
|
|||
|
|