trimming options's callbacks
authorgwen <gremond@cadoles.com>
Mon, 15 Oct 2012 13:06:41 +0000 (15:06 +0200)
committergwen <gremond@cadoles.com>
Mon, 15 Oct 2012 13:06:41 +0000 (15:06 +0200)
test/test_option_owner.py
tiramisu/autolib.py
tiramisu/config.py
tiramisu/option.py

index 247bc21..c71fbb7 100644 (file)
@@ -70,7 +70,7 @@ def test_has_callback():
     descr = make_description()
     # here the owner is 'default'
     config = Config(descr, bool=False)
-    # because dummy has a callback 
+    # because dummy has a callback
     dummy = config.unwrap_from_path('gc.dummy')
     config.cfgimpl_freeze()
     dummy.freeze()
@@ -85,8 +85,7 @@ def test_freeze_and_has_callback_with_setoption():
     dummy.freeze()
     raises(TypeError, "config.gc.setoption('dummy', True, 'gen_config')")
 
-def test_cannot_override():
-    descr = make_description()
-    config = Config(descr, bool=False)
-    raises(TypeError, "config.override({'gc.dummy': True})")
-
+#def test_cannot_override():
+#    descr = make_description()
+#    config = Config(descr, bool=False)
+#    raises(TypeError, "config.override({'gc.dummy': True})")
index 0002f5c..42fcf7f 100644 (file)
@@ -19,8 +19,7 @@
 # the whole pypy projet is under MIT licence
 # ____________________________________________________________
 "enables us to carry out a calculation and return an option's value"
-from tiramisu.error import (PropertiesOptionError, ConflictConfigError,
-    NoValueReturned)
+from tiramisu.error import PropertiesOptionError, ConflictConfigError
 # ____________________________________________________________
 # automatic Option object
 #def special_owner_factory(name, owner, value,
@@ -28,10 +27,12 @@ from tiramisu.error import (PropertiesOptionError, ConflictConfigError,
 #    # in case of an 'auto' and a 'fill' without a value,
 #    # we have to carry out a calculation
 #    return calc_factory(name, callback, callback_params, config)
-def carry_out_calculation(name, callback, callback_params, config):
+def carry_out_calculation(name, option, config):
     # FIXME we have to know the exact status of the config
     # not to disrupt it
     # config.freeze()
+    callback=option.getcallback()
+    callback_params=option.getcallback_params()
     if callback_params is None:
         callback_params = {}
     tcparams = {}
@@ -44,7 +45,7 @@ def carry_out_calculation(name, callback, callback_params, config):
                 opt_value = getattr(config, path)
                 opt = config.unwrap_from_path(path)
             except PropertiesOptionError, e:
-                if chek_disabled:
+                if check_disabled:
                     continue
                 raise PropertiesOptionError(e)
             is_multi = opt.is_multi()
@@ -87,6 +88,7 @@ def carry_out_calculation(name, callback, callback_params, config):
                 params.append(couple[0])
             else:
                 tcp[key] = couple[0]
+        a=calculate(name, callback, params, tcp)
         return calculate(name, callback, params, tcp)
 
 def calculate(name, callback, params, tcparams):
@@ -94,8 +96,6 @@ def calculate(name, callback, params, tcparams):
         # XXX not only creole...
         from creole import eosfunc
         return getattr(eosfunc, callback)(*params, **tcparams)
-    except NoValueReturned, err:
-        return ""
     except AttributeError, err:
         import traceback
         traceback.print_exc()
index dee5ca1..bd0b553 100644 (file)
 from copy import copy
 from tiramisu.error import (PropertiesOptionError, ConfigError, NotFoundError,
     AmbigousOptionError, ConflictConfigError, NoMatchingOptionFound,
-    MandatoryError, MethodCallError)
+    MandatoryError, MethodCallError, NoValueReturned)
 from tiramisu.option import (OptionDescription, Option, SymLinkOption,
     group_types, Multi, apply_requires)
-from tiramisu.autolib import carry_out_calculation
 
 # ______________________________________________________________________
 # generic owner. 'default' is the general config owner after init time
@@ -226,36 +225,42 @@ class Config(object):
             if opt_or_descr.has_callback():
                 value = self._cfgimpl_values[name]
                 if (not opt_or_descr.is_frozen() or \
-                        not opt_or_descr.is_forced_on_freeze()) and value != None:
+                        not opt_or_descr.is_forced_on_freeze()) and \
+                        not opt_or_descr.getowner(self) == 'default':
                     if opt_or_descr.is_multi():
                         if None not in value:
                             return value
                     else:
                         return value
