require with slaves

This commit is contained in:
Emmanuel Garette 2018-04-06 16:09:10 +02:00
parent 42fc21e6f5
commit 4f2bc05e74
2 changed files with 122 additions and 85 deletions

View File

@ -69,18 +69,6 @@ def make_description3():
return descr return descr
def make_description4():
stroption = StrOption('str', 'Test string option', default="abc",
properties=('mandatory', ))
stroption1 = StrOption('str1', 'Test string option',
properties=('mandatory', ))
stroption2 = UnicodeOption('unicode2', 'Test string option',
properties=('mandatory', ))
stroption3 = StrOption('str3', 'Test string option', multi=True, requires=[{'option': stroption, 'expected': 'yes', 'action': 'mandatory', 'transitive': False}])
descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3])
return descr
def test_mandatory_ro(): def test_mandatory_ro():
descr = make_description() descr = make_description()
api = getapi(Config(descr)) api = getapi(Config(descr))
@ -557,7 +545,14 @@ def test_mandatory_warnings_validate_empty():
def test_mandatory_warnings_requires(): def test_mandatory_warnings_requires():
descr = make_description4() stroption = StrOption('str', 'Test string option', default="abc",
properties=('mandatory', ))
stroption1 = StrOption('str1', 'Test string option',
properties=('mandatory', ))
stroption2 = UnicodeOption('unicode2', 'Test string option',
properties=('mandatory', ))
stroption3 = StrOption('str3', 'Test string option', multi=True, requires=[{'option': stroption, 'expected': 'yes', 'action': 'mandatory', 'transitive': False}])
descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3])
api = getapi(Config(descr)) api = getapi(Config(descr))
api.option('str').value.set('') api.option('str').value.set('')
api.property.read_write() api.property.read_write()
@ -570,6 +565,34 @@ def test_mandatory_warnings_requires():
assert list(api.value.mandatory_warnings()) == ['str1', 'unicode2', 'str3'] assert list(api.value.mandatory_warnings()) == ['str1', 'unicode2', 'str3']
def test_mandatory_warnings_requires_masterslaves():
stroption = StrOption('str', 'Test string option', default="abc",
properties=('mandatory', ))
stroption1 = StrOption('str1', 'Test string option', multi=True)
stroption2 = StrOption('str2', 'Test string option', multi=True, requires=[{'option': stroption, 'expected': 'yes', 'action': 'mandatory', 'transitive': False}])
masterslave = MasterSlaves('master', 'masterslaves', [stroption1, stroption2])
descr = OptionDescription('tiram', '', [stroption, masterslave])
api = getapi(Config(descr))
api.option('str').value.set('')
api.option('master.str1').value.set(['str'])
assert list(api.value.mandatory_warnings()) == ['str']
api.option('str').value.set('yes')
assert list(api.value.mandatory_warnings()) == ['master.str2']
def test_mandatory_warnings_requires_masterslaves_slave():
stroption = StrOption('str', 'Test string option', multi=True)
stroption1 = StrOption('str1', 'Test string option', multi=True)
stroption2 = StrOption('str2', 'Test string option', multi=True, requires=[{'option': stroption1, 'expected': 'yes', 'action': 'mandatory', 'transitive': False}])
masterslave = MasterSlaves('master', 'masterslaves', [stroption, stroption1, stroption2])
descr = OptionDescription('tiram', '', [masterslave])
api = getapi(Config(descr))
api.option('master.str').value.set(['str'])
assert list(api.value.mandatory_warnings()) == []
api.option('master.str1', 0).value.set('yes')
assert list(api.value.mandatory_warnings()) == ['master.str2']
def test_mandatory_od_disabled(): def test_mandatory_od_disabled():
descr = make_description() descr = make_description()
descr = OptionDescription('od', '', [descr]) descr = OptionDescription('od', '', [descr])

View File

