Better support for slave with callback:

- callback must return single value, not a list
- if default value, append slave values with master len
- if not default and append, set default value
This commit is contained in:
Emmanuel Garette 2013-06-11 15:10:38 +02:00
parent 22f0aab0a8
commit 6d1cf308b2
2 changed files with 72 additions and 16 deletions

View File

@ -1,12 +1,17 @@
import autopath import autopath
from py.test import raises from py.test import raises
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, IPOption, OptionDescription StrOption, OptionDescription
from tiramisu.error import PropertiesOptionError, ConflictError from tiramisu.error import PropertiesOptionError, ConflictError
def return_value():
return 'val'
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)
@ -269,3 +274,37 @@ def test_freeze_and_has_callback():
dummy = config.unwrap_from_path('gc.dummy') dummy = config.unwrap_from_path('gc.dummy')
setting[dummy].append('frozen') setting[dummy].append('frozen')
raises(PropertiesOptionError, "config.gc.dummy = True") raises(PropertiesOptionError, "config.gc.dummy = True")
def test_callback_master_and_slaves():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, callback=return_value)
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 == ['val']
#
cfg.val1.val1.append('val2')
assert cfg.val1.val1 == ['val1', 'val2']
assert cfg.val1.val2 == ['val', 'val']
#
cfg.val1.val1 = ['val1', 'val2', 'val3']
assert cfg.val1.val1 == ['val1', 'val2', 'val3']
assert cfg.val1.val2 == ['val', 'val', 'val']
#
cfg.val1.val1.pop(2)
assert cfg.val1.val1 == ['val1', 'val2']
assert cfg.val1.val2 == ['val', 'val']
#
cfg.val1.val2 = ['val2', 'val2']
assert cfg.val1.val2 == ['val2', 'val2']
#
cfg.val1.val1.append('val3')
assert cfg.val1.val2 == ['val2', 'val2', 'val']

View File

@ -115,18 +115,30 @@ class Values(object):
validate_properties): validate_properties):
# options with callbacks # options with callbacks
setting = self.context.cfgimpl_get_settings() setting = self.context.cfgimpl_get_settings()
value = self._get_value(opt, validate)
is_frozen = 'frozen' in setting[opt] is_frozen = 'frozen' in setting[opt]
if opt.impl_has_callback(): #if value is callback and is not set or frozen with force_default_on_freeze
#if value is set and : if opt.impl_has_callback() and (self.is_default_owner(opt) or
# - not frozen (is_frozen and
# - frozen and not force_default_on_freeze 'force_default_on_freeze' in setting[opt])):
if not self.is_default_owner(opt) and ( no_value_slave = False
not is_frozen or (is_frozen and if opt.impl_get_multitype() == multitypes.slave:
not 'force_default_on_freeze' in setting[opt])): masterp = self.context.cfgimpl_get_description().impl_get_path_by_opt(
pass opt.impl_get_master_slaves())
else: mastervalue = getattr(self.context, masterp)
lenmaster = len(mastervalue)
if lenmaster == 0:
value = []
no_value_slave = True
if not no_value_slave:
value = self._getcallback_value(opt) value = self._getcallback_value(opt)
if opt.impl_is_multi():
if opt.impl_get_multitype() == multitypes.slave:
if isinstance(value, list):
raise ValueError('callback must not return list '
'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
@ -136,6 +148,8 @@ class Values(object):
value = self._get_default(opt) value = self._get_default(opt)
if opt.impl_is_multi(): if opt.impl_is_multi():
value = Multi(value, self.context, opt, validate) value = Multi(value, self.context, opt, validate)
else:
value = self._get_value(opt, validate)
if validate: if validate:
opt.impl_validate(value, self.context, 'validator' in setting) opt.impl_validate(value, self.context, 'validator' in setting)
if self.is_default_owner(opt) and \ if self.is_default_owner(opt) and \
@ -287,10 +301,13 @@ class Multi(list):
for slave in self.opt.impl_get_master_slaves(): for slave in self.opt.impl_get_master_slaves():
values = self.context.cfgimpl_get_values() values = self.context.cfgimpl_get_values()
if not values.is_default_owner(slave): if not values.is_default_owner(slave):
if slave.impl_has_callback():
dvalue = values._getcallback_value(slave)
else:
dvalue = slave.impl_getdefault_multi()
#get multi without valid properties #get multi without valid properties
values.getitem(slave, validate_properties=False).append( values.getitem(slave, validate_properties=False).append(
slave.impl_getdefault_multi(), dvalue, force=True)
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)