new api documentation
This commit is contained in:
parent
480ed190aa
commit
0e6032dd88
@ -4,11 +4,11 @@
|
||||
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.option.Option` stands for the option type
|
||||
- :class:`tiramisu.option.OptionDescription` stands for the description (the schema)
|
||||
- :class:`tiramisu.option.Option` stands for the option types
|
||||
- :class:`tiramisu.option.OptionDescription` is the shema, the option's structure
|
||||
|
||||
Accessing the configuration `Option`'s
|
||||
-----------------------------------------
|
||||
@ -83,6 +83,10 @@ the first one is of course the `__setattr__` method
|
||||
|
||||
cfg.name = value
|
||||
|
||||
And if you wanna come back to a default value, do it the pythonic way::
|
||||
|
||||
del(cfg.name)
|
||||
|
||||
.. module:: tiramisu.config
|
||||
|
||||
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
|
||||
the order of the :ref:`optdescr` specification entries,
|
||||
- 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
|
||||
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:: iter_groups
|
||||
.. 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
|
||||
`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
|
||||
----------------------------------------------
|
||||
|
||||
@ -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
|
||||
of another option or option group... Everything is possible.
|
||||
|
||||
For example, the configuration paths have to be unique in the
|
||||
`glossary#schema`, the validation is carried out at the
|
||||
`config.Config._cfgimpl_build()` time in the
|
||||
`config.Config._validate_duplicates()` method.
|
||||
.. currentmodule:: tiramisu.option
|
||||
|
||||
Other hooks are availables to validate upon a whole configuration at any time,
|
||||
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.
|
||||
|
19
doc/error.txt
Normal file
19
doc/error.txt
Normal file
@ -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
|
||||
|
||||
.. |version| replace:: 0.1
|
||||
|
||||
The tasting of `Tiramisu`
|
||||
=========================
|
||||
|
||||
@ -36,6 +34,7 @@ configuration handler.
|
||||
status
|
||||
consistency
|
||||
glossary
|
||||
error
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
@ -100,3 +100,5 @@ configuration, that is :
|
||||
.. autoclass:: ChoiceOption
|
||||
|
||||
.. automethod:: __init__
|
||||
|
||||
|
||||
|
@ -1,10 +1,7 @@
|
||||
.. default-role:: literal
|
||||
|
||||
|
||||
.. TODO: STATUS and settings explained
|
||||
|
||||
The statuses
|
||||
======================
|
||||
Local statuses and global setting
|
||||
=====================================
|
||||
|
||||
Available configuration statuses
|
||||
----------------------------------
|
||||
@ -67,80 +64,51 @@ see `test_option_default.test_force_default_on_freeze()`
|
||||
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
|
||||
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
|
||||
the value of the option.
|
||||
'hidden' in c.cfgimpl_get_settings()
|
||||
'frozen' in c.cfgimpl_get_settings()[opt]
|
||||
|
||||
See `hide()` or `show()` in `Option()` that comes from
|
||||
`option.HiddenBaseType`
|
||||
To access to the global settings::
|
||||
|
||||
corresponding convenience API provided:
|
||||
cfg.cfgimpl_get_settings()
|
||||
cfg.cfgimpl_get_settings()[option1]
|
||||
|
||||
`hide()`:
|
||||
set the `hidden` attribute to `True`
|
||||
to add, or suppress a global property::
|
||||
|
||||
`show()`:
|
||||
set the `hidden` attribute to `False`
|
||||
cfg.cfgimpl_get_settings()[option1].append('hidden')
|
||||
cfg.cfgimpl_get_settings()[option1].remove('hidden')
|
||||
|
||||
**disabled**
|
||||
to activate, deactivate properties::
|
||||
|
||||
This means that an option *doesn't exists* (doesn't say anything
|
||||
much more thant an `AttibuteAccess` error)
|
||||
|
||||
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`
|
||||
cfg.cfgimpl_get_settings().append('hidden')
|
||||
cfg.cfgimpl_get_settings().remove('hidden')
|
||||
|
||||
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
|
||||
instanciated, the owner is `default` because a default value has been
|
||||
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
|
||||
configuration option.
|
||||
|
||||
- At the instance of the `Config` object, the value owner is `default` because
|
||||
- At the instance of the `Config` object, the value owner is `owners.default` because
|
||||
the default values are set at the instance of the configuration option object,
|
||||
|
||||
::
|
||||
|
||||
# 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'
|
||||
|
||||
- at the modification of an option, the owner is `owners.default`, (which is `user`)
|
||||
|
||||
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
|
||||
protected it cannot be modified by attribute access.
|
||||
|
||||
Its inner state is represented by `option.Option.has_callback()`
|
||||
and `option.Option.hascallback_and_isfrozen()`
|
||||
|
||||
**force default**
|
||||
**force_store_value**
|
||||
|
||||
if the configuration option has a default value, the default is
|
||||
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
|
||||
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 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)
|
||||
|
@ -416,7 +416,8 @@ class SubConfig(BaseInformation):
|
||||
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')
|
||||
|
||||
def _impl_build_all_paths(self):
|
||||
@ -457,7 +458,7 @@ class ConfigCommon(SubConfig):
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
class Config(ConfigCommon):
|
||||
class Config(CommonConfig):
|
||||
"main configuration management entry"
|
||||
__slots__ = tuple()
|
||||
|
||||
@ -483,7 +484,7 @@ class Config(ConfigCommon):
|
||||
self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
|
||||
|
||||
|
||||
class MetaConfig(ConfigCommon):
|
||||
class MetaConfig(CommonConfig):
|
||||
__slots__ = ('_impl_children',)
|
||||
|
||||
def __init__(self, children, meta=True):
|
||||
@ -492,7 +493,7 @@ class MetaConfig(ConfigCommon):
|
||||
self._impl_descr = None
|
||||
if meta:
|
||||
for child in children:
|
||||
if not isinstance(child, ConfigCommon):
|
||||
if not isinstance(child, CommonConfig):
|
||||
raise ValueError(_("metaconfig's children must be Config, not {0}"
|
||||
"".format(type(child))))
|
||||
if self._impl_descr is None:
|
||||
@ -575,6 +576,7 @@ def mandatory_warnings(config):
|
||||
where no value has been set
|
||||
|
||||
:returns: generator of mandatory Option's path
|
||||
|
||||
"""
|
||||
#if value in cache, properties are not calculated
|
||||
config.cfgimpl_reset_cache(only=('values',))
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
# Exceptions for an Option
|
||||
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):
|
||||
self.proptype = proptype
|
||||
super(PropertiesOptionError, self).__init__(msg)
|
||||
|
@ -145,6 +145,7 @@ populate_multitypes()
|
||||
|
||||
|
||||
class Property(object):
|
||||
"a property is responsible of the option's value access rules"
|
||||
__slots__ = ('_setting', '_properties', '_opt')
|
||||
|
||||
def __init__(self, setting, prop, opt=None):
|
||||
|
Loading…
Reference in New Issue
Block a user