.. default-role:: literal

Local statuses and global settings
=====================================

Available configuration statuses
----------------------------------

.. currentmodule:: tiramisu

The configuration's status lives in an :class:`setting.Setting()` object.
This configuration status corresponds to specific attributes or bunch of
attributes that can be accessed together with some `setting.Setting`
method:

**read write status**

    The configuration can be accessed by `__get__` and `__set__`
    properties, except for the `hidden` configuration options but, yes, it is
    possible to modify a disabled option.

    To enable read-write status, call 
    :class:`~config.CommonConfig.read_write()` on the config.

**read only status**

    The whole configuration is `frozen`, that is modifiying a value is
    forbidden. We can access to a configuration option only with the
    `__getattr__` property.

    The configuration has not an access to the hidden options
    but can read the disabled options.

    To enable read only status, call :class:`~config.SubConfig.read_only()` on 
    the config.

.. csv-table:: **Configuration's statuses summary**
   :header: " ", "Hidden", "Disabled", "Mandatory"

    "read only status", `False`, `True`, `True`
    "read-write status", `True`, `False`, `False`

.. _`frozen`:

Freezing a configuration
---------------------------

At the configuration level, :class:`~setting.Setting()` enables us to freeze the 
whole configuration, wich means that the frozen :class:`~option.Option()`'s 
values cannot be modified.

It is possible to *freeze* a single :class:`~option.Option()` object with
:meth:`~config.SubConfig.cfgimpl_get_settings()`. If you try to modify a frozen 
option, it raises a `TypeError: trying to change a frozen option object`.

To find out if an option `myoption` is frozen, just make an assertion on the 
settings like that::
    
    'frozen' in cfg.cfgimpl_get_settings()[myoption]

Moreover, frozen option can return their default values if
:meth:`~option.Option.force_default()` is called on this option.

.. glossary::

    force default on freeze

        A single option is frozen and we want the option to return something
        else than his value, typically it is his default value.

        In the option's values, an attribute can be set 
        :attr:`force_default_on_freeze`, that forces this behavior.

Restricted access to an `Option()`
-----------------------------------

.. autoclass:: tiramisu.setting.Property

The `properties` attribute is in charge of the access rules' option's value.

Configuration options access statuses are defined at configuration level
that corresponds to the `option.Option()`'s `properties` attribute,
for example: hidden, disabled. 

Use the pythonic way to know if a property is there::

    'hidden' in c.cfgimpl_get_settings()
    'frozen' in c.cfgimpl_get_settings()[opt]

To access to the global settings::

    cfg.cfgimpl_get_settings()
    cfg.cfgimpl_get_settings()[option1]

to add, or suppress a global property::

    cfg.cfgimpl_get_settings()[option1].append('hidden')
    cfg.cfgimpl_get_settings()[option1].remove('hidden')

to activate, deactivate properties::

    cfg.cfgimpl_get_settings().append('hidden')
    cfg.cfgimpl_get_settings().remove('hidden')

The global properties are living in e :class:`~setting.Setting` object. A 
`Setting` object also takes care of the way to access option values and the 
storage in the cache.

Value owners
-------------

Every configuration option has a **owner**. When the option is instanciated, 
the owner is :obj:`setting.owners.default` because a default value has been set 
(including `None`, wich means that no value has been set yet).

.. method:: config.CommonConfig.getowner() 

   This method can retrieve an Option's owner. 

- At the instance of the `Config` object, the value owner is 
  :obj:`setting.owners.default` because
  the default values are set at the instance of the configuration option 
  object,

- at the modification of an option, the owner is `owners.default`, (which is 
  :obj:`owners.user`)
  
Special behaviors for an option
---------------------------------

**mandatory**

    A mandatory option shall return a value. If a value, or a default value
    has not been set, a error is raised.

**has a callback**

    This means that it is a calculated value and therefore automatically
    protected it cannot be modified by attribute access.

**force_store_value**

    if the configuration option has a default value, the default is
    returned, otherwise the value is calculated.

    Its inner state is represented by `option.Option.force_default()`

Configuration options have default values that are stored in the
`Option()` object itself. Default values, the `default`, can be set in
various ways.

If a default value is modified by overriding it, not only the value of
the option resets to the default that is proposed, but the owner is
modified too, it is reseted to `owners.default`.