Works callback/multi/master-slave
- in multi, never modify _default value - _reset slave when _reset master - if append None in master with callback return not a list, replace None by the value - list support in slave
This commit is contained in:
parent
ada5bfbf6c
commit
0d114001f4
4 changed files with 221 additions and 29 deletions
|
@ -5,13 +5,21 @@ from tiramisu.setting import groups
|
||||||
from tiramisu.config import Config
|
from tiramisu.config import Config
|
||||||
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
|
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
|
||||||
StrOption, OptionDescription
|
StrOption, OptionDescription
|
||||||
from tiramisu.error import PropertiesOptionError, ConflictError
|
from tiramisu.error import PropertiesOptionError, ConflictError, SlaveError
|
||||||
|
|
||||||
|
|
||||||
def return_value():
|
def return_val():
|
||||||
return 'val'
|
return 'val'
|
||||||
|
|
||||||
|
|
||||||
|
def return_list():
|
||||||
|
return ['val', 'val']
|
||||||
|
|
||||||
|
|
||||||
|
def return_value(value):
|
||||||
|
return value
|
||||||
|
|
||||||
|
|
||||||
def make_description():
|
def make_description():
|
||||||
gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
|
gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
|
||||||
gcdummy = BoolOption('dummy', 'dummy', default=False)
|
gcdummy = BoolOption('dummy', 'dummy', default=False)
|
||||||
|
@ -277,7 +285,7 @@ def test_freeze_and_has_callback():
|
||||||
|
|
||||||
|
|
||||||
def test_callback():
|
def test_callback():
|
||||||
val1 = StrOption('val1', "", callback=return_value)
|
val1 = StrOption('val1', "", callback=return_val)
|
||||||
maconfig = OptionDescription('rootconfig', '', [val1])
|
maconfig = OptionDescription('rootconfig', '', [val1])
|
||||||
cfg = Config(maconfig)
|
cfg = Config(maconfig)
|
||||||
cfg.read_write()
|
cfg.read_write()
|
||||||
|
@ -288,9 +296,115 @@ def test_callback():
|
||||||
assert cfg.val1 == 'val'
|
assert cfg.val1 == 'val'
|
||||||
|
|
||||||
|
|
||||||
def test_callback_master_and_slaves():
|
def test_callback_value():
|
||||||
|
val1 = StrOption('val1', "", 'val')
|
||||||
|
val2 = StrOption('val2', "", callback=return_value, callback_params={'': (('val1', False),)})
|
||||||
|
maconfig = OptionDescription('rootconfig', '', [val1, val2])
|
||||||
|
cfg = Config(maconfig)
|
||||||
|
cfg.read_write()
|
||||||
|
assert cfg.val1 == 'val'
|
||||||
|
assert cfg.val2 == 'val'
|
||||||
|
cfg.val1 = 'new-val'
|
||||||
|
assert cfg.val1 == 'new-val'
|
||||||
|
assert cfg.val2 == 'new-val'
|
||||||
|
del(cfg.val1)
|
||||||
|
assert cfg.val1 == 'val'
|
||||||
|
assert cfg.val2 == 'val'
|
||||||
|
|
||||||
|
|
||||||
|
def test_callback_list():
|
||||||
|
val1 = StrOption('val1', "", callback=return_list)
|
||||||
|
maconfig = OptionDescription('rootconfig', '', [val1])
|
||||||
|
cfg = Config(maconfig)
|
||||||
|
cfg.read_write()
|
||||||
|
raises(ValueError, "cfg.val1")
|
||||||
|
|
||||||
|
|
||||||
|
def test_callback_multi():
|
||||||
|
val1 = StrOption('val1', "", callback=return_val, multi=True)
|
||||||
|
maconfig = OptionDescription('rootconfig', '', [val1])
|
||||||
|
cfg = Config(maconfig)
|
||||||
|
cfg.read_write()
|
||||||
|
assert cfg.val1 == ['val']
|
||||||
|
cfg.val1 = ['new-val']
|
||||||
|
assert cfg.val1 == ['new-val']
|
||||||
|
cfg.val1.append('new-val2')
|
||||||
|
assert cfg.val1 == ['new-val', 'new-val2']
|
||||||
|
del(cfg.val1)
|
||||||
|
assert cfg.val1 == ['val']
|
||||||
|
|
||||||
|
|
||||||
|
def test_callback_multi_value():
|
||||||
|
val1 = StrOption('val1', "", ['val'], multi=True)
|
||||||
|
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': (('val1', False),)})
|
||||||
|
maconfig = OptionDescription('rootconfig', '', [val1, val2])
|
||||||
|
cfg = Config(maconfig)
|
||||||
|
cfg.read_write()
|
||||||
|
assert cfg.val1 == ['val']
|
||||||
|
assert cfg.val2 == ['val']
|
||||||
|
cfg.val1 = ['new-val']
|
||||||
|
assert cfg.val1 == ['new-val']
|
||||||
|
assert cfg.val2 == ['new-val']
|
||||||
|
cfg.val1.append('new-val2')
|
||||||
|
assert cfg.val1 == ['new-val', 'new-val2']
|
||||||
|
assert cfg.val2 == ['new-val', 'new-val2']
|
||||||
|
del(cfg.val1)
|
||||||
|
assert cfg.val1 == ['val']
|
||||||
|
assert cfg.val2 == ['val']
|
||||||
|
|
||||||
|
|
||||||
|
def test_callback_multi_list():
|
||||||
|
val1 = StrOption('val1', "", callback=return_list, multi=True)
|
||||||
|
maconfig = OptionDescription('rootconfig', '', [val1])
|
||||||
|
cfg = Config(maconfig)
|
||||||
|
cfg.read_write()
|
||||||
|
assert cfg.val1 == ['val', 'val']
|
||||||
|
cfg.val1 = ['new-val']
|
||||||
|
assert cfg.val1 == ['new-val']
|
||||||
|
cfg.val1.append('new-val2')
|
||||||
|
assert cfg.val1 == ['new-val', 'new-val2']
|
||||||
|
del(cfg.val1)
|
||||||
|
assert cfg.val1 == ['val', 'val']
|
||||||
|
|
||||||
|
|
||||||
|
def test_callback_master_and_slaves_master():
|
||||||
|
val1 = StrOption('val1', "", multi=True, callback=return_val)
|
||||||
|
val2 = StrOption('val2', "", multi=True)
|
||||||
|
interface1 = OptionDescription('val1', '', [val1, val2])
|
||||||
|
interface1.impl_set_group_type(groups.master)
|
||||||
|
maconfig = OptionDescription('rootconfig', '', [interface1])
|
||||||
|
cfg = Config(maconfig)
|
||||||
|
cfg.read_write()
|
||||||
|
assert cfg.val1.val1 == ['val']
|
||||||
|
cfg.val1.val1.append(None)
|
||||||
|
assert cfg.val1.val1 == ['val', 'val']
|
||||||
|
assert cfg.val1.val2 == [None, None]
|
||||||
|
|
||||||
|
|
||||||
|
def test_callback_master_and_slaves_master_list():
|
||||||
|
val1 = StrOption('val1', "", multi=True, callback=return_list)
|
||||||
|
val2 = StrOption('val2', "", multi=True)
|
||||||
|
interface1 = OptionDescription('val1', '', [val1, val2])
|
||||||
|
interface1.impl_set_group_type(groups.master)
|
||||||
|
maconfig = OptionDescription('rootconfig', '', [interface1])
|
||||||
|
cfg = Config(maconfig)
|
||||||
|
cfg.read_write()
|
||||||
|
assert cfg.val1.val1 == ['val', 'val']
|
||||||
|
assert cfg.val1.val2 == [None, None]
|
||||||
|
cfg.val1.val1.append(None)
|
||||||
|
assert cfg.val1.val1 == ['val', 'val', None]
|
||||||
|
assert cfg.val1.val2 == [None, None, None]
|
||||||
|
del(cfg.val1.val1)
|
||||||
|
assert cfg.val1.val1 == ['val', 'val']
|
||||||
|
assert cfg.val1.val2 == [None, None]
|
||||||
|
assert cfg.val1.val1.pop(1)
|
||||||
|
assert cfg.val1.val1 == ['val']
|
||||||
|
assert cfg.val1.val2 == [None]
|
||||||
|
|
||||||
|
|
||||||
|
def test_callback_master_and_slaves_slave():
|
||||||
val1 = StrOption('val1', "", multi=True)
|
val1 = StrOption('val1', "", multi=True)
|
||||||
val2 = StrOption('val2', "", multi=True, callback=return_value)
|
val2 = StrOption('val2', "", multi=True, callback=return_val)
|
||||||
interface1 = OptionDescription('val1', '', [val1, val2])
|
interface1 = OptionDescription('val1', '', [val1, val2])
|
||||||
interface1.impl_set_group_type(groups.master)
|
interface1.impl_set_group_type(groups.master)
|
||||||
maconfig = OptionDescription('rootconfig', '', [interface1])
|
maconfig = OptionDescription('rootconfig', '', [interface1])
|
||||||
|
@ -320,3 +434,56 @@ def test_callback_master_and_slaves():
|
||||||
#
|
#
|
||||||
cfg.val1.val1.append('val3')
|
cfg.val1.val1.append('val3')
|
||||||
assert cfg.val1.val2 == ['val2', 'val2', 'val']
|
assert cfg.val1.val2 == ['val2', 'val2', 'val']
|
||||||
|
|
||||||
|
|
||||||
|
def test_callback_master_and_slaves_slave_list():
|
||||||
|
val1 = StrOption('val1', "", multi=True)
|
||||||
|
val2 = StrOption('val2', "", multi=True, callback=return_list)
|
||||||
|
interface1 = OptionDescription('val1', '', [val1, val2])
|
||||||
|
interface1.impl_set_group_type(groups.master)
|
||||||
|
maconfig = OptionDescription('rootconfig', '', [interface1])
|
||||||
|
cfg = Config(maconfig)
|
||||||
|
cfg.read_write()
|
||||||
|
assert cfg.val1.val2 == []
|
||||||
|
cfg.val1.val1 = ['val1', 'val2']
|
||||||
|
assert cfg.val1.val1 == ['val1', 'val2']
|
||||||
|
assert cfg.val1.val2 == ['val', 'val']
|
||||||
|
cfg.val1.val1 = ['val1']
|
||||||
|
#wrong len
|
||||||
|
raises(SlaveError, 'cfg.val1.val2')
|
||||||
|
|
||||||
|
|
||||||
|
def test_callback_master_and_slaves_value():
|
||||||
|
val1 = StrOption('val1', "", multi=True)
|
||||||
|
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': (('val1.val1', False),)})
|
||||||
|
interface1 = OptionDescription('val1', '', [val1, val2])
|
||||||
|
interface1.impl_set_group_type(groups.master)
|
||||||
|
maconfig = OptionDescription('rootconfig', '', [interface1])
|
||||||
|
cfg = Config(maconfig)
|
||||||
|
cfg.read_write()
|
||||||
|
assert cfg.val1.val1 == []
|
||||||
|
assert cfg.val1.val2 == []
|
||||||
|
#
|
||||||
|
cfg.val1.val1 = ['val1']
|
||||||
|
assert cfg.val1.val1 == ['val1']
|
||||||
|
assert cfg.val1.val2 == ['val1']
|
||||||
|
#
|
||||||
|
cfg.val1.val1.append('val2')
|
||||||
|
assert cfg.val1.val1 == ['val1', 'val2']
|
||||||
|
assert cfg.val1.val2 == ['val1', 'val2']
|
||||||
|
#
|
||||||
|
cfg.val1.val1 = ['val1', 'val2', 'val3']
|
||||||
|
assert cfg.val1.val1 == ['val1', 'val2', 'val3']
|
||||||
|
assert cfg.val1.val2 == ['val1', 'val2', 'val3']
|
||||||
|
#
|
||||||
|
cfg.val1.val1.pop(2)
|
||||||
|
assert cfg.val1.val1 == ['val1', 'val2']
|
||||||
|
assert cfg.val1.val2 == ['val1', 'val2']
|
||||||
|
#
|
||||||
|
cfg.val1.val2 = ['val2', 'val2']
|
||||||
|
assert cfg.val1.val2 == ['val2', 'val2']
|
||||||
|
#
|
||||||
|
cfg.val1.val1.append('val3')
|
||||||
|
assert cfg.val1.val2 == ['val2', 'val2', 'val3']
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -229,8 +229,13 @@ def test_values_with_master_and_slaves_master():
|
||||||
cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.145"]
|
cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145", "192.168.230.145"]
|
||||||
cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0']
|
cfg.ip_admin_eth0.netmask_admin_eth0 = ['255.255.255.0', '255.255.255.0']
|
||||||
raises(SlaveError, 'cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145"]')
|
raises(SlaveError, 'cfg.ip_admin_eth0.ip_admin_eth0 = ["192.168.230.145"]')
|
||||||
|
assert cfg.ip_admin_eth0.netmask_admin_eth0 == ['255.255.255.0', '255.255.255.0']
|
||||||
cfg.ip_admin_eth0.ip_admin_eth0.pop(1)
|
cfg.ip_admin_eth0.ip_admin_eth0.pop(1)
|
||||||
assert cfg.ip_admin_eth0.ip_admin_eth0 == ["192.168.230.145"]
|
assert cfg.ip_admin_eth0.ip_admin_eth0 == ["192.168.230.145"]
|
||||||
|
assert cfg.ip_admin_eth0.netmask_admin_eth0 == ['255.255.255.0']
|
||||||
|
del(cfg.ip_admin_eth0.ip_admin_eth0)
|
||||||
|
assert cfg.ip_admin_eth0.ip_admin_eth0 == []
|
||||||
|
assert cfg.ip_admin_eth0.netmask_admin_eth0 == []
|
||||||
|
|
||||||
|
|
||||||
def test_values_with_master_owner():
|
def test_values_with_master_owner():
|
||||||
|
|
|
@ -30,7 +30,7 @@ from tiramisu.i18n import _
|
||||||
# return calc_factory(name, callback, callback_params, config)
|
# return calc_factory(name, callback, callback_params, config)
|
||||||
|
|
||||||
|
|
||||||
def carry_out_calculation(name, config, callback, callback_params):
|
def carry_out_calculation(name, config, callback, callback_params, index=None):
|
||||||
"a function that carries out a calculation for an option's value"
|
"a function that carries out a calculation for an option's value"
|
||||||
#callback, callback_params = option.getcallback()
|
#callback, callback_params = option.getcallback()
|
||||||
#if callback_params is None:
|
#if callback_params is None:
|
||||||
|
@ -71,7 +71,11 @@ def carry_out_calculation(name, config, callback, callback_params):
|
||||||
|
|
||||||
if one_is_multi:
|
if one_is_multi:
|
||||||
ret = []
|
ret = []
|
||||||
for incr in range(len_multi):
|
if index:
|
||||||
|
range_ = [index]
|
||||||
|
else:
|
||||||
|
range_ = range(len_multi)
|
||||||
|
for incr in range_:
|
||||||
tcp = {}
|
tcp = {}
|
||||||
params = []
|
params = []
|
||||||
for key, couples in tcparams.items():
|
for key, couples in tcparams.items():
|
||||||
|
@ -91,10 +95,13 @@ def carry_out_calculation(name, config, callback, callback_params):
|
||||||
else:
|
else:
|
||||||
tcp[key] = value
|
tcp[key] = value
|
||||||
calc = calculate(name, callback, params, tcp)
|
calc = calculate(name, callback, params, tcp)
|
||||||
if isinstance(calc, list):
|
if index:
|
||||||
ret.extend(calc)
|
ret = calc
|
||||||
else:
|
else:
|
||||||
ret.append(calc)
|
if isinstance(calc, list):
|
||||||
|
ret.extend(calc)
|
||||||
|
else:
|
||||||
|
ret.append(calc)
|
||||||
|
|
||||||
return ret
|
return ret
|
||||||
else:
|
else:
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#
|
#
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
from time import time
|
from time import time
|
||||||
|
from copy import copy
|
||||||
from tiramisu.error import ConfigError, SlaveError
|
from tiramisu.error import ConfigError, SlaveError
|
||||||
from tiramisu.setting import owners, multitypes, expires_time
|
from tiramisu.setting import owners, multitypes, expires_time
|
||||||
from tiramisu.autolib import carry_out_calculation
|
from tiramisu.autolib import carry_out_calculation
|
||||||
|
@ -47,9 +48,13 @@ class Values(object):
|
||||||
def _get_default(self, opt):
|
def _get_default(self, opt):
|
||||||
meta = self.context.cfgimpl_get_meta()
|
meta = self.context.cfgimpl_get_meta()
|
||||||
if meta is not None:
|
if meta is not None:
|
||||||
return meta.cfgimpl_get_values()[opt]
|
value = meta.cfgimpl_get_values()[opt]
|
||||||
else:
|
else:
|
||||||
return opt.impl_getdefault()
|
value = opt.impl_getdefault()
|
||||||
|
if opt.impl_is_multi():
|
||||||
|
return copy(value)
|
||||||
|
else:
|
||||||
|
return value
|
||||||
|
|
||||||
def _get_value(self, opt, validate=True):
|
def _get_value(self, opt, validate=True):
|
||||||
"return value or default value if not set"
|
"return value or default value if not set"
|
||||||
|
@ -72,6 +77,9 @@ class Values(object):
|
||||||
opt.impl_validate(opt.impl_getdefault(), self.context,
|
opt.impl_validate(opt.impl_getdefault(), self.context,
|
||||||
'validator' in setting)
|
'validator' in setting)
|
||||||
self.context.cfgimpl_reset_cache()
|
self.context.cfgimpl_reset_cache()
|
||||||
|
if opt.impl_is_multi() and opt.impl_get_multitype() == multitypes.master:
|
||||||
|
for slave in opt.impl_get_master_slaves():
|
||||||
|
self._reset(slave)
|
||||||
del(self._values[opt])
|
del(self._values[opt])
|
||||||
|
|
||||||
def _is_empty(self, opt, value):
|
def _is_empty(self, opt, value):
|
||||||
|
@ -83,13 +91,14 @@ class Values(object):
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _getcallback_value(self, opt):
|
def _getcallback_value(self, opt, index=None):
|
||||||
callback, callback_params = opt._callback
|
callback, callback_params = opt._callback
|
||||||
if callback_params is None:
|
if callback_params is None:
|
||||||
callback_params = {}
|
callback_params = {}
|
||||||
return carry_out_calculation(opt._name, config=self.context,
|
return carry_out_calculation(opt._name, config=self.context,
|
||||||
callback=callback,
|
callback=callback,
|
||||||
callback_params=callback_params)
|
callback_params=callback_params,
|
||||||
|
index=index)
|
||||||
|
|
||||||
def __getitem__(self, opt):
|
def __getitem__(self, opt):
|
||||||
return self.getitem(opt)
|
return self.getitem(opt)
|
||||||
|
@ -133,11 +142,8 @@ class Values(object):
|
||||||
if not no_value_slave:
|
if not no_value_slave:
|
||||||
value = self._getcallback_value(opt)
|
value = self._getcallback_value(opt)
|
||||||
if opt.impl_is_multi() and opt.impl_get_multitype() == multitypes.slave:
|
if opt.impl_is_multi() and opt.impl_get_multitype() == multitypes.slave:
|
||||||
if isinstance(value, list):
|
if not isinstance(value, list):
|
||||||
raise ValueError('callback must not return list '
|
value = [value for i in range(lenmaster)]
|
||||||
'in slave {0}: {1}'.format(opt._name,
|
|
||||||
value))
|
|
||||||
value = [value for i in range(lenmaster)]
|
|
||||||
if opt.impl_is_multi():
|
if opt.impl_is_multi():
|
||||||
value = Multi(value, self.context, opt, validate)
|
value = Multi(value, self.context, opt, validate)
|
||||||
#suppress value if already set
|
#suppress value if already set
|
||||||
|
@ -297,20 +303,27 @@ class Multi(list):
|
||||||
raise SlaveError(_("cannot append a value on a multi option {0}"
|
raise SlaveError(_("cannot append a value on a multi option {0}"
|
||||||
" which is a slave").format(self.opt._name))
|
" which is a slave").format(self.opt._name))
|
||||||
elif self.opt.impl_get_multitype() == multitypes.master:
|
elif self.opt.impl_get_multitype() == multitypes.master:
|
||||||
for slave in self.opt.impl_get_master_slaves():
|
values = self.context.cfgimpl_get_values()
|
||||||
values = self.context.cfgimpl_get_values()
|
if value is None and self.opt.impl_has_callback():
|
||||||
if not values.is_default_owner(slave):
|
value = values._getcallback_value(self.opt)
|
||||||
if slave.impl_has_callback():
|
#Force None il return a list
|
||||||
dvalue = values._getcallback_value(slave)
|
if isinstance(value, list):
|
||||||
else:
|
value = None
|
||||||
dvalue = slave.impl_getdefault_multi()
|
|
||||||
#get multi without valid properties
|
|
||||||
values.getitem(slave, validate_properties=False).append(
|
|
||||||
dvalue, force=True)
|
|
||||||
self._validate(value)
|
self._validate(value)
|
||||||
#set value without valid properties
|
#set value without valid properties
|
||||||
self.context.cfgimpl_get_values()._setvalue(self.opt, self, validate_properties=not force)
|
self.context.cfgimpl_get_values()._setvalue(self.opt, self, validate_properties=not force)
|
||||||
super(Multi, self).append(value)
|
super(Multi, self).append(value)
|
||||||
|
if not force and self.opt.impl_get_multitype() == multitypes.master:
|
||||||
|
for slave in self.opt.impl_get_master_slaves():
|
||||||
|
if not values.is_default_owner(slave):
|
||||||
|
if slave.impl_has_callback():
|
||||||
|
index = self.__len__() - 1
|
||||||
|
dvalue = values._getcallback_value(slave, index=index)
|
||||||
|
else:
|
||||||
|
dvalue = slave.impl_getdefault_multi()
|
||||||
|
#get multi without valid properties
|
||||||
|
values.getitem(slave, validate_properties=False).append(
|
||||||
|
dvalue, force=True)
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
if value is not None and not self.opt._validate(value):
|
if value is not None and not self.opt._validate(value):
|
||||||
|
|
Loading…
Reference in a new issue