diff --git a/doc/config.txt b/doc/config.txt index ed647d3..f4c67d4 100644 --- a/doc/config.txt +++ b/doc/config.txt @@ -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: diff --git a/doc/consistency.txt b/doc/consistency.txt index 82ea23d..73d3671 100644 --- a/doc/consistency.txt +++ b/doc/consistency.txt @@ -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. diff --git a/doc/error.txt b/doc/error.txt new file mode 100644 index 0000000..f3037a0 --- /dev/null +++ b/doc/error.txt @@ -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: + diff --git a/doc/index.txt b/doc/index.txt index add8ac0..2758bfb 100644 --- a/doc/index.txt +++ b/doc/index.txt @@ -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 ================== diff --git a/doc/option.txt b/doc/option.txt index aa37b96..8e4cee3 100644 --- a/doc/option.txt +++ b/doc/option.txt @@ -100,3 +100,5 @@ configuration, that is : .. autoclass:: ChoiceOption .. automethod:: __init__ + + diff --git a/doc/status.txt b/doc/status.txt index 2c78b39..524a7b8 100644 --- a/doc/status.txt +++ b/doc/status.txt @@ -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`. diff --git a/tiramisu/autolib.py b/tiramisu/autolib.py index a2714fd..b7901d1 100644 --- a/tiramisu/autolib.py +++ b/tiramisu/autolib.py @@ -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) diff --git a/tiramisu/config.py b/tiramisu/config.py index eebaca1..5924ff2 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -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',)) diff --git a/tiramisu/error.py b/tiramisu/error.py index 8dc5dc2..f944500 100644 --- a/tiramisu/error.py +++ b/tiramisu/error.py @@ -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) diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 65a98b5..7bb7360 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -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):