allow mandatory value (see 9ddf100118d913c2f4225cca1adb65317b512d84 for more details)
authorEmmanuel Garette <egarette@cadoles.com>
Mon, 16 Sep 2013 18:51:13 +0000 (20:51 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Mon, 16 Sep 2013 18:51:13 +0000 (20:51 +0200)
test/test_option_calculation.py
tiramisu/setting.py
tiramisu/value.py

index d57072f..1441460 100644 (file)
@@ -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')
index 249af37..531e846 100644 (file)
@@ -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:
index 3d172dc..911f4a8 100644 (file)
@@ -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