diff --git a/test/test_option_validator.py b/test/test_option_validator.py index 5e58fb7..04ad30e 100644 --- a/test/test_option_validator.py +++ b/test/test_option_validator.py @@ -5,7 +5,7 @@ import warnings from py.test import raises from tiramisu.config import Config -from tiramisu.option import StrOption, OptionDescription +from tiramisu.option import BoolOption, StrOption, OptionDescription from tiramisu.setting import groups from tiramisu.error import ValueWarning from tiramisu.i18n import _ @@ -43,7 +43,8 @@ def is_context(value, context): def value_values(value, values): if not (value == 'val' and values == ['val'] or value == 'val1' and values == ['val1'] or - value == 'val2' and values == ['val1', 'val2']): + value == 'val2' and values == ['val1', 'val2'] or + value == 'val1' and values == ['val1', None]): raise ValueError('error') @@ -53,6 +54,34 @@ def value_values_index(value, values, index): raise ValueError('error 2') +def value_values_auto(value, values, auto=False): + if auto != False: + raise ValueError('auto should be False') + if not (value == 'val' and values == ['val'] or + value == 'val1' and values == ['val1'] or + value == 'val2' and values == ['val1', 'val2'] or + value == 'val1' and values == ['val1', None]): + raise ValueError('error') + + +def value_values_auto2(value, values, auto=False): + if auto != False: + raise ValueError('auto should be False') + if not (value == 'val1' and values == 'val' or + value == 'val2' and values == 'val'): + raise ValueError('error') + + + +def value_values_index2(value, values, index, auto=False): + if auto != False: + raise ValueError('auto should be False') + if not (value == 'val1' and values == ['val1'] and index == 'val' or + value == 'val1' and values == ['val1', None] and index == 'val' or + value == 'val2' and values == ['val1', 'val2'] and index == 'val'): + raise ValueError('error') + + def test_validator(): opt1 = StrOption('opt1', '', validator=return_true, default='val') raises(ValueError, "StrOption('opt2', '', validator=return_false, default='val')") @@ -91,6 +120,116 @@ def test_validator_params_value_values_index(): cfg.opt1.append('val2') +def test_validator_params_value_values_master(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, validator=value_values) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1.impl_set_group_type(groups.master) + root = OptionDescription('root', '', [interface1]) + cfg = Config(root) + assert cfg.ip_admin_eth0.ip_admin_eth0 == [] + cfg.ip_admin_eth0.ip_admin_eth0.append('val1') + cfg.ip_admin_eth0.ip_admin_eth0.append('val2') + + +def test_validator_params_value_values_index_master(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, validator=value_values_index) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1.impl_set_group_type(groups.master) + root = OptionDescription('root', '', [interface1]) + cfg = Config(root) + assert cfg.ip_admin_eth0.ip_admin_eth0 == [] + cfg.ip_admin_eth0.ip_admin_eth0.append('val1') + cfg.ip_admin_eth0.ip_admin_eth0.append('val2') + + +def test_validator_params_value_values_slave(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=value_values) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1.impl_set_group_type(groups.master) + root = OptionDescription('root', '', [interface1]) + cfg = Config(root) + assert cfg.ip_admin_eth0.ip_admin_eth0 == [] + cfg.ip_admin_eth0.ip_admin_eth0.append('val') + cfg.ip_admin_eth0.netmask_admin_eth0[0] = 'val1' + cfg.ip_admin_eth0.ip_admin_eth0.append('val') + cfg.ip_admin_eth0.netmask_admin_eth0[1] = 'val2' + + +def test_validator_params_value_values_index_slave(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=value_values_index) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1.impl_set_group_type(groups.master) + root = OptionDescription('root', '', [interface1]) + cfg = Config(root) + assert cfg.ip_admin_eth0.ip_admin_eth0 == [] + cfg.ip_admin_eth0.ip_admin_eth0.append('val') + cfg.ip_admin_eth0.netmask_admin_eth0[0] = 'val1' + cfg.ip_admin_eth0.ip_admin_eth0.append('val') + cfg.ip_admin_eth0.netmask_admin_eth0[1] = 'val2' + + +def test_validator_params_value_values_notmulti(): + raises(TypeError, "opt1 = StrOption('opt1', '', validator=value_values, default='val')") + + +def test_validator_params_value_values_kwargs(): + v = BoolOption('v', '', default=False) + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, default=["ip"]) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', + "masque du sous-reseau", + multi=True, + validator=value_values_auto, + validator_params={'auto': ((v, False),)}) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1.impl_set_group_type(groups.master) + root = OptionDescription('root', '', [v, interface1]) + cfg = Config(root) + assert cfg.ip_admin_eth0.ip_admin_eth0 == ['ip'] + cfg.ip_admin_eth0.netmask_admin_eth0[0] = 'val1' + cfg.ip_admin_eth0.ip_admin_eth0.append('val') + cfg.ip_admin_eth0.netmask_admin_eth0[1] = 'val2' + + +def test_validator_params_value_values_kwargs_values(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', + "masque du sous-reseau", + multi=True, + validator=value_values_auto2, + validator_params={'values': ((ip_admin_eth0, False),)}) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1.impl_set_group_type(groups.master) + root = OptionDescription('root', '', [interface1]) + cfg = Config(root) + assert cfg.ip_admin_eth0.ip_admin_eth0 == [] + cfg.ip_admin_eth0.ip_admin_eth0.append('val') + cfg.ip_admin_eth0.netmask_admin_eth0[0] = 'val1' + cfg.ip_admin_eth0.ip_admin_eth0.append('val') + cfg.ip_admin_eth0.netmask_admin_eth0[1] = 'val2' + + +def test_validator_params_value_values_kwargs_index(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', + "masque du sous-reseau", + multi=True, + validator=value_values_index2, + validator_params={'index': ((ip_admin_eth0, False),)}) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1.impl_set_group_type(groups.master) + root = OptionDescription('root', '', [interface1]) + cfg = Config(root) + assert cfg.ip_admin_eth0.ip_admin_eth0 == [] + cfg.ip_admin_eth0.ip_admin_eth0.append('val') + cfg.ip_admin_eth0.netmask_admin_eth0[0] = 'val1' + cfg.ip_admin_eth0.ip_admin_eth0.append('val') + cfg.ip_admin_eth0.netmask_admin_eth0[1] = 'val2' + + def test_validator_params_context(): opt1 = StrOption('opt1', '', validator=is_context, validator_params={'': ((None,),)}, default='val') root = OptionDescription('root', '', [opt1]) @@ -245,3 +384,21 @@ def test_validator_warning_master_slave(): assert len(w) == 1 assert w[0].message.opt == ip_admin_eth0 assert str(w[0].message) == msg_err.format('val', ip_admin_eth0._display_name, display_name_ip, 'test error') + + +def test_validator_slave_param(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', + "masque du sous-reseau", + multi=True, + validator=return_true, + validator_params={'param': ((ip_admin_eth0, False),)}) + interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) + interface1.impl_set_group_type(groups.master) + root = OptionDescription('root', '', [interface1]) + cfg = Config(root) + assert cfg.ip_admin_eth0.ip_admin_eth0 == [] + cfg.ip_admin_eth0.ip_admin_eth0.append('yes') + cfg.ip_admin_eth0.netmask_admin_eth0 = ['val'] + cfg.ip_admin_eth0.ip_admin_eth0 = ['yes', 'yes'] + cfg.ip_admin_eth0.netmask_admin_eth0[1] = 'val' diff --git a/tiramisu/autolib.py b/tiramisu/autolib.py index d5a37af..8c54f38 100644 --- a/tiramisu/autolib.py +++ b/tiramisu/autolib.py @@ -25,7 +25,7 @@ from .setting import undefined def carry_out_calculation(option, context, callback, callback_params, - index=undefined, value_index=None): + index=undefined): """a function that carries out a calculation for an option's value :param option: the option @@ -150,7 +150,7 @@ def carry_out_calculation(option, context, callback, callback_params, #Not an option, set full context tcparams.setdefault(key, []).append((context.duplicate(), False)) elif callbk[0] == 'index': - tcparams.setdefault(key, []).append((value_index, False)) + tcparams.setdefault(key, []).append((index, False)) else: # callbk is something link (opt, True|False) opt, force_permissive = callbk @@ -182,7 +182,7 @@ def carry_out_calculation(option, context, callback, callback_params, has_option = True value = list(value) - if opt.impl_is_master_slaves() and \ + if opt != option and opt.impl_is_master_slaves() and \ opt.impl_get_master_slaves().in_same_group(option): master_slave = True is_multi = True diff --git a/tiramisu/option/baseoption.py b/tiramisu/option/baseoption.py index 1509120..631c809 100644 --- a/tiramisu/option/baseoption.py +++ b/tiramisu/option/baseoption.py @@ -140,16 +140,8 @@ class Base(StorageBase): type(properties), name)) if validator is not None: - if validator_params is None: - func_args = getargspec(validator) - defaults = func_args.defaults - if defaults is None: - defaults = [] - args = func_args.args[0:len(func_args.args)-len(defaults)] - if len(args) == 2: - validator_params = {'': ((self, False),)} - elif len(args) == 3: - validator_params = {'': ((self, False), ('index',))} + if multi: # and validator_params is None: + validator_params = self._build_validator_params(validator, validator_params) validate_callback(validator, validator_params, 'validator') self._set_validator(validator, validator_params) @@ -176,6 +168,33 @@ class Base(StorageBase): self.impl_set_callback(callback, callback_params, _init=True) self.commit(session) + def _build_validator_params(self, validator, validator_params): + func_args = getargspec(validator) + defaults = func_args.defaults + if defaults is None: + defaults = [] + args = func_args.args[0:len(func_args.args)-len(defaults)] + if validator_params is not None: + len_args = len(validator_params.get('', [])) + if len_args != 0 and len(args) <= len_args: + args = args[0:len(args)-len_args] + if len(args) >= 2: + if validator_params is not None and args[1] in validator_params: + args = [] + elif validator_params is not None and '' in validator_params: + params = list(validator_params['']) + params.append((self, False)) + validator_params[''] = tuple(params) + else: + if validator_params is None: + validator_params = {} + validator_params[''] = ((self, False),) + if len(args) == 3 and args[2] not in validator_params: + params = list(validator_params['']) + params.append(('index',)) + validator_params[''] = tuple(params) + return validator_params + def _set_has_dependency(self): if not isinstance(self, SymLinkOption): self._has_dependency = True @@ -545,7 +564,7 @@ class Option(OnlyOption): value = carry_out_calculation(current_opt, context=context, callback=validator, callback_params=validator_params_, - value_index=_index) + index=_index) if isinstance(value, Exception): return value