validator's function can have 1 arg, 2 args or 3 args
authorEmmanuel Garette <egarette@cadoles.com>
Mon, 16 Jan 2017 08:25:56 +0000 (09:25 +0100)
committerEmmanuel Garette <egarette@cadoles.com>
Mon, 16 Jan 2017 08:25:56 +0000 (09:25 +0100)
test/test_option_validator.py
tiramisu/autolib.py
tiramisu/option/baseoption.py

index 5e58fb7..04ad30e 100644 (file)
@@ -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'
index d5a37af..8c54f38 100644 (file)
@@ -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
index 1509120..631c809 100644 (file)
@@ -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