undefined is no more a valid value and Calculation could be a valid value

This commit is contained in:
egarette@silique.fr 2023-11-18 21:12:13 +01:00
parent 73c8db5839
commit 059c5f7407
14 changed files with 205 additions and 101 deletions

View file

@ -352,18 +352,6 @@ def test_cache_callback():
'val3': {None: ('new2', None)}, 'val3': {None: ('new2', None)},
'val4': {None: ('new3', None)}, 'val4': {None: ('new3', None)},
'val5': {None: (['yes'], 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() # assert not list_sessions()
@ -394,7 +382,7 @@ def test_cache_leader_and_followers():
# len is 0 so don't get any value # len is 0 so don't get any value
compare(values.get_cached(), {'val1.val1': {None: ([], None)}}) 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)} val_val2_props = {idx_val2: (val1_val2_props, None), None: (set(), None)}
compare(settings.get_cached(), {None: {None: (set(global_props), None)}, compare(settings.get_cached(), {None: {None: (set(global_props), None)},
'val1.val1': {None: (val1_val1_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)}, compare(values.get_cached(), {'val1.val1': {None: ([None], None)},
'val1.val2': {idx_val2: (val_val2, 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.value.dict()
cfg.option('val1.val2', 1).value.set('oui') 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)}}) 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)}, 'val1.val1': {None: (val1_val1_props, None)},
}) })
compare(values.get_cached(), {'val1.val1': {None: ([], 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)}, compare(settings.get_cached(), {None: {None: (set(global_props), None)},
'val1.val1': {None: (val1_val1_props, None)}, 'val1.val1': {None: (val1_val1_props, None)},
}) })

View file

@ -264,12 +264,12 @@ def test_get_modified_values():
compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}}) compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}})
cfg.option('od.g4').value.set(False) cfg.option('od.g4').value.set(False)
compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}, 'od.g4': {None: [False, 'user']}}) 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']}}) compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}, 'od.g4': {None: [True, 'user']}})
cfg.option('od.g4').value.reset() cfg.option('od.g4').value.reset()
compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}}) compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}})
assert cfg.option('od.g6').ismulti() 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']}}) compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}, 'od.g6': {None: [[None], 'user']}})
cfg.option('od.g6').value.set([]) cfg.option('od.g6').value.set([])
compare(cfg.value.exportation(), {'od.g5': {None: ['yes', 'user']}, 'od.g6': {None: [[], 'user']}}) 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) cfg = get_config(cfg, config_type)
assert cfg.option('test1').value.get() == [] assert cfg.option('test1').value.get() == []
assert cfg.option('test2').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('test2').value.get() == [1]
assert cfg.option('test3').value.get() == [2] 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 cfg.option('test3').value.get() == [2, 1]
# assert not list_sessions() # assert not list_sessions()

View file

@ -6,7 +6,7 @@ do_autopath()
import pytest import pytest
from tiramisu import Config from tiramisu import Config
from tiramisu import IntOption, StrOption, OptionDescription, DynOptionDescription, PasswordOption, UsernameOption, \ from tiramisu import IntOption, StrOption, OptionDescription, DynOptionDescription, PasswordOption, UsernameOption, \
SymLinkOption, Leadership, undefined, Calculation, Params, \ SymLinkOption, Leadership, Calculation, Params, \
ParamOption, ParamValue, ParamIndex, calc_value ParamOption, ParamValue, ParamIndex, calc_value
from tiramisu.error import PropertiesOptionError, ConfigError from tiramisu.error import PropertiesOptionError, ConfigError
from tiramisu.setting import groups from tiramisu.setting import groups
@ -457,7 +457,7 @@ def test_mandatory_leader_empty():
cfg.property.read_write() cfg.property.read_write()
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] 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.ip_admin_eth0').value.get() == [None]
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None
cfg.property.read_only() cfg.property.read_only()
@ -503,7 +503,7 @@ def test_mandatory_warnings_leader_empty():
od1 = OptionDescription('o', '', [interface1]) od1 = OptionDescription('o', '', [interface1])
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() 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.ip_admin_eth0').value.get() == [None]
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).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']) compare(cfg.value.mandatory(), ['ip_admin_eth0.ip_admin_eth0'])

