From 57f4dd8d3f383889f8c3358e0d90090d505a51dc Mon Sep 17 00:00:00 2001 From: Emmanuel Garette Date: Mon, 16 Sep 2013 20:51:13 +0200 Subject: [PATCH] allow mandatory value (see 9ddf100118d913c2f4225cca1adb65317b512d84 for more details) --- test/test_option_calculation.py | 28 +++++++++++++++++++++++++--- tiramisu/setting.py | 8 +++++++- tiramisu/value.py | 15 +++++++++++++-- 3 files changed, 45 insertions(+), 6 deletions(-) diff --git a/test/test_option_calculation.py b/test/test_option_calculation.py index d57072f..1441460 100644 --- a/test/test_option_calculation.py +++ b/test/test_option_calculation.py @@ -5,7 +5,7 @@ from tiramisu.setting import groups from tiramisu.config import Config from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \ StrOption, OptionDescription -from tiramisu.error import PropertiesOptionError, ConflictError, SlaveError +from tiramisu.error import PropertiesOptionError, ConflictError, SlaveError, ConfigError def return_val(): @@ -500,7 +500,7 @@ def test_callback_hidden(): cfg.od2.opt2 -def test_callback_disable_make_dict(): +def test_callback_two_disabled(): opt1 = BoolOption('opt1', '', properties=('disabled',)) opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': (('od1.opt1', False),)}, properties=('disabled',)) od1 = OptionDescription('od1', '', [opt1]) @@ -508,4 +508,26 @@ def test_callback_disable_make_dict(): maconfig = OptionDescription('rootconfig', '', [od1, od2]) cfg = Config(maconfig) cfg.read_write() - raises(PropertiesOptionError, 'cfg.od1.opt1') + raises(PropertiesOptionError, 'cfg.od2.opt2') + + +def test_callback_calculating_disabled(): + opt1 = BoolOption('opt1', '', properties=('disabled',)) + opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': (('od1.opt1', False),)}) + od1 = OptionDescription('od1', '', [opt1]) + od2 = OptionDescription('od2', '', [opt2]) + maconfig = OptionDescription('rootconfig', '', [od1, od2]) + cfg = Config(maconfig) + cfg.read_write() + raises(ConfigError, 'cfg.od2.opt2') + + +def test_callback_calculating_mandatory(): + opt1 = BoolOption('opt1', '', properties=('disabled',)) + opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': (('od1.opt1', False),)}, properties=('mandatory',)) + od1 = OptionDescription('od1', '', [opt1]) + od2 = OptionDescription('od2', '', [opt2]) + maconfig = OptionDescription('rootconfig', '', [od1, od2]) + cfg = Config(maconfig) + cfg.read_only() + raises(ConfigError, 'cfg.od2.opt2') diff --git a/tiramisu/setting.py b/tiramisu/setting.py index 249af37..531e846 100644 --- a/tiramisu/setting.py +++ b/tiramisu/setting.py @@ -385,13 +385,17 @@ class Settings(object): #____________________________________________________________ def validate_properties(self, opt_or_descr, is_descr, is_write, path, value=None, force_permissive=False, - force_properties=None): + force_properties=None, force_permissives=None): """ validation upon the properties related to `opt_or_descr` :param opt_or_descr: an option or an option description object :param force_permissive: behaves as if the permissive property was present + :param force_properties: set() with properties that is force to add + in global properties + :param force_permissives: set() with permissives that is force to add + in global permissives :param is_descr: we have to know if we are in an option description, just because the mandatory property doesn't exist here @@ -408,6 +412,8 @@ class Settings(object): self_properties = copy(self._getproperties()) if force_permissive is True or 'permissive' in self_properties: properties -= self._p_.getpermissive() + if force_permissives is not None: + properties -= force_permissives # global properties if force_properties is not None: diff --git a/tiramisu/value.py b/tiramisu/value.py index 3d172dc..911f4a8 100644 --- a/tiramisu/value.py +++ b/tiramisu/value.py @@ -177,9 +177,16 @@ class Values(object): # options with callbacks setting = self.context().cfgimpl_get_settings() is_frozen = 'frozen' in setting[opt] + # For calculating properties, we need value (ie for mandatory value). + # If value is calculating with a PropertiesOptionError's option + # _getcallback_value raise a ConfigError. + # We can not raise ConfigError if this option should raise + # PropertiesOptionError too. So we get config_error and raise + # ConfigError if properties did not raise. + config_error = None + force_permissives = None # if value is callback and is not set # or frozen with force_default_on_freeze - config_error = None if opt.impl_has_callback() and ( self._is_default_owner(path) or (is_frozen and 'force_default_on_freeze' in setting[opt])): @@ -198,6 +205,9 @@ class Values(object): value = self._getcallback_value(opt) except ConfigError as config_error: value = None + # should not raise PropertiesOptionError if option is + # mandatory + force_permissives = set(['mandatory']) else: if (opt.impl_is_multi() and opt.impl_get_multitype() == multitypes.slave): @@ -222,7 +232,8 @@ class Values(object): if validate_properties: setting.validate_properties(opt, False, False, value=value, path=path, force_permissive=force_permissive, - force_properties=force_properties) + force_properties=force_properties, + force_permissives=force_permissives) if config_error is not None: raise ConfigError(config_error) return value