slave's requires with multi is different than slave's requires with non multi option

This commit is contained in:
Emmanuel Garette 2016-11-14 21:14:45 +01:00
parent b3fcf1986f
commit fb16dd2a79
6 changed files with 72 additions and 62 deletions

View File

@ -603,13 +603,15 @@ def test_mandatory_slave():
config.ip_admin_eth0.ip_admin_eth0.append('ip') config.ip_admin_eth0.ip_admin_eth0.append('ip')
config.read_only() config.read_only()
assert config.ip_admin_eth0.ip_admin_eth0 == ['ip'] 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.read_write()
config.ip_admin_eth0.netmask_admin_eth0 = [''] config.ip_admin_eth0.netmask_admin_eth0 = ['']
config.read_only() config.read_only()
assert config.ip_admin_eth0.ip_admin_eth0 == ['ip'] 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.read_write()
config.ip_admin_eth0.netmask_admin_eth0 = ['ip'] config.ip_admin_eth0.netmask_admin_eth0 = ['ip']

View File

@ -489,9 +489,9 @@ def test_reset_properties_force_store_value():
def test_pprint(): def test_pprint():
msg_error = _('cannot access to {} {} because has {} {}') msg_error = _('cannot access to {} "{}" because has {} {}')
msg_is = _("the value of {0} is {1}") msg_is = _('the value of "{0}" is "{1}"')
msg_is_not = _("the value of {0} is not {1}") msg_is_not = _('the value of "{0}" is not "{1}"')
s = StrOption("string", "", default=["string"], default_multi="string", multi=True, properties=('hidden', 'disabled')) s = StrOption("string", "", default=["string"], default_multi="string", multi=True, properties=('hidden', 'disabled'))
s2 = StrOption("string2", "", default="string") s2 = StrOption("string2", "", default="string")
@ -519,21 +519,21 @@ def test_pprint():
except Exception, err: except Exception, err:
pass 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: try:
config.options.val2 config.options.val2
except Exception, err: except Exception, err:
pass 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: try:
config.val3 config.val3
except Exception, err: except Exception, err:
pass 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: try:
config.string config.string

View File

@ -206,7 +206,7 @@ def test_groups_with_master_hidden_in_config2():
raises(PropertiesOptionError, "cfg.getattr('netmask_admin_eth0')") raises(PropertiesOptionError, "cfg.getattr('netmask_admin_eth0')")
cfg.ip_admin_eth0.append('192.168.1.1') cfg.ip_admin_eth0.append('192.168.1.1')
assert cfg.ip_admin_eth0 == ['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) del(cfg.ip_admin_eth0)
assert cfg.ip_admin_eth0 == [] assert cfg.ip_admin_eth0 == []
#del #del

View File

@ -185,7 +185,7 @@ class MasterSlaves(object):
master_is_meta = values._is_meta(master, masterp, session) master_is_meta = values._is_meta(master, masterp, session)
multi = values._get_multi(opt, path) multi = values._get_multi(opt, path)
#if masterlen is [], test properties (has no value, don't get any value) #if masterlen is [], test properties (has no value, don't get any value)
if masterlen == 0: #if masterlen == 0:
if validate_properties: if validate_properties:
props = context.cfgimpl_get_settings().validate_properties(opt, False, props = context.cfgimpl_get_settings().validate_properties(opt, False,
False, False,
@ -195,8 +195,7 @@ class MasterSlaves(object):
setting_properties=setting_properties) setting_properties=setting_properties)
if props: if props:
return props return props
else: #else:
one_has_value = False
if index is None: if index is None:
indexes = range(0, masterlen) indexes = range(0, masterlen)
else: else:
@ -217,19 +216,17 @@ class MasterSlaves(object):
if isinstance(value, Exception): if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError): if isinstance(value, PropertiesOptionError):
err = value err = value
if index is None:
multi.append_properties_error(value) multi.append_properties_error(value)
else:
multi = value
else: else:
return value return value
elif index is None: elif index is None:
multi.append(value, setitem=False, force=True, validate=validate, multi.append(value, setitem=False, force=True, validate=validate,
force_permissive=force_permissive) force_permissive=force_permissive)
one_has_value = True
else: else:
multi = value multi = value
one_has_value = True
if not one_has_value:
#raise last err
return err
return multi return multi
def validate(self, values, opt, value, path, session): def validate(self, values, opt, value, path, session):

View File

@ -514,9 +514,9 @@ class Settings(object):
prop_msg = 'property' prop_msg = 'property'
else: else:
prop_msg = 'properties' prop_msg = 'properties'
return PropertiesOptionError(_("cannot access to {0} {1} " return PropertiesOptionError(_('cannot access to {0} "{1}" '
"because has {2} {3}" 'because has {2} {3}'
"").format(opt_type, '').format(opt_type,
opt_or_descr.impl_get_display_name(), opt_or_descr.impl_get_display_name(),
prop_msg, prop_msg,
display_list(props)), props, display_list(props)), props,

View File

@ -604,6 +604,17 @@ class Values(object):
settings = context.cfgimpl_get_settings() settings = context.cfgimpl_get_settings()
setting_properties = context.cfgimpl_get_settings()._getproperties() setting_properties = context.cfgimpl_get_settings()._getproperties()
setting_properties.update(['mandatory', 'empty']) 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): def _mandatory_warnings(description, currpath=None):
if currpath is None: if currpath is None:
@ -633,16 +644,16 @@ class Values(object):
self_properties=self_properties, self_properties=self_properties,
validate=True, validate=True,
display_warnings=False) display_warnings=False)
if not isinstance(err, Exception): if opt.impl_is_master_slaves('slave') and isinstance(err, list):
pass for val in err:
elif isinstance(err, PropertiesOptionError): ret = _is_properties_option(val, path)
if err.proptype == ['mandatory']: if ret is not None:
yield path yield ret
elif isinstance(err, ConfigError): break
#assume that uncalculated value is an empty value
yield path
else: else:
raise err ret = _is_properties_option(err, path)
if ret is not None:
yield ret
descr = self._getcontext().cfgimpl_get_description() descr = self._getcontext().cfgimpl_get_description()
for path in _mandatory_warnings(descr): for path in _mandatory_warnings(descr):