View file

@ -299,6 +299,23 @@ def test_callback(config_type):
# assert not list_sessions() # 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(): def test_params():
with pytest.raises(ValueError): with pytest.raises(ValueError):
Params('str') Params('str')
@ -541,6 +558,21 @@ def test_callback_multi(config_type):
# assert not list_sessions() # 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): def test_callback_multi_value(config_type):
val1 = StrOption('val1', "", ['val'], multi=True) val1 = StrOption('val1', "", ['val'], multi=True)
option = ParamOption(val1) option = ParamOption(val1)
@ -577,6 +609,30 @@ def test_callback_multi_value(config_type):
# assert not list_sessions() # 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): def test_callback_multi_list(config_type):
val1 = StrOption('val1', "", Calculation(return_list), multi=True, properties=('notunique',)) val1 = StrOption('val1', "", Calculation(return_list), multi=True, properties=('notunique',))
od1 = OptionDescription('rootconfig', '', [val1]) od1 = OptionDescription('rootconfig', '', [val1])
@ -611,7 +667,7 @@ def test_callback_multi_callback(config_type):
cfg.property.read_write() cfg.property.read_write()
cfg = get_config(cfg, config_type) cfg = get_config(cfg, config_type)
assert cfg.option('val1.val1').value.get() == ['val'] 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 cfg.option('val1.val1').value.get() == ['val1', None]
# assert not list_sessions() # assert not list_sessions()
@ -624,27 +680,53 @@ def test_callback_multi_callback_default(config_type):
cfg.property.read_write() cfg.property.read_write()
cfg = get_config(cfg, config_type) cfg = get_config(cfg, config_type)
assert cfg.option('val1.val1').value.get() == [] 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 cfg.option('val1.val1').value.get() == ['val1', 'val']
# assert not list_sessions() # assert not list_sessions()
def test_callback_leader_and_followers_leader(config_type): 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',)) val1 = StrOption('val1', "", default=['val'], multi=True)
val2 = StrOption('val2', "", multi=True) val2 = StrOption('val2', "", default=Calculation(return_value, Params(ParamOption(val1))), default_multi=Calculation(return_val), multi=True, properties=('notunique',))
interface1 = Leadership('val1', '', [val1, val2]) val3 = StrOption('val3', "", multi=True)
od1 = OptionDescription('rootconfig', '', [interface1]) interface1 = Leadership('val2', '', [val2, val3])
od1 = OptionDescription('rootconfig', '', [val1, interface1])
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
cfg = get_config(cfg, config_type) cfg = get_config(cfg, config_type)
assert cfg.option('val1.val1').value.get() == ['val'] assert cfg.option('val1').value.get() == ['val']
cfg.option('val1.val1').value.set([undefined, undefined]) assert cfg.option('val2.val2').value.get() == ['val']
assert cfg.option('val1.val1').value.get() == ['val', 'val'] #
assert cfg.option('val1.val2', 0).value.get() == None cfg.option('val1').value.set(['val1', 'val2'])
assert cfg.option('val1.val2', 1).value.get() == None 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() # 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): def test_callback_follower(config_type):
val1 = StrOption('val1', "", multi=True) val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", Calculation(return_value3, Params(ParamValue(['string', 'new']), {'index': ParamIndex()})), 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() # 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): def test_callback_leader_and_followers_leader2(config_type):
val1 = StrOption('val1', "", multi=True) val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, default_multi='val2') 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.send()
cfg_ori.property.read_write() cfg_ori.property.read_write()
cfg = get_config(cfg_ori, config_type) 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': if config_type == 'tiramisu-api':
cfg.send() cfg.send()
cfg_ori.property.read_only() 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.val1').value.get() == ['val', 'val']
assert cfg.option('val1.val2', 0).value.get() == None assert cfg.option('val1.val2', 0).value.get() == None
assert cfg.option('val1.val2', 1).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.val1').value.get() == ['val', 'val', None]
assert cfg.option('val1.val2', 0).value.get() == None assert cfg.option('val1.val2', 0).value.get() == None
assert cfg.option('val1.val2', 1).value.get() == None assert cfg.option('val1.val2', 1).value.get() == None

View file

