multi options
authorgwen <gremond@cadoles.com>
Wed, 17 Oct 2012 09:14:17 +0000 (11:14 +0200)
committergwen <gremond@cadoles.com>
Wed, 17 Oct 2012 09:14:17 +0000 (11:14 +0200)
tiramisu/autolib.py
tiramisu/config.py
tiramisu/option.py

index 8f321cf..55b655e 100644 (file)
@@ -38,58 +38,65 @@ def carry_out_calculation(name, option, config):
     tcparams = {}
     one_is_multi = False
     len_multi = 0
-    for key, value in callback_params.items():
-        if type(value) == tuple:
-            path, check_disabled = value
-            try:
-                #opt_value = getattr(config, path)
-                opt_value = config._getattr(path, permissive=True)
-                opt = config.unwrap_from_path(path)
-            except PropertiesOptionError, err:
-                if check_disabled:
-                    continue
-                raise PropertiesOptionError(err, err.proptype)
-            is_multi = opt.is_multi()
-            if is_multi:
-                if opt_value != None:
-                    len_value = len(opt_value)
-                    if len_multi != 0 and len_multi != len_value:
-                        raise ConflictConfigError('unable to carry out a calculation, '
-                        'option values with multi types must have same length for: '
-                         + name)
-                    len_multi = len_value
-                one_is_multi = True
-            tcparams[key] = (opt_value, is_multi)
-        else:
-            tcparams[key] = (value, False)
+
+    for key, values in callback_params.items():
+        for value in values:
+            if type(value) == tuple:
+                path, check_disabled = value
+                try:
+                    opt_value = config._getattr(path, permissive=True)
+                    opt = config.unwrap_from_path(path)
+                except PropertiesOptionError, err:
+                    if check_disabled:
+                        continue
+                    raise PropertiesOptionError(err, err.proptype)
+                is_multi = opt.is_multi()
+                if is_multi:
+                    if opt_value != None:
+                        len_value = len(opt_value)
+                        if len_multi != 0 and len_multi != len_value:
+                            raise ConflictConfigError('unable to carry out a calculation, '
+                            'option values with multi types must have same length for: '
+                             + name)
+                        len_multi = len_value
+                    one_is_multi = True
+                tcparams.setdefault(key, []).append((opt_value, is_multi))
+            else:
+                tcparams.setdefault(key, []).append((value, False))
 
     if one_is_multi:
         ret = []
         for incr in range(len_multi):
             tcp = {}
-            for key, couple in tcparams.items():
-                value, ismulti = couple
-                if ismulti and value != None:
-                    if key == '':
-                        params.append(value[incr])
-                    else:
-                        tcp[key] = value[incr]
-                else:
-                    if key == '':
-                        params.append(value)
+            params = []
+            for key, couples in tcparams.items():
+                for couple in couples:
+                    value, ismulti = couple
+                    if ismulti and value != None:
+                        if key == '':
+                            params.append(value[incr])
+                        else:
+                            if len(value) > incr:
+                                tcp[key] = value[incr]
+                            else:
+                                tcp[key] = ''
                     else:
-                        tcp[key] = value
-            ret.append(calculate(name, callback, tcp))
+                        if key == '':
+                            params.append(value)
+                        else:
+                            tcp[key] = value
+            ret.append(calculate(name, callback, params, tcp))
         return ret
     else:
         tcp = {}
         params = []
-        for key, couple in tcparams.items():
-            if key == '':
-                params.append(couple[0])
-            else:
-                tcp[key] = couple[0]
-        a=calculate(name, callback, params, tcp)
+        for key, couples in tcparams.items():
+            for couple in couples:
+                if key == '':
+                    value = couple[0]
+                    params.append(value)
+                else:
+                    tcp[key] = couple[0]
         return calculate(name, callback, params, tcp)
 
 def calculate(name, callback, params, tcparams):
index 72a0312..b7b3252 100644 (file)
@@ -239,7 +239,8 @@ class Config(object):
                 value = self._cfgimpl_values[name]
                 if (not opt_or_descr.is_frozen() or \
                         not opt_or_descr.is_forced_on_freeze()) and \
-                        not opt_or_descr.getowner(self) == 'default':
+                        not opt_or_descr.is_default_owner(self, all_default=False):
+                        #not opt_or_descr.getowner(self) == 'default':
                     if opt_or_descr.is_multi():
                         if None not in value:
                             return value
@@ -251,28 +252,52 @@ class Config(object):
                 except NoValueReturned, err:
                     pass
                 else:
-                    # 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 == []:
+                        owners = copy(self._cfgimpl_value_owners[name])
+                        self._cfgimpl_value_owners[name] = []
+                        if not isinstance(result, list):
+                            # for example, [1, 2, 3, None] -> [1, 2, 3, result]
                             _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)
+                                if len(owners) > cpt:
+                                    if owners[cpt] == 'default':
+                                        _result.append(result)
+                                        self._cfgimpl_value_owners[name][cpt] = 'default'
+                                    else:
+                                        _result.append(val)
+                                else:
+                                    _result.append(val)
+                                    self._cfgimpl_value_owners[name][cpt] = 'default'
+                        else:
+                            # for example, [1, None, 2, None] + [a, b, c, d]
+                            # = [1, b, 2, d]
+                            _result = Multi([], value.config, value.child)
+                            for cpt in range(max(len(value), len(result))):
+                                if len(value) > cpt:
+                                    val = value[cpt]
+                                else:
+                                    val = ''
+                                if len(result) > cpt:
+                                    rval = result[cpt]
+                                if len(owners) > cpt:
+                                    if owners[cpt] == 'default':
+                                        _result.append(rval)
+                                        self._cfgimpl_value_owners[name][cpt] = 'default'
+                                    else:
+                                        _result.append(val)
+                                else:
+                                    _result.append(rval)
+                                    self._cfgimpl_value_owners[name][cpt] = 'default'
                     else:
+                        # this result **shall not** be a list
+                        if isinstance(result, list):
+                            raise ConfigError('invalid calculated value returned'
+                                ' for option {0} : shall not be a list'.format(name))
                         _result = result
+                    if _result != None and not opt_or_descr.validate(_result):
+                        raise ConfigError('invalid calculated value returned'
+                            ' for option {0}'.format(name))
                     self._cfgimpl_values[name] = _result
 
             # mandatory options
@@ -286,6 +311,7 @@ class Config(object):
             # frozen and force default
             if not opt_or_descr.has_callback() and opt_or_descr.is_forced_on_freeze():
                 return opt_or_descr.getdefault()
+
         return self._cfgimpl_values[name]
 
     def unwrap_from_name(self, name):
index abeb991..2d1d7cc 100644 (file)
@@ -59,7 +59,7 @@ class Multi(list):
         self.setoption(value)
 
     def setoption(self, value, key=None):
-        owners = self.child.getowner(self.config)
+        #owners = self.child.getowner(self.config)
         # None is replaced by default_multi
         if value == None:
             defval = self.child.getdefault()
@@ -220,12 +220,18 @@ 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):
+    def is_default_owner(self, config, all_default=True):
         if self.is_multi():
-            for owner in self.getowner(config):
-                if owner != 'default':
+            owners = self.getowner(config)
+            for owner in owners:
+                if all_default and owner != 'default':
                     return False
-            return True
+                if not all_default and owner == 'default':
+                    return True
+            if all_default or owners == []:
+                return True
+            else:
+                return False
         else:
             if self.getowner(config) == 'default':
                 return True