propertyerror are transitive in consistency, now it's possible to set non-transitive...
[tiramisu.git] / tiramisu / option / baseoption.py
index 74b26ca..8d08c80 100644 (file)
@@ -25,7 +25,7 @@ import warnings
 from tiramisu.i18n import _
 from tiramisu.setting import log, undefined
 from tiramisu.autolib import carry_out_calculation
-from tiramisu.error import ConfigError, ValueWarning
+from tiramisu.error import ConfigError, ValueWarning, PropertiesOptionError
 from tiramisu.storage import get_storages_option
 
 
@@ -403,7 +403,8 @@ class Option(OnlyOption):
     _empty = ''
 
     def _launch_consistency(self, func, option, value, context, index,
-                            submulti_index, all_cons_opts, warnings_only):
+                            submulti_index, all_cons_opts, warnings_only,
+                            transitive):
         """Launch consistency now
 
         :param func: function name, this name should start with _cons_
@@ -420,47 +421,55 @@ class Option(OnlyOption):
         :type all_cons_opts: `list` of `tiramisu.option.Option`
         :param warnings_only: specific raise error for warning
         :type warnings_only: `boolean`
+        :param transitive: propertyerror is transitive
+        :type transitive: `boolean`
         """
         if context is not undefined:
             descr = context.cfgimpl_get_description()
 
         all_cons_vals = []
         for opt in all_cons_opts:
-            #get value
-            if (isinstance(opt, DynSymLinkOption) and option._dyn == opt._dyn) or \
-                    option == opt:
-                opt_value = value
-            else:
-                #if context, calculate value, otherwise get default value
-                if context is not undefined:
-                    if isinstance(opt, DynSymLinkOption):
-                        path = opt.impl_getpath(context)
+            try:
+                #get value
+                if (isinstance(opt, DynSymLinkOption) and option._dyn == opt._dyn) or \
+                        option == opt:
+                    opt_value = value
+                else:
+                    #if context, calculate value, otherwise get default value
+                    if context is not undefined:
+                        if isinstance(opt, DynSymLinkOption):
+                            path = opt.impl_getpath(context)
+                        else:
+                            path = descr.impl_get_path_by_opt(opt)
+                        opt_value = context.getattr(path, validate=False,
+                                                    force_permissive=True)
                     else:
-                        path = descr.impl_get_path_by_opt(opt)
-                    opt_value = context.getattr(path, validate=False,
-                                                force_permissive=True)
+                        opt_value = opt.impl_getdefault()
+
+                #append value
+                if not self.impl_is_multi() or (isinstance(opt, DynSymLinkOption)
+                                                and option._dyn == opt._dyn) or \
+                        option == opt:
+                    all_cons_vals.append(opt_value)
+                elif self.impl_is_submulti():
+                    try:
+                        all_cons_vals.append(opt_value[index][submulti_index])
+                    except IndexError:
+                        #value is not already set, could be higher index
+                        #so return if no value
+                        return
                 else:
-                    opt_value = opt.impl_getdefault()
-
-            #append value
-            if not self.impl_is_multi() or (isinstance(opt, DynSymLinkOption)
-                                            and option._dyn == opt._dyn) or \
-                    option == opt:
-                all_cons_vals.append(opt_value)
-            elif self.impl_is_submulti():
-                try:
-                    all_cons_vals.append(opt_value[index][submulti_index])
-                except IndexError:
-                    #value is not already set, could be higher index
-                    #so return if no value
-                    return
-            else:
-                try:
-                    all_cons_vals.append(opt_value[index])
-                except IndexError:
-                    #value is not already set, could be higher index
-                    #so return if no value
-                    return
+                    try:
+                        all_cons_vals.append(opt_value[index])
+                    except IndexError:
+                        #value is not already set, could be higher index
+                        #so return if no value
+                        return
+            except PropertiesOptionError as err:
+                if transitive:
+                    raise err
+                else:
+                    pass
         getattr(self, func)(all_cons_opts, all_cons_vals, warnings_only)
 
     def impl_validate(self, value, context=undefined, validate=True,
@@ -636,14 +645,22 @@ class Option(OnlyOption):
         :type func: `str`
         :param other_opts: options used to validate value
         :type other_opts: `list` of `tiramisu.option.Option`
-        :param params: extra params (only warnings_only are allowed)
+        :param params: extra params (warnings_only and transitive are allowed)
         """
         if self.impl_is_readonly():  # pragma: optional cover
             raise AttributeError(_("'{0}' ({1}) cannot add consistency, option is"
                                    " read-only").format(
                                        self.__class__.__name__,
                                        self.impl_getname()))
-        warnings_only = params.get('warnings_only', False)
+        warnings_only = False
+        transitive = True
+        for key, value in params.items():
+            if key == 'warnings_only':
+                warnings_only = value
+            elif key == 'transitive':
+                transitive = value
+            else:
+                raise ValueError(_('unknow parameter {0} in consistency').format(key))
         if self._is_subdyn():
             dynod = self._impl_getsubdyn()
         else:
@@ -678,16 +695,17 @@ class Option(OnlyOption):
                     if not self.impl_is_submulti():
                         self._launch_consistency(func, self, val, undefined, idx,
                                                  None, all_cons_opts,
-                                                 warnings_only)
+                                                 warnings_only, transitive)
                     else:
                         for slave_idx, val in enumerate(value):
                             self._launch_consistency(func, self, val, None,
                                                      idx, slave_idx,
                                                      all_cons_opts,
-                                                     warnings_only)
+                                                     warnings_only, transitive)
             else:
                 self._launch_consistency(func, self, value, undefined, None,
-                                         None, all_cons_opts, warnings_only)
+                                         None, all_cons_opts, warnings_only,
+                                         transitive)
         self._add_consistency(func, all_cons_opts, params)
         self.impl_validate(self.impl_getdefault())