remove try/except
[tiramisu.git] / tiramisu / option / masterslave.py
index 7a9057f..603018b 100644 (file)
 # the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
 # the whole pypy projet is under MIT licence
 # ____________________________________________________________
-from tiramisu.i18n import _
-from tiramisu.setting import log
-from tiramisu.error import SlaveError, ConfigError
-from .baseoption import SymLinkOption, Option
+from ..i18n import _
+from ..setting import log, undefined
+from ..error import SlaveError, PropertiesOptionError
+from .baseoption import DynSymLinkOption, SymLinkOption, Option
 
 
 class MasterSlaves(object):
     __slots__ = ('master', 'slaves')
 
-    def __init__(self, name, childs):
+    def __init__(self, name, childs, validate=True):
         #if master (same name has group) is set
         #for collect all slaves
         self.master = None
         slaves = []
         for child in childs:
-            if isinstance(child, SymLinkOption):
+            if isinstance(child, SymLinkOption):  # pragma: optional cover
                 raise ValueError(_("master group {0} shall not have "
                                    "a symlinkoption").format(name))
-            if not isinstance(child, Option):
+            if not isinstance(child, Option):  # pragma: optional cover
                 raise ValueError(_("master group {0} shall not have "
                                    "a subgroup").format(name))
-            if not child.impl_is_multi():
+            if not child.impl_is_multi():  # pragma: optional cover
                 raise ValueError(_("not allowed option {0} "
                                    "in group {1}"
                                    ": this option is not a multi"
-                                   "").format(child._name, name))
-            if child._name == name:
+                                   "").format(child.impl_getname(), name))
+            if child.impl_getname() == name:
                 self.master = child
             else:
+                if child.impl_getdefault() != []:
+                    raise ValueError(_("not allowed default value for option {0} "
+                                       "in group {1}").format(child.impl_getname(),
+                                                              name))
                 slaves.append(child)
-        if self.master is None:
+        if self.master is None:  # pragma: optional cover
             raise ValueError(_('master group with wrong'
                                ' master name for {0}'
                                ).format(name))
-        callback, callback_params = self.master.impl_get_callback()
-        if callback is not None and callback_params is not None:
-            for key, callbacks in callback_params.items():
-                for callbk in callbacks:
-                    if isinstance(callbk, tuple):
-                        if callbk[0] in slaves:
-                            raise ValueError(_("callback of master's option shall "
-                                               "not refered a slave's ones"))
+        if validate:
+            callback, callback_params = self.master.impl_get_callback()
+            if callback is not None and callback_params != {}:  # pragma: optional cover
+                for key, callbacks in callback_params.items():
+                    for callbk in callbacks:
+                        if isinstance(callbk, tuple):
+                            if callbk[0] in slaves:
+                                raise ValueError(_("callback of master's option shall "
+                                                   "not refered a slave's ones"))
         #everything is ok, store references
         self.slaves = tuple(slaves)
         for child in childs:
             child._master_slaves = self
 
     def is_master(self, opt):
-        return opt == self.master
+        return opt == self.master or (isinstance(opt, DynSymLinkOption) and
+                                      opt._opt == self.master)
+
+    def getmaster(self, opt):
+        if isinstance(opt, DynSymLinkOption):
+            suffix = opt.impl_getsuffix()
+            name = self.master.impl_getname() + suffix
+            base_path = opt._dyn.split('.')[0] + '.'
+            path = base_path + name
+            master = self.master._impl_to_dyn(name, path)
+        else:  # pragma: no dynoptiondescription cover
+            master = self.master
+        return master
+
+    def getslaves(self, opt):
+        if isinstance(opt, DynSymLinkOption):
+            for slave in self.slaves:
+                suffix = opt.impl_getsuffix()
+                name = slave.impl_getname() + suffix
+                base_path = opt._dyn.split('.')[0] + '.'
+                path = base_path + name
+                yield slave._impl_to_dyn(name, path)
+        else:  # pragma: no dynoptiondescription cover
+            for slave in self.slaves:
+                yield slave
 
     def in_same_group(self, opt):
-        return opt == self.master or opt in self.slaves
+        if isinstance(opt, DynSymLinkOption):
+            return opt._opt == self.master or opt._opt in self.slaves
+        else:  # pragma: no dynoptiondescription cover
+            return opt == self.master or opt in self.slaves
 
-    def reset(self, values):
-        for slave in self.slaves:
-            values.reset(slave)
+    def reset(self, opt, values, setting_properties):
+        for slave in self.getslaves(opt):
+            values.reset(slave, validate=False, _setting_properties=setting_properties)
 
