tiramisu/autolib.py: optimpl_ => impl_
authorEmmanuel Garette <egarette@cadoles.com>
Fri, 10 May 2013 13:10:06 +0000 (15:10 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Fri, 10 May 2013 13:10:06 +0000 (15:10 +0200)
tiramisu/option.py: consistency simplication and allow multi
tiramisu/option.py: don't touch cache if force_permissive or force_properties
tiramisu/values.py: set validate paramaters in Multi()

test/test_option_consistency.py
tiramisu/autolib.py
tiramisu/option.py
tiramisu/value.py

index 9af6452..23905c4 100644 (file)
@@ -11,7 +11,7 @@ def test_consistency_not_equal():
     a = IntOption('a', '')
     b = IntOption('b', '')
     od = OptionDescription('od', '', [a, b])
-    a.impl_add_consistency('not_equal', (a, b))
+    a.impl_add_consistency('not_equal', b)
     c = Config(od)
     assert c.a is None
     assert c.b is None
@@ -22,17 +22,32 @@ def test_consistency_not_equal():
     c.b = 2
 
 
+def test_consistency_not_equal_multi():
+    a = IntOption('a', '', multi=True)
+    b = IntOption('b', '', multi=True)
+    od = OptionDescription('od', '', [a, b])
+    a.impl_add_consistency('not_equal', b)
+    c = Config(od)
+    assert c.a == []
+    assert c.b == []
+    c.a = [1]
+    del(c.a)
+    c.a = [1]
+    raises(ValueError, "c.b = [1]")
+    c.b = [2]
+
+
 def test_consistency_default():
     a = IntOption('a', '', 1)
     b = IntOption('b', '', 1)
-    raises(ValueError, "a.impl_add_consistency('not_equal', (a, b))")
+    raises(ValueError, "a.impl_add_consistency('not_equal', b)")
 
 
 def test_consistency_default_diff():
     a = IntOption('a', '', 3)
     b = IntOption('b', '', 1)
     od = OptionDescription('od', '', [a, b])
-    a.impl_add_consistency('not_equal', (a, b))
+    a.impl_add_consistency('not_equal', b)
     c = Config(od)
     raises(ValueError, "c.a = 1")
     c.a = 2
@@ -46,7 +61,7 @@ def test_consistency_ip_netmask():
     a = IPOption('a', '')
     b = NetmaskOption('b', '')
     od = OptionDescription('od', '', [a, b])
-    b.impl_add_consistency('ip_netmask', (b, a))
+    b.impl_add_consistency('ip_netmask', a)
     c = Config(od)
     c.a = '192.168.1.1'
     c.b = '255.255.255.0'
@@ -60,7 +75,7 @@ def test_consistency_network_netmask():
     a = NetworkOption('a', '')
     b = NetmaskOption('b', '')
     od = OptionDescription('od', '', [a, b])
-    b.impl_add_consistency('network_netmask', (b, a))
+    b.impl_add_consistency('network_netmask', a)
     c = Config(od)
     c.a = '192.168.1.1'
     c.b = '255.255.255.255'
@@ -68,3 +83,32 @@ def test_consistency_network_netmask():
     c.a = '192.168.1.0'
     c.b = '255.255.255.0'
     raises(ValueError, "c.a = '192.168.1.1'")
+
+
+#FIXME pas de multi si pas de multi en maitre
+def test_consistency_ip_netmask_multi():
+    a = IPOption('a', '', multi=True)
+    b = NetmaskOption('b', '', multi=True)
+    od = OptionDescription('od', '', [a, b])
+    b.impl_add_consistency('ip_netmask', a)
+    c = Config(od)
+    c.a = ['192.168.1.1']
+    c.b = ['255.255.255.0']
+    c.a = ['192.168.1.2']
+    c.b = ['255.255.255.255']
+    c.b = ['255.255.255.0']
+    raises(ValueError, "c.a = ['192.168.1.0']")
+
+
+def test_consistency_network_netmask_multi():
+    a = NetworkOption('a', '', multi=True)
+    b = NetmaskOption('b', '', multi=True)
+    od = OptionDescription('od', '', [a, b])
+    b.impl_add_consistency('network_netmask', a)
+    c = Config(od)
+    c.a = ['192.168.1.1']
+    c.b = ['255.255.255.255']
+    del(c.b)
+    c.a = ['192.168.1.0']
+    c.b = ['255.255.255.0']
+    raises(ValueError, "c.a = ['192.168.1.1']")
index 6a659a3..60927af 100644 (file)
@@ -56,7 +56,7 @@ def carry_out_calculation(name, config, callback, callback_params):
                     if check_disabled:
                         continue
                     raise PropertiesOptionError(err, err.proptype)
-                is_multi = opt.optimpl_is_multi()
+                is_multi = opt.impl_is_multi()
                 if is_multi:
                     if opt_value is not None:
                         len_value = len(opt_value)
index 970d348..8598037 100644 (file)
@@ -189,8 +189,50 @@ class Option(BaseInformation):
             return False
         return not self == other
 
-    def _launch_consistency(self, func, opt, value, context, index, opts):
-        return getattr(self, func)(opt, value, context, index, opts)
+    def _launch_consistency(self, func, opt, vals, context, index, opt_):
+        if context is not None:
+            descr = context.cfgimpl_get_description()
+        if opt is self:
+            #values are for self, search opt_ values
+            values = vals
+            if context is not None:
+                path = descr.impl_get_path_by_opt(opt_)
+                values_ = context._getattr(path, validate=False)
+            else:
+                values_ = opt_.impl_getdefault()
+            if index is not None:
+                #value is not already set, could be higher
+                try:
+                    values_ = values_[index]
+                except IndexError:
+                    values_ = None
+        else:
+            #values are for opt_, search self values
+            values_ = vals
+            if context is not None:
+                path = descr.impl_get_path_by_opt(self)
+                values = context._getattr(path, validate=False)
+            else:
+                values = self.impl_getdefault()
+            if index is not None:
+                #value is not already set, could be higher
+                try:
+                    values = values[index]
+                except IndexError:
+                    values = None
+        if index is None and self.impl_is_multi():
+            for index in range(0, len(values)):
+                try:
+                    value = values[index]
+                    value_ = values_[index]
+                except IndexError:
+                    value = None
+                    value_ = None
+                if None not in (value, value_):
+                    getattr(self, func)(opt_._name, value, value_)
+        else:
+            if None not in (values, values_):
+                getattr(self, func)(opt_._name, values, values_)
 
     def impl_validate(self, value, context=None, validate=True):
         """
@@ -282,38 +324,23 @@ class Option(BaseInformation):
     def impl_is_multi(self):
         return self._multi
 
-    def impl_add_consistency(self, func, opts):
+    def impl_add_consistency(self, func, opt):
         if self._consistencies is None:
             self._consistencies = []
-        if self not in opts:
-            opts = list(opts)
-            opts.append(self)
-            opts = tuple(opts)
+        if not isinstance(opt, Option):
+            raise ValueError('consistency must be set with an option')
+        if self is opt:
+            raise ValueError('cannot add consistency with itself')
         func = '_cons_{}'.format(func)
-        for opt in opts:
-            if opt != self:
-                self._launch_consistency(func, opt, self.impl_getdefault(), None, None, opts)
-        self._consistencies.append((func, opts))
+        self._launch_consistency(func, self, self.impl_getdefault(), None, None, opt)
+        self._consistencies.append((func, opt))
         self.impl_validate(self.impl_getdefault(), None)
 
-    def _cons_not_equal(self, opt, value, context, index, opts):
-        values = [value]
-        if context is not None:
-            descr = context.cfgimpl_get_description()
-        for opt_ in opts:
-            if opt_ is not opt:
-                if context is not None:
-                    path = descr.impl_get_path_by_opt(opt_)
-                    val = context._getattr(path, validate=False)
-                else:
-                    val = opt.impl_getdefault()
-                if val is not None:
-                    if val in values:
-                        raise ValueError(_("invalid value {0} for option {1} "
-                                           "must be different as {2} option"
-                                           "").format(val, self._name,
-                                                      opt_._name))
-                    values.append(val)
+    def _cons_not_equal(self, optname, value, value_):
+        if value == value_:
+            raise ValueError(_("invalid value {0} for option {1} "
+                               "must be different as {2} option"
+                               "").format(value, self._name, optname))
 
 
 class ChoiceOption(Option):
@@ -466,63 +493,42 @@ class NetmaskOption(Option):
         except ValueError:
             return False
 
-    def _cons_network_netmask(self, opt, value, context, index, opts):
+    def _cons_network_netmask(self, optname, value, value_):
         #opts must be (netmask, network) options
-        self.__cons_netmask(opt, value, context, index, opts, False)
+        self.__cons_netmask(optname, value, value_, False)
 
-    def _cons_ip_netmask(self, opt, value, context, index, opts):
+    def _cons_ip_netmask(self, optname, value, value_):
         #opts must be (netmask, ip) options
-        self.__cons_netmask(opt, value, context, index, opts, True)
-
-    def __cons_netmask(self, opt, value, context, index, opts, make_net):
-        opt_netmask, opt_ipnetwork = opts
-        if context is not None:
-            descr = context.cfgimpl_get_description()
-        if opt is opt_ipnetwork:
-            val_ipnetwork = value
-            if context is not None:
-                path = descr.impl_get_path_by_opt(opt_netmask)
-                val_netmask = context._getattr(path, validate=False)
-            else:
-                val_netmask = opt_netmask.impl_getdefault()
-            if opt_netmask.impl_is_multi():
-                val_netmask = val_netmask[index]
-        else:
-            val_netmask = value
-            if context is not None:
-                path = descr.impl_get_path_by_opt(opt_ipnetwork)
-                val_ipnetwork = context._getattr(path, validate=False)
-            else:
-                val_ipnetwork = opt_ipnetwork.impl_getdefault()
-            if opt_ipnetwork.impl_is_multi():
-                val_ipnetwork = val_ipnetwork[index]
-        if None not in (val_ipnetwork, val_netmask):
-            msg = None
-            try:
-                ip = IP('{0}/{1}'.format(val_ipnetwork, val_netmask),
-                        make_net=make_net)
-                #if cidr == 32, ip same has network
-                if ip.prefixlen() != 32:
-                    try:
-                        IP('{0}/{1}'.format(val_ipnetwork, val_netmask),
-                           make_net=not make_net)
-                    except ValueError:
-                        if not make_net:
-                            msg = _("invalid network {0} ({1}) with netmask {2} ({3}),"
-                                    " this network is an ip")
-                    else:
-                        if make_net:
-                            msg = _("invalid ip {0} ({1}) with netmask {2} ({3}),"
-                                    " this ip is a network")
+        self.__cons_netmask(optname, value, value_, True)
 
-            except ValueError:
-                if make_net:
-                    msg = _("invalid ip {0} ({1}) with netmask {2} ({3})")
+    #def __cons_netmask(self, opt, value, context, index, opts, make_net):
+    def __cons_netmask(self, optname, val_netmask, val_ipnetwork, make_net):
+        msg = None
+        try:
+            ip = IP('{0}/{1}'.format(val_ipnetwork, val_netmask),
+                    make_net=make_net)
+            #if cidr == 32, ip same has network
+            if ip.prefixlen() != 32:
+                try:
+                    IP('{0}/{1}'.format(val_ipnetwork, val_netmask),
+                        make_net=not make_net)
+                except ValueError:
+                    if not make_net:
+                        msg = _("invalid network {0} ({1}) with netmask {2} ({3}),"
+                                " this network is an ip")
                 else:
-                    msg = _("invalid network {0} ({1}) with netmask {2} ({3})")
-            if msg is not None:
-                raise ValueError(msg.format(val_ipnetwork, opt_ipnetwork._name,
-                                            val_netmask, opt_netmask._name))
+                    if make_net:
+                        msg = _("invalid ip {0} ({1}) with netmask {2} ({3}),"
+                                " this ip is a network")
+
+        except ValueError:
+            if make_net:
+                msg = _("invalid ip {0} ({1}) with netmask {2} ({3})")
+            else:
+                msg = _("invalid network {0} ({1}) with netmask {2} ({3})")
+        if msg is not None:
+            raise ValueError(msg.format(val_ipnetwork, optname,
+                                        val_netmask, self._name))
 
 
 class DomainnameOption(Option):
@@ -674,9 +680,10 @@ class OptionDescription(BaseInformation):
             if not isinstance(option, OptionDescription):
                 if option._consistencies is not None:
                     for consistency in option._consistencies:
-                        func, opts = consistency
-                        for opt in opts:
-                            _consistencies.setdefault(opt, []).append((func, opts))
+                        func, opt = consistency
+                        opts = (option, opt)
+                        _consistencies.setdefault(opt, []).append((func, opts))
+                        _consistencies.setdefault(option, []).append((func, opts))
             else:
                 _currpath.append(attr)
                 option.impl_build_cache(cache_path, cache_option, _currpath, _consistencies)
@@ -759,10 +766,9 @@ class OptionDescription(BaseInformation):
         consistencies = self._consistencies.get(opt)
         if consistencies is not None:
             for consistency in consistencies:
-                func, opts = consistency
-                #ret = getattr(opts[0], func)(opt, value, context, index, opts)
-                ret = opts[0]._launch_consistency(func, opt, value, context,
-                                                  index, opts)
+                opt_ = consistency[1]
+                ret = opt_[0]._launch_consistency(consistency[0], opt, value, context,
+                                                  index, opt_[1])
                 if ret is False:
                     return False
         return True
index 47046a0..24da71a 100644 (file)
@@ -99,7 +99,7 @@ class Values(object):
             if exp < created:
                 return value
         val = self._getitem(opt, validate, force_permissive, force_properties)
-        if validate:
+        if validate and force_permissive is False and force_properties is None:
             self._set_cache(opt, val)
         return val
 
@@ -119,14 +119,14 @@ class Values(object):
             else:
                 value = self._getcallback_value(opt)
                 if opt.impl_is_multi():
-                    value = Multi(value, self.context, opt)
+                    value = Multi(value, self.context, opt, validate)
                 #suppress value if already set
                 self._reset(opt)
         # frozen and force default
         elif is_frozen and 'force_default_on_freeze' in setting[opt]:
             value = self._get_default(opt)
             if opt.impl_is_multi():
-                value = Multi(value, self.context, opt)
+                value = Multi(value, self.context, opt, validate)
         if validate:
             opt.impl_validate(value, self.context, 'validator' in setting)
         if self.is_default_owner(opt) and \
@@ -209,7 +209,7 @@ class Multi(list):
     that support item notation for the values of multi options"""
     __slots__ = ('opt', 'context')
 
-    def __init__(self, value, context, opt):
+    def __init__(self, value, context, opt, validate=True):
         """
         :param value: the Multi wraps a list value
         :param context: the home config that has the values
@@ -219,7 +219,7 @@ class Multi(list):
         self.context = context
         if not isinstance(value, list):
             value = [value]
-        if self.opt.impl_get_multitype() == multitypes.slave:
+        if validate and self.opt.impl_get_multitype() == multitypes.slave:
             value = self._valid_slave(value)
         elif self.opt.impl_get_multitype() == multitypes.master:
             self._valid_master(value)