new api documentation

This commit is contained in:
gwen 2013-05-21 18:42:56 +02:00
parent 480ed190aa
commit 0e6032dd88
10 changed files with 93 additions and 105 deletions

View File

@ -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:

View File

@ -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.

19
doc/error.txt Normal file
View 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:

View File

@ -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
================== ==================

View File

@ -100,3 +100,5 @@ configuration, that is :
.. autoclass:: ChoiceOption .. autoclass:: ChoiceOption
.. automethod:: __init__ .. automethod:: __init__

View File

@ -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`.

View File

@ -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)

View File

@ -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',))

View File

@ -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)

View File

@ -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):