diff --git a/test/test_option_calculation.py b/test/test_option_calculation.py index 8ca8687..117de9d 100644 --- a/test/test_option_calculation.py +++ b/test/test_option_calculation.py @@ -28,6 +28,12 @@ def return_value(value=None): return value +def return_value2(*args, **kwargs): + value = list(args) + value.extend(kwargs.values()) + return value + + def make_description(): gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref') gcdummy = BoolOption('dummy', 'dummy', default=False) @@ -675,3 +681,13 @@ def test_callback_multi_multi(): raises(ConfigError, "cfg.val4") assert cfg.val5 == ['val1', 'val4', 'val2', 'val4', 'val3', 'val4'] assert cfg.val7 == ['val1', 'val21', 'val2', 'val22', 'val3', 'val23'] + + +def test_multi_with_no_value(): + #First option return [] (so without value) + val1 = StrOption('val1', "", ['val'], multi=True) + val2 = StrOption('val2', "", multi=True) + val3 = StrOption('val3', '', multi=True, callback=return_value, callback_params={'': ((val2, False),), 'value': ((val1, False),)}) + od = OptionDescription('od', '', [val1, val2, val3]) + c = Config(od) + raises(ConfigError, "c.val3") diff --git a/tiramisu/autolib.py b/tiramisu/autolib.py index de8a8c5..efb7c0e 100644 --- a/tiramisu/autolib.py +++ b/tiramisu/autolib.py @@ -41,6 +41,13 @@ def carry_out_calculation(name, config, callback, callback_params, :param max_len: max length for a multi :type max_len: int + The callback_params is a dict. Key is used to build args (if key is '') + and kwargs (otherwise). Values are tuple of: + - values + - tuple with option and boolean's force_permissive (True when don't raise + if PropertiesOptionError) + Values could have multiple values only when key is ''. + * if no callback_params: => calculate() @@ -92,7 +99,6 @@ def carry_out_calculation(name, config, callback, callback_params, - a multi option with an other multi option but with same length opt1 == [1, 2, 3] opt2 == [11, 12, 13] - callback_params={'': ((opt1, False), (opt2, False))} => calculate(1, 11) => calculate(2, 12) => calculate(3, 13) @@ -100,9 +106,13 @@ def carry_out_calculation(name, config, callback, callback_params, - a multi option with an other multi option but with different length opt1 == [1, 2, 3] opt2 == [11, 12] - callback_params={'': ((opt1, False), (opt2, False))} => ConfigError() + - a multi option without value with a simple option + opt1 == [] + opt2 == 11 + => [] + * if callback_params={'value': ((opt1, False), (opt2, False))} => ConfigError() @@ -114,39 +124,47 @@ def carry_out_calculation(name, config, callback, callback_params, If calculate return list, this list is extend to return value. """ tcparams = {} + # if callback_params has a callback, launch several time calculate() one_is_multi = False - len_multi = 0 + # multi's option should have same value for all option + len_multi = None for key, callbacks in callback_params.items(): for callbk in callbacks: if isinstance(callbk, tuple): + # callbk is something link (opt, True|False) option, force_permissive = callbk + path = config.cfgimpl_get_description().impl_get_path_by_opt( + option) # get value try: - path = config.cfgimpl_get_description().impl_get_path_by_opt(option) value = config._getattr(path, force_permissive=True) except PropertiesOptionError as err: if force_permissive: continue raise ConfigError(_('unable to carry out a calculation, ' 'option {0} has properties: {1} for: ' - '{2}').format(option._name, err.proptype, + '{2}').format(option._name, + err.proptype, name)) is_multi = option.impl_is_multi() if is_multi: - if value is not None: - len_value = len(value) - if len_multi != 0 and len_multi != len_value: - raise ConfigError(_('unable to carry out a ' - 'calculation, option value with' - ' multi types must have same ' - 'length for: {0}').format(name)) - len_multi = len_value + len_value = len(value) + if len_multi is not None and len_multi != len_value: + raise ConfigError(_('unable to carry out a ' + 'calculation, option value with' + ' multi types must have same ' + 'length for: {0}').format(name)) + len_multi = len_value one_is_multi = True tcparams.setdefault(key, []).append((value, is_multi)) else: + # callbk is a value and not a multi tcparams.setdefault(key, []).append((callbk, False)) + # if one value is a multi, launch several time calculate + # if index is set, return a value + # if no index, return a list if one_is_multi: ret = [] if index: @@ -161,19 +179,20 @@ def carry_out_calculation(name, config, callback, callback_params, else: range_ = range(len_multi) for incr in range_: - tcp = {} - params = [] + args = [] + kwargs = {} for key, couples in tcparams.items(): for couple in couples: value, ismulti = couple - if ismulti and value is not None: - if key == '': - params.append(value[incr]) - else: - tcp[key] = value[incr] + if ismulti: + val = value[incr] else: - params.append(value) - calc = calculate(name, callback, params, tcp) + val = value + if key == '': + args.append(val) + else: + kwargs[key] = val + calc = calculate(callback, args, kwargs) if index: ret = calc else: @@ -183,24 +202,26 @@ def carry_out_calculation(name, config, callback, callback_params, ret.append(calc) return ret else: - tcp = {} - params = [] + # no value is multi + # return a single value + args = [] + kwargs = {} for key, couples in tcparams.items(): for couple in couples: + # couple[1] (ismulti) is always False if key == '': - value = couple[0] - params.append(value) + args.append(couple[0]) else: - tcp[key] = couple[0] - return calculate(name, callback, params, tcp) + kwargs[key] = couple[0] + return calculate(callback, args, kwargs) -def calculate(name, callback, params, tcparams): +def calculate(callback, args, kwargs): """wrapper that launches the 'callback' - :param callback: callback name - :param params: in the callback's arity, the unnamed parameters - :param tcparams: in the callback's arity, the named parameters + :param callback: callback function + :param args: in the callback's arity, the unnamed parameters + :param kwargs: in the callback's arity, the named parameters """ - return callback(*params, **tcparams) + return callback(*args, **kwargs)