diff --git a/test/test_cache.py b/test/test_cache.py index cb0cb03..13466d6 100644 --- a/test/test_cache.py +++ b/test/test_cache.py @@ -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') diff --git a/test/test_mandatory.py b/test/test_mandatory.py index 0790a69..ee04be2 100644 --- a/test/test_mandatory.py +++ b/test/test_mandatory.py @@ -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) diff --git a/tiramisu/option/masterslave.py b/tiramisu/option/masterslave.py index d1ad634..7f5e048 100644 --- a/tiramisu/option/masterslave.py +++ b/tiramisu/option/masterslave.py @@ -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) diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 6588de2..bb9829e 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -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) diff --git a/tiramisu/value.py b/tiramisu/value.py index 0c7d7ec..22efbbb 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -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,