pop and append in multi values
authorgwen <gremond@cadoles.com>
Tue, 4 Dec 2012 14:18:13 +0000 (15:18 +0100)
committergwen <gremond@cadoles.com>
Tue, 4 Dec 2012 14:18:13 +0000 (15:18 +0100)
tiramisu/config.py
tiramisu/option.py

index 13fb6e9..3f725c9 100644 (file)
@@ -74,7 +74,7 @@ class Config(object):
             if isinstance(child, Option):
                 if child.is_multi():
                     childdef = Multi(copy(child.getdefault()), config=self,
-                                     child=child)
+                                     opt=child)
                     self._cfgimpl_values[child._name] = childdef
                     self._cfgimpl_previous_values[child._name] = list(childdef)
                 else:
@@ -203,7 +203,7 @@ class Config(object):
                         _result.append(default_multi)
         else:
             _result = result
-        return Multi(_result, value.config, value.child)
+        return Multi(_result, value.config, opt=value.opt)
 
     def _getattr(self, name, permissive=False):
         """
index 007bf84..96625b9 100644 (file)
@@ -40,38 +40,81 @@ for act1, act2 in requires_actions:
 # multi types
 
 class Multi(list):
-    "container that support items for the values of list (multi) options"
-    def __init__(self, lst, config, child):
+    """multi options values container
+    that support item notation for the values of multi options"""
+    def __init__(self, lst, config, opt):
+        """
+        :lst: the Multi wraps a list value
+        :param config: the parent config
+        :param opt: the option object that have this Multi value
+        """
         self.config = config
-        self.child = child
+        self.opt = opt
         super(Multi, self).__init__(lst)
 
     def __setitem__(self, key, value):
-        return self.setoption(value, key)
+        return self._setvalue(value, key, who=settings.owner)
 
     def append(self, value):
-        self.setoption(value)
-
-    def setoption(self, value, key=None, who=None):
-        if who is None:
-            who = settings.owner
+        """the list value can be updated (appened)
+        only if the option is a master"""
+        try:
+            master = self.config._cfgimpl_descr.get_master_name()
+            if master != self.opt._name:
+                raise IndexError("in a group with a master, you mustn't add "
+                        "a value in a slave's Multi value")
+            for name, multi in self.config:
+                if master == multi.opt._name:
+                    multi._setvalue(value, who=settings.owner)
+                else:
+                    default_value = multi.opt.getdefault_multi()
+                    multi._setvalue(default_value)
+        except TypeError:
+            self._setvalue(value, who=settings.owner)
+
+    def _setvalue(self, value, key=None, who=None):
         if value != None:
-            if not self.child._validate(value):
+            if not self.opt._validate(value):
                 raise ConfigError("invalid value {0} "
-                    "for option {1}".format(str(value), self.child._name))
+                    "for option {1}".format(str(value), self.opt._name))
         oldvalue = list(self)
         if key is None:
             ret = super(Multi, self).append(value)
         else:
             ret = super(Multi, self).__setitem__(key, value)
-        self.child.setowner(self.config, who)
-        self.config._cfgimpl_previous_values[self.child._name] = oldvalue
+        if who != None:
+            self.opt.setowner(self.config, who)
+        self.config._cfgimpl_previous_values[self.opt._name] = oldvalue
         return ret
 
     def pop(self, key):
+        """the list value can be updated (poped)
+        only if the option is a master
+        """
+        try:
+            master = self.config._cfgimpl_descr.get_master_name()
+            if master != self.opt._name:
+                raise IndexError("in a group with a master, you mustn't remove "
+                        "a value in a slave's Multi value")
+            for name, multi in self.config:
+                if master == multi.opt._name:
+                    multi._pop(key)
+                else:
+                    change_who = False
+                    # the value owner has to be updated because
+                    # the default value¬†doesn't have the same length
+                    # of the new value
+                    if len(multi.opt.getdefault()) >= len(multi):
+                        change_who = True
+                    multi._pop(key, change_who=change_who)
+        except TypeError:
+            self._pop(key)
+
+    def _pop(self, key, change_who=True):
         oldvalue = list(self)
-        self.child.setowner(self.config, settings.owner)
-        self.config._cfgimpl_previous_values[self.child._name] = oldvalue
+        if change_who:
+            self.opt.setowner(self.config, settings.owner)
+        self.config._cfgimpl_previous_values[self.opt._name] = oldvalue
         return super(Multi, self).pop(key)
 # ____________________________________________________________
 #