coverage for tiramisu/option/masterslave.py
authorEmmanuel Garette <egarette@cadoles.com>
Sat, 4 Feb 2017 13:34:56 +0000 (14:34 +0100)
committerEmmanuel Garette <egarette@cadoles.com>
Sat, 4 Feb 2017 13:34:56 +0000 (14:34 +0100)
test/test_dyn_optiondescription.py
test/test_parsing_group.py
tiramisu/error.py
tiramisu/option/baseoption.py
tiramisu/option/masterslave.py
tiramisu/setting.py

index 254acf4..d6e798a 100644 (file)
@@ -1064,7 +1064,7 @@ def test_masterslaves_submulti_dyndescription():
     assert cfg.getowner(st1val1) == owner
     assert cfg.getowner(st1val2) == owners.default
     assert cfg.getowner(st2val1, 0) == owner
-#    assert cfg.getowner(st2val2) == owners.default
+    assert cfg.getowner(st2val2) == owners.default
 
 
 def test_masterslaves_consistency_ip_dyndescription():
@@ -1094,6 +1094,22 @@ def test_masterslaves_consistency_ip_dyndescription():
     assert cfg.netval2.broadval2 == []
 
 
+def test_masterslaves_consistency_ip_dyndescription_propertyerror():
+    a = NetworkOption('net', '', multi=True)
+    b = NetmaskOption('mask', '', multi=True, properties=('mandatory',))
+    c = BroadcastOption('broad', '', multi=True)
+    b.impl_add_consistency('network_netmask', a)
+    c.impl_add_consistency('broadcast', a, b)
+    dod = DynOptionDescription('net', '', [a, b, c], callback=return_list)
+    dod.impl_set_group_type(groups.master)
+    od = OptionDescription('od', '', [dod])
+    cfg = Config(od)
+    cfg.read_write()
+    cfg.netval1.netval1 = ['192.168.1.0']
+    cfg.read_only()
+    raises(PropertiesOptionError, "cfg.netval1.netval1")
+
+
 def test_masterslaves_callback_dyndescription():
     st1 = StrOption('st1', "", multi=True)
     st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'value': ((st1, False),)})
index c091aa0..dc34954 100644 (file)
@@ -341,6 +341,13 @@ def test_reset_values_with_master_and_slaves():
     assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
 
 
+def test_reset_values_with_master_and_slaves_default_value():
+    ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['192.168.230.145'])
+    netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, default=['255.255.255.0'])
+    interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
+    raises(ValueError, "interface1.impl_set_group_type(groups.master)")
+
+
 def test_reset_values_with_master_and_slaves_default():
     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['192.168.230.145'])
     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
index 7407d41..987263e 100644 (file)
@@ -56,24 +56,40 @@ class PropertiesOptionError(AttributeError):
         self._settings = settings
         self._datas = datas
         self._type = option_type
+        self._orig_opt = None
         super(PropertiesOptionError, self).__init__(msg)
 
+    def set_orig_opt(self, opt):
+        self._orig_opt = opt
+
     def __str__(self):
         #this part is a bit slow, so only execute when display
         if self._settings is None:
             req = {}
         else:
             req = self._settings.apply_requires(**self._datas)
-        if req != {}:
-            msg = []
-            for action, msg_ in req.items():
-                msg.append('{0} ({1})'.format(action, display_list(msg_)))
-            if len(req) == 1:
+        if req != {} or self._orig_opt is not None:
+            if req != {}:
+                only_one = len(req) == 1
+                msg = []
+                for action, msg_ in req.items():
+                    msg.append('{0} ({1})'.format(action, display_list(msg_)))
+            else:
+                only_one = len(self.proptype) == 1
+                msg = self.proptype
+            if only_one:
                 prop_msg = _('property')
             else:
                 prop_msg = _('properties')
             msg = display_list(msg)
-            return str(_('cannot access to {0} "{1}" because has {2} {3}').format(self._type, self._datas['opt'].impl_get_display_name(), prop_msg, msg))
+            if self._orig_opt:
+                return str(_('cannot access to {0} "{1}" because "{2}" has {3} {4}').format(self._type,
+                                                                                      self._orig_opt.impl_get_display_name(),
+                                                                                      self._datas['opt'].impl_get_display_name(),
+                                                                                      prop_msg,
+                                                                                      msg))
+            else:
+                return str(_('cannot access to {0} "{1}" because has {2} {3}').format(self._type, self._datas['opt'].impl_get_display_name(), prop_msg, msg))
         else:
             return super(PropertiesOptionError, self).__str__()
 
index b4883a2..81f6b01 100644 (file)
@@ -404,10 +404,13 @@ class BaseOption(Base):
             if not isinstance(value, unicode) and not isinstance(value, str):
                 return ValueError(_('invalid unicode or string'))
 
-    def impl_get_display_name(self):
+    def impl_get_display_name(self, dyn_name=None):
         name = self.impl_getdoc()
         if name is None or name == '':
