better mandatory/empty support for mandatory_warnings
authorEmmanuel Garette <egarette@cadoles.com>
Wed, 29 Jun 2016 19:42:54 +0000 (21:42 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Wed, 29 Jun 2016 19:42:54 +0000 (21:42 +0200)
test/test_cache.py
test/test_mandatory.py
tiramisu/option/masterslave.py
tiramisu/setting.py
tiramisu/value.py

index cb0cb03..13466d6 100644 (file)
@@ -284,9 +284,9 @@ def test_force_cache():
                                                         'u2': {None: (None, None)},
                                                         'u3': {None: ([], None)},
                                                         'u4': {None: (None, None)}}
-    assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u1': {None: (set([]), None)},
+    assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u1': {None: (set(['empty']), None)},
                                                           'u2': {None: (set([]), None)},
-                                                          'u3': {None: (set([]), None)},
+                                                          'u3': {None: (set(['empty']), None)},
                                                           'u4': {None: (set(['disabled']), None)}}
     c.read_only()
 
@@ -294,9 +294,9 @@ def test_force_cache():
     assert c.cfgimpl_get_values()._p_.get_cached(c) == {'u1': {None: ([], None)},
                                                         'u2': {None: (None, None)},
                                                         'u3': {None: ([], None)}}
-    assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u1': {None: (set([]), None)},
+    assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u1': {None: (set(['empty']), None)},
                                                           'u2': {None: (set([]), None)},
-                                                          'u3': {None: (set([]), None)},
+                                                          'u3': {None: (set(['empty']), None)},
                                                           'u4': {None: (set(['disabled']), None)}}
 
     c.cfgimpl_get_settings().remove('cache')
index 0790a69..ee04be2 100644 (file)
@@ -434,6 +434,23 @@ def test_mandatory_master():
     del(config)
 
 
+def test_mandatory_warnings_master():
+    ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True,
+                              properties=('mandatory', ))
+    netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau",
+                                   multi=True)
+    interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
+    interface1.impl_set_group_type(groups.master)
+    o = OptionDescription('o', '', [interface1])
+    config = Config(o)
+    assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['ip_admin_eth0.ip_admin_eth0']
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
+
+
 def test_mandatory_master_empty():
     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau",
@@ -478,6 +495,37 @@ def test_mandatory_master_empty():
     del(config)
 
 
+def test_mandatory_warnings_master_empty():
+    ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
+    netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau",
+                                   multi=True)
+    interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
+    interface1.impl_set_group_type(groups.master)
+    o = OptionDescription('o', '', [interface1])
+    config = Config(o)
+    config.read_write()
+    config.ip_admin_eth0.ip_admin_eth0.append()
+    assert config.ip_admin_eth0.ip_admin_eth0 == [None]
+    assert config.ip_admin_eth0.netmask_admin_eth0 == [None]
+    assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['ip_admin_eth0.ip_admin_eth0']
+    del(config.ip_admin_eth0.ip_admin_eth0)
+    del(config.ip_admin_eth0.netmask_admin_eth0)
+    #
+    config.ip_admin_eth0.ip_admin_eth0.append('')
+    assert config.ip_admin_eth0.ip_admin_eth0 == ['']
+    assert config.ip_admin_eth0.netmask_admin_eth0 == [None]
+    assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['ip_admin_eth0.ip_admin_eth0']
+    #
+    config.read_write()
+    config.ip_admin_eth0.ip_admin_eth0 = ['ip']
+    assert list(config.cfgimpl_get_values().mandatory_warnings()) == []
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
+
+
 def test_mandatory_slave():
     ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
     netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau",
@@ -514,6 +562,29 @@ def test_mandatory_slave():
     del(config)
 
 
+def test_mandatory_warnings_slave():
+    ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
+    netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau",
+                                   multi=True, properties=('mandatory', ))
+    interface1 = OptionDescription('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
+    interface1.impl_set_group_type(groups.master)
+    o = OptionDescription('o', '', [interface1])
+    config = Config(o)
+    config.read_only()
+    assert config.ip_admin_eth0.ip_admin_eth0 == []
+    assert config.ip_admin_eth0.netmask_admin_eth0 == []
+    #
+    config.read_write()
+    assert list(config.cfgimpl_get_values().mandatory_warnings()) == []
+    config.ip_admin_eth0.ip_admin_eth0.append('ip')
+    assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['ip_admin_eth0.netmask_admin_eth0']
+    try:
+        delete_session('config', config.impl_getsessionid())
+    except ValueError:
+        pass
+    del(config)
+
+
 def test_mandatory_warnings_symlink():
     descr = make_description_sym()
     config = Config(descr)
index d1ad634..7f5e048 100644 (file)
@@ -220,6 +220,7 @@ class MasterSlaves(object):
                                                  # not self_properties,
                                                  # depends to index
                                                  #self_properties=self_properties,
+                                                 setting_properties=setting_properties,
                                                  masterlen=masterlen,
                                                  from_masterslave=True,
                                                  returns_raise=True)
index 6588de2..bb9829e 100644 (file)
@@ -391,9 +391,13 @@ class Settings(object):
                     is_cached, props = self._p_.getcache(path, ntime, index)
             if not is_cached:
                 props = self._p_.getproperties(path, opt.impl_getproperties())
+                if opt.impl_is_multi() and not opt.impl_is_master_slaves('slave'):
+                    props.add('empty')
                 if apply_requires:
-                    props = copy(props)
-                    props |= self.apply_requires(opt, path, setting_properties, index)
+                    requires = self.apply_requires(opt, path, setting_properties, index)
+                    if requires != set([]):
+                        props = copy(props)
+                        props |= requires
                     if 'cache' in setting_properties:
                         if 'expire' in setting_properties:
                             ntime = ntime + expires_time
@@ -477,9 +481,8 @@ class Settings(object):
                     not self._getcontext().cfgimpl_get_values()._isempty(
                         opt_or_descr, value, index=index):
                 properties.remove('mandatory')
-            elif opt_or_descr.impl_is_multi() and \
+            elif 'empty' in properties and \
                     'empty' in setting_properties and \
-                    not opt_or_descr.impl_is_master_slaves('slave') and \
                     self._getcontext().cfgimpl_get_values()._isempty(
                         opt_or_descr, value, force_allow_empty_list=True):
                 properties.add('mandatory')
@@ -488,6 +491,8 @@ class Settings(object):
                 properties.add('frozen')
             elif 'frozen' in properties and not check_frozen:
                 properties.remove('frozen')
+            if 'empty' in properties:
+                properties.remove('empty')
         # at this point an option should not remain in properties
         if properties != frozenset():
             props = list(properties)
index 0c7d7ec..22efbbb 100644 (file)
@@ -616,7 +616,7 @@ class Values(object):
         context = self._getcontext()
         settings = context.cfgimpl_get_settings()
         setting_properties = context.cfgimpl_get_settings()._getproperties()
-        setting_properties.add('mandatory')
+        setting_properties.update(['mandatory', 'empty'])
 
         def _mandatory_warnings(description, currpath=None):
             if currpath is None:
@@ -638,7 +638,7 @@ class Values(object):
                     self_properties = settings._getproperties(opt, path,
                                                               read_write=False,
                                                               setting_properties=setting_properties)
-                    if 'mandatory' in self_properties:
+                    if 'mandatory' in self_properties or 'empty' in self_properties:
                         err = self._get_cached_value(opt, path=path,
                                                      trusted_cached_properties=False,
                                                      force_permissive=force_permissive,