tiramisu/doc/browse.md

351 lines
6.7 KiB
Markdown
Raw Normal View History

2022-11-13 15:04:12 +01:00
# 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).