-            name = self.impl_getname()
+            if dyn_name is not None:
+                name = dyn_name
+            else:
+                name = self.impl_getname()
         if isinstance(name, unicode):
             name = name.encode('utf8')
         return name
@@ -483,6 +486,7 @@ class Option(OnlyOption):
                             if debug:  # pragma: no cover
                                 log.debug('propertyerror in _launch_consistency: {0}'.format(opt_value))
                             if transitive:
+                                opt_value.set_orig_opt(option)
                                 return opt_value
                             else:
                                 opt_value = None
@@ -1073,6 +1077,9 @@ class DynSymLinkOption(object):
     def impl_getname(self):
         return self._name
 
+    def impl_get_display_name(self):
+        return self._impl_getopt().impl_get_display_name(dyn_name=self.impl_getname())
+
     def _impl_getopt(self):
         return self._opt
 
index 21048c9..972c4ef 100644 (file)
@@ -32,28 +32,29 @@ class MasterSlaves(object):
     __slots__ = ('_p_')
 
     def __init__(self, name, childs=None, validate=True, add=True):
-        #if master (same name has group) is set
-        #for collect all slaves
-        if isinstance(name, StorageMasterSlaves):
+        if isinstance(name, StorageMasterSlaves):  # pragma: no cover
+            # only for sqlalchemy
             self._p_ = name
         else:
+            #if master (same name has group) is set
+            #for collect all slaves
             slaves = []
             if childs[0].impl_getname() == name:
                 master = childs[0]
             else:
                 raise ValueError(_('master group with wrong'
                                    ' master name for {0}'
-                                   ).format(name))
+                                  ).format(name))
             for child in childs[1:]:
                 if child.impl_getdefault() != []:
                     raise ValueError(_("not allowed default value for option {0} "
-                                       "in group {1}").format(child.impl_getname(),
-                                                              name))
+                                       "in master/slave object {1}").format(child.impl_getname(),
+                                                                            name))
                 slaves.append(child)
             if validate:
                 callback, callback_params = master.impl_get_callback()
-                if callback is not None and callback_params != {}:  # pragma: optional cover
-                    for key, callbacks in callback_params.items():
+                if callback is not None and callback_params != {}:
+                    for callbacks in callback_params.values():
                         for callbk in callbacks:
                             if isinstance(callbk, tuple):
                                 if callbk[0] in slaves:
@@ -88,14 +89,14 @@ class MasterSlaves(object):
                 base_path = opt._dyn.split('.')[0] + '.'
                 path = base_path + name
                 yield slave._impl_to_dyn(name, path)
-        else:  # pragma: no dynoptiondescription cover
+        else:
             for slave in self._p_._sm_getslaves():
                 yield slave
 
     def in_same_group(self, opt):
         if opt.impl_is_dynsymlinkoption():
             return opt._opt == self._p_._sm_getmaster() or opt._opt in self._p_._sm_getslaves()
-        else:  # pragma: no dynoptiondescription cover
+        else:
             return opt == self._p_._sm_getmaster() or opt in self._p_._sm_getslaves()
 
     def reset(self, opt, values, setting_properties):
@@ -181,6 +182,8 @@ class MasterSlaves(object):
                                     undefined, force_permissive,
                                     master=master)
         if isinstance(masterlen, Exception):
+            if isinstance(masterlen, PropertiesOptionError):
+                masterlen.set_orig_opt(opt)
             return masterlen
         master_is_meta = values._is_meta(master, masterp, session)
         multi = values._get_multi(opt, path)
@@ -264,8 +267,8 @@ class MasterSlaves(object):
         return len(value)
 
     def validate_slave_length(self, masterlen, valuelen, name, opt, setitem=False):
-        if valuelen > masterlen or (valuelen < masterlen and setitem):  # pragma: optional cover
-            if debug:
+        if valuelen > masterlen or (valuelen < masterlen and setitem):
+            if debug:  # pragma: no cover
                 log.debug('validate_slave_length: masterlen: {0}, valuelen: {1}, '
                           'setitem: {2}'.format(masterlen, valuelen, setitem))
             raise SlaveError(_("invalid len for the slave: {0}"
index ab6bede..8a99795 100644 (file)
@@ -514,16 +514,14 @@ class Settings(object):
                     prop_msg = _('property')
                 else:
                     prop_msg = _('properties')
-                name = opt_or_descr.impl_get_display_name()
-                if isinstance(name, unicode):
-                    name = name.encode('utf8')
                 return PropertiesOptionError(_('cannot access to {0} "{1}" '
                                                'because has {2} {3}'
                                                '').format(opt_type,
-                                                          name,
+                                                          opt_or_descr.impl_get_display_name(),
                                                           prop_msg,
-                                                          display_list(props)), props,
-                                                          self, datas, opt_type)
+                                                          display_list(props)),
+                                               props,
+                                               self, datas, opt_type)
 
     def setpermissive(self, permissive, opt=None, path=None):
         """