-    def pop(self, values, index):
-        #FIXME pas test de meta ...
-        for slave in self.slaves:
+    def pop(self, opt, values, index):
+        for slave in self.getslaves(opt):
             if not values.is_default_owner(slave, validate_properties=False,
-                                           validate_meta=False):
-                values._get_cached_item(slave, validate=False,
-                                        validate_properties=False
-                                        ).pop(index, force=True)
+                                           validate_meta=False, index=index):
+                values._get_cached_value(slave, validate=False,
+                                         validate_properties=False
+                                         ).pop(index, force=True)
         pass
 
     def getitem(self, values, opt, path, validate, force_permissive,
-                force_properties, validate_properties):
-        if opt == self.master:
+                trusted_cached_properties, validate_properties, slave_path=undefined,
+                slave_value=undefined, setting_properties=undefined,
+                self_properties=undefined, index=None,
+                returns_raise=False):
+        if self.is_master(opt):
             return self._getmaster(values, opt, path, validate,
-                                   force_permissive, force_properties,
-                                   validate_properties)
+                                   force_permissive,
+                                   validate_properties, slave_path,
+                                   slave_value, self_properties, index,
+                                   returns_raise)
         else:
             return self._getslave(values, opt, path, validate,
-                                  force_permissive, force_properties,
-                                  validate_properties)
+                                  force_permissive, trusted_cached_properties,
+                                  validate_properties, setting_properties,
+                                  self_properties, index, returns_raise)
 
     def _getmaster(self, values, opt, path, validate, force_permissive,
-                   force_properties, validate_properties):
-        value = values._get_validated_value(opt, path, validate,
-                                            force_permissive,
-                                            force_properties,
-                                            validate_properties)
-        if validate is True:
+                   validate_properties, c_slave_path,
+                   c_slave_value, self_properties, index, returns_raise):
+        value = values._get_cached_value(opt, path=path, validate=validate,
+                                         force_permissive=force_permissive,
+                                         validate_properties=validate_properties,
+                                         self_properties=self_properties,
+                                         from_masterslave=True, index=index,
+                                         returns_raise=True)
+        if isinstance(value, Exception):
+            return value
+        if index is None and validate is True:
             masterlen = len(value)
-            for slave in self.slaves:
-                try:
-                    slave_path = values._get_opt_path(slave)
-                    slave_value = values._get_validated_value(slave,
-                                                              slave_path,
-                                                              False,
-                                                              False,
-                                                              None, False,
-                                                              None)  # not undefined
-                    slavelen = len(slave_value)
-                    self.validate_slave_length(masterlen, slavelen, slave._name)
-                except ConfigError:
-                    pass
+            for slave in self.getslaves(opt):
+                slave_path = slave.impl_getpath(values._getcontext())
+                slavelen = values._p_.get_max_length(slave_path)
+                self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
         return value
 
     def _getslave(self, values, opt, path, validate, force_permissive,
-                  force_properties, validate_properties):
-        value = values._get_validated_value(opt, path, validate,
-                                            force_permissive,
-                                            force_properties,
-                                            validate_properties,
-                                            None)  # not undefined
-        return self.get_slave_value(values, opt, value, validate, validate_properties)
-
-    def setitem(self, values, opt, value, path):
-        if opt == self.master:
-            masterlen = len(value)
-            for slave in self.slaves:
-                slave_path = values._get_opt_path(slave)
-                slave_value = values._get_validated_value(slave,
-                                                          slave_path,
-                                                          False,
-                                                          False,
-                                                          None, False,
-                                                          None)  # not undefined
-                slavelen = len(slave_value)
-                self.validate_slave_length(masterlen, slavelen, slave._name)
-        else:
-            self.validate_slave_length(self.get_length(values), len(value),
-                                       opt._name, setitem=True)
-
-    def get_length(self, values, validate=True):
-        masterp = values._get_opt_path(self.master)
-        return len(self.getitem(values, self.master, masterp, validate, False,
-                                None, True))
-
-    def validate_slave_length(self, masterlen, valuelen, name, setitem=False):
-        if valuelen > masterlen or (valuelen < masterlen and setitem):
-            log.debug('validate_slave_length: masterlen: {0}, valuelen: {1}, '
-                      'setitem: {2}'.format(masterlen, valuelen, setitem))
-            raise SlaveError(_("invalid len for the slave: {0}"
-                               " which has {1} as master").format(
-                                   name, self.master._name))
-
-    def get_slave_value(self, values, opt, value, validate=True,
-                        validate_properties=True):
+                  trusted_cached_properties, validate_properties, setting_properties,
+                  self_properties, index, returns_raise):
         """
         if master has length 0:
             return []
@@ -182,19 +177,104 @@ class MasterSlaves(object):
                 list is smaller than master: return list + None
                 list is greater than master: raise SlaveError
         """