@ -703,6 +703,86 @@ class Values(object):
#______________________________________________________________________ #______________________________________________________________________
# mandatory warnings # mandatory warnings
def _mandatory_warnings(self,
context,
config_bag,
description,
currpath,
config,
od_setting_properties):
settings = context.cfgimpl_get_settings()
is_masterslaves = description.impl_is_master_slaves()
lenmaster = None
optmaster = None
pathmaster = None
for option in description.impl_getchildren(config_bag, context):
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = option
name = option.impl_getname()
path = '.'.join(currpath + [name])
if option.impl_is_optiondescription():
sconfig_bag.setting_properties = od_setting_properties
try:
subconfig = config.getattr(name,
None,
sconfig_bag)
except PropertiesOptionError as err:
pass
else:
for path in self._mandatory_warnings(context,
config_bag,
option,
currpath + [name],
subconfig,
od_setting_properties):
yield path
elif not option.impl_is_symlinkoption():
# don't verifying symlink
try:
if not option.impl_is_master_slaves('slave'):
self_properties = settings.getproperties(path,
None,
sconfig_bag)
sconfig_bag.properties = self_properties
if 'mandatory' in self_properties or 'empty' in self_properties:
value = config.getattr(name,
None,
sconfig_bag)
if is_masterslaves:
lenmaster = len(value)
pathmaster = name
optmaster = option
else:
if lenmaster is None:
# master is a length (so int) if value is already calculated
# otherwise get value and calculate length
nconfig_bag = config_bag.copy('nooption')
nconfig_bag.option = optmaster
values = config.getattr(pathmaster,
None,
nconfig_bag)
lenmaster = len(values)
for index in range(lenmaster):
self_properties = settings.getproperties(path,
index,
sconfig_bag)
sconfig_bag.properties = self_properties
values = config.getattr(name,
index,
sconfig_bag)
except PropertiesOptionError as err:
if err.proptype == ['mandatory']:
yield path
if is_masterslaves and lenmaster is None:
break
except ConfigError as err:
#assume that uncalculated value is an empty value
yield path
if is_masterslaves and lenmaster is None:
break
def mandatory_warnings(self, def mandatory_warnings(self,
config_bag): config_bag):
@ -712,7 +792,6 @@ class Values(object):
:returns: generator of mandatory Option's path :returns: generator of mandatory Option's path
""" """
context = self._getcontext() context = self._getcontext()
settings = context.cfgimpl_get_settings()
# copy # copy
od_setting_properties = config_bag.setting_properties - {'mandatory', 'empty'} od_setting_properties = config_bag.setting_properties - {'mandatory', 'empty'}
setting_properties = set(config_bag.setting_properties) setting_properties = set(config_bag.setting_properties)
@ -720,77 +799,12 @@ class Values(object):
config_bag.setting_properties = frozenset(setting_properties) config_bag.setting_properties = frozenset(setting_properties)
config_bag.force_permissive = True config_bag.force_permissive = True
config_bag.display_warnings = False config_bag.display_warnings = False
def _mandatory_warnings(description, currpath, config):
is_masterslaves = description.impl_is_master_slaves()
lenmaster = None
optmaster = None
pathmaster = None
for option in description.impl_getchildren(config_bag, context):
sconfig_bag = config_bag.copy('nooption')
sconfig_bag.option = option
name = option.impl_getname()
path = '.'.join(currpath + [name])
if option.impl_is_optiondescription():
sconfig_bag.setting_properties = od_setting_properties
try:
subconfig = config.getattr(name,
None,
sconfig_bag)
except PropertiesOptionError as err:
pass
else:
for path in _mandatory_warnings(option,
currpath + [name],
subconfig):
yield path
elif not option.impl_is_symlinkoption():
# don't check symlink
self_properties = settings.getproperties(path,
None,
sconfig_bag)
sconfig_bag.properties = self_properties
if 'mandatory' in self_properties or 'empty' in self_properties:
try:
if option.impl_is_master_slaves('slave'):
if lenmaster is None:
# master is a length (so int) if value is already calculated
# otherwise get value and calculate length
nconfig_bag = config_bag.copy('nooption')
nconfig_bag.option = optmaster
values = config.getattr(pathmaster,
None,
nconfig_bag)
lenmaster = len(values)
#if not lenmaster:
# settings.validate_properties(path,
# None,
# sconfig_bag)
#else:
for index in range(lenmaster):
values = config.getattr(name,
index,
sconfig_bag)
else:
value = config.getattr(name,
None,
sconfig_bag)
if is_masterslaves:
lenmaster = len(value)
pathmaster = name
optmaster = option
except PropertiesOptionError as err:
if err.proptype == ['mandatory']:
yield path
if is_masterslaves and lenmaster is None:
break
except ConfigError as err:
#assume that uncalculated value is an empty value
yield path
if is_masterslaves and lenmaster is None:
break
descr = context.cfgimpl_get_description() descr = context.cfgimpl_get_description()
for path in _mandatory_warnings(descr, [], context): for path in self._mandatory_warnings(context,
config_bag,
descr,
[],
context,
od_setting_properties):
yield path yield path