new api documentation
This commit is contained in:
parent
480ed190aa
commit
0e6032dd88
|
@ -4,11 +4,11 @@
|
||||||
Configuration handling basics
|
Configuration handling basics
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
Tiramisu is designed with three main objects :
|
Tiramisu is made of almost three main objects :
|
||||||
|
|
||||||
- :class:`tiramisu.config.Config` witch is the whole configuration entry point
|
- :class:`tiramisu.config.Config` witch is the whole configuration entry point
|
||||||
- :class:`tiramisu.option.Option` stands for the option type
|
- :class:`tiramisu.option.Option` stands for the option types
|
||||||
- :class:`tiramisu.option.OptionDescription` stands for the description (the schema)
|
- :class:`tiramisu.option.OptionDescription` is the shema, the option's structure
|
||||||
|
|
||||||
Accessing the configuration `Option`'s
|
Accessing the configuration `Option`'s
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
@ -83,6 +83,10 @@ the first one is of course the `__setattr__` method
|
||||||
|
|
||||||
cfg.name = value
|
cfg.name = value
|
||||||
|
|
||||||
|
And if you wanna come back to a default value, do it the pythonic way::
|
||||||
|
|
||||||
|
del(cfg.name)
|
||||||
|
|
||||||
.. module:: tiramisu.config
|
.. module:: tiramisu.config
|
||||||
|
|
||||||
The handling of options is split into two parts: the description of
|
The handling of options is split into two parts: the description of
|
||||||
|
@ -108,7 +112,7 @@ it is possible to
|
||||||
- `iter` on config, notice that there is an iteration order wich is
|
- `iter` on config, notice that there is an iteration order wich is
|
||||||
the order of the :ref:`optdescr` specification entries,
|
the order of the :ref:`optdescr` specification entries,
|
||||||
- compare two configs (equality),
|
- compare two configs (equality),
|
||||||
- export the whole config into a `dict` with `config.make_dict()`,
|
- export the whole config into a `dict` with `config.SubConfig.make_dict()`,
|
||||||
|
|
||||||
`option.Option()` objects in a config are iterable in the pythonic
|
`option.Option()` objects in a config are iterable in the pythonic
|
||||||
way, that is something like `[(name, value) for name, value in config]`.
|
way, that is something like `[(name, value) for name, value in config]`.
|
||||||
|
@ -135,3 +139,10 @@ To iter on groups in the same manner, use the
|
||||||
.. automethod:: find_first
|
.. automethod:: find_first
|
||||||
.. automethod:: iter_groups
|
.. automethod:: iter_groups
|
||||||
.. automethod:: __iter__
|
.. automethod:: __iter__
|
||||||
|
|
||||||
|
or a SubConfig, or a MetaConfig :
|
||||||
|
|
||||||
|
|
||||||
|
.. autoclass:: SubConfig
|
||||||
|
:members:
|
||||||
|
:special-members:
|
||||||
|
|
|
@ -45,29 +45,6 @@ third one is the callback's action name (`hide`, `show`...)::
|
||||||
Take a look at an example here
|
Take a look at an example here
|
||||||
`test_option_consistency.test_hidden_if_in()`
|
`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
|
|
||||||
|
|
||||||
- `test_option_consistency.test_newoption_add_in_descr()`
|
|
||||||
- `test_option_consistency.test_newoption_add_in_subdescr()`
|
|
||||||
- `test_option_consistency.test_newoption_add_in_config()`
|
|
||||||
|
|
||||||
Validation upon a whole configuration object
|
Validation upon a whole configuration object
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
|
@ -77,10 +54,21 @@ 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
|
has a certain value, and the value of this option can change the owner
|
||||||
of another option or option group... Everything is possible.
|
of another option or option group... Everything is possible.
|
||||||
|
|
||||||
For example, the configuration paths have to be unique in the
|
.. currentmodule:: tiramisu.option
|
||||||
`glossary#schema`, the validation is carried out at the
|
|
||||||
`config.Config._cfgimpl_build()` time in the
|
Other hooks are availables to validate upon a whole configuration at any time,
|
||||||
`config.Config._validate_duplicates()` method.
|
for example the consistency between two options (typically, an
|
||||||
|
:class:`IPOption` and a :class:`NetworkOption`).
|
||||||
|
|
||||||
|
Values that are calculated
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
An option that have a callback is considered to have a value that is to be
|
||||||
|
calculated.
|
||||||
|
|
||||||
|
An option's property with a `force_store_value` attribute is considered to be
|
||||||
|
modified at the first calculation.
|
||||||
|
|
||||||
|
.. automodule:: tiramisu.autolib
|
||||||
|
:members:
|
||||||
|
|
||||||
Other hook are availables to validate upon a whole configuration at any
|
|
||||||
time.
|
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
Errors that may be encountered
|
||||||
|
==================================
|
||||||
|
|
||||||
|
Three builtins exceptions are used :
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
- **ValueError** : Validation error, parameters error, a list instead
|
||||||
|
of a Multi, or if the value does not make sense
|
||||||
|
|
||||||
|
- **TypeError** : type error in a parameter
|
||||||
|
|
||||||
|
- **AttributeError** : wrong path or unknownd option or optiondescription
|
||||||
|
|
||||||
|
And five user-defined exceptions :
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
.. automodule:: tiramisu.error
|
||||||
|
:members:
|
||||||
|
|
|
@ -7,8 +7,6 @@
|
||||||
|
|
||||||
.. title:: tiramisu
|
.. title:: tiramisu
|
||||||
|
|
||||||
.. |version| replace:: 0.1
|
|
||||||
|
|
||||||
The tasting of `Tiramisu`
|
The tasting of `Tiramisu`
|
||||||
=========================
|
=========================
|
||||||
|
|
||||||
|
@ -36,6 +34,7 @@ configuration handler.
|
||||||
status
|
status
|
||||||
consistency
|
consistency
|
||||||
glossary
|
glossary
|
||||||
|
error
|
||||||
|
|
||||||
Indices and tables
|
Indices and tables
|
||||||
==================
|
==================
|
||||||
|
|
|
@ -100,3 +100,5 @@ configuration, that is :
|
||||||
.. autoclass:: ChoiceOption
|
.. autoclass:: ChoiceOption
|
||||||
|
|
||||||
.. automethod:: __init__
|
.. automethod:: __init__
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,7 @@
|
||||||
.. default-role:: literal
|
.. default-role:: literal
|
||||||
|
|
||||||
|
Local statuses and global setting
|
||||||
.. TODO: STATUS and settings explained
|
=====================================
|
||||||
|
|
||||||
The statuses
|
|
||||||
======================
|
|
||||||
|
|
||||||
Available configuration statuses
|
Available configuration statuses
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
@ -67,80 +64,51 @@ see `test_option_default.test_force_default_on_freeze()`
|
||||||
Restricted access to an `Option()`
|
Restricted access to an `Option()`
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
|
.. currentmodule:: tiramisu.setting
|
||||||
|
|
||||||
|
.. autoclass:: Property
|
||||||
|
|
||||||
|
The `properties` attribute is in charge of the access rules' option's value.
|
||||||
|
|
||||||
Configuration options access statuses are defined at configuration level
|
Configuration options access statuses are defined at configuration level
|
||||||
that corresponds to the `option.Option()`'s `properties` attribute,
|
that corresponds to the `option.Option()`'s `properties` attribute,
|
||||||
for example
|
for example: hidden, disabled.
|
||||||
|
|
||||||
**hidden**
|
Use the pythonic way to know if a property is there::
|
||||||
|
|
||||||
This means that an option raises an error if we try to access
|
'hidden' in c.cfgimpl_get_settings()
|
||||||
the value of the option.
|
'frozen' in c.cfgimpl_get_settings()[opt]
|
||||||
|
|
||||||
See `hide()` or `show()` in `Option()` that comes from
|
To access to the global settings::
|
||||||
`option.HiddenBaseType`
|
|
||||||
|
|
||||||
corresponding convenience API provided:
|
cfg.cfgimpl_get_settings()
|
||||||
|
cfg.cfgimpl_get_settings()[option1]
|
||||||
|
|
||||||
`hide()`:
|
to add, or suppress a global property::
|
||||||
set the `hidden` attribute to `True`
|
|
||||||
|
|
||||||
`show()`:
|
cfg.cfgimpl_get_settings()[option1].append('hidden')
|
||||||
set the `hidden` attribute to `False`
|
cfg.cfgimpl_get_settings()[option1].remove('hidden')
|
||||||
|
|
||||||
**disabled**
|
to activate, deactivate properties::
|
||||||
|
|
||||||
This means that an option *doesn't exists* (doesn't say anything
|
cfg.cfgimpl_get_settings().append('hidden')
|
||||||
much more thant an `AttibuteAccess` error)
|
cfg.cfgimpl_get_settings().remove('hidden')
|
||||||
|
|
||||||
See in `option.DisabledBaseType` the origins of
|
|
||||||
`Option.enable()` or `Option.disable()`
|
|
||||||
|
|
||||||
corresponding convenience API provided:
|
|
||||||
|
|
||||||
`disable()`:
|
|
||||||
set the `disabled` attribute to `True`
|
|
||||||
|
|
||||||
`enable()`:
|
|
||||||
set the `disabled` attribute to `False`
|
|
||||||
|
|
||||||
Value owners
|
Value owners
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
|
.. method:: tiramisu.config.Config.getowner()
|
||||||
|
|
||||||
|
This method can retrieve an Option's owner.
|
||||||
|
|
||||||
Every configuration option has a **owner**. When the option is
|
Every configuration option has a **owner**. When the option is
|
||||||
instanciated, the owner is `default` because a default value has been
|
instanciated, the owner is `default` because a default value has been
|
||||||
set (including `None`, take a look at the tests).
|
set (including `None`, take a look at the tests).
|
||||||
|
|
||||||
The `value_owner` is the man who did it. Yes, the man who changed the value of the
|
- At the instance of the `Config` object, the value owner is `owners.default` because
|
||||||
configuration option.
|
|
||||||
|
|
||||||
- At the instance of the `Config` object, the value owner is `default` because
|
|
||||||
the default values are set at the instance of the configuration option object,
|
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 `user`)
|
||||||
|
|
||||||
# let's expect there is an option named 'name'
|
|
||||||
config = Config(descr, bool=False)
|
|
||||||
# the override method has been called
|
|
||||||
config._cfgimpl_value_owners['name'] == 'default'
|
|
||||||
|
|
||||||
- at the modification of an option, the owner is `default_owner`, (which is `user`)
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
# modification of the value by attribute access
|
|
||||||
config.gc.dummy = True
|
|
||||||
assert config.gc._cfgimpl_value_owners['dummy'] == 'user'
|
|
||||||
assert config._cfgimpl_values['gc']._cfgimpl_value_owners['dummy'] == 'user'
|
|
||||||
|
|
||||||
- the default owner can be set with the `set_owner()` method
|
|
||||||
|
|
||||||
::
|
|
||||||
|
|
||||||
config.set_owner('spam')
|
|
||||||
config.set(dummy=True)
|
|
||||||
assert config.gc._cfgimpl_value_owners['dummy'] == 'spam'
|
|
||||||
assert config._cfgimpl_values['gc']._cfgimpl_value_owners['dummy'] == 'spam'
|
|
||||||
|
|
||||||
|
|
||||||
Special behaviors for an option
|
Special behaviors for an option
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
@ -155,10 +123,7 @@ Special behaviors for an option
|
||||||
This means that it is a calculated value and therefore automatically
|
This means that it is a calculated value and therefore automatically
|
||||||
protected it cannot be modified by attribute access.
|
protected it cannot be modified by attribute access.
|
||||||
|
|
||||||
Its inner state is represented by `option.Option.has_callback()`
|
**force_store_value**
|
||||||
and `option.Option.hascallback_and_isfrozen()`
|
|
||||||
|
|
||||||
**force default**
|
|
||||||
|
|
||||||
if the configuration option has a default value, the default is
|
if the configuration option has a default value, the default is
|
||||||
returned, otherwise the value is calculated.
|
returned, otherwise the value is calculated.
|
||||||
|
@ -171,4 +136,4 @@ various ways.
|
||||||
|
|
||||||
If a default value is modified by overriding it, not only the value of
|
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
|
the option resets to the default that is proposed, but the owner is
|
||||||
modified too, it is reseted to `default`.
|
modified too, it is reseted to `owners.default`.
|
||||||
|
|
|
@ -115,6 +115,7 @@ def calculate(name, callback, params, tcparams):
|
||||||
|
|
||||||
:param callback: callback name
|
:param callback: callback name
|
||||||
:param params: in the callback's arity, the unnamed parameters
|
:param params: in the callback's arity, the unnamed parameters
|
||||||
:params tcparams: in the callback's arity, the named parameters
|
:param tcparams: in the callback's arity, the named parameters
|
||||||
|
|
||||||
"""
|
"""
|
||||||
return callback(*params, **tcparams)
|
return callback(*params, **tcparams)
|
||||||
|
|
|
@ -416,7 +416,8 @@ class SubConfig(BaseInformation):
|
||||||
return context_descr.impl_get_path_by_opt(descr)
|
return context_descr.impl_get_path_by_opt(descr)
|
||||||
|
|
||||||
|
|
||||||
class ConfigCommon(SubConfig):
|
class CommonConfig(SubConfig):
|
||||||
|
"abstract base class for the Config and the MetaConfig"
|
||||||
__slots__ = ('_impl_values', '_impl_settings', '_impl_meta')
|
__slots__ = ('_impl_values', '_impl_settings', '_impl_meta')
|
||||||
|
|
||||||
def _impl_build_all_paths(self):
|
def _impl_build_all_paths(self):
|
||||||
|
@ -457,7 +458,7 @@ class ConfigCommon(SubConfig):
|
||||||
|
|
||||||
|
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
class Config(ConfigCommon):
|
class Config(CommonConfig):
|
||||||
"main configuration management entry"
|
"main configuration management entry"
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
|
@ -483,7 +484,7 @@ class Config(ConfigCommon):
|
||||||
self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
|
self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
|
||||||
|
|
||||||
|
|
||||||
class MetaConfig(ConfigCommon):
|
class MetaConfig(CommonConfig):
|
||||||
__slots__ = ('_impl_children',)
|
__slots__ = ('_impl_children',)
|
||||||
|
|
||||||
def __init__(self, children, meta=True):
|
def __init__(self, children, meta=True):
|
||||||
|
@ -492,7 +493,7 @@ class MetaConfig(ConfigCommon):
|
||||||
self._impl_descr = None
|
self._impl_descr = None
|
||||||
if meta:
|
if meta:
|
||||||
for child in children:
|
for child in children:
|
||||||
if not isinstance(child, ConfigCommon):
|
if not isinstance(child, CommonConfig):
|
||||||
raise ValueError(_("metaconfig's children must be Config, not {0}"
|
raise ValueError(_("metaconfig's children must be Config, not {0}"
|
||||||
"".format(type(child))))
|
"".format(type(child))))
|
||||||
if self._impl_descr is None:
|
if self._impl_descr is None:
|
||||||
|
@ -575,6 +576,7 @@ def mandatory_warnings(config):
|
||||||
where no value has been set
|
where no value has been set
|
||||||
|
|
||||||
:returns: generator of mandatory Option's path
|
:returns: generator of mandatory Option's path
|
||||||
|
|
||||||
"""
|
"""
|
||||||
#if value in cache, properties are not calculated
|
#if value in cache, properties are not calculated
|
||||||
config.cfgimpl_reset_cache(only=('values',))
|
config.cfgimpl_reset_cache(only=('values',))
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
# Exceptions for an Option
|
# Exceptions for an Option
|
||||||
class PropertiesOptionError(AttributeError):
|
class PropertiesOptionError(AttributeError):
|
||||||
"attempt to access to an option with a property that is'nt allowed"
|
"attempt to access to an option with a property that is not allowed"
|
||||||
def __init__(self, msg, proptype):
|
def __init__(self, msg, proptype):
|
||||||
self.proptype = proptype
|
self.proptype = proptype
|
||||||
super(PropertiesOptionError, self).__init__(msg)
|
super(PropertiesOptionError, self).__init__(msg)
|
||||||
|
|
|
@ -145,6 +145,7 @@ populate_multitypes()
|
||||||
|
|
||||||
|
|
||||||
class Property(object):
|
class Property(object):
|
||||||
|
"a property is responsible of the option's value access rules"
|
||||||
__slots__ = ('_setting', '_properties', '_opt')
|
__slots__ = ('_setting', '_properties', '_opt')
|
||||||
|
|
||||||
def __init__(self, setting, prop, opt=None):
|
def __init__(self, setting, prop, opt=None):
|
||||||
|
|
Loading…
Reference in New Issue