From 6d1cf308b2d440be6b93fddd74988b1592881698 Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Tue, 11 Jun 2013 15:10:38 +0200 Subject: [PATCH] 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 --- test/test_option_calculation.py | 41 +++++++++++++++++++++++++++- tiramisu/value.py | 47 ++++++++++++++++++++++----------- 2 files changed, 72 insertions(+), 16 deletions(-) diff --git a/test/test_option_calculation.py b/test/test_option_calculation.py index 0f76c2f..d5dc0cc 100644 --- a/test/test_option_calculation.py +++ b/test/test_option_calculation.py @@ -1,12 +1,17 @@ import autopath from py.test import raises +from tiramisu.setting import groups from tiramisu.config import Config from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \ - StrOption, IPOption, OptionDescription + StrOption, OptionDescription from tiramisu.error import PropertiesOptionError, ConflictError +def return_value(): + return 'val' + + def make_description(): gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref') gcdummy = BoolOption('dummy', 'dummy', default=False) @@ -269,3 +274,37 @@ def test_freeze_and_has_callback(): dummy = config.unwrap_from_path('gc.dummy') setting[dummy].append('frozen') 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'] diff --git a/tiramisu/value.py b/tiramisu/value.py index 0f21d8c..9e65db2 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -115,27 +115,41 @@ class Values(object): validate_properties): # options with callbacks setting = self.context.cfgimpl_get_settings() - value = self._get_value(opt, validate) is_frozen = 'frozen' in setting[opt] - if opt.impl_has_callback(): - #if value is set and : - # - not frozen - # - frozen and not force_default_on_freeze - if not self.is_default_owner(opt) and ( - not is_frozen or (is_frozen and - not 'force_default_on_freeze' in setting[opt])): - pass - else: + #if value is callback and is not set or frozen with force_default_on_freeze + if opt.impl_has_callback() and (self.is_default_owner(opt) or + (is_frozen and + 'force_default_on_freeze' in setting[opt])): + no_value_slave = False + if opt.impl_get_multitype() == multitypes.slave: + masterp = self.context.cfgimpl_get_description().impl_get_path_by_opt( + opt.impl_get_master_slaves()) + 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) if opt.impl_is_multi(): - value = Multi(value, self.context, opt, validate) - #suppress value if already set - self._reset(opt) + 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(): + value = Multi(value, self.context, opt, validate) + #suppress value if already set + self._reset(opt) # frozen and force default elif is_frozen and 'force_default_on_freeze' in setting[opt]: value = self._get_default(opt) if opt.impl_is_multi(): value = Multi(value, self.context, opt, validate) + else: + value = self._get_value(opt, validate) if validate: opt.impl_validate(value, self.context, 'validator' in setting) if self.is_default_owner(opt) and \ @@ -287,10 +301,13 @@ class Multi(list): for slave in self.opt.impl_get_master_slaves(): values = self.context.cfgimpl_get_values() 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 values.getitem(slave, validate_properties=False).append( - slave.impl_getdefault_multi(), - force=True) + dvalue, force=True) self._validate(value) #set value without valid properties self.context.cfgimpl_get_values()._setvalue(self.opt, self, validate_properties=not force)