@ -115,8 +115,10 @@ def test_force_default_on_freeze_multi():
cfg_ori.property.read_write() cfg_ori.property.read_write()
cfg = cfg_ori cfg = cfg_ori
# FIXME cfg = get_config(cfg_ori, config_type) # FIXME cfg = get_config(cfg_ori, config_type)
cfg.option('dummy1').value.set([undefined, True]) default = cfg.option('dummy1').value.default()[0]
cfg.option('dummy2').value.set([undefined, False]) 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() owner = cfg.owner.get()
assert cfg.option('dummy1').owner.get() == owner assert cfg.option('dummy1').owner.get() == owner
assert cfg.option('dummy2').owner.get() == owner assert cfg.option('dummy2').owner.get() == owner

View file

@ -143,7 +143,7 @@ def test_setitem(config_type):
od1 = OptionDescription("options", "", [s]) od1 = OptionDescription("options", "", [s])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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 cfg.option('string').value.get() == ['string', 'foo']
# assert not list_sessions() # assert not list_sessions()

View file

@ -8,7 +8,7 @@ from tiramisu import BoolOption, StrOption, IPOption, NetmaskOption, NetworkOpti
IntOption, OptionDescription, Leadership, Config, Params, ParamValue, ParamOption, \ IntOption, OptionDescription, Leadership, Config, Params, ParamValue, ParamOption, \
ParamSelfOption, ParamIndex, ParamInformation, ParamSelfInformation, ParamSelfOption, Calculation, \ ParamSelfOption, ParamIndex, ParamInformation, ParamSelfInformation, ParamSelfOption, Calculation, \
valid_ip_netmask, valid_network_netmask, \ 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.setting import groups
from tiramisu.error import ValueErrorWarning, ConfigError, PropertiesOptionError from tiramisu.error import ValueErrorWarning, ConfigError, PropertiesOptionError
from tiramisu.i18n import _ from tiramisu.i18n import _
@ -713,7 +713,7 @@ def test_validator_network_netmask_multi_follower_default_multi(config_type):
cfg = Config(od2) cfg = Config(od2)
cfg.property.read_write() cfg.property.read_write()
cfg = get_config(cfg, config_type) 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.a').value.get() == ['192.168.1.0']
assert cfg.option('a.b', 0).value.get() == '255.255.255.0' assert cfg.option('a.b', 0).value.get() == '255.255.255.0'
# assert not list_sessions() # 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']) cfg.option('a.b', 0).value.set([u'192.168.1.0'])
with pytest.raises(ValueError): with pytest.raises(ValueError):
cfg.option('a.b', 1).value.set([u'192.168.1.1']) 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', 0).value.set('255.255.255.0')
cfg.option('a.b', 1).value.set('255.255.255.255') 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() # 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() cfg.option('a.b', 0).value.get()
with pytest.raises(ValueError): with pytest.raises(ValueError):
cfg.option('a.b', 1).value.get() 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', 0).value.set('255.255.255.0')
cfg.option('a.b', 1).value.set('255.255.255.255') 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']) cfg.option('a.a').value.set(['192.168.1.0', '192.168.1.1'])

View file

