documentation on the requirements and docstring updates
This commit is contained in:
parent
1ddd88fc99
commit
747d994762
|
@ -50,17 +50,27 @@ Configuration options can specify requirements as parameters at the init
|
|||
time, the specification of some links between options or groups allows
|
||||
to carry out a dependencies calculation. For example, an option can ben
|
||||
hidden if another option has been set with some expected value. This is
|
||||
just an example, because the possibilities are hudge.
|
||||
just an example, the possibilities are hudge.
|
||||
|
||||
A requirement is specified using a list of triplets. The first element
|
||||
of the triplet gives the path of the option that is required, the second
|
||||
element is the value wich is expected to trigger the callback, and the
|
||||
third one is the callback's action name (`hide`, `show`...)::
|
||||
A requirement is a list of dictionnaries that have fairly this form::
|
||||
|
||||
stroption = StrOption('str', 'Test string option', default="abc",
|
||||
requires=[('int', 1, 'hide')])
|
||||
[{'option': a, 'expected': False, 'action': 'disabled', 'inverse': True,
|
||||
'transitive':True, 'same_action': True}]
|
||||
|
||||
Requirements are validated in :class:`setting.Setting`.
|
||||
Actually a transformation is made to this dictionnary during the validation of
|
||||
this requires at the :class:`~option.Option()`'s init. The dictionnairy becomes
|
||||
a tuple, wich is passed to the :meth:`~setting.Settings.apply_requires()`
|
||||
method. Take a look at the code to fully understand the exact meaning of the
|
||||
requirements:
|
||||
|
||||
.. automethod:: tiramisu.setting.Settings.apply_requires
|
||||
|
||||
|
||||
The path of the option is required, the second element is the value wich is
|
||||
expected to trigger the callback, it is required too, and the third one is the
|
||||
callback's action name (`hide`, `show`...), wich is a
|
||||
:class:`~setting.Property()`. Requirements are validated in
|
||||
:class:`setting.Setting`.
|
||||
|
||||
Validation upon a whole configuration object
|
||||
----------------------------------------------
|
||||
|
|
|
@ -926,6 +926,11 @@ class OptionDescription(BaseInformation):
|
|||
def validate_requires_arg(requires, name):
|
||||
"""check malformed requirements
|
||||
and tranform dict to internal tuple
|
||||
|
||||
:param requires: have a look at the
|
||||
:meth:`tiramisu.setting.Settings.apply_requires` method to
|
||||
know more about
|
||||
the description of the requires dictionnary
|
||||
"""
|
||||
if requires is None:
|
||||
return None
|
||||
|
@ -934,7 +939,6 @@ def validate_requires_arg(requires, name):
|
|||
|
||||
for require in requires:
|
||||
if not type(require) == dict:
|
||||
print require
|
||||
raise ValueError(_("malformed requirements type for option:"
|
||||
" {0}, must be a dict").format(name))
|
||||
valid_keys = ('option', 'expected', 'action', 'inverse', 'transitive',
|
||||
|
|
|
@ -242,7 +242,8 @@ class Settings(object):
|
|||
props = self._p_.getproperties(path, default_properties)
|
||||
else:
|
||||
if path is None:
|
||||
raise ValueError(_('if opt is not None, path should not be None in _getproperties'))
|
||||
raise ValueError(_('if opt is not None, path should not be'
|
||||
' None in _getproperties'))
|
||||
ntime = None
|
||||
if self._p_.hascache('property', path):
|
||||
ntime = time()
|
||||
|
@ -287,13 +288,15 @@ class Settings(object):
|
|||
validation upon the properties related to `opt_or_descr`
|
||||
|
||||
:param opt_or_descr: an option or an option description object
|
||||
:param force_permissive: behaves as if the permissive property was present
|
||||
:param force_permissive: behaves as if the permissive property
|
||||
was present
|
||||
:param is_descr: we have to know if we are in an option description,
|
||||
just because the mandatory property doesn't exist there
|
||||
just because the mandatory property
|
||||
doesn't exist here
|
||||
|
||||
:param is_write: in the validation process, an option is to be modified,
|
||||
the behavior can be different (typically with the `frozen`
|
||||
property)
|
||||
the behavior can be different
|
||||
(typically with the `frozen` property)
|
||||
"""
|
||||
# opt properties
|
||||
properties = copy(self._getproperties(opt_or_descr, path))
|
||||
|
@ -374,12 +377,55 @@ class Settings(object):
|
|||
self._p_.reset_all_cache('property')
|
||||
|
||||
def apply_requires(self, opt, path):
|
||||
"carries out the jit (just in time requirements between options"
|
||||
"""carries out the jit (just in time) requirements between options
|
||||
|
||||
a requirement is a tuple of this form that comes from the option's
|
||||
requirements validation::
|
||||
|
||||
(option, expected, action, inverse, transitive, same_action)
|
||||
|
||||
let's have a look at all the tuple's items:
|
||||
|
||||
- **option** is the target option's name or path
|
||||
|
||||
- **expected** is the target option's value that is going to trigger an action
|
||||
|
||||
- **action** is the (property) action to be accomplished if the target option
|
||||
happens to have the expected value
|
||||
|
||||
- if **inverse** is `True` and if the target option's value does not
|
||||
apply, then the property action must be removed from the option's
|
||||
properties list (wich means that the property is inverted)
|
||||
|
||||
- **transitive**: but what happens if the target option cannot be
|
||||
accessed ? We don't kown the target option's value. Actually if some
|
||||
property in the target option is not present in the permissive, the
|
||||
target option's value cannot be accessed. In this case, the
|
||||
**action** have to be applied to the option. (the **action** property
|
||||
is then added to the option).
|
||||
|
||||
- **same_action**: actually, if **same_action** is `True`, the
|
||||
transitivity is not accomplished. The transitivity is accomplished
|
||||
only if the target option **has the same property** that the demanded
|
||||
action. If the target option's value is not accessible because of
|
||||
another reason, because of a property of another type, then an
|
||||
exception :exc:`~error.RequirementError` is raised.
|
||||
|
||||
And at last, if no target option matches the expected values, the
|
||||
action must be removed from the option's properties list.
|
||||
|
||||
:param opt: the option on wich the requirement occurs
|
||||
:type opt: `option.Option()`
|
||||
:param path: the option's path in the config
|
||||
:type path: str
|
||||
"""
|
||||
if opt._requires is None:
|
||||
return
|
||||
|
||||
# filters the callbacks
|
||||
setting = Property(self, self._getproperties(opt, path, False), opt, path=path)
|
||||
setting = Property(self,
|
||||
self._getproperties(opt, path, False),
|
||||
opt, path=path)
|
||||
for requires in opt._requires:
|
||||
matches = False
|
||||
for require in requires:
|
||||
|
@ -392,7 +438,8 @@ class Settings(object):
|
|||
" '{0}' with requirement on: "
|
||||
"'{1}'").format(path, reqpath))
|
||||
try:
|
||||
value = self.context._getattr(reqpath, force_permissive=True)
|
||||
value = self.context._getattr(reqpath,
|
||||
force_permissive=True)
|
||||
except PropertiesOptionError, err:
|
||||
if not transitive:
|
||||
continue
|
||||
|
|
Loading…
Reference in New Issue