-        #if slave, had values until master's one
-        masterlen = self.get_length(values, validate)
-        valuelen = len(value)
-        if validate:
-            self.validate_slave_length(masterlen, valuelen, opt._name)
-        path = values._get_opt_path(opt)
-        if valuelen < masterlen:
-            for num in range(0, masterlen - valuelen):
-                index = valuelen + num
-                value.append(values._get_validated_value(opt, path, True,
-                                                         False, None,
-                                                         validate_properties,
-                                                         index=index),
-                             setitem=False,
-                             force=True)
-        return value
+        master = self.getmaster(opt)
+        context = values._getcontext()
+        masterp = master.impl_getpath(context)
+        masterlen = self.get_length(values, opt, validate, undefined,
+                                    undefined, force_permissive,
+                                    master=master, returns_raise=returns_raise)
+        if isinstance(masterlen, Exception):
+            return masterlen
+        master_is_meta = values._is_meta(master, masterp)
+        multi = values._get_multi(opt, path)
+        #if masterlen is [], test properties (has no value, don't get any value)
+        if masterlen == 0:
+            if validate_properties:
+                props = context.cfgimpl_get_settings().validate_properties(opt, False,
+                                                                           False,
+                                                                           value=multi,
+                                                                           path=path,
+                                                                           force_permissive=force_permissive,
+                                                                           setting_properties=setting_properties)
+                if props:
+                    if returns_raise:
+                        return props
+                    else:
+                        raise props
+        else:
+            one_has_value = False
+            if index is None:
+                indexes = range(0, masterlen)
+            else:
+                indexes = [index]
+            for idx in indexes:
+                value = values._get_cached_value(opt, path, validate,
+                                                 force_permissive,
+                                                 trusted_cached_properties,
+                                                 validate_properties,
+                                                 with_meta=master_is_meta,
+                                                 index=idx,
+                                                 # not self_properties,
+                                                 # depends to index
+                                                 #self_properties=self_properties,
+                                                 masterlen=masterlen,
+                                                 from_masterslave=True,
+                                                 returns_raise=True)
+                if isinstance(value, Exception):
+                    if isinstance(value, PropertiesOptionError):
+                        err = value
+                        multi.append_properties_error(value)
+                    else:
+                        return value
+                else:
+                    multi.append(value, setitem=False, force=True, validate=validate)
+                    one_has_value = True
+            if not one_has_value:
+                #raise last err
+                if returns_raise:
+                    return err
+                else:
+                    raise err
+        return multi
+
+    def validate(self, values, opt, value, path, returns_raise):
+        if self.is_master(opt):
+            masterlen = len(value)
+            #for regen slave path
+            base_path = '.'.join(path.split('.')[:-1]) + '.'
+            for slave in self.getslaves(opt):
+                slave_path = base_path + slave.impl_getname()
+                slavelen = values._p_.get_max_length(slave_path)
+                self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), opt)
+        else:
+            val_len = self.get_length(values, opt, slave_path=path, returns_raise=returns_raise)
+            if isinstance(val_len, Exception):
+                return val_len
+            self.validate_slave_length(val_len,
+                                       len(value),
+                                       opt.impl_getname(), opt, setitem=True)
+
+    def get_length(self, values, opt, validate=True, slave_path=undefined,
+                   slave_value=undefined, force_permissive=False, master=None,
+                   masterp=None, returns_raise=False):
+        """get master len with slave option"""
+        if master is None:
+            master = self.getmaster(opt)
+        if masterp is None:
+            masterp = master.impl_getpath(values._getcontext())
+        if slave_value is undefined:
+            slave_path = undefined
+        value = self.getitem(values, master, masterp, validate,
+                             force_permissive, None, True, slave_path,
+                             slave_value, returns_raise=returns_raise)
+        if isinstance(value, Exception):
+            return value
+        return len(value)
+
+    def validate_slave_length(self, masterlen, valuelen, name, opt, setitem=False):
+        if valuelen > masterlen or (valuelen < masterlen and setitem):  # pragma: optional cover
+            log.debug('validate_slave_length: masterlen: {0}, valuelen: {1}, '
+                      'setitem: {2}'.format(masterlen, valuelen, setitem))
+            raise SlaveError(_("invalid len for the slave: {0}"
+                               " which has {1} as master").format(
+                                   name, self.getmaster(opt).impl_getname()))