-                result = carry_out_calculation(name,
-                            callback=opt_or_descr.getcallback(),
-                            callback_params=opt_or_descr.getcallback_params(),
-                            config=self._cfgimpl_get_toplevel())
-                # this result **shall not** be a list
-                # for example, [1, 2, 3, None] -> [1, 2, 3, result]
-                if isinstance(result, list):
-                    raise ConfigError('invalid calculated value returned'
-                        ' for option {0} : shall not be a list'.format(name))
-                if result != None and not opt_or_descr._validate(result):
-                    raise ConfigError('invalid calculated value returned'
-                        ' for option {0}'.format(name))
-                if opt_or_descr.is_multi():
-                    if value == []:
-                        _result = Multi([result], value.config, value.child)
-                    else:
-                        _result = Multi([], value.config, value.child)
-                        for val in value:
-                            if val == None:
-                                val = result
-                            _result.append(val)
+                try:
+                    result = opt_or_descr.getcallback_value(
+                            self._cfgimpl_get_toplevel())
+                except NoValueReturned, err:
+                    pass
                 else:
-                    _result = result
-                return _result
+                    # this result **shall not** be a list
+                    # for example, [1, 2, 3, None] -> [1, 2, 3, result]
+                    if isinstance(result, list):
+                        raise ConfigError('invalid calculated value returned'
+                            ' for option {0} : shall not be a list'.format(name))
+                    if result != None and not opt_or_descr._validate(result):
+                        raise ConfigError('invalid calculated value returned'
+                            ' for option {0}'.format(name))
+                    if opt_or_descr.is_multi():
+                        if value == []:
+                            _result = Multi([result], value.config, value.child)
+                        else:
+                            _result = Multi([], value.config, value.child)
+                            #for val in value:
+                            owners = opt_or_descr.getowner(self)
+                            for cpt in range(len(value)):
+                                val = value[cpt]
+                                if owners[cpt] == 'default':
+                                    val = result
+                                _result.append(val)
+                    else:
+                        _result = result
+                    self._cfgimpl_values[name] = _result
 
             # mandatory options
             homeconfig = self._cfgimpl_get_toplevel()
@@ -335,9 +340,9 @@ class Config(object):
                 else:
                     newowner = who
         if type(child) != SymLinkOption:
-            if child.has_callback() and who=='default':
-                raise TypeError("trying to set a value to an option "
-                    "wich has a callback: {0}".format(name))
+            #if child.has_callback() and who=='default':
+            #    raise TypeError("trying to set a default value to an option "
+            #        "which has a callback: {0}".format(name))
             child.setoption(self, value, who)
             if (value is None and who != 'default' and not child.is_multi()):
                 child.setowner(self, 'default')
index e6d78fb..ed1cbfb 100644 (file)
@@ -23,6 +23,8 @@
 from tiramisu.basetype import HiddenBaseType, DisabledBaseType
 from tiramisu.error import (ConfigError, ConflictConfigError, NotFoundError,
     RequiresError, RequirementRecursionError, MandatoryError)
+from tiramisu.autolib import carry_out_calculation
+
 requires_actions = [('hide', 'show'), ('enable', 'disable'), ('freeze', 'unfreeze')]
 
 available_actions = []
@@ -191,6 +193,11 @@ class Option(HiddenBaseType, DisabledBaseType):
         else:
             return True
 
+    def getcallback_value(self, config):
+        return carry_out_calculation(self._name,
+                option=self,
+                config=config)
+
     def getcallback_params(self):
         "if a callback has been defined, returns his arity"
         return self.callback_params
@@ -213,6 +220,17 @@ class Option(HiddenBaseType, DisabledBaseType):
         "config *must* be only the **parent** config (not the toplevel config)"
         return config._cfgimpl_value_owners[self._name]
 
+    def is_default_owner(self, config):
+        if self.is_multi():
+            for owner in self.getowner(config):
+                if owner != 'default':
+                    return False
+            return True
+        else:
+            if self.getowner(config) == 'default':
+                return True
+            return False
+
     def setoption(self, config, value, who):
         """changes the option's value with the value_owner's who
         :param config: the parent config is necessary here to store the value