@ -7,7 +7,7 @@ import warnings
from tiramisu.setting import groups, owners from tiramisu.setting import groups, owners
from tiramisu import StrOption, IntOption, OptionDescription, submulti, Leadership, Config, \ from tiramisu import StrOption, IntOption, OptionDescription, submulti, Leadership, Config, \
MetaConfig, undefined, Params, ParamOption, Calculation MetaConfig, Params, ParamOption, Calculation
from tiramisu.error import LeadershipError, PropertiesOptionError from tiramisu.error import LeadershipError, PropertiesOptionError
@ -107,26 +107,26 @@ def test_append_submulti():
owner = cfg.owner.get() owner = cfg.owner.get()
assert cfg.option('multi').value.get() == [] assert cfg.option('multi').value.get() == []
assert cfg.option('multi').owner.get() == owners.default 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').owner.get() == owner
assert cfg.option('multi').value.get() == [[]] 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('multi').value.get() == [[], ['no']]
# #
assert cfg.option('multi2').value.get() == [] assert cfg.option('multi2').value.get() == []
assert cfg.option('multi2').owner.get() == owners.default 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').owner.get() == owner
assert cfg.option('multi2').value.get() == [['yes']] 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('multi2').value.get() == [['yes'], ['no']]
# #
assert cfg.option('multi3').value.get() == [['yes']] assert cfg.option('multi3').value.get() == [['yes']]
assert cfg.option('multi3').owner.get() == owners.default 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').owner.get() == owner
assert cfg.option('multi3').value.get() == [['yes'], []] 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 cfg.option('multi3').value.get() == [['yes'], [], ['no']]
# assert not list_sessions() # assert not list_sessions()
@ -193,7 +193,7 @@ def test_callback_submulti_str():
owner = cfg.owner.get() owner = cfg.owner.get()
assert cfg.option('multi').owner.get() == owners.default assert cfg.option('multi').owner.get() == owners.default
assert cfg.option('multi').value.get() == [['val']] 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').owner.get() == owner
assert cfg.option('multi').value.get() == [['val'], ['val']] assert cfg.option('multi').value.get() == [['val'], ['val']]
cfg.option('multi').value.reset() cfg.option('multi').value.reset()
@ -209,13 +209,13 @@ def test_callback_submulti_list():
owner = cfg.owner.get() owner = cfg.owner.get()
assert cfg.option('multi').value.get() == [['val', 'val']] assert cfg.option('multi').value.get() == [['val', 'val']]
assert cfg.option('multi').owner.get() == owners.default 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').owner.get() == owner
#assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val']] assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val']]
#cfg.option('multi').value.set([['val', 'val'], undefined, undefined]) 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']] assert cfg.option('multi').value.get() == [['val', 'val'], ['val', 'val'], ['val', 'val']]
#cfg.option('multi').value.reset() cfg.option('multi').value.reset()
#assert cfg.option('multi').owner.get() == owners.default assert cfg.option('multi').owner.get() == owners.default
# assert not list_sessions() # assert not list_sessions()
@ -227,7 +227,7 @@ def test_callback_submulti_list_list():
owner = cfg.owner.get() owner = cfg.owner.get()
assert cfg.option('multi').value.get() == [['val', 'val']] assert cfg.option('multi').value.get() == [['val', 'val']]
assert cfg.option('multi').owner.get() == owners.default 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').owner.get() == owner
assert cfg.option('multi').value.get() == [['val', 'val'], []] assert cfg.option('multi').value.get() == [['val', 'val'], []]
cfg.option('multi').value.reset() cfg.option('multi').value.reset()

View file

@ -28,6 +28,7 @@ from .setting import ConfigBag, OptionBag, owners, groups, undefined, \
from .config import KernelConfig, KernelGroupConfig, KernelMetaConfig, KernelMixConfig from .config import KernelConfig, KernelGroupConfig, KernelMetaConfig, KernelMixConfig
from .option import RegexpOption, OptionDescription, ChoiceOption from .option import RegexpOption, OptionDescription, ChoiceOption
from .todict import TiramisuDict from .todict import TiramisuDict
from .autolib import Calculation
TIRAMISU_VERSION = 4 TIRAMISU_VERSION = 4
@ -615,15 +616,7 @@ class TiramisuOptionValue(CommonTiramisuOption):
"""Change option's value""" """Change option's value"""
option_bag = options_bag[-1] option_bag = options_bag[-1]
values = option_bag.config_bag.context.get_values() values = option_bag.config_bag.context.get_values()
if isinstance(value, list): if not isinstance(value, Calculation) and option_bag.option.impl_is_leader() and \
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 \
len(value) < self._config_bag.context.get_length_leadership(options_bag[-2]): len(value) < self._config_bag.context.get_length_leadership(options_bag[-2]):
raise LeadershipError(_('cannot reduce length of the leader "{}"' raise LeadershipError(_('cannot reduce length of the leader "{}"'
'').format(option_bag.option.impl_get_display_name())) '').format(option_bag.option.impl_get_display_name()))

View file

