.. default-role:: literal

The global configuration's consistency
========================================

:module: :api:`config.py`
:tests: :api:`test_option_consistency.py`

Option's values type validation
--------------------------------

When a value is set to the option, the value is validated by the 
option's :api:`option.Option()` validator's type.

Notice that if the option is `multi`, that is the `multi` attribute is set to 
`True`, then the validation of the option value accepts a list of values 
of the same type.

Requirements
------------

Configuration options can specify requirements as parameters at the init 
time, the specification of some links between options or groups allows 
to carry out a dependencies calculation. For example, an option can ben 
hidden if another option has been set with some expected value. This is 
just an example, because the possibilities are hudge.

A requirement is specified using a list of triplets. The first element 
of the triplet gives the path of the option that is required, the second 
element is the value wich is expected to trigger the callback, and the 
third one is the callback's action name (`hide`, `show`...)::

    stroption = StrOption('str', 'Test string option', default="abc", 
                          requires=[('int', 1, 'hide')])

Take a look at an example here 
:api:`test_option_consistency.test_hidden_if_in()`

Config updates
---------------

New configuration options and groups can be dynamically added. 

The configuration has to be *updated* after that the description has been 
passed to the Config objet, see:

::

    >>> config = Config(descr)
    >>> newoption = BoolOption('newoption', 'dummy twoo', default=False)
    >>> descr.add_child(newoption)
    >>> config.update()
    >>> config.newoption
    False

in 

- :api:`test_option_consistency.test_newoption_add_in_descr()`
- :api:`test_option_consistency.test_newoption_add_in_subdescr()`
- :api:`test_option_consistency.test_newoption_add_in_config()`


Validation upon a whole configuration object
----------------------------------------------

An option's integrity can be validated towards a whole configuration.

This type of validation is very open. Let's take a use case : an option 
has a certain value, and the value of this option can change the owner 
of another option or option group... Everything is possible.

For example, the configuration paths have to be unique in the 
:ref:`glossary#schema`, the validation is carried out at the 
:api:`config.Config._cfgimpl_build()` time in the 
:api:`config.Config._validate_duplicates()` method.

Other hook are availables to validate upon a whole configuration at any 
time.

.. FIXME : get the validates hooks from the original config pypy's code

Identical option names 
----------------------

If an :api:`option.Option()` happens to be defined twice in the 
:ref:`glossary#schema` (e.g. the :api:`option.OptionDescription()`), 
:that is the two options actually have the same name, an exception is raised.

The calculation is currently carried out in the samespace, for example 
if `config.gc.name` is defined, another option in `gc` with the name 
`name` is **not** allowed, whereas `config.whateverelse.name` is still 
allowed. 
    
.. the calculation was carried out by the requires, wich is not a goog idead

    Type constraints with the `multi` type
    ----------------------------------------

    By convention, if a multi option has somme requires, the constraints on 
    the multi type is in all the OptionGroup (a group has to be `multi`, and 
    a multi of the same length).

    See :api:`test_option_consistency.test_multi_constraints()`

