update doc
[tiramisu.git] / doc / config.txt
index 9bce1cb..3c6d9bc 100644 (file)
@@ -6,17 +6,20 @@ Options handling basics
 
 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 types
 - :class:`tiramisu.option.OptionDescription` is the shema, the option's structure
+- :class:`tiramisu.config.Config` which is the whole configuration entry point
+
+.. image:: config.png
 
 Accessing the `Option`'s
 -------------------------
 
-The `Config` object attribute access notation stands for the value of the
-configuration's `Option`. That is, the `Config`'s object attribute is the name
-of the `Option`, and the value is the value accessed by the `__getattr__`
-attribute access mechanism.
+The :class:`~tiramisu.config.Config` object attribute access notation stands for 
+the value of the configuration's :class:`~tiramisu.option.Option`.
+:class:`~tiramisu.config.Config`'s object attribute is the name of the option, 
+and the value is the value accessed by the `__getattr__` attribute access 
+mechanism.
 
 If the attribute of the `Config` called by `__getattr__` has not been set before
 (by the classic `__setattr__` mechanism), the default value of the `Option`
@@ -26,25 +29,29 @@ object is returned, and if no `Option` has been declared in the
 
 ::
 
+    >>> from tiramisu.config import Config 
+    >>> from tiramisu.option import BoolOption, OptionDescription
+    >>> 
     >>> gcdummy = BoolOption('dummy', 'dummy', default=False)
-    >>> gcdummy.getdefault()
+    >>> gcdummy.impl_getdefault()
     False
-    >>> descr = OptionDescription('tiramisu', '', [gcdummy])
-    >>> cfg = Config(descr)
     >>> cfg.dummy
     False
+    >>> descr = OptionDescription('tiramisu', '', [gcdummy])
+    >>> cfg = Config(descr)
     >>> cfg.dummy = True
     >>> cfg.dummy
     True
     >>> cfg.idontexist
     AttributeError: 'OptionDescription' object has no attribute 'idontexist'
 
-The `Option` objects (in this case the `BoolOption`), are organized into a tree
-into nested `OptionDescription` objects. Every option has a name, as does every
-option group. The parts of the full name of the option are separated by dots:
-e.g. ``cfg.optgroup.optname``.
+The `Option` objects (in this case the :class:`~tiramisu.option.BoolOption`), 
+are organized into a tree into nested 
+:class:`~tiramisu.option.OptionDescription` objects. Every option has a name, 
+as does every option group. The parts of the full name of the option are 
+separated by dots: e.g. ``cfg.optgroup.optname``.
 
-Let's make the protocol of accessing a config's attribute explicit
+Let's make the protocol of accessing a `Config`'s attribute explicit
 (because explicit is better than implicit):
 
 1. If the option has not been declared, an `AttributeError` is raised,
@@ -59,26 +66,14 @@ Let's make the protocol of accessing a config's attribute explicit
    the value of the option.
 
 But there are special exceptions. We will see later on that an option can be a
-:term:`mandatory option`. A mandatory option is an option that must have a defined value.
-If no value have been set yet, the value is `None`.
-When the option is called to retrieve a value, an exception is raised.
-
-What if a value has been set and `None` is to be returned again ? Don't
-worry, an option value can be "reseted" with the help of the `option.Option.reset()`
-method.
-
-If you know the path:
-
-::
-
-    >>> config.gc.dummy
-    False
+:term:`mandatory option`. A mandatory option is an option that must have a value 
+defined.
 
-Setting the values of the options
-----------------------------------------
+Setting the value of an option
+------------------------------
 
-An important part of the setting of the configuration consists of setting the
-values of the configuration options. There are different ways of setting values,
+An important part of the setting's configuration consists of setting the
+value's option. There are different ways of setting values,
 the first one is of course the `__setattr__` method
 
 ::
@@ -103,18 +98,17 @@ bundled into a configuration object which has a reference to its option
 description (and therefore makes sure that the configuration values
 adhere to the option description).
 
-
 Common manipulations
 ------------------------
 
-Let's perform some common manipulation on some options:
+Let's perform some common manipulation on some options
 
 >>> from tiramisu.config import Config
 >>> from tiramisu.option import UnicodeOption, OptionDescription
->>>
+>>> #
 >>> var1 = UnicodeOption('var1', 'first variable')
 >>> var2 = UnicodeOption('var2', '', u'value')
->>>
+>>> #
 >>> od1 = OptionDescription('od1', 'first OD', [var1, var2])
 >>> rootod = OptionDescription('rootod', '', [od1])
 
