# 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: ``` [, ] ``` 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: ``` ``` 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).