From 059c5f7407f10a483b54a02b58a89a0d6e196aab Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Sat, 18 Nov 2023 21:12:13 +0100 Subject: [PATCH] undefined is no more a valid value and Calculation could be a valid value --- tests/test_cache.py | 18 +--- tests/test_config.py | 8 +- tests/test_mandatory.py | 6 +- tests/test_option_callback.py | 131 ++++++++++++++++++++++++--- tests/test_option_default.py | 6 +- tests/test_option_setting.py | 2 +- tests/test_option_validator.py | 10 +- tests/test_submulti.py | 32 +++---- tiramisu/api.py | 11 +-- tiramisu/autolib.py | 3 + tiramisu/config.py | 1 + tiramisu/option/leadership.py | 2 +- tiramisu/option/optiondescription.py | 6 +- tiramisu/value.py | 70 ++++++++------ 14 files changed, 205 insertions(+), 101 deletions(-) diff --git a/tests/test_cache.py b/tests/test_cache.py index 2911e43..f46b877 100644 --- a/tests/test_cache.py +++ b/tests/test_cache.py @@ -352,18 +352,6 @@ def test_cache_callback(): 'val3': {None: ('new2', None)}, 'val4': {None: ('new3', None)}, 'val5': {None: (['yes'], None)}}) - cfg.option('val5').value.set([undefined, 'new4']) - compare(values.get_cached(), {'val1': {None: ('new', None)}, - 'val2': {None: ('new', None)}, - 'val3': {None: ('new2', None)}, - 'val4': {None: ('new3', None)}, - 'val5': {None: (['yes', 'new4'], None)}}) - cfg.value.dict() - compare(values.get_cached(), {'val1': {None: ('new', None)}, - 'val2': {None: ('new', None)}, - 'val3': {None: ('new2', None)}, - 'val4': {None: ('new3', None)}, - 'val5': {None: (['yes', 'new4'], None)}}) # assert not list_sessions() @@ -394,7 +382,7 @@ def test_cache_leader_and_followers(): # len is 0 so don't get any value compare(values.get_cached(), {'val1.val1': {None: ([], None)}}) # - cfg.option('val1.val1').value.set([undefined]) + cfg.option('val1.val1').value.set([None]) val_val2_props = {idx_val2: (val1_val2_props, None), None: (set(), None)} compare(settings.get_cached(), {None: {None: (set(global_props), None)}, 'val1.val1': {None: (val1_val1_props, None)}, @@ -412,7 +400,7 @@ def test_cache_leader_and_followers(): compare(values.get_cached(), {'val1.val1': {None: ([None], None)}, 'val1.val2': {idx_val2: (val_val2, None)}, }) - cfg.option('val1.val1').value.set([undefined, undefined]) + cfg.option('val1.val1').value.set([None, None]) cfg.value.dict() cfg.option('val1.val2', 1).value.set('oui') compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)}}) @@ -444,7 +432,7 @@ def test_cache_leader_callback(): 'val1.val1': {None: (val1_val1_props, None)}, }) compare(values.get_cached(), {'val1.val1': {None: ([], None)}}) - cfg.option('val1.val1').value.set([undefined]) + cfg.option('val1.val1').value.set([None]) compare(settings.get_cached(), {None: {None: (set(global_props), None)}, 'val1.val1': {None: (val1_val1_props, None)}, }) diff --git a/tests/test_config.py b/tests/test_config.py index 148c2cc..d151ea3 100644 --- a/tests/test_config.py +++ b/tests/test_config.py @@ -264,12 +264,12 @@ def test_get_modified_values(): compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}}) cfg.option('od.g4').value.set(False) compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}, 'od.g4': {None: [False, 'user']}}) - cfg.option('od.g4').value.set(undefined) + cfg.option('od.g4').value.set(True) compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}, 'od.g4': {None: [True, 'user']}}) cfg.option('od.g4').value.reset() compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}}) assert cfg.option('od.g6').ismulti() - cfg.option('od.g6').value.set([undefined]) + cfg.option('od.g6').value.set([None]) compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}, 'od.g6': {None: [[None], 'user']}}) cfg.option('od.g6').value.set([]) compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}, 'od.g6': {None: [[], 'user']}}) @@ -329,10 +329,10 @@ def test_config_multi(config_type): cfg = get_config(cfg, config_type) assert cfg.option('test1').value.get() == [] assert cfg.option('test2').value.get() == [] - cfg.option('test2').value.set([undefined]) + cfg.option('test2').value.set([1]) assert cfg.option('test2').value.get() == [1] assert cfg.option('test3').value.get() == [2] - cfg.option('test3').value.set([undefined, undefined]) + cfg.option('test3').value.set([2, 1]) assert cfg.option('test3').value.get() == [2, 1] # assert not list_sessions() diff --git a/tests/test_mandatory.py b/tests/test_mandatory.py index a5624b3..f568434 100644 --- a/tests/test_mandatory.py +++ b/tests/test_mandatory.py @@ -6,7 +6,7 @@ do_autopath() import pytest from tiramisu import Config from tiramisu import IntOption, StrOption, OptionDescription, DynOptionDescription, PasswordOption, UsernameOption, \ - SymLinkOption, Leadership, undefined, Calculation, Params, \ + SymLinkOption, Leadership, Calculation, Params, \ ParamOption, ParamValue, ParamIndex, calc_value from tiramisu.error import PropertiesOptionError, ConfigError from tiramisu.setting import groups @@ -457,7 +457,7 @@ def test_mandatory_leader_empty(): cfg.property.read_write() assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] # - cfg.option('ip_admin_eth0.ip_admin_eth0').value.set([undefined]) + cfg.option('ip_admin_eth0.ip_admin_eth0').value.set([None]) assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [None] assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None cfg.property.read_only() @@ -503,7 +503,7 @@ def test_mandatory_warnings_leader_empty(): od1 = OptionDescription('o', '', [interface1]) cfg = Config(od1) cfg.property.read_write() - cfg.option('ip_admin_eth0.ip_admin_eth0').value.set([undefined]) + cfg.option('ip_admin_eth0.ip_admin_eth0').value.set([None]) assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [None] assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None compare(cfg.value.mandatory(), ['ip_admin_eth0.ip_admin_eth0']) diff --git a/tests/test_option_callback.py b/tests/test_option_callback.py index 96003a6..620814f 100644 --- a/tests/test_option_callback.py +++ b/tests/test_option_callback.py @@ -299,6 +299,23 @@ def test_callback(config_type): # assert not list_sessions() +def test_callback_set(config_type): + val1 = StrOption('val1', "") + val2 = StrOption('val2', "") + od1 = OptionDescription('rootconfig', '', [val1, val2]) + cfg = Config(od1) + cfg.property.read_write() + cfg = get_config(cfg, config_type) + cfg.option('val2').value.set(Calculation(return_value, Params(ParamOption(val1)))) + assert cfg.option('val2').value.get() == None + # + cfg.option('val1').value.set('new-val') + assert cfg.option('val2').value.get() == 'new-val' + # + cfg.option('val1').value.reset() + assert cfg.option('val2').value.get() == None + + def test_params(): with pytest.raises(ValueError): Params('str') @@ -541,6 +558,21 @@ def test_callback_multi(config_type): # assert not list_sessions() +def test_callback_multi_set(config_type): + val1 = StrOption('val1', "", multi=True) + od1 = OptionDescription('rootconfig', '', [val1]) + cfg = Config(od1) + cfg.property.read_write() + cfg = get_config(cfg, config_type) + assert cfg.option('val1').value.get() == [] + # + cfg.option('val1').value.set([Calculation(return_val)]) + assert cfg.option('val1').value.get() == ['val'] + cfg.option('val1').value.reset() + assert cfg.option('val1').value.get() == [] +# assert not list_sessions() + + def test_callback_multi_value(config_type): val1 = StrOption('val1', "", ['val'], multi=True) option = ParamOption(val1) @@ -577,6 +609,30 @@ def test_callback_multi_value(config_type): # assert not list_sessions() +def test_callback_multi_value_set(config_type): + val1 = StrOption('val1', "", ['val1'], multi=True) + val2 = StrOption('val2', "", ['val2'], multi=True) + od1 = OptionDescription('rootconfig', '', [val1, val2]) + cfg = Config(od1) + cfg.property.read_write() + cfg = get_config(cfg, config_type) + assert cfg.option('val1').value.get() == ['val1'] + assert cfg.option('val2').value.get() == ['val2'] + # + cfg.option('val2').value.set(Calculation(return_value, Params(ParamOption(val1)))) + assert cfg.option('val1').value.get() == ['val1'] + assert cfg.option('val2').value.get() == ['val1'] + # + cfg.option('val1').value.set(['val1', 'yes']) + assert cfg.option('val2').value.get() == ['val1', 'yes'] + assert cfg.option('val2').value.get() == ['val1', 'yes'] + # + cfg.option('val2').value.reset() + assert cfg.option('val1').value.get() == ['val1', 'yes'] + assert cfg.option('val2').value.get() == ['val2'] +# assert not list_sessions() + + def test_callback_multi_list(config_type): val1 = StrOption('val1', "", Calculation(return_list), multi=True, properties=('notunique',)) od1 = OptionDescription('rootconfig', '', [val1]) @@ -611,7 +667,7 @@ def test_callback_multi_callback(config_type): cfg.property.read_write() cfg = get_config(cfg, config_type) assert cfg.option('val1.val1').value.get() == ['val'] - cfg.option('val1.val1').value.set(['val1', undefined]) + cfg.option('val1.val1').value.set(['val1', None]) assert cfg.option('val1.val1').value.get() == ['val1', None] # assert not list_sessions() @@ -624,27 +680,53 @@ def test_callback_multi_callback_default(config_type): cfg.property.read_write() cfg = get_config(cfg, config_type) assert cfg.option('val1.val1').value.get() == [] - cfg.option('val1.val1').value.set(['val1', undefined]) + cfg.option('val1.val1').value.set(['val1', 'val']) assert cfg.option('val1.val1').value.get() == ['val1', 'val'] # assert not list_sessions() def test_callback_leader_and_followers_leader(config_type): - val1 = StrOption('val1', "", default=[Calculation(return_val)], default_multi=Calculation(return_val), multi=True, properties=('notunique',)) - val2 = StrOption('val2', "", multi=True) - interface1 = Leadership('val1', '', [val1, val2]) - od1 = OptionDescription('rootconfig', '', [interface1]) + val1 = StrOption('val1', "", default=['val'], multi=True) + val2 = StrOption('val2', "", default=Calculation(return_value, Params(ParamOption(val1))), default_multi=Calculation(return_val), multi=True, properties=('notunique',)) + val3 = StrOption('val3', "", multi=True) + interface1 = Leadership('val2', '', [val2, val3]) + od1 = OptionDescription('rootconfig', '', [val1, interface1]) cfg = Config(od1) cfg.property.read_write() cfg = get_config(cfg, config_type) - assert cfg.option('val1.val1').value.get() == ['val'] - cfg.option('val1.val1').value.set([undefined, undefined]) - assert cfg.option('val1.val1').value.get() == ['val', 'val'] - assert cfg.option('val1.val2', 0).value.get() == None - assert cfg.option('val1.val2', 1).value.get() == None + assert cfg.option('val1').value.get() == ['val'] + assert cfg.option('val2.val2').value.get() == ['val'] + # + cfg.option('val1').value.set(['val1', 'val2']) + assert cfg.option('val1').value.get() == ['val1', 'val2'] + assert cfg.option('val2.val2').value.get() == ['val1', 'val2'] + assert cfg.option('val2.val3', 0).value.get() == None + assert cfg.option('val2.val3', 1).value.get() == None + # + cfg.option('val1').value.set(['val']) + assert cfg.option('val2.val2').value.get() == ['val'] + assert cfg.option('val2.val3', 0).value.get() == None # assert not list_sessions() +def test_callback_leader_and_followers_leader_set(config_type): + val1 = StrOption('val1', "", default=['val1', 'val2'], multi=True) + val2 = StrOption('val2', "", multi=True) + val3 = StrOption('val3', "", multi=True) + interface1 = Leadership('val2', '', [val2, val3]) + od1 = OptionDescription('rootconfig', '', [val1, interface1]) + cfg = Config(od1) + cfg.property.read_write() + cfg = get_config(cfg, config_type) + assert cfg.option('val1').value.get() == ['val1', 'val2'] + # + cfg.option('val2.val2').value.set(Calculation(return_value, Params(ParamOption(val1)))) + assert cfg.option('val2.val2').value.get() == ['val1', 'val2'] + assert cfg.option('val2.val3', 0).value.get() == None + assert cfg.option('val2.val3', 1).value.get() == None + #assert not list_sessions() + + def test_callback_follower(config_type): val1 = StrOption('val1', "", multi=True) val2 = StrOption('val2', "", Calculation(return_value3, Params(ParamValue(['string', 'new']), {'index': ParamIndex()})), multi=True) @@ -670,6 +752,28 @@ def test_callback_follower(config_type): # assert not list_sessions() +def test_callback_follower_set(config_type): + val1 = StrOption('val1', "") + val2 = StrOption('val2', "", default=['val1'], multi=True) + val3 = StrOption('val3', "", multi=True) + interface1 = Leadership('val2', '', [val2, val3]) + od1 = OptionDescription('rootconfig', '', [val1, interface1]) + cfg = Config(od1) + cfg.property.read_write() + cfg = get_config(cfg, config_type) + cfg.option('val1').value.set('val') + assert cfg.option('val1').value.get() == 'val' + assert cfg.option('val2.val2').value.get() == ['val1'] + assert cfg.option('val2.val3', 0).value.get() == None + # + cfg.option('val2.val3', 0).value.set(Calculation(return_value, Params(ParamOption(val1)))) + assert cfg.option('val2.val3', 0).value.get() == 'val' + # + cfg.option('val1').value.set('val1') + assert cfg.option('val2.val3', 0).value.get() == 'val1' +# assert not list_sessions() + + def test_callback_leader_and_followers_leader2(config_type): val1 = StrOption('val1', "", multi=True) val2 = StrOption('val2', "", multi=True, default_multi='val2') @@ -704,7 +808,7 @@ def test_callback_leader_and_followers_leader_mandatory1(config_type): cfg.send() cfg_ori.property.read_write() cfg = get_config(cfg_ori, config_type) - cfg.option('val1.val1').value.set([undefined, 'val3']) + cfg.option('val1.val1').value.set(['val', 'val3']) if config_type == 'tiramisu-api': cfg.send() cfg_ori.property.read_only() @@ -860,7 +964,8 @@ def test_callback_leader_and_followers_leader_list(config_type): assert cfg.option('val1.val1').value.get() == ['val', 'val'] assert cfg.option('val1.val2', 0).value.get() == None assert cfg.option('val1.val2', 1).value.get() == None - cfg.option('val1.val1').value.set(['val', 'val', undefined]) + default_multi = cfg.option('val1.val1').defaultmulti() + cfg.option('val1.val1').value.set(['val', 'val', default_multi]) assert cfg.option('val1.val1').value.get() == ['val', 'val', None] assert cfg.option('val1.val2', 0).value.get() == None assert cfg.option('val1.val2', 1).value.get() == None diff --git a/tests/test_option_default.py b/tests/test_option_default.py index 965b3d3..5ff883b 100644 --- a/tests/test_option_default.py +++ b/tests/test_option_default.py @@ -115,8 +115,10 @@ def test_force_default_on_freeze_multi(): cfg_ori.property.read_write() cfg = cfg_ori # FIXME cfg = get_config(cfg_ori, config_type) - cfg.option('dummy1').value.set([undefined, True]) - cfg.option('dummy2').value.set([undefined, False]) + default = cfg.option('dummy1').value.default()[0] + cfg.option('dummy1').value.set([default, True]) + default = cfg.option('dummy2').value.default()[0] + cfg.option('dummy2').value.set([default, False]) owner = cfg.owner.get() assert cfg.option('dummy1').owner.get() == owner assert cfg.option('dummy2').owner.get() == owner diff --git a/tests/test_option_setting.py b/tests/test_option_setting.py index 1cdf17b..85aca5d 100644 --- a/tests/test_option_setting.py +++ b/tests/test_option_setting.py @@ -143,7 +143,7 @@ def test_setitem(config_type): od1 = OptionDescription("options", "", [s]) cfg = Config(od1) cfg = get_config(cfg, config_type) - cfg.option('string').value.set([undefined, 'foo']) + cfg.option('string').value.set(['string', 'foo']) assert cfg.option('string').value.get() == ['string', 'foo'] # assert not list_sessions() diff --git a/tests/test_option_validator.py b/tests/test_option_validator.py index 8c313fa..40c26ba 100644 --- a/tests/test_option_validator.py +++ b/tests/test_option_validator.py @@ -8,7 +8,7 @@ from tiramisu import BoolOption, StrOption, IPOption, NetmaskOption, NetworkOpti IntOption, OptionDescription, Leadership, Config, Params, ParamValue, ParamOption, \ ParamSelfOption, ParamIndex, ParamInformation, ParamSelfInformation, ParamSelfOption, Calculation, \ valid_ip_netmask, valid_network_netmask, \ - valid_in_network, valid_broadcast, valid_not_equal, undefined + valid_in_network, valid_broadcast, valid_not_equal from tiramisu.setting import groups from tiramisu.error import ValueErrorWarning, ConfigError, PropertiesOptionError from tiramisu.i18n import _ @@ -713,7 +713,7 @@ def test_validator_network_netmask_multi_follower_default_multi(config_type): cfg = Config(od2) cfg.property.read_write() cfg = get_config(cfg, config_type) - cfg.option('a.a').value.set([undefined]) + cfg.option('a.a').value.set(['192.168.1.0']) assert cfg.option('a.a').value.get() == ['192.168.1.0'] assert cfg.option('a.b', 0).value.get() == '255.255.255.0' # assert not list_sessions() @@ -745,10 +745,10 @@ def test_validator_network_netmask_multi_follower_default(config_type): cfg.option('a.b', 0).value.set([u'192.168.1.0']) with pytest.raises(ValueError): cfg.option('a.b', 1).value.set([u'192.168.1.1']) - cfg.option('a.a').value.set(['192.168.1.0', undefined]) + cfg.option('a.a').value.set(['192.168.1.0', '192.168.1.1']) cfg.option('a.b', 0).value.set('255.255.255.0') cfg.option('a.b', 1).value.set('255.255.255.255') - cfg.option('a.a').value.set([u'192.168.1.0', u'192.168.1.1']) + cfg.option('a.a').value.set(['192.168.1.0', '192.168.1.1']) # assert not list_sessions() @@ -790,7 +790,7 @@ def test_validator_network_netmask_multi_follower_callback(config_type): cfg.option('a.b', 0).value.get() with pytest.raises(ValueError): cfg.option('a.b', 1).value.get() - cfg.option('a.a').value.set(['192.168.1.0', undefined]) + cfg.option('a.a').value.set(['192.168.1.0', '192.168.1.1']) cfg.option('a.b', 0).value.set('255.255.255.0') cfg.option('a.b', 1).value.set('255.255.255.255') cfg.option('a.a').value.set(['192.168.1.0', '192.168.1.1']) diff --git a/tests/test_submulti.py b/tests/test_submulti.py index 93d5a3d..4e2f1b2 100644 --- a/tests/test_submulti.py +++ b/tests/test_submulti.py @@ -7,7 +7,7 @@ import warnings from tiramisu.setting import groups, owners from tiramisu import StrOption, IntOption, OptionDescription, submulti, Leadership, Config, \ - MetaConfig, undefined, Params, ParamOption, Calculation + MetaConfig, Params, ParamOption, Calculation from tiramisu.error import LeadershipError, PropertiesOptionError @@ -107,26 +107,26 @@ def test_append_submulti(): owner = cfg.owner.get() assert cfg.option('multi').value.get() == [] assert cfg.option('multi').owner.get() == owners.default - cfg.option('multi').value.set([undefined]) + cfg.option('multi').value.set([[]]) assert cfg.option('multi').owner.get() == owner assert cfg.option('multi').value.get() == [[]] - cfg.option('multi').value.set([undefined, ['no']]) + cfg.option('multi').value.set([[], ['no']]) assert cfg.option('multi').value.get() == [[], ['no']] # assert cfg.option('multi2').value.get() == [] assert cfg.option('multi2').owner.get() == owners.default - cfg.option('multi2').value.set([undefined]) + cfg.option('multi2').value.set([cfg.option('multi2').defaultmulti()]) assert cfg.option('multi2').owner.get() == owner assert cfg.option('multi2').value.get() == [['yes']] - cfg.option('multi2').value.set([undefined, ['no']]) + cfg.option('multi2').value.set([cfg.option('multi2').defaultmulti(), ['no']]) assert cfg.option('multi2').value.get() == [['yes'], ['no']] # assert cfg.option('multi3').value.get() == [['yes']] assert cfg.option('multi3').owner.get() == owners.default - cfg.option('multi3').value.set([undefined, undefined]) + cfg.option('multi3').value.set([cfg.option('multi2').defaultmulti(), []]) assert cfg.option('multi3').owner.get() == owner assert cfg.option('multi3').value.get() == [['yes'], []] - cfg.option('multi3').value.set([undefined, undefined, ['no']]) + cfg.option('multi3').value.set([cfg.option('multi2').defaultmulti(), [], ['no']]) assert cfg.option('multi3').value.get() == [['yes'], [], ['no']] # assert not list_sessions() @@ -193,7 +193,7 @@ def test_callback_submulti_str(): owner = cfg.owner.get() assert cfg.option('multi').owner.get() == owners.default assert cfg.option('multi').value.get() == [['val']] - cfg.option('multi').value.set([['val'], undefined]) + cfg.option('multi').value.set([['val'], cfg.option('multi').defaultmulti()]) assert cfg.option('multi').owner.get() == owner assert cfg.option('multi').value.get() == [['val'], ['val']] cfg.option('multi').value.reset() @@ -209,13 +209,13 @@ def test_callback_submulti_list(): owner = cfg.owner.get() assert cfg.option('multi').value.get() == [['val', 'val']] assert cfg.option('multi').owner.get() == owners.default - cfg.option('multi').value.set([['val', 'val'], undefined]) - #assert cfg.option('multi').owner.get() == owner - #assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val']] - #cfg.option('multi').value.set([['val', 'val'], undefined, undefined]) - #assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val'], ['val', 'val']] - #cfg.option('multi').value.reset() - #assert cfg.option('multi').owner.get() == owners.default + cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').defaultmulti()]) + assert cfg.option('multi').owner.get() == owner + assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val']] + cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').defaultmulti(), cfg.option('multi').defaultmulti()]) + assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val'], ['val', 'val']] + cfg.option('multi').value.reset() + assert cfg.option('multi').owner.get() == owners.default # assert not list_sessions() @@ -227,7 +227,7 @@ def test_callback_submulti_list_list(): owner = cfg.owner.get() assert cfg.option('multi').value.get() == [['val', 'val']] assert cfg.option('multi').owner.get() == owners.default - cfg.option('multi').value.set([['val', 'val'], undefined]) + cfg.option('multi').value.set([['val', 'val'], cfg.option('multi').defaultmulti()]) assert cfg.option('multi').owner.get() == owner assert cfg.option('multi').value.get() == [['val', 'val'], []] cfg.option('multi').value.reset() diff --git a/tiramisu/api.py b/tiramisu/api.py index 289a7d4..46bce7f 100644 --- a/tiramisu/api.py +++ b/tiramisu/api.py @@ -28,6 +28,7 @@ from .setting import ConfigBag, OptionBag, owners, groups, undefined, \ from .config import KernelConfig, KernelGroupConfig, KernelMetaConfig, KernelMixConfig from .option import RegexpOption, OptionDescription, ChoiceOption from .todict import TiramisuDict +from .autolib import Calculation TIRAMISU_VERSION = 4 @@ -615,15 +616,7 @@ class TiramisuOptionValue(CommonTiramisuOption): """Change option's value""" option_bag = options_bag[-1] values = option_bag.config_bag.context.get_values() - if isinstance(value, list): - while undefined in value: - idx = value.index(undefined) - soption_bag = option_bag.copy() - soption_bag.index = idx - value[idx] = values.get_default_value(soption_bag) - elif value == undefined: - value = values.get_default_value(option_bag) - if option_bag.option.impl_is_leader() and \ + if not isinstance(value, Calculation) and option_bag.option.impl_is_leader() and \ len(value) < self._config_bag.context.get_length_leadership(options_bag[-2]): raise LeadershipError(_('cannot reduce length of the leader "{}"' '').format(option_bag.option.impl_get_display_name())) diff --git a/tiramisu/autolib.py b/tiramisu/autolib.py index e355955..91e9ece 100644 --- a/tiramisu/autolib.py +++ b/tiramisu/autolib.py @@ -212,6 +212,9 @@ class Calculation: for_settings=for_settings, ) + def __deepcopy__(x, memo): + return x + def manager_callback(callback: Callable, param: Param, diff --git a/tiramisu/config.py b/tiramisu/config.py index e12387d..318a715 100644 --- a/tiramisu/config.py +++ b/tiramisu/config.py @@ -31,6 +31,7 @@ from .setting import OptionBag, ConfigBag, Settings, undefined, groups from .value import Values, owners from .i18n import _ from .cacheobj import Cache +from .autolib import Calculation class _SubConfig: diff --git a/tiramisu/option/leadership.py b/tiramisu/option/leadership.py index 9737e52..ff677e2 100644 --- a/tiramisu/option/leadership.py +++ b/tiramisu/option/leadership.py @@ -186,7 +186,7 @@ class Leadership(OptionDescription): ) values.set_storage_value(foption_bag_index.path, index, - values.get_value(foption_bag_index), + values.get_value(foption_bag_index)[0], owner, ) diff --git a/tiramisu/option/optiondescription.py b/tiramisu/option/optiondescription.py index 0d31088..72c5e50 100644 --- a/tiramisu/option/optiondescription.py +++ b/tiramisu/option/optiondescription.py @@ -144,7 +144,7 @@ class CacheOptionDescription(BaseOption): leader = option.impl_get_leadership().get_leader() for leader_option_bag in do_option_bags(leader): leader_option_bag.properties = frozenset() - follower_len = len(values.get_value(leader_option_bag)) + follower_len = len(values.get_value(leader_option_bag)[0]) if option.issubdyn(): subpath = leader_option_bag.option.rootpath doption = option.to_dynoption(subpath, @@ -162,7 +162,7 @@ class CacheOptionDescription(BaseOption): ) if values.hasvalue(subpath, index=index): continue - value = values.get_value(option_bag) + value = values.get_value(option_bag)[0] if value is None: continue values.set_storage_value(subpath, @@ -173,7 +173,7 @@ class CacheOptionDescription(BaseOption): else: for option_bag in do_option_bags(option): option_bag.properties = frozenset() - value = values.get_value(option_bag) + value = values.get_value(option_bag)[0] if value is None: continue if values.hasvalue(option_bag.path): diff --git a/tiramisu/value.py b/tiramisu/value.py index d16c52b..7f337c3 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -65,7 +65,7 @@ class Values: ) # no cached value so get value if not is_cached: - value = self.get_value(option_bag) + value, has_calculation = self.get_value(option_bag) # validates and warns value if not validated: validate = option_bag.option.impl_validate(value, @@ -78,7 +78,7 @@ class Values: check_error=False, ) # set value to cache - if not is_cached: + if not is_cached and not has_calculation: cache.setcache(option_bag, value, validated=validate, @@ -106,7 +106,10 @@ class Values: # the value is a default value # get it value = self.get_default_value(option_bag) - return value + value, has_calculation = self.get_calculated_value(option_bag, + value, + ) + return value, has_calculation def get_default_value(self, option_bag: OptionBag, @@ -122,9 +125,9 @@ class Values: return moption_bag.config_bag.context.get_values().get_cached_value(moption_bag) # now try to get calculated value: - value = self.get_calculated_value(option_bag, - option_bag.option.impl_getdefault(), - ) + value, _has_calculation = self.get_calculated_value(option_bag, + option_bag.option.impl_getdefault(), + ) if option_bag.index is not None and isinstance(value, (list, tuple)) \ and (not option_bag.option.impl_is_submulti() or \ not value or isinstance(value[0], list)): @@ -135,9 +138,9 @@ class Values: else: # no value for this index, retrieve default multi value # default_multi is already a list for submulti - value = self.get_calculated_value(option_bag, - option_bag.option.impl_getdefault_multi(), - ) + value, _has_calculation = self.get_calculated_value(option_bag, + option_bag.option.impl_getdefault_multi(), + ) return value def get_calculated_value(self, @@ -147,6 +150,7 @@ class Values: ) -> Any: """value could be a calculation, in this case do calculation """ + has_calculation = False if isinstance(value, Calculation): try: value = value.execute(option_bag) @@ -154,18 +158,21 @@ class Values: msg = _(f'error when calculating "{option_bag.option.impl_get_display_name()}": ' f'{err} : {option_bag.path}') raise ConfigError(msg) from err + has_calculation = True elif isinstance(value, list): # if value is a list, do subcalculation for idx, val in enumerate(value): - value[idx] = self.get_calculated_value(option_bag, - val, - reset_cache=False, - ) + value[idx], _has_calculation = self.get_calculated_value(option_bag, + val, + reset_cache=False, + ) + if _has_calculation: + has_calculation = True if reset_cache: self.reset_cache_after_calculation(option_bag, value, ) - return value + return value, has_calculation #______________________________________________________________________ def check_force_to_metaconfig(self, @@ -248,27 +255,31 @@ class Values: """set value to option """ owner = self.get_context_owner() - if 'validator' in option_bag.config_bag.properties: - self.setvalue_validation(value, - option_bag, - ) + setting_properties = option_bag.config_bag.properties + ori_value = value + if 'validator' in setting_properties: + value, has_calculation = self.setvalue_validation(value, + option_bag, + ) - if isinstance(value, list): + elif isinstance(value, list): # copy value = value.copy() self._setvalue(option_bag, - value, + ori_value, owner, ) - setting_properties = option_bag.config_bag.properties validator = 'validator' in setting_properties and \ 'demoting_error_warning' not in setting_properties - if validator: + if validator and not has_calculation: cache = option_bag.config_bag.context.get_values_cache() cache.setcache(option_bag, value, validated=validator, ) + elif 'validator' in setting_properties and has_calculation: + cache = option_bag.config_bag.context.get_values_cache() + cache.delcache(option_bag.path) if 'force_store_value' in setting_properties and option_bag.option.impl_is_leader(): leader = option_bag.option.impl_get_leadership() leader.follower_force_store_value(value, @@ -286,10 +297,10 @@ class Values: # First validate properties with this value opt = option_bag.option settings.validate_frozen(option_bag) - val = self.get_calculated_value(option_bag, - value, - False, - ) + val, has_calculation = self.get_calculated_value(option_bag, + value, + False, + ) settings.validate_mandatory(val, option_bag, ) @@ -300,10 +311,11 @@ class Values: ) if 'warnings' in option_bag.config_bag.properties: # No error found so emit warnings - opt.impl_validate(value, + opt.impl_validate(val, option_bag, check_error=False, ) + return val, has_calculation def _setvalue(self, option_bag: OptionBag, @@ -362,7 +374,7 @@ class Values: option_bag.config_bag, properties=frozenset(), ) - indexes = range(len(self.get_value(loption_bag))) + indexes = range(len(self.get_value(loption_bag)[0])) else: indexes = [None] for index in indexes: @@ -370,7 +382,7 @@ class Values: index, option_bag.config_bag, ) - default_value = [self.get_value(coption_bag), owners.forced] + default_value = [self.get_value(coption_bag)[0], owners.forced] self._values.setdefault(coption_bag.path, {})[index] = default_value def _get_modified_parent(self,