@@ -135,11 +129,10 @@ None
 >>> print c.od1.var2
 value
 
-let's modify a value (careful to the value's type...)
+let's modify a value (be careful to the value's type...)
 
 >>> c.od1.var1 = 'value'
 Traceback (most recent call last):
-[...]
 ValueError: invalid value value for option var1
 >>> c.od1.var1 = u'value'
 >>> print c.od1.var1
@@ -155,19 +148,17 @@ let's come back to the default value
 value
 
 The value is saved in a :class:`~tiramisu.value.Value` object. It is on this 
-object that we have to trigger the `reset`, wich take the option itself 
+object that we have to trigger the `reset`, which take the option itself 
 (`var2`) as a parameter.
 
-On the other side, in the `read_only` mode, it is not possible to modify the value::
+On the other side, in the `read_only` mode, it is not possible to modify the value
+
+>>> c.read_only()
+>>> c.od1.var2 = u'value2'
+Traceback (most recent call last):
+tiramisu.error.PropertiesOptionError: cannot change the value for option var2 this option is frozen
+
 
-    >>> c.read_only()
-    >>> c.od1.var2 = u'value2'
-    Traceback (most recent call last):
-    [...]
-    tiramisu.error.PropertiesOptionError: 
-    cannot change the value to var2 
-    for option ['frozen'] this option is frozen
-    
 let's retrieve the option `var1` description
 
 >>> var1.impl_get_information('doc')
@@ -197,7 +188,7 @@ That's why a tree of options can easily be searched. First, let's build such a t
 >>> c = Config(rootod)
 >>> c.read_write()
 
