multi-action available now in requires
authorgwen <gremond@cadoles.com>
Thu, 20 Sep 2012 08:51:35 +0000 (10:51 +0200)
committergwen <gremond@cadoles.com>
Thu, 20 Sep 2012 08:51:35 +0000 (10:51 +0200)
tiramisu/config.py
tiramisu/option.py

index d268787..5d5c0f2 100644 (file)
@@ -38,6 +38,8 @@ class Config(object):
     _cfgimpl_frozen = True
     _cfgimpl_owner = default_owner
     _cfgimpl_toplevel = None
+# TODO implement unicity by name
+#    _cfgimpl_unique_names = True
     
     def __init__(self, descr, parent=None, **overrides):
         self._cfgimpl_descr = descr
@@ -61,6 +63,26 @@ class Config(object):
             else:
                 raise ConflictConfigError('duplicate option name: ' 
                     '{0}'.format(dup._name))
+
+# TODO implement unicity by name
+#    def _validate_duplicates_for_names(self, children):
+#        "validates duplicates names agains the whole config"
+#        rootconfig = self._cfgimpl_get_toplevel()
+#        if self._cfgimpl_unique_names:
+#            for dup in children:
+#                try:
+#                    print dup._name
+#                    try:
+#                        print rootconfig.get(dup._name)
+#                    except AttributeError:
+#                        pass
+#                    raise NotFoundError
+#                    #rootconfig.get(dup._name)
+#                except NotFoundError:
+#                    pass # no identical names, it's fine
+#                else:
+#                    raise ConflictConfigError('duplicate option name: ' 
+#                        '{0}'.format(dup._name))
         
     def _cfgimpl_build(self, overrides):
         self._validate_duplicates(self._cfgimpl_descr._children)
@@ -424,7 +446,7 @@ class Config(object):
         self.cfgimpl_unfreeze()
         rootconfig = self._cfgimpl_get_toplevel()
         rootconfig.cfgimpl_enable_property('hidden')
-        rootconfig.cfgimpl_disable_property('disabled')
+        rootconfig.cfgimpl_enable_property('disabled')
         rootconfig._cfgimpl_mandatory = False
     # ____________________________________________________________
     def getkey(self):
index 277bc2b..0e7fa10 100644 (file)
 from tiramisu.basetype import HiddenBaseType, DisabledBaseType
 from tiramisu.error import (ConfigError, ConflictConfigError, NotFoundError, 
     RequiresError, RequirementRecursionError, MandatoryError)
-available_actions = ['hide', 'show', 'enable', 'disable', 'freeze', 'unfreeze']
-reverse_actions = {'hide': 'show', 'show': 'hide', 
-                   'disable': 'enable', 'enable': 'disable',
-                   'freeze': 'unfreeze', 'unfreeze': 'freeze'}
+requires_actions = [('hide', 'show'), ('enable', 'disable'), ('freeze', 'unfreeze')]
+
+available_actions = []
+reverse_actions = {}
+for act1, act2 in requires_actions:
+    available_actions.extend([act1, act2])
+    reverse_actions[act1] = act2
+    reverse_actions[act2] = act1
+
 # ____________________________________________________________
 # OptionDescription authorized group_type values
 group_types = ['default', 'family', 'group', 'master']
@@ -450,45 +455,51 @@ class OptionDescription(HiddenBaseType, DisabledBaseType):
             if isinstance(child, OptionDescription):
                 child.enable()
 # ____________________________________________________________
+
+def validate_requires_arg(requires, name):
+    # malformed requirements
+    config_action = []
+    for req in requires:
+        if not type(req) == tuple and len(req) != 3:
+            raise RequiresError("malformed requirements for option:"
+                                           " {0}".format(name))
+        action = req[2]
+        if action not in available_actions:
+            raise RequiresError("malformed requirements for option: {0}"
+                                "unknown action: {1}".format(name, action))
+        if reverse_actions[action] in config_action:
+            raise RequiresError("inconsistency in action types for option: {0}"
+                                "action: {1} in contradiction with {2}\n"
+                                " ({3})".format(name, action,
+                                    reverse_actions[action], requires))
+        config_action.append(action)
+
+def build_actions(requires):
+    trigger_actions = {}
+    for require in requires:
+        action = require[2]
+        trigger_actions.setdefault(action, []).append(require)
+    return trigger_actions
+
 def apply_requires(opt, config):
-    if hasattr(opt, '_requires'):
-        if opt._requires is not None:
-            # malformed requirements
-            rootconfig = config._cfgimpl_get_toplevel()
-            for req in opt._requires:
-                if not type(req) == tuple and len(req) in (3, 4):
-                    raise RequiresError("malformed requirements for option:"
-                                                   " {0}".format(opt._name))
-            # all actions **must** be identical
-            actions = [req[2] for req in opt._requires]
-            action = actions[0]
-            for act in actions:
-                if act != action:
-                    raise RequiresError("malformed requirements for option:"
-                                                   " {0}".format(opt._name))
-            # filters the callbacks
+    if hasattr(opt, '_requires') and opt._requires is not None:
+        rootconfig = config._cfgimpl_get_toplevel()
+        validate_requires_arg(opt._requires, opt._name)
+        # filters the callbacks
+        trigger_actions = build_actions(opt._requires)
+        for requires in trigger_actions.values():
             matches = False
-            for req in opt._requires:
-                if len(req) == 3:
-                    name, expected, action = req
-                    inverted = False
-                if len(req) == 4:
-                    name, expected, action, inverted = req
-                    if inverted == 'inverted':
-                        inverted = True
+            for require in requires:
+                name, expected, action = require
                 path = config._cfgimpl_get_path() + '.' + opt._name
                 if name.startswith(path):
-                    raise RequirementRecursionError("malformed requirements imbrication "
-                          "detected for option: '{0}' with requirement on: '{1}'".format(path, name))
-                homeconfig, shortname = \
-                                      rootconfig._cfgimpl_get_home_by_path(name)
+                    raise RequirementRecursionError("malformed requirements "
+                          "imbrication detected for option: '{0}' "
+                          "with requirement on: '{1}'".format(path, name))
+                homeconfig, shortname = rootconfig._cfgimpl_get_home_by_path(name)
                 if shortname in homeconfig._cfgimpl_values:
                     value = homeconfig._cfgimpl_values[shortname]
-                    if (not inverted and value == expected) or \
-                            (inverted and value != expected):
-                        if action not in available_actions:
-                            raise RequiresError("malformed requirements"
-                                           " for option: {0}".format(opt._name))
+                    if value == expected:
                         getattr(opt, action)() #.hide() or show() or...
                         # FIXME generic programming opt.property_launch(action, False)
                         matches = True