159 lines
4.5 KiB
Plaintext
159 lines
4.5 KiB
Plaintext
.. default-role:: literal
|
|
|
|
=======================
|
|
Configuration Handling
|
|
=======================
|
|
|
|
:module: :api:`config.py`
|
|
:tests: - :api:`test_config.py`
|
|
- :api:`test_option_setting.py`
|
|
|
|
Main Assumption
|
|
===============
|
|
|
|
Configuration option objects :api:`config.Config()` are produced at the
|
|
entry points and handed down to where they are actually used. This keeps
|
|
configuration local but available everywhere and consistent.
|
|
|
|
`Config` and `Option` objects
|
|
==============================
|
|
|
|
Configuration option objects can be created in different ways. Let's perform
|
|
very basic `Config` object manipulations:
|
|
|
|
::
|
|
|
|
>>> from tiramisu.config import Config
|
|
>>> from tiramisu.option import OptionDescription, BoolOption
|
|
>>> descr = OptionDescription("optgroup", "", [
|
|
... BoolOption("bool", "", default=False)])
|
|
>>>
|
|
>>> config = Config(descr)
|
|
>>> config.bool
|
|
False
|
|
>>> config.bool = True
|
|
>>> config.bool
|
|
True
|
|
|
|
Take a look at :api:`test_config.test_base_config()` or
|
|
:api:`test_config.test_base_config_and_groups()`.
|
|
|
|
|
|
Accessing the configuration `Option`'s
|
|
-----------------------------------------
|
|
|
|
The `Config` object attribute access notation stands for the value of the
|
|
configuration's `Option`. That is, the `Config`'s object attribute is the name
|
|
of the `Option`, and the value is the value accessed by the `__getattr__`
|
|
attribute access mechanism.
|
|
|
|
If the attribute of the `Config` called by `__getattr__` has not been set before
|
|
(by the classic `__setattr__` mechanism), the default value of the `Option`
|
|
object is returned, and if no `Option` has been declared in the
|
|
`OptionDescription` (that is the schema of the configuration), an
|
|
`AttributeError` is raised.
|
|
|
|
::
|
|
|
|
>>> gcdummy = BoolOption('dummy', 'dummy', default=False)
|
|
>>> gcdummy._name
|
|
'dummy'
|
|
>>> gcdummy.getdefault()
|
|
False
|
|
>>> descr = OptionDescription('tiramisu', '', [gcdummy])
|
|
>>> cfg = Config(descr)
|
|
>>> cfg.dummy
|
|
False
|
|
>>> cfg.dummy = True
|
|
>>> cfg.dummy
|
|
True
|
|
>>> cfg.idontexist
|
|
AttributeError: 'OptionDescription' object has no attribute 'idontexist'
|
|
|
|
The configuration `Option` objects (in this case the `BoolOption`), are
|
|
organized into a tree into nested `OptionDescription` objects. Every
|
|
option has a name, as does every option group. The parts of the full
|
|
name of the option are separated by dots: e.g.
|
|
``config.optgroup.optname``.
|
|
|
|
**Can you repeat it, what is the protocol of accessing a config's attribute ?**
|
|
|
|
1. If the option has not been declared, an `AttributeError` 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.
|
|
|
|
If you do not want to use the pythonic way, that is the attribute access
|
|
way to obtain the value of the configuration option, you can also search
|
|
for it recursively in the whole config namespaces with the ``get()``
|
|
method :
|
|
|
|
::
|
|
|
|
>>> config.get('bool')
|
|
True
|
|
|
|
|
|
To find the right option, `get()` searches recursively into the whole
|
|
tree. For example, to find an option which is in the `gc` namespace
|
|
there are two possibilites.
|
|
|
|
If you know the path:
|
|
|
|
::
|
|
|
|
>>> config.gc.dummy
|
|
False
|
|
|
|
If you don't remember the path:
|
|
|
|
::
|
|
|
|
>>> config.get('dummy')
|
|
False
|
|
|
|
Setting the values of the options
|
|
----------------------------------------
|
|
|
|
An important part of the setting of the configuration consists of setting the
|
|
values of the configuration options. There are different ways of setting values,
|
|
the first one is of course the `__setattr__` method
|
|
|
|
::
|
|
|
|
cfg.name = value
|
|
|
|
wich has the same effect that the "global" `set()` method : it expects that
|
|
the value owner is the default :ref:`glossary#valueowner`
|
|
|
|
::
|
|
|
|
cfg.set(name=value)
|
|
|
|
The global `setoption()` method of the config objects can set a value with a specific owner
|
|
|
|
::
|
|
|
|
cfg.setoption('name', value, 'owner')
|
|
|
|
|
|
Finally, the local `setoption()` method directly in the `Option` object can be
|
|
used. While the `Option` object refers to his parent, the config knows that the
|
|
value has been changed and no bad side effect won't occur
|
|
|
|
::
|
|
|
|
>>> booloption = BoolOption('bool', 'Test boolean option', default=True)
|
|
>>> descr = OptionDescription('descr', '', [booloption])
|
|
>>> cfg = Config(descr)
|
|
>>> booloption.setoption(cfg, False, 'owner')
|
|
>>> cfg.bool
|
|
>>> False
|
|
|