From 9831f7cf0cd27c7974e7b63e7f411fd1c346a5f7 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Tue, 28 Nov 2017 22:42:30 +0100 Subject: [PATCH] add test for master/slave and callback --- test/api/test_owner.py | 499 ++++++++++++++++++++------- tiramisu/api.py | 51 +++ tiramisu/autolib.py | 39 ++- tiramisu/config.py | 265 +++++++------- tiramisu/option/baseoption.py | 2 +- tiramisu/option/option.py | 55 +-- tiramisu/option/optiondescription.py | 266 +++++++------- tiramisu/setting.py | 28 +- tiramisu/storage/dictionary/value.py | 31 +- tiramisu/value.py | 18 +- 10 files changed, 808 insertions(+), 446 deletions(-) diff --git a/test/api/test_owner.py b/test/api/test_owner.py index 9c74c2b..d1fe343 100644 --- a/test/api/test_owner.py +++ b/test/api/test_owner.py @@ -10,6 +10,7 @@ from tiramisu import Config, MetaConfig, \ StrOption, OptionDescription, MasterSlaves, DynOptionDescription, \ getapi, submulti, undefined, owners from tiramisu.error import PropertiesOptionError, APIError, ConfigError +from tiramisu.api import display_count from collections import OrderedDict ICON = u'\u2937' @@ -45,6 +46,10 @@ def return_list(val=None, suffix=None): return ['val1', 'val2'] +def return_str(val, suffix=None): + return val + + def display_info(func): def wrapper(*args, **kwargs): if DISPLAY: @@ -151,8 +156,8 @@ def autocheck_default_owner(api, path, confread, confwrite, **kwargs): raises(PropertiesOptionError, "api.config(conf).option(path, 0).owner.get()") assert api.forcepermissive.config(conf).option(path, 0).owner.get() == 'default' # - assert api.config(conf).option(path, 0).owner.isdefault() - raises(PropertiesOptionError, "api.forcepermissive.config(conf).option(path, 0).owner.isdefault()") + raises(PropertiesOptionError, "api.config(conf).option(path, 0).owner.isdefault()") + assert api.forcepermissive.config(conf).option(path, 0).owner.isdefault() else: raises(PropertiesOptionError, "api.config(conf).option(path, 0).owner.get()") raises(PropertiesOptionError, "api.forcepermissive.config(conf).option(path, 0).owner.get()") @@ -168,13 +173,6 @@ def autocheck_default_owner(api, path, confread, confwrite, **kwargs): do(confwrite) -def _getdefault(api, path, multi, isslave, submulti_): - empty_value = api.unrestraint.option(path).option.getdefault() - if isslave and empty_value == []: - empty_value = api.unrestraint.option(path).option.getdefaultmulti() - return empty_value - - def _autocheck_default_value(api, path, conf, **kwargs): """set and get values """ @@ -184,7 +182,7 @@ def _autocheck_default_value(api, path, conf, **kwargs): isslave = api.unrestraint.option(path).option.isslave() # set default value (different if value is multi or not) - empty_value = _getdefault(api, path, multi, isslave, submulti_) + empty_value = kwargs['default'] # test default value (should be empty) # cannot test for slave (we cannot get all values for a slave) @@ -221,7 +219,7 @@ def autocheck_default_value(api, path, confread, confwrite, **kwargs): -def _autocheck_set_value(api, path, conf, **kwargs): +def _set_value(api, path, conf, **kwargs): set_permissive = kwargs.get('set_permissive', True) multi = api.unrestraint.option(path).option.ismulti() submulti_ = api.unrestraint.option(path).option.issubmulti() @@ -230,9 +228,16 @@ def _autocheck_set_value(api, path, conf, **kwargs): if not multi: first_value = FIRST_VALUE elif submulti_ is False: - first_value = LIST_FIRST_VALUE + if not isslave: + first_value = LIST_FIRST_VALUE + else: + second_value = LIST_SECOND_VALUE[1] + else: - first_value = SUBLIST_FIRST_VALUE + if not isslave: + first_value = SUBLIST_FIRST_VALUE + else: + second_value = SUBLIST_SECOND_VALUE[1] # for slave should have an index and good length # for master must append, not set @@ -255,19 +260,19 @@ def _autocheck_set_value(api, path, conf, **kwargs): elif isslave: if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): if not set_permissive: - api.config(conf).option(path, 0).value.set(first_value[0]) + api.config(conf).option(path, 1).value.set(second_value) else: - api.forcepermissive.config(conf).option(path, 0).value.set(first_value[0]) + api.forcepermissive.config(conf).option(path, 1).value.set(second_value) elif not kwargs.get('propertyerror', False): - raises(PropertiesOptionError, "api.config(conf).option(path, 0).value.set(first_value[0])") + raises(PropertiesOptionError, "api.config(conf).option(path, 1).value.set(second_value)") if set_permissive: - api.forcepermissive.config(conf).option(path, 0).value.set(first_value[0]) + api.forcepermissive.config(conf).option(path, 1).value.set(second_value) else: - raises(PropertiesOptionError, "api.config(conf).option(path, 0).value.set(first_value[0])") + raises(PropertiesOptionError, "api.config(conf).option(path, 1).value.set(second_value)") raises(PropertiesOptionError, - "api.forcepermissive.config(conf).option(path, 0).value.set(first_value[0])") + "api.forcepermissive.config(conf).option(path, 1).value.set(second_value)") raises(APIError, - "api.unrestraint.config(conf).option(path).value.set([first_value[0], first_value[1]])") + "api.unrestraint.config(conf).option(path).value.set([second_value, second_value])") else: if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): @@ -287,7 +292,7 @@ def _autocheck_set_value(api, path, conf, **kwargs): @autocheck def autocheck_set_value(api, path, confread, confwrite, **kwargs): - _autocheck_set_value(api, path, confwrite, **kwargs) + _set_value(api, path, confwrite, **kwargs) @autocheck @@ -295,7 +300,8 @@ def autocheck_get_value_permissive(api, path, confread, confwrite, **kwargs): multi = api.unrestraint.option(path).option.ismulti() submulti_ = api.unrestraint.option(path).option.issubmulti() isslave = api.unrestraint.option(path).option.isslave() - _autocheck_set_value(api, path, confwrite, **kwargs) + _set_value(api, path, confwrite, **kwargs) + empty_value = kwargs['default'] if not multi: first_value = FIRST_VALUE elif submulti_ is False: @@ -307,14 +313,27 @@ def autocheck_get_value_permissive(api, path, confread, confwrite, **kwargs): # get value after set value without permissive if isslave: if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): - assert api.config(conf).option(path, 0).value.get() == first_value[0] - assert api.forcepermissive.config(conf).option(path, 0).value.get() == first_value[0] + assert api.config(conf).option(path, 0).value.get() == empty_value + assert api.forcepermissive.config(conf).option(path, 0).value.get() == empty_value + if submulti_: + assert api.config(conf).option(path, 1).value.get() == SUBLIST_SECOND_VALUE[1] + assert api.forcepermissive.config(conf).option(path, 1).value.get() == SUBLIST_SECOND_VALUE[1] + else: + assert api.config(conf).option(path, 1).value.get() == LIST_SECOND_VALUE[1] + assert api.forcepermissive.config(conf).option(path, 1).value.get() == LIST_SECOND_VALUE[1] elif kwargs.get('permissive', False): - raises(PropertiesOptionError, "api.config(conf).option(path, 0).value.get()") - assert api.forcepermissive.config(conf).option(path, 0).value.get() == first_value + raises(PropertiesOptionError, "assert api.config(conf).option(path, 0).value.get()") + raises(PropertiesOptionError, "assert api.config(conf).option(path, 1).value.get()") + assert api.forcepermissive.config(conf).option(path, 0).value.get() == empty_value + if submulti_: + assert api.forcepermissive.config(conf).option(path, 1).value.get() == SUBLIST_SECOND_VALUE[1] + else: + assert api.forcepermissive.config(conf).option(path, 1).value.get() == LIST_SECOND_VALUE[1] else: - raises(PropertiesOptionError, "api.config(conf).option(path, 0).value.get()") - raises(PropertiesOptionError, "api.forcepermissive.config(conf).option(path, 0).value.get()") + raises(PropertiesOptionError, "assert api.config(conf).option(path, 0).value.get()") + raises(PropertiesOptionError, "assert api.config(conf).option(path, 1).value.get()") + raises(PropertiesOptionError, "assert api.forcepermissive.config(conf).option(path, 0).value.get()") + raises(PropertiesOptionError, "assert api.forcepermissive.config(conf).option(path, 1).value.get()") else: if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): assert api.config(conf).option(path).value.get() == first_value @@ -331,25 +350,39 @@ def autocheck_get_value_permissive(api, path, confread, confwrite, **kwargs): def _autocheck_get_value(api, path, conf, **kwargs): + set_permissive = kwargs.get('set_permissive', True) multi = api.unrestraint.option(path).option.ismulti() submulti_ = api.unrestraint.option(path).option.issubmulti() isslave = api.unrestraint.option(path).option.isslave() - empty_value = _getdefault(api, path, multi, isslave, submulti_) + empty_value = kwargs['default'] if not multi: first_value = FIRST_VALUE elif submulti_ is False: - first_value = LIST_FIRST_VALUE + if not isslave: + first_value = LIST_FIRST_VALUE + else: + second_value = LIST_SECOND_VALUE[1] + else: - first_value = SUBLIST_FIRST_VALUE + if not isslave: + first_value = SUBLIST_FIRST_VALUE + else: + second_value = SUBLIST_SECOND_VALUE[1] # get value after set value without permissive if isslave: if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): - assert api.config(conf).option(path, 0).value.get() == first_value[0] - assert api.forcepermissive.config(conf).option(path, 0).value.get() == first_value[0] + assert api.config(conf).option(path, 0).value.get() == empty_value + assert api.config(conf).option(path, 1).value.get() == second_value + assert api.forcepermissive.config(conf).option(path, 0).value.get() == empty_value + assert api.forcepermissive.config(conf).option(path, 1).value.get() == second_value elif kwargs.get('permissive', False): raises(PropertiesOptionError, "api.config(conf).option(path, 0).value.get()") assert api.forcepermissive.config(conf).option(path, 0).value.get() == empty_value + if set_permissive: + assert api.forcepermissive.config(conf).option(path, 1).value.get() == second_value + else: + assert api.forcepermissive.config(conf).option(path, 1).value.get() == empty_value else: raises(PropertiesOptionError, "api.config(conf).option(path, 0).value.get()") raises(PropertiesOptionError, "api.forcepermissive.config(conf).option(path, 0).value.get()") @@ -359,7 +392,10 @@ def _autocheck_get_value(api, path, conf, **kwargs): assert api.forcepermissive.config(conf).option(path).value.get() == first_value elif kwargs.get('permissive', False): raises(PropertiesOptionError, "api.config(conf).option(path).value.get()") - assert api.forcepermissive.config(conf).option(path).value.get() == empty_value + if set_permissive: + assert api.forcepermissive.config(conf).option(path).value.get() == first_value + else: + assert api.forcepermissive.config(conf).option(path).value.get() == empty_value else: raises(PropertiesOptionError, "api.config(conf).option(path).value.get()") raises(PropertiesOptionError, "api.forcepermissive.config(conf).option(path).value.get()") @@ -367,10 +403,10 @@ def _autocheck_get_value(api, path, conf, **kwargs): @autocheck def autocheck_get_value(api, path, confread, confwrite, **kwargs): - _autocheck_set_value(api, path, confwrite, set_permissive=False, **kwargs) - _autocheck_get_value(api, path, confread, **kwargs) + _set_value(api, path, confwrite, set_permissive=False, **kwargs) + _autocheck_get_value(api, path, confread, set_permissive=False, **kwargs) if confread != confwrite: - _autocheck_get_value(api, path, confwrite, **kwargs) + _autocheck_get_value(api, path, confwrite, set_permissive=False, **kwargs) @autocheck @@ -386,11 +422,7 @@ def autocheck_value_slave(api, path, confread, confwrite, **kwargs): multi = api.unrestraint.option(path).option.ismulti() submulti_ = api.forcepermissive.option(path).option.issubmulti() - if not submulti_: - second_value = LIST_SECOND_VALUE - else: - second_value = SUBLIST_SECOND_VALUE - empty_value = _getdefault(api, path, multi, isslave, submulti_) + empty_value = kwargs['default'] def do(conf): if not kwargs.get('permissive', False): @@ -409,7 +441,7 @@ def autocheck_value_slave(api, path, confread, confwrite, **kwargs): for idx in range(length): value.append(api.forcepermissive.option(path, idx).value.get()) - assert value == [empty_value, second_value[1]] + assert value == [empty_value, empty_value] # cannot access to a slave with index too high if submulti_ is False: value = LIST_FIRST_VALUE[0] @@ -443,8 +475,8 @@ def autocheck_reset_value(api, path, confread, confwrite, **kwargs): else: first_value = SUBLIST_FIRST_VALUE second_value = SUBLIST_SECOND_VALUE - empty_value = _getdefault(api, path, multi, isslave, submulti_) - _autocheck_set_value(api, path, confwrite, **kwargs) + empty_value = kwargs['default'] + _set_value(api, path, confwrite, **kwargs) # reset value without permissive if not isslave: @@ -479,11 +511,88 @@ def autocheck_reset_value(api, path, confread, confwrite, **kwargs): do(confwrite) +@autocheck +def autocheck_append_value(api, path, confread, confwrite, **kwargs): + ismaster = api.unrestraint.option(path).option.ismaster() + submulti_ = api.unrestraint.option(path).option.issubmulti() + if not ismaster: + return + + if not kwargs.get('propertyerror', False): + master_value = api.forcepermissive.config(confread).option(path).value.get() + len_value = len(master_value) + master_value.append(undefined) + assert len(api.forcepermissive.config(confread).option(path).value.get()) == len_value + api.forcepermissive.config(confwrite).option(path).value.set(master_value) + new_master_value = api.forcepermissive.config(confread).option(path).value.get() + len_new = len(new_master_value) + assert len_value + 1 == len_new + assert new_master_value[-1] == kwargs['default_multi'] + slave_path = path.rsplit('.', 1)[0] + '.third' + for idx in range(len_new): + assert api.forcepermissive.config(confread).option(slave_path, idx).value.get() == kwargs['default_multi'] + # + if not submulti_: + value = 'value' + else: + value = ['value'] + master_value.append(value) + assert len(api.forcepermissive.config(confread).option(path).value.get()) == len(new_master_value) + api.forcepermissive.config(confwrite).option(path).value.set(master_value) + assert api.forcepermissive.config(confread).option(path).value.get()[-1] == value + + +@autocheck +def autocheck_pop_value(api, path, confread, confwrite, **kwargs): + ismaster = api.unrestraint.option(path).option.ismaster() + submulti_ = api.unrestraint.option(path).option.issubmulti() + if not ismaster: + return + + if not kwargs.get('propertyerror', False): + if not submulti_: + values = ['value1', 'value2', 'value3', 'value4'] + slave = 'slave' + else: + values = [['value1'], ['value2'], ['value3'], ['value4']] + slave = ['slave'] + slaves = [kwargs['default_multi'], slave, kwargs['default_multi'], kwargs['default_multi']] + a_slave = path.rsplit('.', 1)[0] + '.third' + api.forcepermissive.config(confwrite).option(path).value.set(values) + api.forcepermissive.config(confwrite).option(a_slave, 1).value.set(slave) + api.forcepermissive.config(confread).option(a_slave, 0).value.get() == kwargs['default_multi'] + assert api.forcepermissive.config(confread).option(a_slave, 0).owner.isdefault() is True + api.forcepermissive.config(confread).option(a_slave, 1).value.get() == slave + assert api.forcepermissive.config(confread).option(a_slave, 1).owner.isdefault() is False + api.forcepermissive.config(confread).option(a_slave, 2).value.get() == kwargs['default_multi'] + assert api.forcepermissive.config(confread).option(a_slave, 2).owner.isdefault() is True + api.forcepermissive.config(confread).option(a_slave, 3).value.get() == kwargs['default_multi'] + assert api.forcepermissive.config(confread).option(a_slave, 3).owner.isdefault() is True + # + api.forcepermissive.config(confwrite).option(path).value.pop(3) + api.forcepermissive.config(confread).option(a_slave, 0).value.get() == kwargs['default_multi'] + assert api.forcepermissive.config(confread).option(a_slave, 0).owner.isdefault() is True + api.forcepermissive.config(confread).option(a_slave, 1).value.get() == slave + assert api.forcepermissive.config(confread).option(a_slave, 1).owner.isdefault() is False + api.forcepermissive.config(confread).option(a_slave, 2).value.get() == kwargs['default_multi'] + assert api.forcepermissive.config(confread).option(a_slave, 2).owner.isdefault() is True + # + api.forcepermissive.config(confwrite).option(path).value.pop(0) + api.forcepermissive.config(confread).option(a_slave, 0).value.get() == slave + assert api.forcepermissive.config(confread).option(a_slave, 0).owner.isdefault() is False + api.forcepermissive.config(confread).option(a_slave, 1).value.get() == kwargs['default_multi'] + assert api.forcepermissive.config(confread).option(a_slave, 1).owner.isdefault() is True + # + api.forcepermissive.config(confwrite).option(path).value.pop(0) + api.forcepermissive.config(confread).option(a_slave, 0).value.get() == kwargs['default_multi'] + assert api.forcepermissive.config(confread).option(a_slave, 0).owner.isdefault() is True + + @autocheck def autocheck_reset_value_permissive(api, path, confread, confwrite, **kwargs): # check if is a multi, a master or a slave isslave = api.unrestraint.option(path).option.isslave() - _autocheck_set_value(api, path, confwrite, **kwargs) + _set_value(api, path, confwrite, **kwargs) # reset value with permissive if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): @@ -510,12 +619,18 @@ def autocheck_reset_value_permissive(api, path, confread, confwrite, **kwargs): def autocheck_display(api, path, confread, confwrite, **kwargs): """re set value """ + if kwargs['callback']: + return make_dict = kwargs['make_dict'] make_dict_value = kwargs['make_dict_value'] + #print(make_dict) + #print(make_dict_value) + #print(api.config(confread).config.make_dict()) assert api.config(confread).config.make_dict() == make_dict if confread != confwrite: assert(api.config(confwrite).config.make_dict()) == make_dict - _autocheck_set_value(api, path, confwrite, **kwargs) + _set_value(api, path, confwrite, **kwargs) + #print(api.config(confread).config.make_dict()) assert api.config(confread).config.make_dict() == make_dict_value if confread != confwrite: assert(api.config(confwrite).config.make_dict()) == make_dict_value @@ -550,8 +665,12 @@ def _check_default_properties(api, path, conf, kwargs, props_permissive, props): raises(APIError, "api.unrestraint.option(path).property.get()") else: if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): - assert set(api.config(conf).option(path, 0).property.get()) == set(props) - assert set(api.config(conf).option(path, 1).property.get()) == set(props) + assert set(api.config(conf).option(path, 0).property.get()) == set(props_permissive) + assert set(api.config(conf).option(path, 1).property.get()) == set(props_permissive) + elif not kwargs.get('propertyerror', False): + raises(PropertiesOptionError, "api.config(conf).option(path).property.get()") + assert set(api.forcepermissive.config(conf).option(path, 0).property.get()) == set(props) + assert set(api.forcepermissive.config(conf).option(path, 1).property.get()) == set(props) else: raises(PropertiesOptionError, "api.config(conf).option(path, 0).property.get()") raises(APIError, "api.unrestraint.option(path, 0).property.get()") @@ -697,25 +816,25 @@ def _check_owner(api, path, conf, kwargs, owner, permissive_owner): raises(PropertiesOptionError, "api.forcepermissive.config(conf).option(path).owner.get()") else: if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): - assert api.option(path, 0).owner.get() == 'default' - assert api.option(path, 1).owner.get() == owner - assert api.forcepermissive.option(path, 0).owner.get() == 'default' - assert api.forcepermissive.option(path, 1).owner.get() == owner + assert api.config(conf).option(path, 0).owner.get() == 'default' + assert api.forcepermissive.config(conf).option(path, 0).owner.get() == 'default' + assert api.config(conf).option(path, 1).owner.get() == owner + assert api.forcepermissive.config(conf).option(path, 1).owner.get() == owner elif not kwargs.get('propertyerror', False): - raises(PropertiesOptionError, "api.option(path, 0).owner.get()") - raises(PropertiesOptionError, "api.option(path, 1).owner.get()") - assert api.forcepermissive.option(path, 0).owner.get() == 'default' - assert api.forcepermissive.option(path, 1).owner.get() == permissive_owner + raises(PropertiesOptionError, "api.config(conf).option(path, 0).owner.get()") + raises(PropertiesOptionError, "api.config(conf).option(path, 1).owner.get()") + assert api.forcepermissive.config(conf).option(path, 0).owner.get() == 'default' + assert api.forcepermissive.config(conf).option(path, 1).owner.get() == permissive_owner else: - raises(PropertiesOptionError, "api.option(path, 0).owner.get()") - raises(PropertiesOptionError, "api.forcepermissive.option(path, 0).owner.get()") + raises(PropertiesOptionError, "api.config(conf).option(path, 0).owner.get()") + raises(PropertiesOptionError, "api.forcepermissive.config(conf).option(path, 0).owner.get()") @autocheck def autocheck_owner_with_value(api, path, confread, confwrite, **kwargs): """value is now changed, check owner in this case """ - _autocheck_set_value(api, path, confwrite, **kwargs) + _set_value(api, path, confwrite, **kwargs) _check_owner(api, path, confwrite, kwargs, OWNER, OWNER) if confread != confwrite: _check_owner(api, path, confread, kwargs, owners.meta, owners.meta) @@ -723,15 +842,28 @@ def autocheck_owner_with_value(api, path, confread, confwrite, **kwargs): @autocheck def autocheck_default_owner_with_value(api, path, confread, confwrite, **kwargs): - _autocheck_set_value(api, path, confwrite, **kwargs) + isslave = api.unrestraint.option(path).option.isslave() + _set_value(api, path, confwrite, **kwargs) # test if is default owner without permissive - if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): - assert api.config(confwrite).option(path).owner.isdefault() is False - assert api.config(confread).option(path).owner.isdefault() is False + if not isslave: + if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): + assert api.config(confwrite).option(path).owner.isdefault() is False + if confwrite != confread: + assert api.config(confread).option(path).owner.isdefault() is False + else: + raises(PropertiesOptionError, "api.config(confwrite).option(path).owner.isdefault()") + raises(PropertiesOptionError, "api.config(confread).option(path).owner.isdefault()") else: - raises(PropertiesOptionError, "api.config(confwrite).option(path).owner.isdefault()") - raises(PropertiesOptionError, "api.config(confread).option(path).owner.isdefault()") + if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False): + assert api.config(confwrite).option(path, 0).owner.isdefault() is True + assert api.config(confwrite).option(path, 1).owner.isdefault() is False + if confwrite != confread: + assert api.config(confread).option(path, 0).owner.isdefault() is True + assert api.config(confread).option(path, 1).owner.isdefault() is False + else: + raises(PropertiesOptionError, "api.config(confwrite).option(path, 0).owner.isdefault()") + raises(PropertiesOptionError, "api.config(confread).option(path, 0).owner.isdefault()") @autocheck @@ -739,7 +871,7 @@ def autocheck_default_owner_with_value_permissive(api, path, confread, confwrite # check if is a isslave isslave = api.unrestraint.option(path).option.isslave() - _autocheck_set_value(api, path, confwrite, **kwargs) + _set_value(api, path, confwrite, **kwargs) def do(conf): # test if is default owner with permissive @@ -771,7 +903,7 @@ def autocheck_set_owner(api, path, confread, confwrite, **kwargs): # test set owner without permissive isslave = api.unrestraint.option(path).option.isslave() - _autocheck_set_value(api, path, confwrite, **kwargs) + _set_value(api, path, confwrite, **kwargs) # set owner without permissive if not isslave: @@ -797,7 +929,7 @@ def autocheck_set_owner(api, path, confread, confwrite, **kwargs): def autocheck_set_owner_permissive(api, path, confread, confwrite, **kwargs): isslave = api.unrestraint.option(path).option.isslave() - _autocheck_set_value(api, path, confwrite, **kwargs) + _set_value(api, path, confwrite, **kwargs) # set owner with permissive if not kwargs.get('propertyerror', False): @@ -848,7 +980,7 @@ def autocheck_option(api, path, confread, confwrite, **kwargs): assert doc == "{}'s option".format(expected_name) -@autocheck +#@autocheck def autocheck_permissive(api, path, confread, confwrite, **kwargs): """test permissive for hidden and disabled value """ @@ -966,7 +1098,7 @@ def autocheck_find(api, path, confread, confwrite, **kwargs): do(confwrite) -def check_all(cfg, paths, path, meta, multi, default, default_multi, require, consistency, weakrefs, **kwargs): +def check_all(cfg, paths, path, meta, multi, default, default_multi, require, consistency, callback, weakrefs, **kwargs): def _build_make_dict(): dico = {} dico_value = {} @@ -976,15 +1108,24 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co value = LIST_FIRST_VALUE else: value = SUBLIST_FIRST_VALUE - if not default or submulti: + if not default or multi is submulti: if not multi: default_value = None else: default_value = [] else: default_value = value + kwargs['default'] = default_value + if '.' in path: + if paths.get(path, {}) is None: + isslave = False + else: + isslave = paths.get(path, {}).get(path.rsplit('.', 1)[0], {}).get('master') is True and not path.endswith('.first') + if isslave and not multi is submulti: + kwargs['default'] = None is_dyn = False + is_master = False dyns = [] has_value = False for cpath, options in paths.items(): @@ -999,6 +1140,8 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co continue if options.get(dirname, {}).get('dyn'): is_dyn = True + if options.get(dirname, {}).get('master'): + is_master = True no_propertieserror = not options.get(name, {}).get('disabled') and not options.get(name, {}).get('hidden') allow_req = require and req if is_dyn: @@ -1009,11 +1152,11 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co dico_value[cpath] = value else: dico_value[cpath] = default_value + has_value = True if is_dyn: idx = 0 for cpath in list(paths.keys())[len(dyns):]: - if dyns[idx]: dico[cpath] = default_value if path == cpath: @@ -1048,6 +1191,43 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co else: dico[cpath + 'extraoptconsistency'] = value dico_value[cpath + 'extraoptconsistency'] = value + if is_master: + for cpath in list(paths.keys())[len(dyns):]: + if cpath.endswith('.first'): + second_path = cpath.rsplit('.', 1)[0] + '.second' + third_path = cpath.rsplit('.', 1)[0] + '.third' + cons_path = cpath.rsplit('.', 1)[0] + '.extraoptconsistency' + # + if default_multi: + if multi is not submulti: + dvalue = SECOND_VALUE + else: + dvalue = LIST_SECOND_VALUE + else: + dvalue = [] + if dvalue == [] and multi is not submulti: + dvalue = None + # + kwargs['default_multi'] = dvalue + if isslave: + kwargs['default'] = dvalue + len_master = len(dico[cpath]) + if second_path in dico: + dico[second_path] = [dvalue] * len_master + if third_path in dico: + dico[third_path] = [dvalue] * len_master + if cons_path in dico: + dico[cons_path] = [dvalue] * len_master + # + len_master = len(dico_value[cpath]) + if second_path in dico_value: + dico_value[second_path] = [dvalue] * len_master + if third_path in dico_value: + dico_value[third_path] = [dvalue] * len_master + cons_path = cpath.rsplit('.', 1)[0] + '.extraoptconsistency' + if cons_path in dico_value: + dico_value[cons_path] = [dvalue] * len_master + break return dico, dico_value if DISPLAY: text = u' {} launch tests for {}'.format(ICON, path) @@ -1075,6 +1255,7 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co idx = 0 for req in requires: kwargs['make_dict'], kwargs['make_dict_value'] = _build_make_dict() + kwargs['callback'] = callback for func in autocheck_registers: cfg_name = 'conftest' + str(idx) idx += 1 @@ -1085,12 +1266,42 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co ncfg = MetaConfig([ncfg], session_id='metatest') weakrefs.append(weakref.ref(cfg)) api = getapi(ncfg) + ckwargs = copy(kwargs) if api.unrestraint.option(path).option.isslave(): - master_path = path.rsplit('.', 1)[0] + '.master' - api.option(master_path).value.set(LIST_SECOND_VALUE) + dirname = path.rsplit('.', 1)[0] + master_path = dirname + '.first' + if multi is submulti: + value = SUBLIST_SECOND_VALUE + else: + value = LIST_SECOND_VALUE + api.option(master_path).value.set(value) + ckwargs['make_dict'][master_path] = value + ckwargs['make_dict_value'][master_path] = value + if default_multi: + if multi is not submulti: + dvalue = SECOND_VALUE + else: + dvalue = LIST_SECOND_VALUE + elif multi is submulti: + dvalue = [] + else: + dvalue = None + if dirname + '.second' in ckwargs['make_dict']: + ckwargs['make_dict'][dirname + '.second'] = [dvalue] * len(value) + ckwargs['make_dict_value'][dirname + '.second'] = [dvalue] * len(value) + if path == dirname + '.second': + ckwargs['make_dict_value'][dirname + '.second'][-1] = ckwargs['make_dict_value'][master_path][-1] + if dirname + '.third' in ckwargs['make_dict']: + ckwargs['make_dict'][dirname + '.third'] = [dvalue] * len(value) + ckwargs['make_dict_value'][dirname + '.third'] = [dvalue] * len(value) + if path == dirname + '.third': + ckwargs['make_dict_value'][dirname + '.third'][-1] = ckwargs['make_dict_value'][master_path][-1] + if dirname + '.extraoptconsistency' in ckwargs['make_dict']: + ckwargs['make_dict'][dirname + '.extraoptconsistency'] = [dvalue] * len(value) + ckwargs['make_dict_value'][dirname + '.extraoptconsistency'] = [dvalue] * len(value) + #FIXME devrait etre dans la config ca ... api.read_write() - ckwargs = copy(kwargs) if req: api.option('extraoptrequire').value.set('value') if 'permissive' in ckwargs and not 'permissive_od' in ckwargs or \ @@ -1108,8 +1319,10 @@ def check_all(cfg, paths, path, meta, multi, default, default_multi, require, co msg += u' as a multi' elif multi is submulti: msg += u' as a submulti' - if multi is True: + if default is True: msg += u' with default value' + if callback is True: + msg += u' (callback)' print(u'{}: {}'.format(msg, ckwargs)) raise err del api @@ -1123,12 +1336,11 @@ def check_deref(weakrefs): assert wrf() is None -def make_conf(options, meta, multi, default, default_multi, require, consistency): +def make_conf(options, meta, multi, default, default_multi, require, consistency, callback): weakrefs = [] dyn = [] goptions = [] - def make_option(path, option_infos): - #FIXME + def make_option(path, option_infos, in_master, master): option_type = 'str' option_properties = [] option_requires = [] @@ -1144,20 +1356,34 @@ def make_conf(options, meta, multi, default, default_multi, require, consistency isslave = option_infos.get('slave', False) args = [path, "{}'s option".format(path)] kwargs = {} + call_kwargs = {} if option_properties != []: kwargs['properties'] = tuple(option_properties) + if callback: + call_kwargs['properties'] = tuple(option_properties) if option_requires != []: - kwargs['requires'] = option_requires + if callback: + call_kwargs['requires'] = option_requires + else: + kwargs['requires'] = option_requires if multi and path is not 'extraoptrequire': kwargs['multi'] = multi - if default and not submulti: + if callback: + call_kwargs['multi'] = multi + if ((not in_master or master) and default) and path is not 'extraoptrequire' and not path.endswith('extraoptconsistency'): if multi is False: value = FIRST_VALUE elif multi is True: value = LIST_FIRST_VALUE else: value = SUBLIST_EMPTY_VALUE - kwargs['default'] = value + if callback: + kwargs['callback'] = return_str + call_kwargs['default'] = value + else: + kwargs['default'] = value + elif callback: + return None, None if default_multi and path is not 'extraoptrequire': if multi is not submulti: value = SECOND_VALUE @@ -1166,6 +1392,12 @@ def make_conf(options, meta, multi, default, default_multi, require, consistency kwargs['default_multi'] = value tiramisu_option = OPTIONS_TYPE[option_type]['option'] + if callback: + largs = [path + 'call', "{}'s callback option".format(path)] + objcall = tiramisu_option(*largs, **call_kwargs) + kwargs['callback_params'] = {'': ((objcall, False),)} + else: + objcall = None obj = tiramisu_option(*args, **kwargs) if not 'extraopt' in path and consistency: if require: @@ -1173,8 +1405,7 @@ def make_conf(options, meta, multi, default, default_multi, require, consistency else: gopt = goptions[0] obj.impl_add_consistency('not_equal', gopt, warnings_only=True) - weakrefs.append(weakref.ref(obj)) - return obj + return obj, objcall def make_optiondescriptions(path, collected): infos = collected.get('properties', {}) @@ -1234,13 +1465,33 @@ def make_conf(options, meta, multi, default, default_multi, require, consistency local_collect_options = local_collect_options[optiondescription] local_collect_options['properties'].update(option.get(optiondescription, {})) option_name = path.split('.')[-1] - obj = make_option(option_name, option.get(option_name)) + if '.' in path: + name_od = path.rsplit('.', 1)[0] + else: + name_od = '' + in_master = collect_options.get(name_od, {}).get('properties', {}).get('master') + master = in_master and path.endswith('first') + obj, objcall = make_option(option_name, option.get(option_name), in_master, master) + if obj is None: + return None, None, None + weakrefs.append(weakref.ref(obj)) + if callback: + weakrefs.append(weakref.ref(objcall)) + if '.' in path: + if master: + local_collect_options.setdefault('options', []).insert(0, obj) + else: + local_collect_options.setdefault('options', []).append(obj) + else: + local_collect_options.setdefault('options', []).append(obj) goptions.append(obj) - local_collect_options.setdefault('options', []).append(obj) + if callback: + local_collect_options.setdefault('options', []).append(objcall) + goptions.append(objcall) rootod = make_optiondescriptions('root', collect_options) if rootod is None: - return None, None + return None, None, None cfg = Config(rootod, session_id='conftest') weakrefs.append(weakref.ref(cfg)) del goptions @@ -1266,9 +1517,9 @@ DICT_PATHS = [ ('subod.second', {'second': {'disabled': True}}), ('subod.subsubod.third', {'third': {'hidden': True}})]), #test a config with masterslaves - OrderedDict([('odmaster.first', {'master': {'master': True}}), - ('odmaster.second', {'second': {'disabled': True, 'slave': True}}), - ('odmaster.third', {'third': {'hidden': True, 'slave': True}})]), + OrderedDict([('odmaster.first', {'odmaster': {'master': True}}), + ('odmaster.second', {'odmaster': {'master': True}, 'second': {'disabled': True, 'slave': True}}), + ('odmaster.third', {'odmaster': {'master': True}, 'third': {'hidden': True, 'slave': True}})]), #test a config with dynoption OrderedDict([('subod.first', {'subod': {'dyn': True}}), ('subod.second', {'second': {'disabled': True}}), @@ -1338,33 +1589,39 @@ def test_options(paths): lpaths = list(paths.keys()) for meta in (False, True): - for consistency in (False, True): - for require in (False, True): - for default_multi in (False, True): - for default in (False, True): - for multi in (False, True, submulti): - if multi is submulti and consistency: - continue - if multi is False and default_multi: - continue - cfg, weakrefs, dyn = make_conf(paths, meta, multi, default, default_multi, require, consistency) - if cfg is None: - continue - if dyn: - cnt = 0 - idx = 0 - for index, lpath in enumerate(lpaths): - if paths[lpath]: - cnt += 1 - else: - check_all(cfg, paths, lpaths[index], meta, multi, default, - default_multi, require, consistency, weakrefs, **get_kwargs(lpaths[idx])) - idx += 1 - if idx == cnt: - idx = 0 - else: - for lpath in lpaths: - check_all(cfg, paths, lpath, meta, multi, default, - default_multi, require, consistency, weakrefs, **get_kwargs(lpath)) - del cfg - check_deref(weakrefs) + for callback in (False, True): + for consistency in (False, True): + for require in (False, True): + for default_multi in (False, True): + if callback and default_multi: + continue + for default in (False, True): + for multi in (False, True, submulti): + if multi is submulti and default: + continue + if multi is submulti and consistency: + continue + if multi is False and default_multi: + continue + cfg, weakrefs, dyn = make_conf(paths, meta, multi, default, default_multi, require, consistency, callback) + if cfg is None: + continue + if dyn: + cnt = 0 + idx = 0 + for index, lpath in enumerate(lpaths): + if paths[lpath]: + cnt += 1 + else: + check_all(cfg, paths, lpaths[index], meta, multi, default, + default_multi, require, consistency, callback, weakrefs, **get_kwargs(lpaths[idx])) + idx += 1 + if idx == cnt: + idx = 0 + else: + for lpath in lpaths: + check_all(cfg, paths, lpath, meta, multi, default, + default_multi, require, consistency, callback, weakrefs, **get_kwargs(lpath)) + del cfg + check_deref(weakrefs) + display_count() diff --git a/tiramisu/api.py b/tiramisu/api.py index 9472fd0..7696135 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -18,12 +18,56 @@ from inspect import ismethod, getdoc from .error import APIError, PropertiesOptionError from .i18n import _ from .setting import owners, undefined +from time import time +from copy import deepcopy try: from .value import Multi except: Multi = list +COUNT_TIME = False +#COUNT_TIME = {} + + +def count(func): + global MOD_COUNT_TIME + func_name = func.__name__ + def wrapper(*args, **kwargs): + time1 = time() + ret = func(*args, **kwargs) + time2 = time() + diff = (time2 - time1) * 1000.0 + MOD_COUNT_TIME[func_name]['max'] = max(MOD_COUNT_TIME[func_name]['max'], diff) + MOD_COUNT_TIME[func_name]['min'] = min(MOD_COUNT_TIME[func_name]['min'], diff) + MOD_COUNT_TIME[func_name]['total'] += diff + MOD_COUNT_TIME[func_name]['nb'] += 1 + #print('%s function took %0.3f ms' % (func_name, diff)) + #print(COUNT_TIME) + return ret + if COUNT_TIME is not False: + COUNT_TIME[func_name] = {'max': 0, + 'min': 1000, + 'nb': 0, + 'total': 0} + MOD_COUNT_TIME = deepcopy(COUNT_TIME) + return wrapper + return func + + +def display_count(): + if COUNT_TIME is not False: + global MOD_COUNT_TIME + #print(MOD_COUNT_TIME) + for func in MOD_COUNT_TIME: + print('>', func) + print('=> nb:', MOD_COUNT_TIME[func]['nb']) + if MOD_COUNT_TIME[func]['nb'] != 0: + print('=> min:', MOD_COUNT_TIME[func]['min']) + print('=> max:', MOD_COUNT_TIME[func]['max']) + print('=> moy:', MOD_COUNT_TIME[func]['total'] / MOD_COUNT_TIME[func]['nb']) + MOD_COUNT_TIME = deepcopy(COUNT_TIME) + class CommonTiramisuOption(object): icon = '\u2937' tmpl_help = u' {} {}: {}' @@ -164,6 +208,7 @@ class TiramisuOptionOwner(CommonTiramisuOption): index=self.index, force_permissive=self.force_permissive) + @count def isdefault(self): """is option has defaut value""" return self.values.is_default_owner(self.opt, @@ -285,6 +330,7 @@ class TiramisuOptionValue(CommonTiramisuOption): force_permissive, force_unrestraint) + @count def get(self): self._test_slave_index() settings = self.config.cfgimpl_get_settings() @@ -296,6 +342,7 @@ class TiramisuOptionValue(CommonTiramisuOption): value = list(value) return value + @count def set(self, value): """set a value for a specified option""" self._test_slave_index() @@ -305,17 +352,21 @@ class TiramisuOptionValue(CommonTiramisuOption): idx = value.index(undefined) value[idx] = values.getdefaultvalue(self.opt, self.path, + self.setting_properties, idx) else: if value == undefined: value = values.getdefaultvalue(self.opt, self.path, + self.setting_properties, self.index) self.config.setattr(self.path, value, index=self.index, + setting_properties=self.setting_properties, force_permissive=self.force_permissive) + @count def pop(self, index): """pop value for a specified master values """ diff --git a/tiramisu/autolib.py b/tiramisu/autolib.py index d263034..6d0937c 100644 --- a/tiramisu/autolib.py +++ b/tiramisu/autolib.py @@ -18,15 +18,22 @@ # the whole pypy projet is under MIT licence # ____________________________________________________________ "enables us to carry out a calculation and return an option's value" -from .error import PropertiesOptionError, ConfigError, SlaveError +from .error import PropertiesOptionError, ConfigError, SlaveError, display_list from .i18n import _ from .setting import undefined from .storage import get_default_values_storages, get_default_settings_storages # ____________________________________________________________ -def carry_out_calculation(option, context, callback, callback_params, - index=undefined, validate=True, is_validator=False): +def carry_out_calculation(option, + context, + callback, + callback_params, + setting_properties=undefined, + index=undefined, + validate=True, + is_validator=False): + """a function that carries out a calculation for an option's value :param option: the option @@ -172,20 +179,16 @@ def carry_out_calculation(option, context, callback, callback_params, else: valid = validate # get value - value = context.getattr(path, force_permissive=True, - validate=valid, returns_raise=True) - if isinstance(value, Exception): - if isinstance(value, PropertiesOptionError): - if force_permissive: - continue - err = ConfigError(_('unable to carry out a calculation' - ', option {0} has properties: {1} ' - 'for: {2}').format(opt.impl_getname(), - value.proptype, - option.impl_getname())) - return err - else: - raise value + try: + value = context.getattr(path, + force_permissive=True, + validate=valid, + setting_properties=setting_properties) + except PropertiesOptionError as err: + if force_permissive: + continue + raise ConfigError(_('unable to carry out a calculation for "{}"' + ', {}').format(option.impl_get_display_name(), err)) # convert to list, not modifie this multi if value.__class__.__name__ == 'Multi': has_option = True @@ -259,7 +262,7 @@ def calculate(option, callback, is_validator, args, kwargs): return callback(*args, **kwargs) except ValueError as err: if is_validator: - return err + raise err error = err except Exception as err: error = err diff --git a/tiramisu/config.py b/tiramisu/config.py index 7a24619..db7c908 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -82,13 +82,14 @@ class SubConfig(object): self._impl_path = subpath if setting_properties is not undefined: self._impl_setting_properties = setting_properties - if descr.impl_get_group_type() == groups.master: + if setting_properties is not None and descr.impl_get_group_type() == groups.master: self._impl_length = descr.get_length(context().cfgimpl_get_values(), + setting_properties=setting_properties, validate=validate, force_permissive=force_permissive) def cfgimpl_get_length(self): - return self._impl_length + return getattr(self, '_impl_length') def reset_one_option_cache(self, values, @@ -183,8 +184,7 @@ class SubConfig(object): """Pythonesque way of parsing group's ordered options. iteration only on Options (not OptionDescriptions)""" setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().get_context_properties() - for child in self.cfgimpl_get_description()._impl_getchildren( - context=self._cfgimpl_get_context()): + for child in self.cfgimpl_get_description().impl_getchildren(context=self._cfgimpl_get_context()): if not child.impl_is_optiondescription(): try: name = child.impl_getname() @@ -230,8 +230,7 @@ class SubConfig(object): raise TypeError(_("unknown group_type: {0}").format(group_type)) context = self._cfgimpl_get_context() setting_properties = context.cfgimpl_get_settings().get_context_properties() - for child in self.cfgimpl_get_description()._impl_getchildren( - context=context): + for child in self.cfgimpl_get_description().impl_getchildren(context=context): if child.impl_is_optiondescription(): try: if group_type is None or (group_type is not None and @@ -312,8 +311,6 @@ class SubConfig(object): name, value) context = self._cfgimpl_get_context() - if setting_properties is None: - setting_properties = context.cfgimpl_get_settings().get_context_properties() if '.' in name: # pragma: optional cover self, name = self.cfgimpl_get_home_by_path(name, force_permissive=force_permissive, @@ -338,19 +335,14 @@ class SubConfig(object): setting_properties, _commit) - def __delattr__(self, name): - self.delattr(name) - def delattr(self, name, index=None, force_permissive=False, setting_properties=None, - validate=True, - not_raises=False): + validate=True): + context = self._cfgimpl_get_context() - if setting_properties is None: - setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True) if '.' in name: # pragma: optional cover self, name = self.cfgimpl_get_home_by_path(name, force_permissive=force_permissive, @@ -362,40 +354,31 @@ class SubConfig(object): elif child.impl_is_symlinkoption() and \ not isinstance(child, DynSymLinkOption): # pragma: no dynoptiondescription cover raise TypeError(_("can't delete a SymlinkOption")) - else: - subpath = self._get_subpath(name) - values = self.cfgimpl_get_values() - if index is not None: - if child.impl_is_master_slaves('master'): - ret = values.reset_master(self, - child, - subpath, - index, - force_permissive, - setting_properties) - elif child.impl_is_master_slaves('slave'): - ret = values.reset_slave(child, - subpath, - index, - setting_properties, - force_permissive=force_permissive, - validate=validate) - else: - raise ValueError(_("can delete value with index only with a master or a slave")) - else: - ret = values.reset(child, + subpath = self._get_subpath(name) + values = self.cfgimpl_get_values() + if index is not None: + if child.impl_is_master_slaves('master'): + values.reset_master(self, + child, + subpath, + index, + force_permissive, + setting_properties) + elif child.impl_is_master_slaves('slave'): + values.reset_slave(child, subpath, + index, setting_properties, force_permissive=force_permissive, validate=validate) - if ret: - if not_raises: - return ret - raise ret - - def __getattr__(self, name): - setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().get_context_properties() - return self.getattr(name, setting_properties) + else: + raise ValueError(_("can delete value with index only with a master or a slave")) + else: + values.reset(child, + subpath, + setting_properties, + force_permissive=force_permissive, + validate=validate) def _get_subpath(self, name): if self._impl_path is None: @@ -418,73 +401,73 @@ class SubConfig(object): :return: option's value if name is an option name, OptionDescription otherwise """ - # attribute access by passing a path, - # for instance getattr(self, "creole.general.family.adresse_ip_eth0") - context = self._cfgimpl_get_context() if '.' in name: - homeconfig, name = self.cfgimpl_get_home_by_path(name, - force_permissive=force_permissive, - validate_properties=validate_properties, - setting_properties=setting_properties) - if isinstance(homeconfig, Exception): - cfg = homeconfig - else: - cfg = homeconfig.getattr(name, - force_permissive=force_permissive, - validate=validate, - validate_properties=validate_properties, - setting_properties=setting_properties, - index=index) - else: - option = self.cfgimpl_get_description().__getattr__(name, - context=context) - subpath = self._get_subpath(name) - if setting_properties: - self.cfgimpl_get_settings().validate_properties(option, - subpath, - setting_properties, - index=index, - force_permissive=force_permissive) - if option.impl_is_symlinkoption() and not isinstance(option, DynSymLinkOption): - path = context.cfgimpl_get_description().impl_get_path_by_opt(option.impl_getopt()) - cfg = context.getattr(path, - validate=validate, - validate_properties=validate_properties, - force_permissive=force_permissive, - setting_properties=setting_properties, - index=index) - elif option.impl_is_optiondescription(): - if returns_option is True: - return option - return SubConfig(option, - self._impl_context, - setting_properties, - validate, - force_permissive, - subpath) - else: - if option.impl_is_master_slaves('slave') and index is not None and \ - index >= self._impl_length: - raise IndexError(_('index ({}) is higher than the master length ({}) for "{}"' - '').format(index, - self._impl_length, - subpath)) - if validate: - self.cfgimpl_get_description().impl_validate(context, - force_permissive, - setting_properties) + self, name = self.cfgimpl_get_home_by_path(name, + force_permissive=force_permissive, + validate_properties=validate_properties, + setting_properties=setting_properties) + + context = self._cfgimpl_get_context() + option = self.cfgimpl_get_description().__getattr__(name, + context=context) + if option.impl_is_symlinkoption() and isinstance(option, DynSymLinkOption): + # FIXME peuvent-il vraiment etre le 2 ? + # si non supprimer tout ces tests inutiles + raise Exception('oui ca existe ...') + if option.impl_is_symlinkoption() and not isinstance(option, DynSymLinkOption): + if returns_option is True: + return option + path = context.cfgimpl_get_description().impl_get_path_by_opt(option.impl_getopt()) + return context.getattr(path, + validate=validate, + validate_properties=validate_properties, + force_permissive=force_permissive, + setting_properties=setting_properties, + index=index) + + subpath = self._get_subpath(name) + if setting_properties: + self.cfgimpl_get_settings().validate_properties(option, + subpath, + setting_properties, + index=index, + force_permissive=force_permissive) + if option.impl_is_optiondescription(): + if returns_option is True: + return option + return SubConfig(option, + self._impl_context, + setting_properties, + validate, + force_permissive, + subpath) + + if option.impl_is_master_slaves('slave'): + if index is None: + raise IndexError(_('index is mandatory for the slave "{}"' + '').format(subpath)) + length = self.cfgimpl_get_length() + if index >= length: + raise IndexError(_('index ({}) is higher than the master length ({}) ' + 'for "{}"').format(index, + length, + subpath)) + elif index: + raise IndexError(_('index is forbidden for the not slave "{}"' + '').format(subpath)) + if validate: + self.cfgimpl_get_description().impl_validate(context, + force_permissive, + setting_properties) - if not returns_option: - cfg = self.cfgimpl_get_values().get_cached_value(option, - path=subpath, - validate=validate, - setting_properties=setting_properties, - force_permissive=force_permissive, - index=index) if returns_option is True: return option - else: - return cfg + return self.cfgimpl_get_values().get_cached_value(option, + path=subpath, + validate=validate, + setting_properties=setting_properties, + force_permissive=force_permissive, + index=index) def find(self, setting_properties, @@ -589,7 +572,8 @@ class SubConfig(object): byname, _subpath, only_first, - self._cfgimpl_get_context()) + self._cfgimpl_get_context(), + setting_properties) for path, option in options: if not _filter_by_value(): continue @@ -712,7 +696,7 @@ class SubConfig(object): fullpath=fullpath) #withoption can be set to None below ! if withoption is None: - for opt in self.cfgimpl_get_description().impl_getchildren(): + for opt in self.cfgimpl_get_description().impl_getchildren(setting_properties): path = opt.impl_getname() self._make_sub_dict(opt, path, @@ -728,7 +712,7 @@ class SubConfig(object): return pathsvalues def _make_sub_dict(self, - opt, + option, path, pathsvalues, _currpath, @@ -737,31 +721,47 @@ class SubConfig(object): force_permissive=False, fullpath=False): try: - value = self.getattr(path, - force_permissive=force_permissive, - setting_properties=setting_properties) - except PropertiesOptionError as err: + if not option.impl_is_optiondescription() and option.impl_is_master_slaves('slave'): + ret = [] + length = self.cfgimpl_get_length() + if length: + for idx in range(length): + ret.append(self.getattr(path, + index=idx, + force_permissive=force_permissive, + setting_properties=setting_properties)) + elif setting_properties: + self.cfgimpl_get_settings().validate_properties(option, + path, + setting_properties, + force_permissive=force_permissive) + else: + ret = self.getattr(path, + force_permissive=force_permissive, + setting_properties=setting_properties) + except PropertiesOptionError: pass else: - if opt.impl_is_optiondescription(): - pathsvalues += value.make_dict(setting_properties, - flatten=flatten, - _currpath=_currpath + path.split('.'), - force_permissive=force_permissive, - fullpath=fullpath) + if option.impl_is_optiondescription(): + pathsvalues += ret.make_dict(setting_properties, + flatten=flatten, + _currpath=_currpath + path.split('.'), + force_permissive=force_permissive, + fullpath=fullpath) else: if flatten: - name = opt.impl_getname() + name = option.impl_getname() + elif fullpath: + #FIXME + #root_path = self.cfgimpl_get_path() + #if root_path is None: + # name = opt.impl_getname() + #else: + # name = '.'.join([root_path, opt.impl_getname()]) + name = self._get_subpath(name) else: - if fullpath: - root_path = self.cfgimpl_get_path() - if root_path is None: - name = opt.impl_getname() - else: - name = '.'.join([root_path, opt.impl_getname()]) - else: - name = '.'.join(_currpath + [opt.impl_getname()]) - pathsvalues.append((name, value)) + name = '.'.join(_currpath + [option.impl_getname()]) + pathsvalues.append((name, ret)) def cfgimpl_get_path(self, dyn=True): @@ -830,7 +830,8 @@ class _CommonConfig(SubConfig): if isinstance(self, Exception): return self option = self.cfgimpl_get_description().__getattr__(path, - context=self._cfgimpl_get_context()) + context=self._cfgimpl_get_context(), + setting_properties=setting_properties) if not validate_properties: return option else: diff --git a/tiramisu/option/baseoption.py b/tiramisu/option/baseoption.py index 7562406..8a6d984 100644 --- a/tiramisu/option/baseoption.py +++ b/tiramisu/option/baseoption.py @@ -232,7 +232,7 @@ class Base(object): if callback is None and callback_params is not None: raise ValueError(_("params defined for a callback function but " "no callback defined" - " yet for option {0}").format( + ' yet for option "{0}"').format( self.impl_getname())) if not _init and self.impl_get_callback()[0] is not None: raise ConfigError(_("a callback is already set for {0}, " diff --git a/tiramisu/option/option.py b/tiramisu/option/option.py index 76207c0..0037ce5 100644 --- a/tiramisu/option/option.py +++ b/tiramisu/option/option.py @@ -164,7 +164,7 @@ class Option(OnlyOption): :type func: `str` :param option: option that value is changing :type option: `tiramisu.option.Option` - :param value: new value of this option + :param value: new value of this opion :param context: Config's context, if None, check default value instead :type context: `tiramisu.config.Config` :param index: only for multi option, consistency should be launch for @@ -192,9 +192,9 @@ class Option(OnlyOption): all_cons_vals.append(value) all_cons_opts.append(opt) else: - #if context, calculate value, otherwise get default value path = None is_multi = opt.impl_is_multi() and not opt.impl_is_master_slaves() + #if context, calculate value, otherwise get default value if context is not undefined: if isinstance(opt, DynSymLinkOption): path = opt.impl_getpath(context) @@ -218,12 +218,14 @@ class Option(OnlyOption): raise err else: opt_value = None - else: # pragma: no cover - return opt_value - elif index is None: - opt_value = opt.impl_getdefault() + #elif index is None: else: - opt_value = opt.impl_getdefault()[index] + opt_value = opt.impl_getdefault() + if index is not None: + if len(opt_value) >= index: + opt_value = opt.impl_getdefault_multi() + else: + opt_value = opt_value[index] if self.impl_is_multi() and index is None: # only check propertyerror for master/slaves is transitive @@ -237,16 +239,20 @@ class Option(OnlyOption): all_cons_opts.append(opt) if val_consistencies: - err = getattr(self, func)(current_opt, all_cons_opts, all_cons_vals, warnings_only) - if err: + try: + getattr(self, func)(current_opt, all_cons_opts, all_cons_vals, warnings_only) + except ValueError as err: if warnings_only: - msg = _('attention, "{0}" could be an invalid {1} for "{2}", {3}').format( - value, self._display_name, current_opt.impl_get_display_name(), err) + msg = _('attention, "{0}" could be an invalid {1} for "{2}", {3}' + '').format(value, + self._display_name, + current_opt.impl_get_display_name(), + err) warnings.warn_explicit(ValueWarning(msg, self), ValueWarning, self.__class__.__name__, 0) else: - return err + raise err def impl_is_unique(self): return getattr(self, '_unique', False) @@ -295,7 +301,7 @@ class Option(OnlyOption): if display_error and self.impl_is_unique() and len(set(value)) != len(value): for idx, val in enumerate(value): if val in value[idx+1:]: - return ValueError(_('invalid value "{}", this value is already in "{}"' + raise ValueError(_('invalid value "{}", this value is already in "{}"' '').format(val, self.impl_get_display_name())) @@ -321,6 +327,7 @@ class Option(OnlyOption): context=context, callback=validator, callback_params=validator_params_, + setting_properties=setting_properties, index=_index, is_validator=True) if isinstance(value, Exception): @@ -353,7 +360,7 @@ class Option(OnlyOption): '').format(_value, self._display_name, self.impl_get_display_name()) - return ValueError(msg) + raise ValueError(msg) error = None is_warnings_only = getattr(self, '_warnings_only', False) if ((display_error and not is_warnings_only) or @@ -401,7 +408,7 @@ class Option(OnlyOption): msg = _('"{0}" is an invalid {1} for "{2}"' '').format(_value, self._display_name, self.impl_get_display_name()) - return ValueError(msg) + raise ValueError(msg) if is_multi is None: is_multi = self.impl_is_multi() @@ -414,12 +421,12 @@ class Option(OnlyOption): if err: return err if not isinstance(value, list): - return ValueError(_('invalid value "{0}" for "{1}" which' + raise ValueError(_('invalid value "{0}" for "{1}" which' ' must be a list').format( value, self.impl_get_display_name())) for idx, val in enumerate(value): if isinstance(val, list): # pragma: no cover - return ValueError(_('invalid value "{}" for "{}" ' + raise ValueError(_('invalid value "{}" for "{}" ' 'which must not be a list').format(val, self.impl_get_display_name())) err = do_validation(val, force_index) @@ -433,12 +440,12 @@ class Option(OnlyOption): else: lst = multi if value in lst: - return ValueError(_('invalid value "{}", this value is already' + raise ValueError(_('invalid value "{}", this value is already' ' in "{}"').format(value, self.impl_get_display_name())) return do_validation(value, force_index) elif not isinstance(value, list): - return ValueError(_('invalid value "{0}" for "{1}" which ' + raise ValueError(_('invalid value "{0}" for "{1}" which ' 'must be a list').format(value, self.impl_getname())) elif self.impl_is_submulti(): @@ -447,7 +454,7 @@ class Option(OnlyOption): if err: return err if not isinstance(val, list): - return ValueError(_('invalid value "{0}" for "{1}" ' + raise ValueError(_('invalid value "{0}" for "{1}" ' 'which must be a list of list' '').format(val, self.impl_getname())) @@ -671,7 +678,7 @@ class Option(OnlyOption): equal_name = [] for opt in equal: equal_name.append(opt.impl_get_display_name()) - return ValueError(msg.format(display_list(list(equal_name)))) + raise ValueError(msg.format(display_list(list(equal_name)))) def _second_level_validation(self, value, @@ -707,8 +714,8 @@ class Option(OnlyOption): default = self.impl_getdefault() if (not is_multi and (default is not None or default_multi is not None)) or \ (is_multi and (default != [] or default_multi is not None)): - raise ValueError(_("default value not allowed if option: {0} " - "is calculated").format(self.impl_getname())) + raise ValueError(_('default value not allowed if option "{0}" ' + 'is calculated').format(self.impl_getname())) def impl_getdefault(self): "accessing the default value" @@ -773,4 +780,4 @@ class RegexpOption(Option): return err match = self._regexp.search(value) if not match: - return ValueError() + raise ValueError() diff --git a/tiramisu/option/optiondescription.py b/tiramisu/option/optiondescription.py index f9a75bf..6a77476 100644 --- a/tiramisu/option/optiondescription.py +++ b/tiramisu/option/optiondescription.py @@ -65,7 +65,8 @@ class CacheOptionDescription(BaseOption): else: init = False - for option in self._impl_getchildren(dyn=False): + for option in self.impl_getchildren(setting_properties=undefined, + dyn=False): cache_option.append(option) if path == '': subpath = option.impl_getname() @@ -199,7 +200,8 @@ class CacheOptionDescription(BaseOption): if cache_path is None: cache_path = [] cache_option = [] - for option in self._impl_getchildren(dyn=False): + for option in self.impl_getchildren(setting_properties=undefined, + dyn=False): attr = option.impl_getname() path = str('.'.join(_currpath + [attr])) cache_option.append(option) @@ -223,7 +225,8 @@ class OptionDescriptionWalk(CacheOptionDescription): byname, _subpath, only_first, - context): + context, + setting_properties): find_results = [] def _rebuild_dynpath(path, @@ -251,8 +254,8 @@ class OptionDescriptionWalk(CacheOptionDescription): found = False if byname.startswith(name): subdyn = option._subdyn() - for suffix in subdyn._impl_get_suffixes( - context): + for suffix in subdyn._impl_get_suffixes(context, + setting_properties): if byname == name + suffix: found = True path = _rebuild_dynpath(path, @@ -278,8 +281,8 @@ class OptionDescriptionWalk(CacheOptionDescription): if byname is None: if option._is_subdyn(): name = option.impl_getname() - for suffix in option._subdyn._impl_get_suffixes( - context): + for suffix in option._subdyn._impl_get_suffixes(context, + setting_properties): spath = _rebuild_dynpath(path, suffix, option._subdyn) @@ -299,22 +302,22 @@ class OptionDescriptionWalk(CacheOptionDescription): return _filter_by_name(path, option) opts, paths = self._cache_paths - for index in xrange(0, len(paths)): + for index, path in enumerate(paths): option = opts[index] if option.impl_is_optiondescription(): continue - path = paths[index] 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( - context): - spath = _rebuild_dynpath(path, suffix, + for suffix in option._subdyn._impl_get_suffixes(context, + setting_properties): + spath = _rebuild_dynpath(path, + suffix, option._subdyn) - find_results.append((spath, option._impl_to_dyn( - name + suffix, spath))) + find_results.append((spath, option._impl_to_dyn(name + suffix, + spath))) else: find_results.append((path, option)) else: @@ -324,15 +327,9 @@ class OptionDescriptionWalk(CacheOptionDescription): return find_results return find_results - def _impl_st_getchildren(self, - context, - only_dyn=False): - for child in self._children[1]: - if only_dyn is False or child.impl_is_dynoptiondescription(): - yield(child) - def _getattr(self, name, + setting_properties, suffix=undefined, context=undefined, dyn=True): @@ -356,7 +353,8 @@ class OptionDescriptionWalk(CacheOptionDescription): return child else: child = self._impl_search_dynchild(name, - context=context) + context=context, + setting_properties=setting_properties) if child != []: return child error = True @@ -365,16 +363,6 @@ class OptionDescriptionWalk(CacheOptionDescription): 'in OptionDescription {1}' '').format(name, self.impl_getname())) - def impl_getpaths(self, - include_groups=False, - _currpath=None): - """returns a list of all paths in self, recursively - _currpath should not be provided (helps with recursion) - """ - return _impl_getpaths(self, - include_groups, - _currpath) - def impl_get_opt_by_path(self, path): if getattr(self, '_cache_paths', None) is None: @@ -391,25 +379,47 @@ class OptionDescriptionWalk(CacheOptionDescription): raise AttributeError(_('no option {0} found').format(opt)) return self._cache_paths[1][self._cache_paths[0].index(opt)] - def _impl_getchildren(self, - dyn=True, - context=undefined): - for child in self._impl_st_getchildren(context): + def impl_getchildren(self, + setting_properties, + dyn=True, + context=undefined): + for child in self._impl_st_getchildren(): cname = child.impl_getname() if dyn and child.impl_is_dynoptiondescription(): - for value in child._impl_get_suffixes(context): + for value in child._impl_get_suffixes(context, + setting_properties): yield SynDynOptionDescription(child, cname + value, value) else: yield child - def impl_getchildren(self): - return list(self._impl_getchildren()) + def _impl_st_getchildren(self, + only_dyn=False): + for child in self._children[1]: + if only_dyn is False or child.impl_is_dynoptiondescription(): + yield child + + def _impl_search_dynchild(self, + name, + context, + setting_properties): + ret = [] + for child in self._impl_st_getchildren(only_dyn=True): + cname = child.impl_getname() + if name.startswith(cname): + for value in child._impl_get_suffixes(context, + setting_properties): + if name == cname + value: + return SynDynOptionDescription(child, + name, + value) + return ret def __getattr__(self, name, - context=undefined): + context=undefined, + setting_properties=undefined): if name.startswith('_'): return object.__getattribute__(self, name) @@ -417,24 +427,11 @@ class OptionDescriptionWalk(CacheOptionDescription): path = name.split('.')[0] subpath = '.'.join(name.split('.')[1:]) return self.__getattr__(path, context=context).__getattr__(subpath, - context=context) + context=context, + setting_properties=setting_properties) return self._getattr(name, - context=context) - - def _impl_search_dynchild(self, - name, - context): - ret = [] - for child in self._impl_st_getchildren(context, - only_dyn=True): - cname = child.impl_getname() - if name.startswith(cname): - for value in child._impl_get_suffixes(context): - if name == cname + value: - return SynDynOptionDescription(child, - name, - value) - return ret + context=context, + setting_properties=setting_properties) def _impl_get_dynchild(self, child, @@ -466,6 +463,8 @@ class OptionDescription(OptionDescriptionWalk): :param children: a list of options (including optiondescriptions) """ + if not isinstance(children, list): + raise ValueError(_('children in optiondescription "{}"must be a liste').format(name)) super(OptionDescription, self).__init__(name, doc=doc, requires=requires, @@ -509,7 +508,8 @@ class OptionDescription(OptionDescriptionWalk): # ____________________________________________________________ def impl_set_group_type(self, - group_type): + group_type, + setting_properties): """sets a given group object to an OptionDescription :param group_type: an instance of `GroupType` or `MasterGroupType` @@ -523,7 +523,7 @@ class OptionDescription(OptionDescriptionWalk): self._group_type = group_type if isinstance(group_type, groups.MasterGroupType): raise Exception('please use MasterSlaves object instead of OptionDescription') - children = self.impl_getchildren() + children = self.impl_getchildren(setting_properties) for child in children: if child.impl_is_symlinkoption(): # pragma: optional cover raise ValueError(_("master group {0} shall not have " @@ -545,23 +545,6 @@ class OptionDescription(OptionDescriptionWalk): def impl_get_group_type(self): return self._group_type - def __getstate__(self): - raise NotImplementedError() - - def _impl_get_suffixes(self, - context): - callback, callback_params = self.impl_get_callback() - values = carry_out_calculation(self, - context=context, - callback=callback, - callback_params=callback_params) - if len(values) > len(set(values)): - raise ConfigError(_('DynOptionDescription callback return not unique value')) - for val in values: - if not isinstance(val, str) or re.match(NAME_REGEXP, val) is None: - raise ValueError(_("invalid suffix: {0} for option").format(val)) - return values - def impl_validate_value(self, option, value, @@ -570,6 +553,7 @@ class OptionDescription(OptionDescriptionWalk): class DynOptionDescription(OptionDescription): + def __init__(self, name, doc, @@ -584,18 +568,20 @@ class DynOptionDescription(OptionDescription): children, requires, properties) + # check children + set relation to this dynoptiondescription for child in children: if isinstance(child, OptionDescription): if child.impl_get_group_type() != groups.master: raise ConfigError(_('cannot set optiondescription in a ' 'dynoptiondescription')) - for chld in child._impl_getchildren(): + for chld in child.impl_getchildren(setting_properties=undefined): chld._impl_setsubdyn(self) if child.impl_is_symlinkoption(): raise ConfigError(_('cannot set symlinkoption in a ' 'dynoptiondescription')) child._impl_setsubdyn(self) - self.impl_set_callback(callback, + # add callback + self.impl_set_callback(callback, callback_params) def _validate_callback(self, @@ -604,6 +590,22 @@ class DynOptionDescription(OptionDescription): if callback is None: raise ConfigError(_('callback is mandatory for dynoptiondescription')) + def _impl_get_suffixes(self, + context, + setting_properties): + callback, callback_params = self.impl_get_callback() + values = carry_out_calculation(self, + context=context, + callback=callback, + callback_params=callback_params, + setting_properties=setting_properties) + if len(values) > len(set(values)): + raise ConfigError(_('DynOptionDescription callback return not unique value')) + for val in values: + if not isinstance(val, str) or re.match(NAME_REGEXP, val) is None: + raise ValueError(_("invalid suffix: {0} for option").format(val)) + return values + class SynDynOptionDescription(object): __slots__ = ('_opt', '_name', '_suffix') @@ -615,36 +617,33 @@ class SynDynOptionDescription(object): def __getattr__(self, name, + setting_properties=undefined, context=undefined): if name in dir(self._opt): return getattr(self._opt, name) return self._opt._getattr(name, + setting_properties, suffix=self._suffix, context=context) def impl_getname(self): return self._name - def _impl_getchildren(self, - dyn=True, - context=undefined): + def impl_getchildren(self, + setting_properties, + dyn=True, + context=undefined): children = [] - for child in self._opt._impl_getchildren(): + for child in self._opt.impl_getchildren(setting_properties): yield(self._opt._impl_get_dynchild(child, self._suffix)) - def impl_getchildren(self): - return self._impl_getchildren() - def impl_getpath(self, context): path = self.impl_getopt().impl_getpath(context).split('.') path[-1] += self._suffix path.append(self._name) return '.'.join(path) - def impl_getpaths(self, include_groups=False, _currpath=None): - return _impl_getpaths(self, include_groups, _currpath) - def impl_getopt(self): return self._opt @@ -667,6 +666,8 @@ class MasterSlaves(OptionDescription): self._group_type = groups.master slaves = [] master = children[0] + if not children: + raise ValueError(_('children is mandatory in masterslaves "{}"').format(name)) for child in children[1:]: if child.impl_getdefault() != []: raise ValueError(_("not allowed default value for option {0} " @@ -758,15 +759,19 @@ class MasterSlaves(OptionDescription): opt, path, values, - index): + index, + setting_properties, + force_permissive=False): for slave in self.getslaves(opt): slave_path = slave.impl_getpath(values._getcontext()) slavelen = values._p_.get_max_length(slave_path) if not values.is_default_owner(slave, - validate_properties=False, + slave_path, + setting_properties, validate_meta=False, - index=index): + index=index, + force_permissive=force_permissive): #FIXME # just for raise if needed #multi = values.get_cached_value(slave, # validate=False, @@ -834,11 +839,9 @@ class MasterSlaves(OptionDescription): path=path, validate=validate, force_permissive=force_permissive, - validate_properties=validate_properties, self_properties=self_properties, index=index, - setting_properties=setting_properties, - check_frozen=check_frozen) + setting_properties=setting_properties) def _getslave(self, values, opt, path, validate, force_permissive, trusted_cached_properties, validate_properties, setting_properties, @@ -976,7 +979,12 @@ class MasterSlaves(OptionDescription): return value return len(value) - def validate_slave_length(self, masterlen, valuelen, name, opt, setitem=False): + def validate_slave_length(self, + masterlen, + valuelen, + name, + opt, + setitem=False): if valuelen > masterlen or (valuelen < masterlen and setitem): if debug: # pragma: no cover log.debug('validate_slave_length: masterlen: {0}, valuelen: {1}, ' @@ -987,19 +995,49 @@ class MasterSlaves(OptionDescription): " which has {1} as master").format( name, opt.impl_getname())) - def reset_cache(self, opt, obj, type_, resetted_opts): + def reset_cache(self, + opt, + path, + obj, + type_, + resetted_opts): context = obj._getcontext() #FIXME pb avec dyn, devrait etre une option mopt = self.getmaster(None) - mopt.reset_cache(mopt, obj, type_, resetted_opts) + mpath = mopt.impl_getpath(context) + mopt.reset_cache(mopt, + mpath, + obj, + type_, + resetted_opts) for slave in self.getslaves(mopt): - slave.reset_cache(slave, obj, type_, resetted_opts) + spath = slave.impl_getpath(context) + slave.reset_cache(slave, + spath, + obj, + type_, + resetted_opts) - def _getattr(self, name, suffix=undefined, context=undefined, dyn=True): - return super(MasterSlaves, self)._getattr(name, suffix, context, dyn) + def _getattr(self, + name, + setting_properties, + suffix=undefined, + context=undefined, + dyn=True): + return super(MasterSlaves, self)._getattr(name, + setting_properties, + suffix, + context, + dyn) - def impl_validate(self, context, force_permissive, setting_properties, masterlen=None, - slavelen=None, opt=None, setitem=False): + def impl_validate(self, + context, + force_permissive, + setting_properties, + masterlen=None, + slavelen=None, + opt=None, + setitem=False): values = context.cfgimpl_get_values() if masterlen is None: master = self.getmaster(opt) @@ -1021,27 +1059,11 @@ class MasterSlaves(OptionDescription): slavelen = values._p_.get_max_length(slave_path) self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), master) - def impl_validate_value(self, option, value, context): + def impl_validate_value(self, + option, + value, + context): if option.impl_is_master_slaves('master') and isinstance(value, list): if len(value) < context._impl_length: return ValueError(_('cannot reduce length of master "{}"' '').format(option.impl_get_display_name())) - - -def _impl_getpaths(klass, include_groups, _currpath): - """returns a list of all paths in klass, recursively - _currpath should not be provided (helps with recursion) - """ - if _currpath is None: - _currpath = [] - paths = [] - for option in klass._impl_getchildren(): - attr = option.impl_getname() - if option.impl_is_optiondescription(): - if include_groups: - paths.append('.'.join(_currpath + [attr])) - paths += option.impl_getpaths(include_groups=include_groups, - _currpath=_currpath + [attr]) - else: - paths.append('.'.join(_currpath + [attr])) - return paths diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 8c310cf..cbdba5d 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -591,7 +591,11 @@ class Settings(object): #mandatory if 'mandatory' in properties or 'empty' in properties: value = 'pouet' - if self.validate_mandatory(opt_or_descr, index, value, properties): + if self.validate_mandatory(opt_or_descr, + index, + value, + setting_properties, + properties): properties += set(['mandatory']) - set(['empty']) else: properties -= set(['mandatory', 'empty']) @@ -617,15 +621,21 @@ class Settings(object): datas, opt_type) - def validate_mandatory(self, opt, index, value, properties): + def validate_mandatory(self, + opt, + index, + value, + setting_properties, + properties): values = self._getcontext().cfgimpl_get_values() - return 'mandatory' in properties and values.isempty(opt, - value, - index=index) or \ - 'empty' in properties and values.isempty(opt, - value, - force_allow_empty_list=True, - index=index) + return 'mandatory' in setting_properties and \ + ('mandatory' in properties and values.isempty(opt, + value, + index=index) or \ + 'empty' in properties and values.isempty(opt, + value, + force_allow_empty_list=True, + index=index)) #____________________________________________________________ # read only/read write diff --git a/tiramisu/storage/dictionary/value.py b/tiramisu/storage/dictionary/value.py index 7b54c2c..d23e215 100644 --- a/tiramisu/storage/dictionary/value.py +++ b/tiramisu/storage/dictionary/value.py @@ -71,6 +71,8 @@ class Values(Cache): """set value for a path a specified value must be associated to an owner """ + if value == 'y': + raise Exception('pouet') values = [] vidx = None @@ -210,45 +212,48 @@ class Values(Cache): """get owner for a path return: owner object """ - owner = self._getvalue(path, - 3, - index) + owner, value = self._getvalue(path, + index, + with_value) if owner is undefined: owner = default if with_value: - return owner, self._getvalue(path, - 2, - index) + return owner, value else: return owner def _getvalue(self, path, - nb, - index): + index, + with_value): """ _values == ((path1, path2), ((idx1_1, idx1_2), None), ((value1_1, value1_2), value2), ((owner1_1, owner1_2), owner2)) """ + value = undefined if path in self._values[0]: path_idx = self._values[0].index(path) indexes = self._values[1][path_idx] if indexes is None: if index is not None: # pragma: no cover raise ValueError('index is forbidden for {}'.format(path)) - value = self._values[nb][path_idx] + owner = self._values[3][path_idx] + if with_value: + value = self._values[2][path_idx] else: if index is None: # pragma: no cover raise ValueError('index is mandatory for {}'.format(path)) if index in indexes: subidx = indexes.index(index) - value = self._values[nb][path_idx][subidx] + owner = self._values[3][path_idx][subidx] + if with_value: + value = self._values[2][path_idx][subidx] else: - value = undefined + owner = undefined else: - value = undefined + owner = undefined if isinstance(value, tuple): value = list(value) - return value + return owner, value def set_information(self, key, value): """updates the information's attribute diff --git a/tiramisu/value.py b/tiramisu/value.py index 7192fc4..f09ccca 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -165,7 +165,7 @@ class Values(object): display_warnings=display_warnings, setting_properties=setting_properties) if config_error is not None: - return config_error + raise config_error return value def getvalue(self, @@ -227,7 +227,8 @@ class Values(object): return self._getdefaultvalue(opt, path, index, - True) + True, + setting_properties) def _getdefaultvalue(self, opt, @@ -268,6 +269,7 @@ class Values(object): context=context, callback=callback, callback_params=callback_params, + setting_properties=setting_properties, index=index, validate=validate) if isinstance(value, list) and index is not None: @@ -426,6 +428,7 @@ class Values(object): if settings.validate_mandatory(opt, index, value, + setting_properties, properties): datas = {'opt': opt, 'path': path, @@ -539,9 +542,10 @@ class Values(object): #FIXME: validate_meta ne marche que si == False ou undefined ! if validate_meta is not False and validate_meta is not undefined: raise Exception('poeut') - if not isinstance(opt, Option) and not isinstance(opt, - DynSymLinkOption): - raise ConfigError(_('owner only avalaible for an option')) + #if not isinstance(opt, Option) and not isinstance(opt, + # DynSymLinkOption): + # raise ConfigError(_('owner only avalaible for an option')) + #FIXME pas defaut fait ?? context = self._getcontext() if self_properties is undefined: self_properties = context.cfgimpl_get_settings().getproperties(opt, @@ -713,7 +717,9 @@ class Values(object): subconfig.cfgimpl_get_description().pop(opt, path, self, - index) + index, + setting_properties, + force_permissive=force_permissive) #______________________________________________________________________ # information