From 9ea373efdf9e3ba055c3afb749f26c3de275b5cf Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Mon, 9 Apr 2018 21:37:49 +0200 Subject: [PATCH] better dynoption support --- test/auto/test_auto.py | 3 +- test/test_cache.py | 106 +- test/test_dyn_optiondescription.py | 1126 +++++++---------- ..._parsing_group.py => test_masterslaves.py} | 20 + ...calculation.py => test_option_callback.py} | 13 + tiramisu/api.py | 11 +- tiramisu/autolib.py | 16 +- tiramisu/config.py | 102 +- tiramisu/option/baseoption.py | 19 +- tiramisu/option/dynoptiondescription.py | 22 +- tiramisu/option/masterslave.py | 56 +- tiramisu/option/option.py | 8 +- tiramisu/option/optiondescription.py | 125 +- tiramisu/option/symlinkoption.py | 28 - tiramisu/option/syndynoptiondescription.py | 30 +- tiramisu/setting.py | 29 +- tiramisu/value.py | 20 +- 17 files changed, 810 insertions(+), 924 deletions(-) rename test/{test_parsing_group.py => test_masterslaves.py} (97%) rename test/{test_option_calculation.py => test_option_callback.py} (98%) diff --git a/test/auto/test_auto.py b/test/auto/test_auto.py index 37d7640..0ff0767 100644 --- a/test/auto/test_auto.py +++ b/test/auto/test_auto.py @@ -1742,7 +1742,8 @@ def test_options(paths): # if callback and default_multi: # continue # for default in (False,): -# for multi in (False,): +# for multi in (True,): +# print(meta, callback, consistency, require, default_multi, symlink, default, multi) if multi is submulti and default: continue if multi is submulti and consistency: diff --git a/test/test_cache.py b/test/test_cache.py index 187140c..2aa899a 100644 --- a/test/test_cache.py +++ b/test/test_cache.py @@ -210,7 +210,7 @@ def test_reset_cache(): api.option('u1').value.get() assert 'u1' in values._p_.get_cached() assert 'u1' in settings._p_.get_cached() - c.cfgimpl_reset_cache() + c.cfgimpl_reset_cache(None, None, None) assert 'u1' not in values._p_.get_cached() assert 'u1' not in settings._p_.get_cached() api.option('u1').value.get() @@ -222,7 +222,7 @@ def test_reset_cache(): assert 'u1' in settings._p_.get_cached() assert 'u2' in values._p_.get_cached() assert 'u2' in settings._p_.get_cached() - c.cfgimpl_reset_cache() + c.cfgimpl_reset_cache(None, None, None) assert 'u1' not in values._p_.get_cached() assert 'u1' not in settings._p_.get_cached() assert 'u2' not in values._p_.get_cached() @@ -237,62 +237,62 @@ def test_reset_cache(): # values = c.cfgimpl_get_values() # api.option('od1.u1').value.get() # assert 'od1.u1' in values._p_.get_cached() -# c.od1.cfgimpl_reset_cache() +# c.od1.cfgimpl_reset_cache(None, None, None) # assert 'od1.u1' not in values._p_.get_cached() -def test_reset_cache_only_expired(): - od1 = make_description() - c = Config(od1) - api = getapi(c) - api.property.add('expire') - values = c.cfgimpl_get_values() - settings = c.cfgimpl_get_settings() - api.option('u1').value.get() - assert 'u1' in values._p_.get_cached() - assert 'u1' in settings._p_.get_cached() - c.cfgimpl_reset_cache(True) - assert 'u1' in values._p_.get_cached() - assert 'u1' in settings._p_.get_cached() - sleep(1) - api.option('u1').value.get() - sleep(1) - api.option('u2').value.get() - assert 'u1' in values._p_.get_cached() - assert 'u1' in settings._p_.get_cached() - assert 'u2' in values._p_.get_cached() - assert 'u2' in settings._p_.get_cached() - c.cfgimpl_reset_cache(True) - assert 'u1' not in values._p_.get_cached() - assert 'u1' not in settings._p_.get_cached() - assert 'u2' in values._p_.get_cached() - assert 'u2' in settings._p_.get_cached() +#def test_reset_cache_only_expired(): +# od1 = make_description() +# c = Config(od1) +# api = getapi(c) +# api.property.add('expire') +# values = c.cfgimpl_get_values() +# settings = c.cfgimpl_get_settings() +# api.option('u1').value.get() +# assert 'u1' in values._p_.get_cached() +# assert 'u1' in settings._p_.get_cached() +# c.cfgimpl_reset_cache(True) +# assert 'u1' in values._p_.get_cached() +# assert 'u1' in settings._p_.get_cached() +# sleep(1) +# api.option('u1').value.get() +# sleep(1) +# api.option('u2').value.get() +# assert 'u1' in values._p_.get_cached() +# assert 'u1' in settings._p_.get_cached() +# assert 'u2' in values._p_.get_cached() +# assert 'u2' in settings._p_.get_cached() +# c.cfgimpl_reset_cache(True) +# assert 'u1' not in values._p_.get_cached() +# assert 'u1' not in settings._p_.get_cached() +# assert 'u2' in values._p_.get_cached() +# assert 'u2' in settings._p_.get_cached() -def test_cache_not_expire(): - od1 = make_description() - c = Config(od1) - api = getapi(c) - values = c.cfgimpl_get_values() - settings = c.cfgimpl_get_settings() - #api.property.pop('expire') - api.option('u1').value.get() - assert 'u1' in values._p_.get_cached() - assert 'u1' in settings._p_.get_cached() - c.cfgimpl_reset_cache(True) - assert 'u1' in values._p_.get_cached() - assert 'u1' in settings._p_.get_cached() - sleep(1) - api.option('u2').value.get() - assert 'u1' in values._p_.get_cached() - assert 'u1' in settings._p_.get_cached() - assert 'u2' in values._p_.get_cached() - assert 'u2' in settings._p_.get_cached() - c.cfgimpl_reset_cache(True) - assert 'u1' in values._p_.get_cached() - assert 'u1' in settings._p_.get_cached() - assert 'u2' in values._p_.get_cached() - assert 'u2' in settings._p_.get_cached() +#def test_cache_not_expire(): +# od1 = make_description() +# c = Config(od1) +# api = getapi(c) +# values = c.cfgimpl_get_values() +# settings = c.cfgimpl_get_settings() +# #api.property.pop('expire') +# api.option('u1').value.get() +# assert 'u1' in values._p_.get_cached() +# assert 'u1' in settings._p_.get_cached() +# c.cfgimpl_reset_cache(True) +# assert 'u1' in values._p_.get_cached() +# assert 'u1' in settings._p_.get_cached() +# sleep(1) +# api.option('u2').value.get() +# assert 'u1' in values._p_.get_cached() +# assert 'u1' in settings._p_.get_cached() +# assert 'u2' in values._p_.get_cached() +# assert 'u2' in settings._p_.get_cached() +# c.cfgimpl_reset_cache(True) +# assert 'u1' in values._p_.get_cached() +# assert 'u1' in settings._p_.get_cached() +# assert 'u2' in values._p_.get_cached() +# assert 'u2' in settings._p_.get_cached() def test_cache_not_cache(): diff --git a/test/test_dyn_optiondescription.py b/test/test_dyn_optiondescription.py index 9cecec3..6c7d7f3 100644 --- a/test/test_dyn_optiondescription.py +++ b/test/test_dyn_optiondescription.py @@ -11,7 +11,6 @@ from tiramisu import BoolOption, StrOption, ChoiceOption, IPOption, \ Config, getapi from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError from tiramisu.storage import delete_session -#from .test_state import _diff_opts, _diff_conf from py.test import raises @@ -37,48 +36,43 @@ def return_list(val=None, suffix=None): return ['val1', 'val2'] -def return_same_list(): +def return_same_list(suffix): return ['val1', 'val1'] -def return_wrong_list(): +def return_wrong_list(*args, **kwargs): return ['---', ' '] -def return_raise(): +def return_raise(suffix): raise Exception('error') -#def test_build_dyndescription(): -# st = StrOption('st', '') -# dod = DynOptionDescription('dod', '', [st], callback=return_list) -# od = OptionDescription('od', '', [dod]) -# cfg = Config(od) -# assert str(cfg) == """[dodval1] -#[dodval2]""" -# assert str(cfg.dodval1) == "stval1 = None" -# assert str(cfg.dodval2) == "stval2 = None" +def test_build_dyndescription(): + st1 = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st1], callback=return_list) + od1 = OptionDescription('od', '', [dod]) + cfg = Config(od1) + api = getapi(cfg) + assert api.option.make_dict() == {'dodval1.stval1': None, 'dodval2.stval2': None} -#def test_build_dyndescription_raise(): -# st = StrOption('st', '') -# dod = DynOptionDescription('dod', '', [st], callback=return_raise) -# od = OptionDescription('od', '', [dod]) -# cfg = Config(od) -# raises(ConfigError, "str(cfg)") +def test_build_dyndescription_raise(): + st1 = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st1], callback=return_raise) + od1 = OptionDescription('od', '', [dod]) + cfg = Config(od1) + api = getapi(cfg) + raises(ConfigError, "api.option.make_dict()") -#def test_subpath_dyndescription(): -# st = StrOption('st', '') -# dod = DynOptionDescription('dod', '', [st], callback=return_list) -# od = OptionDescription('od', '', [dod]) -# od2 = OptionDescription('od', '', [od]) -# api = getapi(Config(od2)) -# assert str(cfg) == "[od]" -# assert str(cfg.od) == """[dodval1] -#[dodval2]""" -# assert str(cfg.od.dodval1) == "stval1 = None" -# assert str(cfg.od.dodval2) == "stval2 = None" +def test_subpath_dyndescription(): + st1 = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st1], callback=return_list) + od1 = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od1]) + api = getapi(Config(od2)) + assert api.option.make_dict() == {'od.dodval1.stval1': None, 'od.dodval2.stval2': None} def test_list_dyndescription(): @@ -99,36 +93,23 @@ def test_unknown_dyndescription(): api = getapi(Config(od2)) raises(AttributeError, "api.option('od.dodval3').value.get()") raises(AttributeError, "api.option('od.dodval1.novalue').value.get()") + raises(AttributeError, "api.option('od.dodval1.stnoval1').value.get()") -#def test_getdoc_dyndescription(): -# st = StrOption('st', 'doc1') -# dod = DynOptionDescription('dod', 'doc2', [st], callback=return_list) -# od = OptionDescription('od', '', [dod]) -# od2 = OptionDescription('od', '', [od]) -# api = getapi(Config(od2)) -# stval1 = cfg.unwrap_from_path('od.dodval1.stval1') -# stval2 = cfg.unwrap_from_path('od.dodval2.stval2') -# dodval1 = cfg.unwrap_from_path('od.dodval1') -# dodval2 = cfg.unwrap_from_path('od.dodval2') -# assert stval1.impl_getname() == 'stval1' -# assert stval2.impl_getname() == 'stval2' -# assert dodval1.impl_getname() == 'dodval1' -# assert dodval2.impl_getname() == 'dodval2' -# assert stval1.impl_getdoc() == 'doc1' -# assert stval2.impl_getdoc() == 'doc1' -# assert dodval1.impl_getdoc() == 'doc2' -# assert dodval2.impl_getdoc() == 'doc2' - - -#def test_getpaths_dyndescription(): -# st = StrOption('st', '') -# dod = DynOptionDescription('dod', '', [st], callback=return_list) -# od = OptionDescription('od', '', [dod]) -# od2 = OptionDescription('od', '', [od]) -# api = getapi(Config(od2)) -# assert cfg.cfgimpl_get_description().impl_getpaths() == ['od.dodval1.stval1', 'od.dodval2.stval2'] -# assert cfg.cfgimpl_get_description().impl_getpaths(include_groups=True) == ['od', 'od.dodval1', 'od.dodval1.stval1', 'od.dodval2', 'od.dodval2.stval2'] +def test_getdoc_dyndescription(): + st1 = StrOption('st', 'doc1') + dod = DynOptionDescription('dod', 'doc2', [st1], callback=return_list) + od1 = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od1]) + api = getapi(Config(od2)) + assert api.option('od.dodval1.stval1').option.name() == 'stval1' + assert api.option('od.dodval2.stval2').option.name() == 'stval2' + assert api.option('od.dodval1').option.name() == 'dodval1' + assert api.option('od.dodval2').option.name() == 'dodval2' + assert api.option('od.dodval1.stval1').option.doc() == 'doc1' + assert api.option('od.dodval2.stval2').option.doc() == 'doc1' + assert api.option('od.dodval1').option.doc() == 'doc2' + assert api.option('od.dodval2').option.doc() == 'doc2' def test_mod_dyndescription(): @@ -191,7 +172,6 @@ def test_multi_dyndescription(): api.option('od.dodval2.stval2').value.set(['no']) assert api.option('od.dodval1.stval1').value.get() == ['yes'] assert api.option('od.dodval2.stval2').value.get() == ['no'] - #assert cfg.getowner(st) == owners.default assert api.option('od.dodval1.stval1').owner.get() == owner assert api.option('od.dodval2.stval2').owner.get() == owner api.option('od.dodval1.stval1').value.set(['yes', 'yes']) @@ -294,34 +274,24 @@ def test_mandatory_dyndescription(): assert list(api.value.mandatory_warnings()) == ['od.dodval1.stval1', 'od.dodval2.stval2'] -#def test_build_dyndescription_context(): -# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) -# st = StrOption('st', '') -# dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)}) -# od = OptionDescription('od', '', [dod, val1]) -# cfg = Config(od) -# cfg._impl_test = True -# assert str(cfg) == """[dodval1] -#[dodval2] -#val1 = ['val1', 'val2']""" -# assert str(cfg.dodval1) == "stval1 = None" -# assert str(cfg.dodval2) == "stval2 = None" -# cfg.unwrap_from_path('dodval2') +def test_build_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st1 = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st1], callback=return_list, callback_params={'': ((val1, False),)}) + od1 = OptionDescription('od', '', [dod, val1]) + cfg = Config(od1) + api = getapi(cfg) + assert api.option.make_dict() == {'dodval1.stval1': None, 'dodval2.stval2': None, 'val1': ['val1', 'val2']} -#def test_subpath_dyndescription_context(): -# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) -# st = StrOption('st', '') -# dod = DynOptionDescription('dod', '', [st], callback=return_list, callback_params={'': ((val1, False),)}) -# od = OptionDescription('od', '', [dod, val1]) -# od2 = OptionDescription('od', '', [od]) -# api = getapi(Config(od2)) -# assert str(cfg) == "[od]" -# assert str(cfg.od) == """[dodval1] -#[dodval2] -#val1 = ['val1', 'val2']""" -# assert str(cfg.od.dodval1) == "stval1 = None" -# assert str(cfg.od.dodval2) == "stval2 = None" +def test_subpath_dyndescription_context(): + val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) + st1 = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st1], callback=return_list, callback_params={'': ((val1, False),)}) + od1 = OptionDescription('od', '', [dod, val1]) + od2 = OptionDescription('od', '', [od1]) + api = getapi(Config(od2)) + assert api.option.make_dict() == {'od.dodval1.stval1': None, 'od.dodval2.stval2': None, 'od.val1': ['val1', 'val2']} def test_list_dyndescription_context(): @@ -356,7 +326,6 @@ def test_mod_dyndescription_context(): api.option('od.dodval2.stval2').value.set('no') assert api.option('od.dodval1.stval1').value.get() == 'yes' assert api.option('od.dodval2.stval2').value.get() == 'no' - #assert cfg.getowner(st) == owners.default assert api.option('od.dodval1.stval1').owner.get() == owner assert api.option('od.dodval2.stval2').owner.get() == owner @@ -397,7 +366,6 @@ def test_multi_dyndescription_context(): api.option('od.dodval2.stval2').value.set(['no']) assert api.option('od.dodval1.stval1').value.get() == ['yes'] assert api.option('od.dodval2.stval2').value.get() == ['no'] - #assert cfg.getowner(st) == owners.default assert api.option('od.dodval1.stval1').owner.get() == owner assert api.option('od.dodval2.stval2').owner.get() == owner api.option('od.dodval1.stval1').value.set(['yes', 'yes']) @@ -479,7 +447,7 @@ def test_increase_dyndescription_context(): api.property.read_write() assert api.option('od.dodval1.stval1').value.get() is None assert api.option('od.dodval2.stval2').value.get() is None - raises(AttributeError, "api.option('od.dodval3').value.get()") + raises(AttributeError, "api.option('od.dodval3.stval3').value.get()") api.option('od.val1').value.set(['val1', 'val2', 'val3']) assert api.option('od.dodval1.stval1').value.get() is None assert api.option('od.dodval2.stval2').value.get() is None @@ -508,102 +476,103 @@ def test_decrease_dyndescription_context(): raises(AttributeError, "api.option('od.dodval2').value.get()") raises(AttributeError, "api.option('od.dodval3').value.get()") assert api.option('od.dodval1.stval1').owner.isdefault() - #FIXME -# raises(AttributeError, "cfg.getowner(stval2)") + raises(AttributeError, "api.option('od.dodval2.stval2').owner.get()") raises(AttributeError, "api.option('od.dodval2.stval2').value.get()") -# -# -#def test_requires_dyndescription(): -# boolean = BoolOption('boolean', '', True) -# st = StrOption('st', '', requires=[{'option': boolean, 'expected': False, -# 'action': 'disabled'}]) -# dod = DynOptionDescription('dod', '', [st], callback=return_list) -# od = OptionDescription('od', '', [dod]) -# od2 = OptionDescription('od', '', [od, boolean]) -# api = getapi(Config(od2)) -# api.property.read_write() -# assert api.option('od.dodval1.stval1').value.get() is None -# assert api.option('od.dodval2.stval2').value.get() is None -# # -# cfg.boolean = False -# props = [] -# try: -# cfg.od.dodval1.stval1 -# except PropertiesOptionError as err: -# props = err.proptype -# assert props == ['disabled'] -# props = [] -# try: -# cfg.od.dodval2.stval2 -# except PropertiesOptionError as err: -# props = err.proptype -# assert props == ['disabled'] -# # -# cfg.boolean = True -# assert api.option('od.dodval1.stval1').value.get() is None -# assert api.option('od.dodval2.stval2').value.get() is None -# #transitive -# cfg.cfgimpl_get_settings()[boolean].append('disabled') -# props = [] -# try: -# cfg.od.dodval1.stval1 -# except PropertiesOptionError as err: -# props = err.proptype -# assert props == ['disabled'] -# props = [] -# try: -# cfg.od.dodval2.stval2 -# except PropertiesOptionError as err: -# props = err.proptype -# assert props == ['disabled'] -#def test_requires_dyndescription2(): -# boolean = BoolOption('boolean', '', True) -# st = StrOption('st', '') -# dod = DynOptionDescription('dod', '', [st], callback=return_list, -# requires=[{'option': boolean, 'expected': False, -# 'action': 'disabled'}]) -# od = OptionDescription('od', '', [dod]) -# od2 = OptionDescription('od', '', [od, boolean]) -# api = getapi(Config(od2)) -# api.property.read_write() -# assert api.option('od.dodval1.stval1').value.get() is None -# assert api.option('od.dodval2.stval2').value.get() is None -# # -# cfg.boolean = False -# props = [] -# try: -# cfg.od.dodval1.stval1 -# except PropertiesOptionError as err: -# props = err.proptype -# assert props == ['disabled'] -# props = [] -# try: -# cfg.od.dodval2.stval2 -# except PropertiesOptionError as err: -# props = err.proptype -# assert props == ['disabled'] -# # -# cfg.boolean = True -# assert api.option('od.dodval1.stval1').value.get() is None -# assert api.option('od.dodval2.stval2').value.get() is None -# #transitive -# cfg.cfgimpl_get_settings()[boolean].append('disabled') -# props = [] -# try: -# cfg.od.dodval1.stval1 -# except PropertiesOptionError as err: -# props = err.proptype -# assert props == ['disabled'] -# props = [] -# try: -# cfg.od.dodval2.stval2 -# except PropertiesOptionError as err: -# props = err.proptype -# assert props == ['disabled'] -# -# +def test_requires_dyndescription(): + boolean = BoolOption('boolean', '', True) + st1 = StrOption('st', '', requires=[{'option': boolean, 'expected': False, + 'action': 'disabled'}]) + dod = DynOptionDescription('dod', '', [st1], callback=return_list) + od1 = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od1, boolean]) + api = getapi(Config(od2)) + api.property.read_write() + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + # + print('-----------------') + api.option('boolean').value.set(False) + print('-----------------') + props = [] + try: + api.option('od.dodval1.stval1').value.get() + except PropertiesOptionError as err: + props = err.proptype + assert frozenset(props) == frozenset(['disabled']) + props = [] + try: + api.option('od.dodval2.stval2').value.get() + except PropertiesOptionError as err: + props = err.proptype + assert frozenset(props) == frozenset(['disabled']) + # + api.option('boolean').value.set(True) + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + #transitive + api.option('boolean').property.add('disabled') + props = [] + try: + api.option('od.dodval1.stval1').value.get() + except PropertiesOptionError as err: + props = err.proptype + assert frozenset(props) == frozenset(['disabled']) + props = [] + try: + api.option('od.dodval2.stval2').value.get() + except PropertiesOptionError as err: + props = err.proptype + assert frozenset(props) == frozenset(['disabled']) + + +def test_requires_dyndescription2(): + boolean = BoolOption('boolean', '', True) + st1 = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st1], callback=return_list, + requires=[{'option': boolean, 'expected': False, + 'action': 'disabled'}]) + od1 = OptionDescription('od', '', [dod]) + od2 = OptionDescription('od', '', [od1, boolean]) + api = getapi(Config(od2)) + api.property.read_write() + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + # + api.option('boolean').value.set(False) + props = [] + try: + api.option('od.dodval1.stval1').value.get() + except PropertiesOptionError as err: + props = err.proptype + assert frozenset(props) == frozenset(['disabled']) + props = [] + try: + api.option('od.dodval2.stval2').value.get() + except PropertiesOptionError as err: + props = err.proptype + assert frozenset(props) == frozenset(['disabled']) + # + api.option('boolean').value.set(True) + assert api.option('od.dodval1.stval1').value.get() is None + assert api.option('od.dodval2.stval2').value.get() is None + #transitive + api.option('boolean').property.add('disabled') + props = [] + try: + api.option('od.dodval1.stval1').value.get() + except PropertiesOptionError as err: + props = err.proptype + assert frozenset(props) == frozenset(['disabled']) + props = [] + try: + api.option('od.dodval2.stval2').value.get() + except PropertiesOptionError as err: + props = err.proptype + assert frozenset(props) == frozenset(['disabled']) + + def test_validator_dyndescription(): val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) st = StrOption('st', '', validator=return_true, validator_params={'': ('yes',)}, default='val') @@ -649,28 +618,6 @@ def test_find_dyndescription_context(): raises(AttributeError, "api.option.find('strnotexists')") -#def test_iter_all_dyndescription_context(): -# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) -# st = StrOption('st', '') -# dod = DynOptionDescription('dod', '', [st], callback=return_list) -# od = OptionDescription('od', '', [dod, val1]) -# od2 = OptionDescription('od', '', [od]) -# api = getapi(Config(od2)) -# for it in cfg.iter_all(): -# assert it[0] == 'od' -# assert str(it[1]) == str(cfg.od) -# # -# list_od = [] -# for it in cfg.od.iter_all(): -# list_od.append(it[0]) -# assert list_od == ['dodval1', 'dodval2', 'val1'] -# # -# list_od = [] -# for it in cfg.od.dodval1: -# list_od.append(it[0]) -# assert list_od == ['stval1'] - - def test_information_dyndescription_context(): val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) st = StrOption('st', '') @@ -686,25 +633,25 @@ def test_information_dyndescription_context(): assert api.option('od.dodval1.stval1').information.get('testst') == 'val2' assert api.option('od.dodval2.stval2').information.get('testst') == 'val2' assert api.information.get('testcfgod') == 'val3' -# -# -#def test_consistency_dyndescription(): -# st = StrOption('st', '') -# st2 = StrOption('st2', '') -# dod = DynOptionDescription('dod', '', [st, st2], callback=return_list) -# od = OptionDescription('od', '', [dod]) -# st.impl_add_consistency('not_equal', st2) -# od2 = OptionDescription('od', '', [od]) -# api = getapi(Config(od2)) -# api.option('od.dodval1.stval1').value.set('yes') -# raises(ValueError, "cfg.od.dodval1.st2val1 = 'yes'") -# api.option('od.dodval2.stval2').value.set('yes') -# raises(ValueError, "cfg.od.dodval2.st2val2 = 'yes'") -# raises(ValueError, "cfg.od.dodval1.st2val1 = 'yes'") -# del(cfg.od.dodval2.stval2) -# raises(ValueError, "cfg.od.dodval1.st2val1 = 'yes'") -# cfg.od.dodval2.st2val2 = 'yes' -# raises(ValueError, "api.option('od.dodval2.stval2').value.set('yes')") + + +def test_consistency_dyndescription(): + st1 = StrOption('st', '') + st2 = StrOption('st2', '') + dod = DynOptionDescription('dod', '', [st1, st2], callback=return_list) + od1 = OptionDescription('od', '', [dod]) + st1.impl_add_consistency('not_equal', st2) + od2 = OptionDescription('od', '', [od1]) + api = getapi(Config(od2)) + api.option('od.dodval1.stval1').value.set('yes') + raises(ValueError, "api.option('od.dodval1.st2val1').value.set('yes')") + api.option('od.dodval2.stval2').value.set('yes') + raises(ValueError, "api.option('od.dodval2.st2val2').value.set('yes')") + raises(ValueError, "api.option('od.dodval1.st2val1').value.set('yes')") + api.option('od.dodval2.stval2').value.reset() + raises(ValueError, "api.option('od.dodval1.st2val1').value.set('yes')") + api.option('od.dodval2.st2val2').value.set('yes') + raises(ValueError, "api.option('od.dodval2.stval2').value.set('yes')") def test_consistency_dyndescription_default(): @@ -871,242 +818,169 @@ def test_all_dyndescription(): assert api.option('dodval2.urlval2').value.get() is None assert api.option('dodval2.usernameval2').value.get() is None assert api.option('dodval2.filenameval2').value.get() is None -# -# -#def test_consistency_ip_netmask_dyndescription(): -# a = IPOption('a', '') -# b = NetmaskOption('b', '') -# dod = DynOptionDescription('dod', '', [a, b], callback=return_list) -# b.impl_add_consistency('ip_netmask', a) -# od = OptionDescription('od', '', [dod]) -# c = Config(od) -# c.dodval1.aval1 = '192.168.1.1' -# c.dodval1.bval1 = '255.255.255.0' -# c.dodval2.aval2 = '192.168.1.2' -# c.dodval2.bval2 = '255.255.255.255' -## c.dodval2.bval2 = '255.255.255.0' -# -# -#def test_consistency_ip_in_network_dyndescription(): -# a = NetworkOption('a', '') -# b = NetmaskOption('b', '') -# c = IPOption('c', '') -# dod = DynOptionDescription('dod', '', [a, b, c], callback=return_list) -# c.impl_add_consistency('in_network', a, b) -# od = OptionDescription('od', '', [dod]) -# cfg = Config(od) -# cfg.dodval1.aval1 = '192.168.1.0' -# cfg.dodval1.bval1 = '255.255.255.0' -# cfg.dodval1.cval1 = '192.168.1.1' -#def test_masterslaves_dyndescription(): -# st1 = StrOption('st1', "", multi=True) -# st2 = StrOption('st2', "", multi=True) -# stm = MasterSlaves('st1', '', [st1, st2]) -# #stm.impl_set_group_type(groups.master) -# st = DynOptionDescription('st', '', [stm], callback=return_list) -# od = OptionDescription('od', '', [st]) -# od2 = OptionDescription('od', '', [od]) -# api = getapi(Config(od2)) -# print('--------------- 1') -# owner = api.owner.get() -# print('--------------- 2') -# st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1') -# print('--------------- 3') -# st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1') -# print('--------------- 4') -# st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2') -# print('--------------- 5') -# st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2') -# print('--------------- 6') -# assert api.option.make_dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []} -# print('--------------- 7') -# assert cfg.od.stval1.st1val1.st1val1 == [] -# print('--------------- 8') -# assert cfg.od.stval1.st1val1.st2val1 == [] -# print('--------------- 9') -# assert cfg.od.stval2.st1val2.st1val2 == [] -# print('--------------- 10') -# assert cfg.od.stval2.st1val2.st2val2 == [] -# print('--------------- 11') -# assert cfg.getowner(st1val1) == owners.default -# print('--------------- 12') -# assert cfg.getowner(st1val2) == owners.default -# print('--------------- 13') -# assert cfg.getowner(st2val1) == owners.default -# print('--------------- 14') -# assert cfg.getowner(st2val2) == owners.default -# print('--------------- 15') -# # -# cfg.od.stval1.st1val1.st1val1.append('yes') -# print('--------------- 16') -# assert api.option.make_dict() == {'od.stval1.st1val1.st2val1': [None], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes']} -# print('--------------- 17') -# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] -# print('--------------- 18') -# assert cfg.od.stval1.st1val1.st2val1 == [None] -# print('--------------- 19') -# assert cfg.od.stval2.st1val2.st1val2 == [] -# print('--------------- 20') -# assert cfg.od.stval2.st1val2.st2val2 == [] -# print('--------------- 21') -# assert cfg.getowner(st1val1) == owner -# print('--------------- 22') -# assert cfg.getowner(st1val2) == owners.default -# print('--------------- 23') -# assert cfg.getowner(st2val1) == owners.default -# print('--------------- 24') -# assert cfg.getowner(st2val2) == owners.default -# print('--------------- 25') -# # -# cfg.od.stval1.st1val1.st1val1 = ['yes'] -# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] -# assert cfg.od.stval1.st1val1.st2val1 == [None] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1) == owners.default -# assert cfg.getowner(st2val2) == owners.default -# # -# cfg.od.stval1.st1val1.st2val1 = ['no'] -# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] -# assert cfg.od.stval1.st1val1.st2val1 == ['no'] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1, 0) == owner -## assert cfg.getowner(st2val2) == owners.default -# # -# cfg.od.stval1.st1val1.st1val1.pop(0) -# assert cfg.od.stval1.st1val1.st1val1 == [] -# assert cfg.od.stval1.st1val1.st2val1 == [] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st1val2) == owners.default -## assert cfg.getowner(st2val1) == owner -## assert cfg.getowner(st2val2) == owners.default -# # -# cfg.od.stval1.st1val1.st1val1 = ['yes'] -# cfg.od.stval1.st1val1.st2val1 = ['yes'] -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st2val1, 0) == owner -# del(cfg.od.stval1.st1val1.st2val1) -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st1val2) == owners.default -## assert cfg.getowner(st2val1) == owners.default -## assert cfg.getowner(st2val2) == owners.default -# # -# cfg.od.stval1.st1val1.st1val1 = ['yes'] -# cfg.od.stval1.st1val1.st2val1 = ['yes'] -# del(cfg.od.stval1.st1val1.st1val1) -# assert cfg.od.stval1.st1val1.st1val1 == [] -# assert cfg.od.stval1.st1val1.st2val1 == [] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owners.default -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1) == owners.default -# assert cfg.getowner(st2val2) == owners.default -# -# -#def test_masterslaves_default_multi_dyndescription(): -# st1 = StrOption('st1', "", multi=True) -# st2 = StrOption('st2', "", multi=True, default_multi='no') -# stm = MasterSlaves('st1', '', [st1, st2]) -# #stm.impl_set_group_type(groups.master) -# st = DynOptionDescription('st', '', [stm], callback=return_list) -# od = OptionDescription('od', '', [st]) -# od2 = OptionDescription('od', '', [od]) -# api = getapi(Config(od2)) -# owner = api.owner.get() -# st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1') -# st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1') -# st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2') -# st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2') -# assert cfg.od.stval1.st1val1.st1val1 == [] -# assert cfg.od.stval1.st1val1.st2val1 == [] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owners.default -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1) == owners.default -# assert cfg.getowner(st2val2) == owners.default -# cfg.od.stval1.st1val1.st1val1.append('yes') -# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] -# assert cfg.od.stval1.st1val1.st2val1 == ['no'] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1) == owners.default -# assert cfg.getowner(st2val2) == owners.default -# -# -#def test_masterslaves_submulti_dyndescription(): -# st1 = StrOption('st1', "", multi=True) -# st2 = StrOption('st2', "", multi=submulti) -# stm = MasterSlaves('st1', '', [st1, st2]) -# #stm.impl_set_group_type(groups.master) -# st = DynOptionDescription('st', '', [stm], callback=return_list) -# od = OptionDescription('od', '', [st]) -# od2 = OptionDescription('od', '', [od]) -# api = getapi(Config(od2)) -# owner = api.owner.get() -# st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1') -# st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1') -# st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2') -# st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2') -# assert cfg.od.stval1.st1val1.st1val1 == [] -# assert cfg.od.stval1.st1val1.st2val1 == [] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owners.default -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1) == owners.default -# assert cfg.getowner(st2val2) == owners.default -# cfg.od.stval1.st1val1.st1val1.append('yes') -# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] -# assert cfg.od.stval1.st1val1.st2val1 == [[]] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1) == owners.default -# assert cfg.getowner(st2val2) == owners.default -# # -# cfg.od.stval1.st1val1.st2val1[0].append('no') -# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] -# assert cfg.od.stval1.st1val1.st2val1 == [['no']] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1, 0) == owner -# assert cfg.getowner(st2val2) == owners.default +def test_consistency_ip_netmask_dyndescription(): + ipa = IPOption('a', '') + netb = NetmaskOption('b', '') + dod = DynOptionDescription('dod', '', [ipa, netb], callback=return_list) + netb.impl_add_consistency('ip_netmask', ipa) + od1 = OptionDescription('od', '', [dod]) + cfg = Config(od1) + api = getapi(cfg) + api.option('dodval1.aval1').value.set('192.168.1.1') + api.option('dodval1.bval1').value.set('255.255.255.0') + api.option('dodval2.aval2').value.set('192.168.1.2') + api.option('dodval2.bval2').value.set('255.255.255.255') + api.option('dodval2.bval2').value.set('255.255.255.0') +def test_consistency_ip_in_network_dyndescription(): + neta = NetworkOption('a', '') + netb = NetmaskOption('b', '') + ipc = IPOption('c', '') + dod = DynOptionDescription('dod', '', [neta, netb, ipc], callback=return_list) + ipc.impl_add_consistency('in_network', neta, netb) + od1 = OptionDescription('od', '', [dod]) + cfg = Config(od1) + api = getapi(cfg) + api.option('dodval1.aval1').value.set('192.168.1.0') + api.option('dodval1.bval1').value.set('255.255.255.0') + api.option('dodval1.cval1').value.set('192.168.1.1') + + +def test_masterslaves_dyndescription(): + st1 = StrOption('st1', "", multi=True) + st2 = StrOption('st2', "", multi=True) + stm = MasterSlaves('st1', '', [st1, st2]) + st = DynOptionDescription('st', '', [stm], callback=return_list) + od = OptionDescription('od', '', [st]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + owner = api.owner.get() + # + assert api.option.make_dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []} + assert api.option('od.stval1.st1val1.st1val1').value.get() == [] + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st1val1').value.set(['yes']) + assert api.option.make_dict() == {'od.stval1.st1val1.st2val1': [None], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes']} + assert api.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] + assert api.option('od.stval1.st1val1.st2val1', 0).value.get() == None + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st2val1', 0).value.set('no') + assert api.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] + assert api.option('od.stval1.st1val1.st2val1', 0).value.get() == 'no' + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st1val1').value.pop(0) + assert api.option('od.stval1.st1val1.st1val1').value.get() == [] + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st1val1').value.set(['yes']) + api.option('od.stval1.st1val1.st2val1', 0).value.set('yes') + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + api.option('od.stval1.st1val1.st2val1', 0).value.reset() + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.isdefault() + # + api.option('od.stval1.st1val1.st1val1').value.set(['yes']) + api.option('od.stval1.st1val1.st2val1', 0).value.set('yes') + api.option('od.stval1.st1val1.st1val1').value.reset() + assert api.option('od.stval1.st1val1.st1val1').value.get() == [] + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + + +def test_masterslaves_default_multi_dyndescription(): + st1 = StrOption('st1', "", multi=True) + st2 = StrOption('st2', "", multi=True, default_multi='no') + stm = MasterSlaves('st1', '', [st1, st2]) + st = DynOptionDescription('st', '', [stm], callback=return_list) + od = OptionDescription('od', '', [st]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + owner = api.owner.get() + # + assert api.option('od.stval1.st1val1.st1val1').value.get() == [] + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st1val1').value.set(['yes']) + assert api.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] + assert api.option('od.stval1.st1val1.st2val1', 0).value.get() == 'no' + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + + +def test_masterslaves_submulti_dyndescription(): + st1 = StrOption('st1', "", multi=True) + st2 = StrOption('st2', "", multi=submulti) + stm = MasterSlaves('st1', '', [st1, st2]) + std = DynOptionDescription('st', '', [stm], callback=return_list) + od1 = OptionDescription('od', '', [std]) + od2 = OptionDescription('od', '', [od1]) + api = getapi(Config(od2)) + owner = api.owner.get() + # + assert api.option('od.stval1.st1val1.st1val1').value.get() == [] + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st1val1').value.set(['yes']) + assert api.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] + assert api.option('od.stval1.st1val1.st2val1', 0).value.get() == [] + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st2val1', 0).value.set(['no']) + assert api.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] + assert api.option('od.stval1.st1val1.st2val1', 0).value.get() == ['no'] + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + + +#FIXME DynOptionDescription cannot be MasterSlave #def test_masterslaves_consistency_ip_dyndescription(): -# a = NetworkOption('net', '', multi=True) -# b = NetmaskOption('mask', '', multi=True) -# c = BroadcastOption('broad', '', multi=True) -# b.impl_add_consistency('network_netmask', a) -# c.impl_add_consistency('broadcast', a, b) -# dod = DynOptionDescription('net', '', [a, b, c], callback=return_list) +# neta = NetworkOption('net', '', multi=True) +# maskb = NetmaskOption('mask', '', multi=True) +# broadc = BroadcastOption('broad', '', multi=True) +# maskb.impl_add_consistency('network_netmask', neta) +# broadc.impl_add_consistency('broadcast', neta, maskb) +# dod = DynOptionDescription('net', '', [neta, maskb, broadc], callback=return_list) # dod.impl_set_group_type(groups.master) -# od = OptionDescription('od', '', [dod]) -# cfg = Config(od) -# cfg.netval1.netval1 = ['192.168.1.0'] -# cfg.netval1.maskval1 = ['255.255.255.0'] -# cfg.netval1.broadval1 = ['192.168.1.255'] +# od1 = OptionDescription('od', '', [dod]) +# cfg = Config(od1) +# api.option('netval1.netval1').value.set(['192.168.1.0']) +# api.option('netval1.maskval1').value.set(['255.255.255.0']) +# api.option('netval1.broadval1').value.set(['192.168.1.255']) # -# cfg.netval1.netval1 = ['192.168.1.0', '192.168.2.128'] -# cfg.netval1.maskval1 = ['255.255.255.0', '255.255.255.128'] -# cfg.netval1.broadval1 = ['192.168.1.255', '192.168.2.255'] -# cfg.netval1.broadval1[1] = '192.168.2.255' +# api.option('netval1.netval1').value.set(['192.168.1.0', '192.168.2.128']) +# api.option('netval1.maskval1').value.set(['255.255.255.0', '255.255.255.128']) +# api.option('netval1.broadval1').value.set(['192.168.1.255', '192.168.2.255']) # # # assert cfg.netval1.netval1 == ['192.168.1.0', '192.168.2.128'] # assert cfg.netval1.maskval1 == ['255.255.255.0', '255.255.255.128'] @@ -1130,187 +1004,143 @@ def test_all_dyndescription(): # cfg.netval1.netval1 = ['192.168.1.0'] # api.property.read_only() # raises(PropertiesOptionError, "cfg.netval1.netval1") -# -# -#def test_masterslaves_callback_dyndescription(): -# st1 = StrOption('st1', "", multi=True) -# st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'value': ((st1, False),)}) -# stm = MasterSlaves('st1', '', [st1, st2]) -# #stm.impl_set_group_type(groups.master) -# st = DynOptionDescription('st', '', [stm], callback=return_list) -# od = OptionDescription('od', '', [st]) -# od2 = OptionDescription('od', '', [od]) -# api = getapi(Config(od2)) -# owner = api.owner.get() -# st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1') -# st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1') -# st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2') -# st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2') -# assert api.option.make_dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []} -# assert cfg.od.stval1.st1val1.st1val1 == [] -# assert cfg.od.stval1.st1val1.st2val1 == [] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owners.default -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1) == owners.default -# assert cfg.getowner(st2val2) == owners.default -# # -# cfg.od.stval1.st1val1.st1val1.append('yes') -# assert api.option.make_dict() == {'od.stval1.st1val1.st2val1': ['yes'], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes']} -# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] -# assert cfg.od.stval1.st1val1.st2val1 == ['yes'] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1) == owners.default -# assert cfg.getowner(st2val2) == owners.default -# # -# cfg.od.stval1.st1val1.st2val1 = ['no'] -# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] -# assert cfg.od.stval1.st1val1.st2val1 == ['no'] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1, 0) == owner -## assert cfg.getowner(st2val2) == owners.default -# # -# cfg.od.stval1.st1val1.st1val1.pop(0) -# assert cfg.od.stval1.st1val1.st1val1 == [] -# assert cfg.od.stval1.st1val1.st2val1 == [] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st1val2) == owners.default -## assert cfg.getowner(st2val1) == owner -## assert cfg.getowner(st2val2) == owners.default -# # -# cfg.od.stval1.st1val1.st1val1 = ['yes'] -# cfg.od.stval1.st1val1.st2val1 = ['yes'] -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st2val1, 0) == owner -# del(cfg.od.stval1.st1val1.st2val1) -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1) == owners.default -# assert cfg.getowner(st2val2) == owners.default -# # -# cfg.od.stval1.st1val1.st1val1 = ['yes'] -# cfg.od.stval1.st1val1.st2val1 = ['yes'] -# del(cfg.od.stval1.st1val1.st1val1) -# assert cfg.od.stval1.st1val1.st1val1 == [] -# assert cfg.od.stval1.st1val1.st2val1 == [] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.getowner(st1val1) == owners.default -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1) == owners.default -# assert cfg.getowner(st2val2) == owners.default -# # -# cfg.od.stval1.st1val1.st2val1 = [] -# cfg.od.stval1.st1val1.st1val1 = ['yes'] -# assert cfg.od.stval1.st1val1.st2val1 == ['yes'] -# -# -#def test_masterslaves_callback_value_dyndescription(): -# st1 = StrOption('st1', "", multi=True) -# st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'value': ('val',)}) -# stm = MasterSlaves('st1', '', [st1, st2]) -# #stm.impl_set_group_type(groups.master) -# st = DynOptionDescription('st', '', [stm], callback=return_list) -# od = OptionDescription('od', '', [st]) -# od2 = OptionDescription('od', '', [od]) -# api = getapi(Config(od2)) -# assert cfg.od.stval1.st1val1.st1val1 == [] -# assert cfg.od.stval1.st1val1.st2val1 == [] -# cfg.od.stval1.st1val1.st1val1.append('yes') -# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] -# assert cfg.od.stval1.st1val1.st2val1[0] == 'val' -# assert cfg.od.stval1.st1val1.st2val1 == ['val'] -# -# -#def test_masterslaves_callback_nomulti_dyndescription(): -# v1 = StrOption('v1', '', "val") -# st1 = StrOption('st1', "", multi=True) -# st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'': ((v1, False),)}) -# stm = MasterSlaves('st1', '', [st1, st2]) -# #stm.impl_set_group_type(groups.master) -# st = DynOptionDescription('st', '', [stm], callback=return_list) -# od = OptionDescription('od', '', [st]) -# od2 = OptionDescription('od', '', [od, v1]) -# api = getapi(Config(od2)) -# assert cfg.od.stval1.st1val1.st1val1 == [] -# assert cfg.od.stval1.st1val1.st2val1 == [] -# cfg.od.stval1.st1val1.st1val1.append('yes') -# assert cfg.od.stval1.st1val1.st1val1 == ['yes'] -# assert cfg.od.stval1.st1val1.st2val1 == ['val'] -# -# -#def test_masterslaves_callback_samegroup_dyndescription(): -# st1 = StrOption('st1', "", multi=True) -# st2 = StrOption('st2', "", multi=True) -# st3 = StrOption('st3', "", multi=True, callback=return_dynval, callback_params={'': ((st2, False),)}) -# stm = MasterSlaves('st1', '', [st1, st2, st3]) -# #stm.impl_set_group_type(groups.master) -# st = DynOptionDescription('st', '', [stm], callback=return_list) -# od = OptionDescription('od', '', [st]) -# od2 = OptionDescription('od', '', [od]) -# api = getapi(Config(od2)) -# owner = api.owner.get() -# st1val1 = cfg.unwrap_from_path('od.stval1.st1val1.st1val1') -# st2val1 = cfg.unwrap_from_path('od.stval1.st1val1.st2val1') -# st3val1 = cfg.unwrap_from_path('od.stval1.st1val1.st3val1') -# st1val2 = cfg.unwrap_from_path('od.stval2.st1val2.st1val2') -# st2val2 = cfg.unwrap_from_path('od.stval2.st1val2.st2val2') -# st3val2 = cfg.unwrap_from_path('od.stval2.st1val2.st3val2') -# assert api.option.make_dict() == {'od.stval1.st1val1.st1val1': [], -# 'od.stval1.st1val1.st2val1': [], -# 'od.stval1.st1val1.st3val1': [], -# 'od.stval2.st1val2.st1val2': [], -# 'od.stval2.st1val2.st2val2': [], -# 'od.stval2.st1val2.st3val2': []} -# assert cfg.od.stval1.st1val1.st1val1 == [] -# assert cfg.od.stval1.st1val1.st2val1 == [] -# assert cfg.od.stval1.st1val1.st3val1 == [] -# assert cfg.od.stval2.st1val2.st1val2 == [] -# assert cfg.od.stval2.st1val2.st2val2 == [] -# assert cfg.od.stval2.st1val2.st3val2 == [] -# assert cfg.getowner(st1val1) == owners.default -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1) == owners.default -# assert cfg.getowner(st2val2) == owners.default -# assert cfg.getowner(st3val1) == owners.default -# assert cfg.getowner(st3val2) == owners.default -# ## -# cfg.od.stval1.st1val1.st1val1.append('yes') -# assert api.option.make_dict() == {'od.stval1.st1val1.st1val1': ['yes'], -# 'od.stval1.st1val1.st2val1': [None], -# 'od.stval1.st1val1.st3val1': [None], -# 'od.stval2.st1val2.st1val2': [], -# 'od.stval2.st1val2.st2val2': [], -# 'od.stval2.st1val2.st3val2': []} -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st1val2) == owners.default -# assert cfg.getowner(st2val1) == owners.default -# assert cfg.getowner(st2val2) == owners.default -# assert cfg.getowner(st3val1) == owners.default -# assert cfg.getowner(st3val2) == owners.default -# # -# cfg.od.stval1.st1val1.st2val1[0] = 'yes' -# assert api.option.make_dict() == {'od.stval1.st1val1.st1val1': ['yes'], -# 'od.stval1.st1val1.st2val1': ['yes'], -# 'od.stval1.st1val1.st3val1': ['yes'], -# 'od.stval2.st1val2.st1val2': [], -# 'od.stval2.st1val2.st2val2': [], -# 'od.stval2.st1val2.st3val2': []} -# assert cfg.getowner(st1val1) == owner -# assert cfg.getowner(st2val1, 0) == owner -# assert cfg.getowner(st3val1, 0) == owners.default -# assert cfg.getowner(st1val2) == owners.default -# #assert cfg.getowner(st2val2) == owners.default -# #assert cfg.getowner(st3val2) == owners.default + + +def test_masterslaves_callback_dyndescription(): + st1 = StrOption('st1', "", multi=True) + st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'value': ((st1, False),)}) + stm = MasterSlaves('st1', '', [st1, st2]) + st1 = DynOptionDescription('st', '', [stm], callback=return_list) + od1 = OptionDescription('od', '', [st1]) + od2 = OptionDescription('od', '', [od1]) + api = getapi(Config(od2)) + owner = api.owner.get() + assert api.option.make_dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []} + assert api.option('od.stval1.st1val1.st1val1').value.get() ==[] + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st1val1').value.set(['yes']) + assert api.option.make_dict() == {'od.stval1.st1val1.st2val1': ['yes'], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes']} + assert api.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] + assert api.option('od.stval1.st1val1.st2val1', 0).value.get() == 'yes' + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st2val1', 0).value.set('no') + assert api.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] + assert api.option('od.stval1.st1val1.st2val1', 0).value.get() == 'no' + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st1val1').value.pop(0) + assert api.option('od.stval1.st1val1.st1val1').value.get() == [] + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st1val1').value.set(['yes']) + api.option('od.stval1.st1val1.st2val1', 0).value.set('yes') + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + api.option('od.stval1.st1val1.st2val1', 0).value.reset() + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st1val1').value.set(['yes']) + api.option('od.stval1.st1val1.st2val1', 0).value.set('yes') + api.option('od.stval1.st1val1.st1val1').value.reset() + assert api.option('od.stval1.st1val1.st1val1').value.get() == [] + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st1val1').value.set(['yes']) + assert api.option('od.stval1.st1val1.st2val1', 0).value.get() == 'yes' + + +def test_masterslaves_callback_value_dyndescription(): + st1 = StrOption('st1', "", multi=True) + st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'value': ('val',)}) + stm = MasterSlaves('st1', '', [st1, st2]) + st = DynOptionDescription('st', '', [stm], callback=return_list) + od = OptionDescription('od', '', [st]) + od2 = OptionDescription('od', '', [od]) + api = getapi(Config(od2)) + assert api.option('od.stval1.st1val1.st1val1').value.get() == [] + api.option('od.stval1.st1val1.st1val1').value.set(['yes']) + assert api.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] + api.option('od.stval1.st1val1.st2val1', 0).value.set('val') + assert api.option('od.stval1.st1val1.st2val1', 0).value.get() == 'val' + + +def test_masterslaves_callback_nomulti_dyndescription(): + v11 = StrOption('v1', '', "val") + st1 = StrOption('st1', "", multi=True) + st2 = StrOption('st2', "", multi=True, callback=return_dynval, callback_params={'': ((v11, False),)}) + stm = MasterSlaves('st1', '', [st1, st2]) + stt = DynOptionDescription('st', '', [stm], callback=return_list) + od1 = OptionDescription('od', '', [stt]) + od2 = OptionDescription('od', '', [od1, v11]) + api = getapi(Config(od2)) + assert api.option('od.stval1.st1val1.st1val1').value.get() == [] + api.option('od.stval1.st1val1.st1val1').value.set(['yes']) + assert api.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] + assert api.option('od.stval1.st1val1.st2val1', 0).value.get() == 'val' + + +def test_masterslaves_callback_samegroup_dyndescription(): + st1 = StrOption('st1', "", multi=True) + st2 = StrOption('st2', "", multi=True) + st3 = StrOption('st3', "", multi=True, callback=return_dynval, callback_params={'': ((st2, False),)}) + stm = MasterSlaves('st1', '', [st1, st2, st3]) + stt = DynOptionDescription('st', '', [stm], callback=return_list) + od1 = OptionDescription('od', '', [stt]) + od2 = OptionDescription('od', '', [od1]) + api = getapi(Config(od2)) + owner = api.owner.get() + assert api.option.make_dict() == {'od.stval1.st1val1.st1val1': [], + 'od.stval1.st1val1.st2val1': [], + 'od.stval1.st1val1.st3val1': [], + 'od.stval2.st1val2.st1val2': [], + 'od.stval2.st1val2.st2val2': [], + 'od.stval2.st1val2.st3val2': []} + assert api.option('od.stval1.st1val1.st1val1').value.get() == [] + assert api.option('od.stval2.st1val2.st1val2').value.get() == [] + assert api.option('od.stval1.st1val1.st1val1').owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st1val1').value.set(['yes']) + assert api.option.make_dict() == {'od.stval1.st1val1.st1val1': ['yes'], + 'od.stval1.st1val1.st2val1': [None], + 'od.stval1.st1val1.st3val1': [None], + 'od.stval2.st1val2.st1val2': [], + 'od.stval2.st1val2.st2val2': [], + 'od.stval2.st1val2.st3val2': []} + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.isdefault() + assert api.option('od.stval1.st1val1.st3val1', 0).owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() + # + api.option('od.stval1.st1val1.st2val1', 0).value.set('yes') + assert api.option.make_dict() == {'od.stval1.st1val1.st1val1': ['yes'], + 'od.stval1.st1val1.st2val1': ['yes'], + 'od.stval1.st1val1.st3val1': ['yes'], + 'od.stval2.st1val2.st1val2': [], + 'od.stval2.st1val2.st2val2': [], + 'od.stval2.st1val2.st3val2': []} + assert api.option('od.stval1.st1val1.st1val1').owner.get() == owner + assert api.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner + assert api.option('od.stval1.st1val1.st3val1', 0).owner.isdefault() + assert api.option('od.stval2.st1val2.st1val2').owner.isdefault() def test_invalid_conflict_dyndescription(): @@ -1349,19 +1179,19 @@ def test_nocallback_dyndescription(): raises(ConfigError, "DynOptionDescription('dod', '', [st, st2])") -#def test_invalid_samevalue_dyndescription(): -# st = StrOption('st', '') -# dod = DynOptionDescription('dod', '', [st], callback=return_same_list) -# od = OptionDescription('od', '', [dod]) -# cfg = Config(od) -# cfg -# raises(ConfigError, "print(cfg)") -# -# -#def test_invalid_name_dyndescription(): -# st = StrOption('st', '') -# dod = DynOptionDescription('dod', '', [st], callback=return_wrong_list) -# od = OptionDescription('od', '', [dod]) -# cfg = Config(od) -# cfg -# raises(ValueError, "print(cfg)") +def test_invalid_samevalue_dyndescription(): + st1 = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st1], callback=return_same_list) + od1 = OptionDescription('od', '', [dod]) + cfg = Config(od1) + api = getapi(cfg) + raises(ConfigError, "api.option.make_dict()") + + +def test_invalid_name_dyndescription(): + st1 = StrOption('st', '') + dod = DynOptionDescription('dod', '', [st1], callback=return_wrong_list) + od1 = OptionDescription('od', '', [dod]) + cfg = Config(od1) + api = getapi(cfg) + raises(ValueError, "api.option.make_dict()") diff --git a/test/test_parsing_group.py b/test/test_masterslaves.py similarity index 97% rename from test/test_parsing_group.py rename to test/test_masterslaves.py index bdf3c72..9307273 100644 --- a/test/test_parsing_group.py +++ b/test/test_masterslaves.py @@ -604,3 +604,23 @@ def test_wrong_index(): raises(APIError, "api.option('od.ip_admin_eth0', 0).option.get()") assert api.option('od').option.get() raises(APIError, "api.option('od', 0).option.get()") + + +def test_without_master_or_slave(): + raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [])") + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1']) + raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0])") + #empty optiondescription is allowed + OptionDescription('ip_admin_eth0', '', []) + + +def test_master_not_multi(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé") + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) + raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])") + + +def test_slave_not_multi(): + ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) + netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau") + raises(ValueError, "MasterSlaves('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])") diff --git a/test/test_option_calculation.py b/test/test_option_callback.py similarity index 98% rename from test/test_option_calculation.py rename to test/test_option_callback.py index 9f26693..6162a72 100644 --- a/test/test_option_calculation.py +++ b/test/test_option_callback.py @@ -704,6 +704,19 @@ def test_callback_master_and_slaves_master_list(): assert api.option('val1.val2', 0).value.get() == None +def test_callback_master_and_slaves_master_slave_list(): + val1 = StrOption('val1', "", multi=True) + val2 = StrOption('val2', "", multi=True, callback=return_list) + interface1 = MasterSlaves('val1', '', [val1, val2]) + #interface1.impl_set_group_type(groups.master) + maconfig = OptionDescription('rootconfig', '', [interface1]) + api = getapi(Config(maconfig)) + api.property.read_write() + assert api.option('val1.val1').value.get() == [] + api.option('val1.val1').value.set(['val1']) + raises(SlaveError, "api.option('val1.val2', 0).value.get()") + + def test_callback_master_and_slaves_slave(): val1 = StrOption('val1', "", multi=True) val2 = StrOption('val2', "", multi=True, callback=return_val) diff --git a/tiramisu/api.py b/tiramisu/api.py index 4a8a892..25744e6 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -429,8 +429,9 @@ class TiramisuOptionProperty(CommonTiramisuOption): def reset(self): """reset all personalised properties""" self._get_option() - self.settings.reset(opt=self.config_bag.option, - path=self.path) + self.settings.reset(self.config_bag.option, + self.path, + self.config_bag) class TiramisuOptionPermissive(CommonTiramisuOption): @@ -470,12 +471,14 @@ class TiramisuOptionPermissive(CommonTiramisuOption): opt = self._opt self.settings.setpermissive(opt=opt, path=path, + config_bag=self.config_bag, permissive=permissives) else: path = self.path opt = self._get_option() self.settings.setpermissive(opt=opt, path=path, + config_bag=self.config_bag, permissives=permissives) @count @@ -815,7 +818,9 @@ class TiramisuContextProperty(TiramisuContext): @count def reset(self): """remove configuration properties""" - self.config_bag.config.cfgimpl_get_settings().reset() + self.config_bag.config.cfgimpl_get_settings().reset(None, + None, + None) @count def exportation(self): diff --git a/tiramisu/autolib.py b/tiramisu/autolib.py index aeadd47..24f1d87 100644 --- a/tiramisu/autolib.py +++ b/tiramisu/autolib.py @@ -149,7 +149,7 @@ def carry_out_calculation(option, # if callback_params has a callback, launch several time calculate() master_slave = False # multi's option should have same value for all option - if option._is_subdyn(): + if option.issubdyn(): kwargs['suffix'] = option.impl_getsuffix() for key, callbacks in callback_params.items(): for callbk in callbacks: @@ -167,7 +167,7 @@ def carry_out_calculation(option, else: # callbk is something link (opt, True|False) opt, force_permissive = callbk - if opt._is_subdyn(): + if opt.issubdyn(): opt = DynSymLinkOption(opt, option._rootpath, option.impl_getsuffix()) @@ -224,18 +224,18 @@ def carry_out_calculation(option, if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \ option.impl_is_master_slaves('slave'): if args or kwargs: - raise SlaveError(_('function "{}" return the list "{}" for the slave option "{}"' - '').format(callback.__name__, - ret, - option.impl_getname())) - else: raise SlaveError(_('function "{}" with arguments "{}" and "{}" ' 'return the list "{}" for the slave option "{}"' '').format(callback.__name__, args, kwargs, - value, + ret, option.impl_get_display_name())) + else: + raise SlaveError(_('function "{}" return the list "{}" for the slave option "{}"' + '').format(callback.__name__, + ret, + option.impl_getname())) return ret diff --git a/tiramisu/config.py b/tiramisu/config.py index 774f63a..da8493f 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -83,59 +83,77 @@ class SubConfig(object): return self._impl_length def reset_one_option_cache(self, + desc, values, settings, resetted_opts, + config_bag, opt, path): - opt.reset_cache(opt, - path, + if path in resetted_opts: + return + resetted_opts.append(path) + for woption in opt._get_dependencies(self): + option = woption() + if option.impl_is_dynoptiondescription(): + for doption in option.get_syndynoptiondescriptions(config_bag): + doption_path = doption.impl_getpath(self) + self.reset_one_option_cache(desc, + values, + settings, + resetted_opts, + config_bag, + doption, + doption_path) + elif option.issubdyn(): + for doption in desc.build_dynoptions(option, config_bag): + doption_path = doption.impl_getpath(self) + self.reset_one_option_cache(desc, + values, + settings, + resetted_opts, + config_bag, + doption, + doption_path) + else: + option_path = option.impl_getpath(self) + self.reset_one_option_cache(desc, + values, + settings, + resetted_opts, + config_bag, + option, + option_path) + del option + opt.reset_cache(path, values, settings, resetted_opts) - for woption in opt._get_dependencies(self): - option = woption() - option_path = option.impl_getpath(self) - if option_path in resetted_opts: - continue - self.reset_one_option_cache(values, - settings, - resetted_opts, - option, - option_path) - del option def cfgimpl_reset_cache(self, - only_expired=False, - opt=None, - path=None, + opt, + path, + config_bag, resetted_opts=None): """reset all settings in cache - - :param only_expired: if True reset only expired cached values - :type only_expired: boolean """ if resetted_opts is None: resetted_opts = [] context = self.cfgimpl_get_context() + desc = context.cfgimpl_get_description() values = context.cfgimpl_get_values() settings = context.cfgimpl_get_settings() if not None in (opt, path): - if path not in resetted_opts: - self.reset_one_option_cache(values, - settings, - resetted_opts, - opt, - path) - - elif only_expired: - # reset cache for expired cache value ony - datetime = int(time()) - values._p_.reset_expired_cache(datetime) - settings._p_.reset_expired_cache(datetime) + self.reset_one_option_cache(desc, + values, + settings, + resetted_opts, + config_bag, + opt, + path) else: values._p_.reset_all_cache() settings._p_.reset_all_cache() @@ -862,21 +880,25 @@ class GroupConfig(_CommonConfig): return self._impl_children def cfgimpl_reset_cache(self, - only_expired=False, - opt=None, - path=None, + opt, + path, + config_bag, resetted_opts=None): if resetted_opts is None: resetted_opts = [] if isinstance(self, MetaConfig): - super(GroupConfig, self).cfgimpl_reset_cache(only_expired=only_expired, - opt=opt, - path=path, + super(GroupConfig, self).cfgimpl_reset_cache(opt, + path, + config_bag=config_bag, resetted_opts=copy(resetted_opts)) for child in self._impl_children: - child.cfgimpl_reset_cache(only_expired=only_expired, - opt=opt, - path=path, + if config_bag is None: + nconfig_bag = config_bag + else: + nconfig_bag = config_bag.copy('nooption') + child.cfgimpl_reset_cache(opt, + path, + config_bag=nconfig_bag, resetted_opts=copy(resetted_opts)) def set_value(self, diff --git a/tiramisu/option/baseoption.py b/tiramisu/option/baseoption.py index d88d2d1..0727a34 100644 --- a/tiramisu/option/baseoption.py +++ b/tiramisu/option/baseoption.py @@ -369,10 +369,16 @@ class Base(object): if extra is not None: _setattr(self, '_extra', tuple([tuple(extra.keys()), tuple(extra.values())])) - def _impl_setsubdyn(self, - subdyn): + def _setsubdyn(self, + subdyn): self._subdyn = weakref.ref(subdyn) + def issubdyn(self): + return getattr(self, '_subdyn', None) is not None + + def getsubdyn(self): + return self._subdyn() + def impl_getrequires(self): return getattr(self, '_requires', STATIC_TUPLE) @@ -477,9 +483,6 @@ class BaseOption(Base): "to know if a callback has been defined or not" return self.impl_get_callback()[0] is not None - def _is_subdyn(self): - return getattr(self, '_subdyn', None) is not None - def _impl_valid_string(self, value): if not isinstance(value, str): @@ -496,18 +499,14 @@ class BaseOption(Base): return name def reset_cache(self, - opt, path, values, settings, resetted_opts): - if opt in resetted_opts: - return settings._p_.delcache(path) settings._pp_.delcache(path) - if not opt.impl_is_optiondescription(): + if not self.impl_is_optiondescription(): values._p_.delcache(path) - resetted_opts.append(path) def impl_is_symlinkoption(self): return False diff --git a/tiramisu/option/dynoptiondescription.py b/tiramisu/option/dynoptiondescription.py index a9c4c98..127c7d8 100644 --- a/tiramisu/option/dynoptiondescription.py +++ b/tiramisu/option/dynoptiondescription.py @@ -26,6 +26,7 @@ from .optiondescription import OptionDescription from ..setting import groups, undefined from ..error import ConfigError from ..autolib import carry_out_calculation +from .syndynoptiondescription import SynDynOptionDescription NAME_REGEXP = re.compile(r'^[a-zA-Z\d\-_]*$') @@ -42,11 +43,11 @@ class DynOptionDescription(OptionDescription): callback=None, callback_params=None): - super(DynOptionDescription, self).__init__(name, - doc, - children, - requires, - properties) + super().__init__(name, + doc, + children, + requires, + properties) # check children + set relation to this dynoptiondescription for child in children: if isinstance(child, OptionDescription): @@ -54,11 +55,11 @@ class DynOptionDescription(OptionDescription): raise ConfigError(_('cannot set optiondescription in a ' 'dynoptiondescription')) for chld in child.impl_getchildren(config_bag=undefined): - chld._impl_setsubdyn(self) + chld._setsubdyn(self) if child.impl_is_symlinkoption(): raise ConfigError(_('cannot set symlinkoption in a ' 'dynoptiondescription')) - child._impl_setsubdyn(self) + child._setsubdyn(self) # add callback self.impl_set_callback(callback, callback_params) @@ -91,3 +92,10 @@ class DynOptionDescription(OptionDescription): '').format(val, self.impl_get_display_name())) return values + + def get_syndynoptiondescriptions(self, config_bag): + subpath = self.impl_getpath(config_bag.config).rsplit('.', 1)[0] + for suffix in self._impl_get_suffixes(config_bag): + yield SynDynOptionDescription(self, + subpath, + suffix) diff --git a/tiramisu/option/masterslave.py b/tiramisu/option/masterslave.py index 98f3960..92c13cd 100644 --- a/tiramisu/option/masterslave.py +++ b/tiramisu/option/masterslave.py @@ -23,7 +23,7 @@ import weakref from ..i18n import _ -from ..setting import groups, undefined, log, debug +from ..setting import groups, undefined from .optiondescription import OptionDescription from .option import Option from ..error import SlaveError, PropertiesOptionError @@ -46,15 +46,10 @@ class MasterSlaves(OptionDescription): properties=properties) self._group_type = groups.master slaves = [] + if len(children) < 2: + raise ValueError(_('a master and a slave and mandatory in masterslaves "{}"').format(name)) master = children[0] - if not children: - raise ValueError(_('children is mandatory in masterslaves "{}"').format(name)) for idx, child in enumerate(children): - if idx != 0 and child.impl_getdefault() != []: - raise ValueError(_('not allowed default value for option "{0}" ' - 'in master/slave object "{1}"' - '').format(child.impl_get_display_name(), - self.impl_get_display_name())) if child.impl_is_symlinkoption(): # pragma: optional cover raise ValueError(_('master group "{0}" shall not have ' "a symlinkoption").format(self.impl_get_display_name())) @@ -62,9 +57,12 @@ class MasterSlaves(OptionDescription): raise ValueError(_('master group "{0}" shall not have ' 'a subgroup').format(self.impl_get_display_name())) if not child.impl_is_multi(): # pragma: optional cover - raise ValueError(_('not allowed option "{0}" ' - 'in group "{1}"' - ': this option is not a multi' + raise ValueError(_('only multi option allowed in master group "{0}" but option ' + '"{1}" is not a multi').format(self.impl_get_display_name(), + child.impl_get_display_name())) + if idx != 0 and child.impl_getdefault() != []: + raise ValueError(_('not allowed default value for option "{0}" ' + 'in master/slave object "{1}"' '').format(child.impl_get_display_name(), self.impl_get_display_name())) # no empty property for save @@ -144,27 +142,37 @@ class MasterSlaves(OptionDescription): idx) def reset_cache(self, - opt, path, values, settings, resetted_opts): + master = self.getmaster() + slaves = self.getslaves() + self._reset_cache(master, + slaves, + values, + settings, + resetted_opts) + + def _reset_cache(self, + master, + slaves, + values, + settings, + resetted_opts): context = values._getcontext() - #FIXME pb avec dyn, devrait etre une option - mopt = self.getmaster() - mpath = mopt.impl_getpath(context) - mopt.reset_cache(mopt, - mpath, - values, - settings, - resetted_opts) - for slave in self.getslaves(): + mpath = master.impl_getpath(context) + master.reset_cache(mpath, + values, + settings, + None) + for slave in slaves: spath = slave.impl_getpath(context) - slave.reset_cache(slave, - spath, + slave.reset_cache(spath, values, settings, - resetted_opts) + None) + resetted_opts.append(spath) def impl_validate_value(self, option, diff --git a/tiramisu/option/option.py b/tiramisu/option/option.py index db43e98..6a8c051 100644 --- a/tiramisu/option/option.py +++ b/tiramisu/option/option.py @@ -375,8 +375,8 @@ class Option(OnlyOption): other_opts, init=True, func=None): - if self._is_subdyn(): - dynod = self._subdyn() + if self.issubdyn(): + dynod = self.getsubdyn() else: dynod = None if self.impl_is_submulti(): @@ -389,11 +389,11 @@ class Option(OnlyOption): raise ConfigError(_('cannot add consistency with submulti option')) if not isinstance(opt, Option): raise ConfigError(_('consistency must be set with an option, not {}').format(opt)) - if opt._is_subdyn(): + if opt.issubdyn(): if dynod is None: raise ConfigError(_('almost one option in consistency is ' 'in a dynoptiondescription but not all')) - subod = opt._subdyn() + subod = opt.getsubdyn() if dynod != subod: raise ConfigError(_('option in consistency must be in same' ' dynoptiondescription')) diff --git a/tiramisu/option/optiondescription.py b/tiramisu/option/optiondescription.py index d2aa1ef..6f103e5 100644 --- a/tiramisu/option/optiondescription.py +++ b/tiramisu/option/optiondescription.py @@ -23,7 +23,7 @@ from copy import copy from ..i18n import _ from ..setting import ConfigBag, groups, undefined, owners -from .baseoption import BaseOption +from .baseoption import BaseOption, OnlyOption from .option import ALLOWED_CONST_LIST, DynSymLinkOption from .syndynoptiondescription import SynDynOptionDescription from ..error import ConfigError, ConflictError @@ -172,7 +172,7 @@ class CacheOptionDescription(BaseOption): # problem with index raise ConfigError(_('a slave ({0}) cannot have ' 'force_store_value property').format(subpath)) - if option._is_subdyn(): + if option.issubdyn(): raise ConfigError(_('a dynoption ({0}) cannot have ' 'force_store_value property').format(subpath)) if not values._p_.hasvalue(subpath): @@ -225,6 +225,31 @@ class CacheOptionDescription(BaseOption): class OptionDescriptionWalk(CacheOptionDescription): __slots__ = ('_children',) + def build_dynoptions(self, + option, + config_bag): + dynopt = option.getsubdyn() + rootpath = self.impl_get_path_by_opt(dynopt) + if rootpath == '': + ori_index = 0 + else: + ori_index = len(rootpath) + 1 + subpaths = option.impl_getpath(config_bag.config)[ori_index:].split('.')[:-1] + if subpaths != ['']: + subpaths = [rootpath] + subpaths + else: + subpaths = [rootpath] + for suffix in dynopt._impl_get_suffixes(config_bag): + subpath = '.'.join([subp + suffix for subp in subpaths]) + if isinstance(option, OnlyOption): + yield DynSymLinkOption(option, + subpath, + suffix) + else: + yield SynDynOptionDescription(option, + subpath, + suffix) + def impl_get_options_paths(self, bytype, byname, @@ -233,51 +258,24 @@ class OptionDescriptionWalk(CacheOptionDescription): config_bag): find_results = [] - def _rebuild_dynpath(path, - suffix, - dynopt): - found = False - spath = path.split('.') - for length in range(1, len(spath)): - subpath = '.'.join(spath[0:length]) - subopt = self.impl_get_opt_by_path(subpath) - if dynopt == subopt: - found = True - break - if not found: # pragma: no cover - raise ConfigError(_('cannot find dynpath')) - subpath = subpath + suffix - for slength in range(length, len(spath)): - subpath = subpath + '.' + spath[slength] + suffix - return subpath - def _filter_by_name(path, option): name = option.impl_getname() - if option._is_subdyn(): + if option.issubdyn(): found = False if byname.startswith(name): - subdyn = option._subdyn() - for suffix in subdyn._impl_get_suffixes(config_bag): - if byname == name + suffix: + for doption in self.build_dynoptions(option, config_bag): + if byname == doption.impl_getname(): + dpath = doption.impl_getpath(config_bag.config) + find_results.append((dpath, doption)) found = True - path = _rebuild_dynpath(path, - suffix, - subdyn) - if '.' in path: - subpath = path.rsplit('.', 1)[0] - else: - subpath = '' - option = DynSymLinkOption(option, - subpath, - suffix) break if not found: return False else: if not byname == name: return False - find_results.append((path, option)) + find_results.append((path, option)) return True def _filter_by_type(path, @@ -287,20 +285,10 @@ class OptionDescriptionWalk(CacheOptionDescription): #if byname is not None, check option byname in _filter_by_name #not here if byname is None: - if option._is_subdyn(): - name = option.impl_getname() - for suffix in option._subdyn._impl_get_suffixes(config_bag): - path = _rebuild_dynpath(path, - suffix, - option._subdyn) - if '.' in path: - subpath = path.rsplit('.', 1)[0] - else: - subpath = '' - doption = DynSymLinkOption(option, - subpath, - suffix) - find_results.append((subpath, doption)) + if option.issubdyn(): + for doption in self.build_dynoptions(option, config_bag): + dpath = doption.impl_getname(config_bag.config) + find_results.append((dpath, doption)) else: find_results.append((path, option)) return True @@ -322,22 +310,12 @@ class OptionDescriptionWalk(CacheOptionDescription): if _subpath is not None and not path.startswith(_subpath + '.'): continue if bytype == byname is None: - if option._is_subdyn(): - name = option.impl_getname() - for suffix in option._subdyn._impl_get_suffixes(config_bag): - path = _rebuild_dynpath(path, - suffix, - option._subdyn) - if '.' in path: - subpath = path.rsplit('.', 1)[0] - else: - subpath = '' - doption = DynSymLinkOption(option, - subpath, - suffix) - find_results.append((path, doption)) + if option.issubdyn(): + for doption in self.build_dynoptions(option, config_bag): + dpath = doption.impl_getpath(config_bag.config) + find_results.append((dpath, doption)) else: - find_results.append((path, option)) + find_results.append((dpath, option)) else: if _filter(path, option) is False: continue @@ -381,24 +359,23 @@ class OptionDescriptionWalk(CacheOptionDescription): def impl_getchildren(self, config_bag, - context=None, dyn=True): - cname = None + subpath = None for child in self._impl_st_getchildren(): if dyn and child.impl_is_dynoptiondescription(): - if context is None: + if config_bag.config is None: raise ConfigError(_('need context')) - if cname is None: - if context.cfgimpl_get_description() == self: - cname = '' + if subpath is None: + if config_bag.config.cfgimpl_get_description() == self: + subpath = '' else: - cname = self.impl_getpath(context) + subpath = self.impl_getpath(config_bag.config) sconfig_bag = config_bag.copy('nooption') sconfig_bag.option = child - for value in child._impl_get_suffixes(sconfig_bag): + for suffix in child._impl_get_suffixes(sconfig_bag): yield SynDynOptionDescription(child, - cname, - value) + subpath, + suffix) else: yield child diff --git a/tiramisu/option/symlinkoption.py b/tiramisu/option/symlinkoption.py index 88835a0..10fd849 100644 --- a/tiramisu/option/symlinkoption.py +++ b/tiramisu/option/symlinkoption.py @@ -55,37 +55,12 @@ class SymLinkOption(OnlyOption): def impl_getopt(self): return self._opt - #def impl_get_information(self, - # key, - # default=undefined): - # return self._opt.impl_get_information(key, default) - def impl_is_readonly(self): return True - #def impl_getproperties(self): - # return self._opt.impl_getproperties() - - #def impl_get_callback(self): - # return self._opt.impl_get_callback() - - #def impl_has_callback(self): - # "to know if a callback has been defined or not" - # return self._opt.impl_has_callback() - - #def impl_is_multi(self): - # return self._opt.impl_is_multi() - - #def _is_subdyn(self): - # return getattr(self._opt, '_subdyn', None) is not None - def get_consistencies(self): return () - def _has_consistencies(self, - context): - return option._opt._has_consistencies(context) - class DynSymLinkOption(object): __slots__ = ('_rootpath', @@ -110,7 +85,6 @@ class DynSymLinkOption(object): return self._opt == left._opt and \ self._rootpath == left._rootpath and \ self._suffix == left._suffix - return True def impl_getname(self): return self._opt.impl_getname() + self._suffix @@ -126,8 +100,6 @@ class DynSymLinkOption(object): def impl_getpath(self, context): - if self._rootpath == '': - return self.impl_getname() return self._rootpath + '.' + self.impl_getname() def impl_validate(self, diff --git a/tiramisu/option/syndynoptiondescription.py b/tiramisu/option/syndynoptiondescription.py index cbf53d5..c310968 100644 --- a/tiramisu/option/syndynoptiondescription.py +++ b/tiramisu/option/syndynoptiondescription.py @@ -19,7 +19,7 @@ # the whole pypy projet is under MIT licence # ____________________________________________________________ from ..i18n import _ -from ..setting import undefined +from ..setting import groups, undefined from .symlinkoption import DynSymLinkOption @@ -32,7 +32,6 @@ class SynDynOptionDescription(object): opt, subpath, suffix): - self._opt = opt self._subpath = subpath self._suffix = suffix @@ -68,13 +67,13 @@ class SynDynOptionDescription(object): config_bag, dyn=True): children = [] - subpath = self.impl_getpath() + subpath = self.impl_getpath(config_bag.config) for child in self._opt.impl_getchildren(config_bag): yield(self._opt._impl_get_dynchild(child, self._suffix, subpath)) - def impl_getpath(self): + def impl_getpath(self, context): subpath = self._subpath if subpath != '': subpath += '.' @@ -83,16 +82,35 @@ class SynDynOptionDescription(object): def getmaster(self): master = self._opt.getmaster() return DynSymLinkOption(master, - self.impl_getpath(), + self.impl_getpath(None), self._suffix) def getslaves(self): - subpath = self.impl_getpath() + subpath = self.impl_getpath(None) for slave in self._opt.getslaves(): yield DynSymLinkOption(slave, subpath, self._suffix) + def reset_cache(self, + path, + values, + settings, + resetted_opts): + if self.impl_get_group_type() == groups.master: + master = self.getmaster() + slaves = self.getslaves() + self._reset_cache(master, + slaves, + values, + settings, + resetted_opts) + else: + self._opt.reset_cache(path, + values, + settings, + resetted_opts) + def pop(self, *args, **kwargs): diff --git a/tiramisu/setting.py b/tiramisu/setting.py index ce16917..e1a8b8f 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -600,15 +600,21 @@ class Settings(object): self._p_.setproperties(path, properties) #values too because of slave values could have a PropertiesOptionError has value - self._getcontext().cfgimpl_reset_cache(opt=opt, - path=path) + self._getcontext().cfgimpl_reset_cache(opt, + path, + config_bag) - def set_context_permissive(self, permissive): - self.setpermissive(None, None, permissive) + def set_context_permissive(self, + permissive): + self.setpermissive(None, + None, + None, + permissive) def setpermissive(self, opt, path, + config_bag, permissives): """ enables us to put the permissives in the storage @@ -631,15 +637,17 @@ class Settings(object): raise ConfigError(_('cannot add those permissives: {0}').format( ' '.join(forbidden_permissives))) self._pp_.setpermissive(path, permissives) - self._getcontext().cfgimpl_reset_cache(opt=opt, - path=path) + self._getcontext().cfgimpl_reset_cache(opt, + path, + config_bag) #____________________________________________________________ # reset methods def reset(self, - opt=None, - path=None, + opt, + path, + config_bag, all_properties=False): if self._getcontext().cfgimpl_get_meta() is not None: raise ConfigError(_('cannot change property with metaconfig')) @@ -655,8 +663,9 @@ class Settings(object): if opt is not None and path is None: path = opt.impl_getpath(self._getcontext()) self._p_.delproperties(path) - self._getcontext().cfgimpl_reset_cache(opt=opt, - path=path) + self._getcontext().cfgimpl_reset_cache(opt, + path, + config_bag) #____________________________________________________________ # validate properties diff --git a/tiramisu/value.py b/tiramisu/value.py index c6ca796..cabe51d 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -205,8 +205,9 @@ class Values(object): if is_cache and cache_value == _value: return # calculated value is a new value, so reset cache - context.cfgimpl_reset_cache(opt=opt, - path=path) + context.cfgimpl_reset_cache(opt, + path, + config_bag) if opt.impl_is_master_slaves('slave'): index_ = index @@ -409,8 +410,9 @@ class Values(object): config_bag, commit=True): - self._getcontext().cfgimpl_reset_cache(opt=config_bag.option, - path=path) + self._getcontext().cfgimpl_reset_cache(config_bag.option, + path, + config_bag) if isinstance(value, list): # copy value = list(value) @@ -601,8 +603,9 @@ class Values(object): else: self._p_.resetvalue(path, _commit) - context.cfgimpl_reset_cache(opt=opt, - path=path) + context.cfgimpl_reset_cache(config_bag.option, + path, + config_bag) def reset_slave(self, path, @@ -627,8 +630,9 @@ class Values(object): value, config_bag) self._p_.resetvalue_index(path, index) - context.cfgimpl_reset_cache(opt=config_bag.option, - path=path) + context.cfgimpl_reset_cache(config_bag.option, + path, + config_bag) def reset_master(self, subconfig,