From 4f2bc05e74f2d5b2769f70488f602ff02497ccd9 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Fri, 6 Apr 2018 16:09:10 +0200 Subject: [PATCH] require with slaves --- test/test_mandatory.py | 49 +++++++++---- tiramisu/value.py | 158 ++++++++++++++++++++++------------------- 2 files changed, 122 insertions(+), 85 deletions(-) diff --git a/test/test_mandatory.py b/test/test_mandatory.py index deea599..703febd 100644 --- a/test/test_mandatory.py +++ b/test/test_mandatory.py @@ -69,18 +69,6 @@ def make_description3(): 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(): descr = make_description() api = getapi(Config(descr)) @@ -557,7 +545,14 @@ def test_mandatory_warnings_validate_empty(): 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.option('str').value.set('') api.property.read_write() @@ -570,6 +565,34 @@ def test_mandatory_warnings_requires(): 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(): descr = make_description() descr = OptionDescription('od', '', [descr]) diff --git a/tiramisu/value.py b/tiramisu/value.py index 8579c4b..c6ca796 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -703,6 +703,86 @@ class Values(object): #______________________________________________________________________ # 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, config_bag): @@ -712,7 +792,6 @@ class Values(object): :returns: generator of mandatory Option's path """ context = self._getcontext() - settings = context.cfgimpl_get_settings() # copy od_setting_properties = config_bag.setting_properties - {'mandatory', 'empty'} setting_properties = set(config_bag.setting_properties) @@ -720,77 +799,12 @@ class Values(object): config_bag.setting_properties = frozenset(setting_properties) config_bag.force_permissive = True 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() - for path in _mandatory_warnings(descr, [], context): + for path in self._mandatory_warnings(context, + config_bag, + descr, + [], + context, + od_setting_properties): yield path