From 78739103224a5137ce2c27dd9a8b2420332e7eeb Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Sat, 2 Mar 2019 19:43:51 +0100 Subject: [PATCH] doesn't check follower requirement with an other follower or a leader if idx is None (fixes #3) --- test/test_option.py | 5 ++ test/test_requires.py | 87 +++++++++++++++++++++++++++++++++++ tiramisu/option/baseoption.py | 5 +- tiramisu/option/option.py | 6 +-- tiramisu/setting.py | 4 ++ 5 files changed, 103 insertions(+), 4 deletions(-) diff --git a/test/test_option.py b/test/test_option.py index a5e20d2..ea5e603 100644 --- a/test/test_option.py +++ b/test/test_option.py @@ -227,3 +227,8 @@ def test_intoption(): def test_get_display_type(): i1 = IntOption('test1', 'description', min_number=3) assert i1.get_display_type() == 'integer' + + +def test_option_not_in_config(): + i1 = IntOption('test1', 'description', min_number=3) + raises(AttributeError, "i1.impl_getpath()") diff --git a/test/test_requires.py b/test/test_requires.py index d0b1f41..609b3d6 100644 --- a/test/test_requires.py +++ b/test/test_requires.py @@ -1123,3 +1123,90 @@ def test_leadership_requires_no_leader(): raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()") raises(PropertiesOptionError, "api.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get()") assert api.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['192.168.1.2', '192.168.1.1'], 'activate': False} + + +def test_leadership_requires_complet(): + optiontoto = StrOption('unicodetoto', "Unicode leader") + option = StrOption('unicode', "Unicode leader", multi=True) + option1 = StrOption('unicode1', "Unicode follower 1", multi=True) + option2 = StrOption('unicode2', "Values 'test' must show 'Unicode follower 3'", multi=True) + option3 = StrOption('unicode3', "Unicode follower 3", requires=[{'option': option, + 'expected': u'test', + 'action': 'hidden', + 'inverse': True}], + multi=True) + option4 = StrOption('unicode4', "Unicode follower 4", requires=[{'option': option2, + 'expected': u'test', + 'action': 'hidden', + 'inverse': True}], + multi=True) + option5 = StrOption('unicode5', "Unicode follower 5", requires=[{'option': optiontoto, + 'expected': u'test', + 'action': 'hidden', + 'inverse': True}], + multi=True) + option6 = StrOption('unicode6', "Unicode follower 6", requires=[{'option': optiontoto, + 'expected': u'test', + 'action': 'hidden', + 'inverse': True}, + {'option': option2, + 'expected': u'test', + 'action': 'hidden', + 'inverse': True}], + multi=True) + option7 = StrOption('unicode7', "Unicode follower 7", requires=[{'option': option2, + 'expected': u'test', + 'action': 'hidden', + 'inverse': True}, + {'option': optiontoto, + 'expected': u'test', + 'action': 'hidden', + 'inverse': True}], + multi=True) + descr1 = Leadership("unicode", "Common configuration 1", + [option, option1, option2, option3, option4, option5, option6, option7]) + descr = OptionDescription("options", "Common configuration 2", [descr1, optiontoto]) + descr = OptionDescription("unicode1_leadership_requires", "Leader followers with Unicode follower 3 hidden when Unicode follower 2 is test", [descr]) + config = Config(descr) + config.property.read_write() + config.option('options.unicode.unicode').value.set(['test', 'trah']) + config.option('options.unicode.unicode2', 0).value.set('test') + dico = config.value.dict() + assert dico.keys() == set(['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode2', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicodetoto']) + assert dico['options.unicode.unicode'] == ['test', 'trah'] + assert dico['options.unicode.unicode1'] == [None, None] + assert dico['options.unicode.unicode2'] == ['test', None] + assert dico['options.unicode.unicode3'][0] is None + assert isinstance(dico['options.unicode.unicode3'][1], PropertiesOptionError) + assert dico['options.unicode.unicode4'][0] is None + assert isinstance(dico['options.unicode.unicode4'][1], PropertiesOptionError) + assert dico['options.unicodetoto'] is None + del dico['options.unicode.unicode3'][1] + del dico['options.unicode.unicode3'] + del dico['options.unicode.unicode4'][1] + del dico['options.unicode.unicode4'] + # + config.option('options.unicodetoto').value.set('test') + dico = config.value.dict() + assert dico.keys() == set(['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode2', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicode.unicode5', 'options.unicode.unicode6', 'options.unicode.unicode7', 'options.unicodetoto']) + assert dico['options.unicode.unicode'] == ['test', 'trah'] + assert dico['options.unicode.unicode1'] == [None, None] + assert dico['options.unicode.unicode2'] == ['test', None] + assert dico['options.unicode.unicode3'][0] is None + assert isinstance(dico['options.unicode.unicode3'][1], PropertiesOptionError) + assert dico['options.unicode.unicode4'][0] is None + assert isinstance(dico['options.unicode.unicode4'][1], PropertiesOptionError) + assert dico['options.unicode.unicode5'] == [None, None] + assert dico['options.unicode.unicode6'][0] is None + assert isinstance(dico['options.unicode.unicode6'][1], PropertiesOptionError) + assert dico['options.unicode.unicode7'][0] is None + assert isinstance(dico['options.unicode.unicode7'][1], PropertiesOptionError) + assert dico['options.unicodetoto'] == 'test' + del dico['options.unicode.unicode3'][1] + del dico['options.unicode.unicode3'] + del dico['options.unicode.unicode4'][1] + del dico['options.unicode.unicode4'] + del dico['options.unicode.unicode6'][1] + del dico['options.unicode.unicode6'] + del dico['options.unicode.unicode7'][1] + del dico['options.unicode.unicode7'] diff --git a/tiramisu/option/baseoption.py b/tiramisu/option/baseoption.py index b95958f..bbcef07 100644 --- a/tiramisu/option/baseoption.py +++ b/tiramisu/option/baseoption.py @@ -397,7 +397,10 @@ class BaseOption(Base): super(BaseOption, self).__setattr__(name, value) def impl_getpath(self) -> str: - return self._path + try: + return self._path + except AttributeError: + raise AttributeError(_('"{}" not part of any Config').format(self.impl_get_display_name())) def impl_has_callback(self) -> bool: "to know if a callback has been defined or not" diff --git a/tiramisu/option/option.py b/tiramisu/option/option.py index ba0a1cb..b58b402 100644 --- a/tiramisu/option/option.py +++ b/tiramisu/option/option.py @@ -388,13 +388,13 @@ class Option(BaseOption): def impl_is_leader(self): leadership = self.impl_get_leadership() if leadership is None: - return leadership - return self.impl_get_leadership().is_leader(self) + return False + return leadership.is_leader(self) def impl_is_follower(self): leadership = self.impl_get_leadership() if leadership is None: - return leadership + return False return not leadership.is_leader(self) def impl_get_leadership(self): diff --git a/tiramisu/setting.py b/tiramisu/setting.py index f673746..8ce365d 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -523,6 +523,10 @@ class Settings(object): is_indexed = False if option.impl_is_follower(): idx = option_bag.index + if idx is None: + continue + elif option.impl_is_leader() and option_bag.index is None: + continue elif option.impl_is_multi() and option_bag.index is not None: is_indexed = True config_bag = option_bag.config_bag.copy()