diff --git a/tiramisu/autolib.py b/tiramisu/autolib.py index 8f321cf..55b655e 100644 --- a/tiramisu/autolib.py +++ b/tiramisu/autolib.py @@ -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]) + 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[incr] - else: - if key == '': - params.append(value) - 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): diff --git a/tiramisu/config.py b/tiramisu/config.py index 72a0312..b7b3252 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -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): diff --git a/tiramisu/option.py b/tiramisu/option.py index abeb991..2d1d7cc 100644 --- a/tiramisu/option.py +++ b/tiramisu/option.py @@ -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