diff --git a/test/test_mandatory.py b/test/test_mandatory.py index b28a620..639b449 100644 --- a/test/test_mandatory.py +++ b/test/test_mandatory.py @@ -603,13 +603,15 @@ def test_mandatory_slave(): config.ip_admin_eth0.ip_admin_eth0.append('ip') config.read_only() assert config.ip_admin_eth0.ip_admin_eth0 == ['ip'] - raises(PropertiesOptionError, 'config.ip_admin_eth0.netmask_admin_eth0') + assert len(config.ip_admin_eth0.netmask_admin_eth0) == 1 + raises(PropertiesOptionError, 'config.ip_admin_eth0.netmask_admin_eth0[0]') # config.read_write() config.ip_admin_eth0.netmask_admin_eth0 = [''] config.read_only() assert config.ip_admin_eth0.ip_admin_eth0 == ['ip'] - raises(PropertiesOptionError, 'config.ip_admin_eth0.netmask_admin_eth0') + assert len(config.ip_admin_eth0.netmask_admin_eth0) == 1 + raises(PropertiesOptionError, 'config.ip_admin_eth0.netmask_admin_eth0[0]') # config.read_write() config.ip_admin_eth0.netmask_admin_eth0 = ['ip'] diff --git a/test/test_option_setting.py b/test/test_option_setting.py index 5854bba..02544e2 100644 --- a/test/test_option_setting.py +++ b/test/test_option_setting.py @@ -489,9 +489,9 @@ def test_reset_properties_force_store_value(): def test_pprint(): - msg_error = _('cannot access to {} {} because has {} {}') - msg_is = _("the value of {0} is {1}") - msg_is_not = _("the value of {0} is not {1}") + msg_error = _('cannot access to {} "{}" because has {} {}') + msg_is = _('the value of "{0}" is "{1}"') + msg_is_not = _('the value of "{0}" is not "{1}"') s = StrOption("string", "", default=["string"], default_multi="string", multi=True, properties=('hidden', 'disabled')) s2 = StrOption("string2", "", default="string") @@ -519,21 +519,21 @@ def test_pprint(): except Exception, err: pass - assert str(err) == msg_error.format('option', 'str', 'properties', display_list(['disabled (' + display_list([msg_is.format('int', '1'), msg_is.format('string2', 'string')]) + ')', 'hidden (' + msg_is_not.format('int', display_list([2, 3, 4], 'or')) + ')'])) + assert str(err) == msg_error.format('option', 'Test string option', 'properties', display_list(['disabled (' + display_list([msg_is.format('string2', 'string'), msg_is.format('Test int option', '1')]) + ')', 'hidden (' + msg_is_not.format('Test int option', display_list([2, 3, 4], 'or')) + ')'])) try: config.options.val2 except Exception, err: pass - assert str(err) == msg_error.format('optiondescription', 'options', 'property', 'hidden (' + msg_is.format('int', 1) + ')') + assert str(err) == msg_error.format('optiondescription', 'options', 'property', 'hidden (' + msg_is.format('Test int option', 1) + ')') try: config.val3 except Exception, err: pass - assert str(err) == msg_error.format('option', 'val3', 'property', 'hidden (' + display_list([msg_is.format('int', 1), msg_is.format('string2', 'string'), msg_is_not.format('int', display_list([2, 3, 4], 'or'))]) + ')') + assert str(err) == msg_error.format('option', 'val3', 'property', 'hidden (' + display_list([msg_is.format('string2', 'string'), msg_is.format('Test int option', 1), msg_is_not.format('Test int option', display_list([2, 3, 4], 'or'))]) + ')') try: config.string diff --git a/test/test_parsing_group.py b/test/test_parsing_group.py index 9125e90..c9288f9 100644 --- a/test/test_parsing_group.py +++ b/test/test_parsing_group.py @@ -206,7 +206,7 @@ def test_groups_with_master_hidden_in_config2(): raises(PropertiesOptionError, "cfg.getattr('netmask_admin_eth0')") cfg.ip_admin_eth0.append('192.168.1.1') assert cfg.ip_admin_eth0 == ['192.168.1.1'] - raises(PropertiesOptionError, "cfg.netmask_admin_eth0") + raises(PropertiesOptionError, "cfg.netmask_admin_eth0[0]") del(cfg.ip_admin_eth0) assert cfg.ip_admin_eth0 == [] #del diff --git a/tiramisu/option/masterslave.py b/tiramisu/option/masterslave.py index 47ef1b2..21048c9 100644 --- a/tiramisu/option/masterslave.py +++ b/tiramisu/option/masterslave.py @@ -185,51 +185,48 @@ class MasterSlaves(object): master_is_meta = values._is_meta(master, masterp, session) multi = values._get_multi(opt, path) #if masterlen is [], test properties (has no value, don't get any value) - if masterlen == 0: - if validate_properties: - props = context.cfgimpl_get_settings().validate_properties(opt, False, - False, - value=multi, - path=path, - force_permissive=force_permissive, - setting_properties=setting_properties) - if props: - return props + #if masterlen == 0: + if validate_properties: + props = context.cfgimpl_get_settings().validate_properties(opt, False, + False, + value=multi, + path=path, + force_permissive=force_permissive, + setting_properties=setting_properties) + if props: + return props + #else: + if index is None: + indexes = range(0, masterlen) else: - one_has_value = False - if index is None: - indexes = range(0, masterlen) - else: - indexes = [index] - for idx in indexes: - value = values._get_cached_value(opt, path, validate, - force_permissive, - trusted_cached_properties, - validate_properties, - with_meta=master_is_meta, - index=idx, - # not self_properties, - # depends to index - #self_properties=self_properties, - setting_properties=setting_properties, - masterlen=masterlen, - from_masterslave=True) - if isinstance(value, Exception): - if isinstance(value, PropertiesOptionError): - err = value + indexes = [index] + for idx in indexes: + value = values._get_cached_value(opt, path, validate, + force_permissive, + trusted_cached_properties, + validate_properties, + with_meta=master_is_meta, + index=idx, + # not self_properties, + # depends to index + #self_properties=self_properties, + setting_properties=setting_properties, + masterlen=masterlen, + from_masterslave=True) + if isinstance(value, Exception): + if isinstance(value, PropertiesOptionError): + err = value + if index is None: multi.append_properties_error(value) else: - return value - elif index is None: - multi.append(value, setitem=False, force=True, validate=validate, - force_permissive=force_permissive) - one_has_value = True + multi = value else: - multi = value - one_has_value = True - if not one_has_value: - #raise last err - return err + return value + elif index is None: + multi.append(value, setitem=False, force=True, validate=validate, + force_permissive=force_permissive) + else: + multi = value return multi def validate(self, values, opt, value, path, session): diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 6fae963..8dfae0f 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -514,9 +514,9 @@ class Settings(object): prop_msg = 'property' else: prop_msg = 'properties' - return PropertiesOptionError(_("cannot access to {0} {1} " - "because has {2} {3}" - "").format(opt_type, + return PropertiesOptionError(_('cannot access to {0} "{1}" ' + 'because has {2} {3}' + '').format(opt_type, opt_or_descr.impl_get_display_name(), prop_msg, display_list(props)), props, diff --git a/tiramisu/value.py b/tiramisu/value.py index 909b9ab..1a845ba 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -604,6 +604,17 @@ class Values(object): settings = context.cfgimpl_get_settings() setting_properties = context.cfgimpl_get_settings()._getproperties() setting_properties.update(['mandatory', 'empty']) + def _is_properties_option(err, path): + if not isinstance(err, Exception): + pass + elif isinstance(err, PropertiesOptionError): + if err.proptype == ['mandatory']: + return path + elif isinstance(err, ConfigError): + #assume that uncalculated value is an empty value + return path + else: + raise err def _mandatory_warnings(description, currpath=None): if currpath is None: @@ -633,16 +644,16 @@ class Values(object): self_properties=self_properties, validate=True, display_warnings=False) - if not isinstance(err, Exception): - pass - elif isinstance(err, PropertiesOptionError): - if err.proptype == ['mandatory']: - yield path - elif isinstance(err, ConfigError): - #assume that uncalculated value is an empty value - yield path + if opt.impl_is_master_slaves('slave') and isinstance(err, list): + for val in err: + ret = _is_properties_option(val, path) + if ret is not None: + yield ret + break else: - raise err + ret = _is_properties_option(err, path) + if ret is not None: + yield ret descr = self._getcontext().cfgimpl_get_description() for path in _mandatory_warnings(descr):