@ -212,6 +212,9 @@ class Calculation:
for_settings=for_settings, for_settings=for_settings,
) )
def __deepcopy__(x, memo):
return x
def manager_callback(callback: Callable, def manager_callback(callback: Callable,
param: Param, param: Param,

View file

@ -31,6 +31,7 @@ from .setting import OptionBag, ConfigBag, Settings, undefined, groups
from .value import Values, owners from .value import Values, owners
from .i18n import _ from .i18n import _
from .cacheobj import Cache from .cacheobj import Cache
from .autolib import Calculation
class _SubConfig: class _SubConfig:

View file

@ -186,7 +186,7 @@ class Leadership(OptionDescription):
) )
values.set_storage_value(foption_bag_index.path, values.set_storage_value(foption_bag_index.path,
index, index,
values.get_value(foption_bag_index), values.get_value(foption_bag_index)[0],
owner, owner,
) )

View file

@ -144,7 +144,7 @@ class CacheOptionDescription(BaseOption):
leader = option.impl_get_leadership().get_leader() leader = option.impl_get_leadership().get_leader()
for leader_option_bag in do_option_bags(leader): for leader_option_bag in do_option_bags(leader):
leader_option_bag.properties = frozenset() 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(): if option.issubdyn():
subpath = leader_option_bag.option.rootpath subpath = leader_option_bag.option.rootpath
doption = option.to_dynoption(subpath, doption = option.to_dynoption(subpath,
@ -162,7 +162,7 @@ class CacheOptionDescription(BaseOption):
) )
if values.hasvalue(subpath, index=index): if values.hasvalue(subpath, index=index):
continue continue
value = values.get_value(option_bag) value = values.get_value(option_bag)[0]
if value is None: if value is None:
continue continue
values.set_storage_value(subpath, values.set_storage_value(subpath,
@ -173,7 +173,7 @@ class CacheOptionDescription(BaseOption):
else: else:
for option_bag in do_option_bags(option): for option_bag in do_option_bags(option):
option_bag.properties = frozenset() option_bag.properties = frozenset()
value = values.get_value(option_bag) value = values.get_value(option_bag)[0]
if value is None: if value is None:
continue continue
if values.hasvalue(option_bag.path): if values.hasvalue(option_bag.path):

View file

@ -65,7 +65,7 @@ class Values:
) )
# no cached value so get value # no cached value so get value
if not is_cached: if not is_cached:
value = self.get_value(option_bag) value, has_calculation = self.get_value(option_bag)
# validates and warns value # validates and warns value
if not validated: if not validated:
validate = option_bag.option.impl_validate(value, validate = option_bag.option.impl_validate(value,
@ -78,7 +78,7 @@ class Values:
check_error=False, check_error=False,
) )
# set value to cache # set value to cache
if not is_cached: if not is_cached and not has_calculation:
cache.setcache(option_bag, cache.setcache(option_bag,
value, value,
validated=validate, validated=validate,
@ -106,7 +106,10 @@ class Values:
# the value is a default value # the value is a default value
# get it # get it
value = self.get_default_value(option_bag) 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, def get_default_value(self,
option_bag: OptionBag, option_bag: OptionBag,
@ -122,9 +125,9 @@ class Values:
return moption_bag.config_bag.context.get_values().get_cached_value(moption_bag) return moption_bag.config_bag.context.get_values().get_cached_value(moption_bag)
# now try to get calculated value: # now try to get calculated value:
value = self.get_calculated_value(option_bag, value, _has_calculation = self.get_calculated_value(option_bag,
option_bag.option.impl_getdefault(), option_bag.option.impl_getdefault(),
) )
if option_bag.index is not None and isinstance(value, (list, tuple)) \ if option_bag.index is not None and isinstance(value, (list, tuple)) \
and (not option_bag.option.impl_is_submulti() or \ and (not option_bag.option.impl_is_submulti() or \
not value or isinstance(value[0], list)): not value or isinstance(value[0], list)):
@ -135,9 +138,9 @@ class Values:
else: else:
# no value for this index, retrieve default multi value # no value for this index, retrieve default multi value
# default_multi is already a list for submulti # default_multi is already a list for submulti
value = self.get_calculated_value(option_bag, value, _has_calculation = self.get_calculated_value(option_bag,
option_bag.option.impl_getdefault_multi(), option_bag.option.impl_getdefault_multi(),
) )
return value return value
def get_calculated_value(self, def get_calculated_value(self,
@ -147,6 +150,7 @@ class Values:
) -> Any: ) -> Any:
"""value could be a calculation, in this case do calculation """value could be a calculation, in this case do calculation
""" """
has_calculation = False
if isinstance(value, Calculation): if isinstance(value, Calculation):
try: try:
value = value.execute(option_bag) value = value.execute(option_bag)
@ -154,18 +158,21 @@ class Values:
msg = _(f'error when calculating "{option_bag.option.impl_get_display_name()}": ' msg = _(f'error when calculating "{option_bag.option.impl_get_display_name()}": '
f'{err} : {option_bag.path}') f'{err} : {option_bag.path}')
raise ConfigError(msg) from err raise ConfigError(msg) from err
has_calculation = True
elif isinstance(value, list): elif isinstance(value, list):
# if value is a list, do subcalculation # if value is a list, do subcalculation
for idx, val in enumerate(value): for idx, val in enumerate(value):
value[idx] = self.get_calculated_value(option_bag, value[idx], _has_calculation = self.get_calculated_value(option_bag,
val, val,
reset_cache=False, reset_cache=False,
) )
if _has_calculation:
has_calculation = True
if reset_cache: if reset_cache:
self.reset_cache_after_calculation(option_bag, self.reset_cache_after_calculation(option_bag,
value, value,
) )
return value return value, has_calculation
#______________________________________________________________________ #______________________________________________________________________
def check_force_to_metaconfig(self, def check_force_to_metaconfig(self,
@ -248,27 +255,31 @@ class Values:
"""set value to option """set value to option
""" """
owner = self.get_context_owner() owner = self.get_context_owner()
if 'validator' in option_bag.config_bag.properties: setting_properties = option_bag.config_bag.properties
self.setvalue_validation(value, ori_value = value
option_bag, if 'validator' in setting_properties:
) value, has_calculation = self.setvalue_validation(value,
option_bag,
)
if isinstance(value, list): elif isinstance(value, list):
# copy # copy
value = value.copy() value = value.copy()
self._setvalue(option_bag, self._setvalue(option_bag,
value, ori_value,
owner, owner,
) )
setting_properties = option_bag.config_bag.properties
validator = 'validator' in setting_properties and \ validator = 'validator' in setting_properties and \
'demoting_error_warning' not in setting_properties '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 = option_bag.config_bag.context.get_values_cache()
cache.setcache(option_bag, cache.setcache(option_bag,
value, value,
validated=validator, 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(): if 'force_store_value' in setting_properties and option_bag.option.impl_is_leader():
leader = option_bag.option.impl_get_leadership() leader = option_bag.option.impl_get_leadership()
leader.follower_force_store_value(value, leader.follower_force_store_value(value,
@ -286,10 +297,10 @@ class Values:
# First validate properties with this value # First validate properties with this value
opt = option_bag.option opt = option_bag.option
settings.validate_frozen(option_bag) settings.validate_frozen(option_bag)
val = self.get_calculated_value(option_bag, val, has_calculation = self.get_calculated_value(option_bag,
value, value,
False, False,
) )
settings.validate_mandatory(val, settings.validate_mandatory(val,
option_bag, option_bag,
) )
@ -300,10 +311,11 @@ class Values:
) )
if 'warnings' in option_bag.config_bag.properties: if 'warnings' in option_bag.config_bag.properties:
# No error found so emit warnings # No error found so emit warnings
opt.impl_validate(value, opt.impl_validate(val,
option_bag, option_bag,
check_error=False, check_error=False,
) )
return val, has_calculation
def _setvalue(self, def _setvalue(self,
option_bag: OptionBag, option_bag: OptionBag,
@ -362,7 +374,7 @@ class Values:
option_bag.config_bag, option_bag.config_bag,
properties=frozenset(), properties=frozenset(),
) )
indexes = range(len(self.get_value(loption_bag))) indexes = range(len(self.get_value(loption_bag)[0]))
else: else:
indexes = [None] indexes = [None]
for index in indexes: for index in indexes:
@ -370,7 +382,7 @@ class Values:
index, index,
option_bag.config_bag, 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 self._values.setdefault(coption_bag.path, {})[index] = default_value
def _get_modified_parent(self, def _get_modified_parent(self,