-Second, let's find an option by his name::
+Second, let's find an option by it's name::
 
     >>> print c.find(byname='var1')
     [<tiramisu.option.UnicodeOption object at 0x7ff1bf7d6ef0>, 
@@ -245,7 +236,7 @@ If the organisation in a tree is not important,
 {'var5': None, 'var4': None, 'var6': None, 'var1': u'value', 'var3': None, 
 'var2': None}
 
-.. note:: carefull with this `flatten` parameter, here we have just lost 
+.. note:: be carefull with this `flatten` parameter, here we have just lost 
                two options named `var1`
 
 One can export only interesting parts of a tree of options into a dict, for 
@@ -262,7 +253,7 @@ and of course, :meth:`~config.SubConfig.make_dict()` can be called in a subtree:
 >>> print c.od1.make_dict(withoption='var1')
 {'var1': None, 'var3': None, 'var2': None}
 
-the owners
+The owners
 ~~~~~~~~~~~
 
 .. glossary::
@@ -280,24 +271,36 @@ the owners
             
 Then let's retrieve the owner associated to an option::
 
-    >>> print c.getowner('var1')
-    default
-    >>> c.od1.var1 = u'non'
-    >>> print c.getowner('var1')
-    user
-    >>> del(c.var1)
-    >>> print c.getowner('var1')
-    default
-    
-the properties
-~~~~~~~~~~~~~~~~
+   >>> print c.getowner(var1)
+   default
+   >>> c.od1.var1 = u'no'
+   >>> print c.getowner(var1)
+   user
+   >>> del(c.var1)
+   >>> print c.getowner(var1)
+   default
+
+You can create your own owner, for example to distinguish modification made by
+one user to an other one's.
+
+   >>> from tiramisu.setting import owners
+   >>> owners.addowner('toto')
+   >>> c.cfgimpl_get_settings().setowner(owners.toto)
+   >>> print c.getowner(var1)
+   default
+   >>> c.od1.var1 = u'no'
+   >>> print c.getowner(var1)
+   toto
+The properties
+~~~~~~~~~~~~~~
 
 A property is an information on an option's state. 
 Let's create options with properties::
 
     >>> var1 = UnicodeOption('var1', '', u'value', properties=('hidden',))
     >>> var2 = UnicodeOption('var2', '', properties=('mandatory',))
-    >>> var3 = UnicodeOption('var3', '', u'value', properties=('frozen', 'inconnu'))
+    >>> var3 = UnicodeOption('var3', '', u'value', properties=('frozen', 'unknown'))
     >>> var4 = UnicodeOption('var4', '', u'value')
     >>> od1 = OptionDescription('od1', '', [var1, var2, var3])
     >>> od2 = OptionDescription('od2', '', [var4], properties=('hidden',))
@@ -311,7 +314,6 @@ with a hidden option::
 
     >>> print c.od1.var1
     Traceback (most recent call last):
-    [...]
     tiramisu.error.PropertiesOptionError: trying to access to an option named: var1 
     with properties ['hidden']
     >>> c.read_only()
@@ -328,7 +330,6 @@ mode. But in read only mode, an error is raised if no value has been defined::
     >>> c.read_only()
     >>> print c.od1.var2
     Traceback (most recent call last):
-    [...]
     tiramisu.error.PropertiesOptionError: trying to access to an option named: var2 
     with properties ['mandatory']
     >>> c.read_write()
@@ -345,7 +346,6 @@ Let's try to modify a frozen option::
     value
     >>> c.od1.var3 = u'value2'
     Traceback (most recent call last):
-    [...]
     tiramisu.error.PropertiesOptionError: cannot change the value for option var3 this option is frozen
     >>> c.read_only()
     >>> print c.od1.var3
@@ -354,23 +354,21 @@ Let's try to modify a frozen option::
 Tiramisu allows us to use user defined properties. Let's define and use one in 
 read/write or read only mode::
 
-    >>> c.cfgimpl_get_settings().append('inconnu')
+    >>> c.cfgimpl_get_settings().append('unknown')
     >>> print c.od1.var3
     Traceback (most recent call last):
-    [...]
     tiramisu.error.PropertiesOptionError: trying to access to an option named: 
-    var3 with properties ['inconnu']
-    >>> c.cfgimpl_get_settings().remove('inconnu')
+    var3 with properties ['unknown']
+    >>> c.cfgimpl_get_settings().remove('unknown')
     >>> print c.od1.var3
     value 
     
-Properties can also be defined on an option group, (that is, on an 
-:term:`option description`), let's hide a group and try to access to it::
+Properties can also be defined on an option group (that is, on an 
+:term:`option description`) let's hide a group and try to access to it::
 
     >>> c.read_write()
     >>> print c.od2.var4
     Traceback (most recent call last):
-    [...]
     tiramisu.error.PropertiesOptionError: trying to access to an option named: od2 
     with properties ['hidden']
     >>> c.read_only()
@@ -384,7 +382,6 @@ Furthermore, let's retrieve the properties, delete and add the `hidden` property
     ['hidden']
     >>> print c.od1.var1
     Traceback (most recent call last):
-    [...]
     tiramisu.error.PropertiesOptionError: trying to access to an option named: 
     var1 with properties ['hidden']
     >>> c.cfgimpl_get_settings()[rootod.od1.var1].remove('hidden')
@@ -397,7 +394,6 @@ Furthermore, let's retrieve the properties, delete and add the `hidden` property
     ['hidden']
     >>> print c.od1.var1
     Traceback (most recent call last):
-    [...]
     tiramisu.error.PropertiesOptionError: trying to access to an option named: 
     var1 with properties ['hidden']
 
@@ -435,11 +431,10 @@ A multi-option's value can be manipulated like a list::
     >>> print c.od1.var1
     [u'var1']
 
-But it is not possible to set a value to a multi-option wich is not a list::    
+But it is not possible to set a value to a multi-option which is not a list::    
 
     >>> c.od1.var1 = u'error'
     Traceback (most recent call last):
-    [...]
     ValueError: invalid value error for option var1 which must be a list
     
 
@@ -511,17 +506,14 @@ But it is forbidden to change the lenght of a slave::
     slave2 = [u'default', u'default']
     >>> c.master.slave1 = [u'new1']
     Traceback (most recent call last):
-    [...]
     tiramisu.error.SlaveError: invalid len for the slave: slave1 which has master.master as master
     >>> c.master.slave1 = [u'new1', u'new2', u'new3']
-    [...]
     tiramisu.error.SlaveError: invalid len for the slave: slave1 which has master.master as master
     
 you have to call the `pop` function on the master::
 
     >>> c.master.master = [u'oui']
     Traceback (most recent call last):
-    [...]
     tiramisu.error.SlaveError: invalid len for the master: master which has slave1 as slave with greater len
     >>> c.master.master.pop(0)
     u'oui'
@@ -567,6 +559,6 @@ Here are the (useful) methods on ``Config`` (or `SubConfig`).
 A :class:`~config.CommonConfig` is a abstract base class. A
 :class:`~config.SubConfig` is an just in time created objects that wraps an
 ::class:`~option.OptionDescription`. A SubConfig differs from a Config in the
-::fact that a config is a root object and has an environnement, a context wich
-::defines the different properties, access rules, vs... There is generally only
-::one Config, and many SubConfigs.
+fact that a config is a root object and has an environnement, a context which
+defines the different properties, access rules, vs... There is generally only
+one Config, and many SubConfigs.