list is Multi now which enables us to implement item access
[tiramisu.git] / config.py
index fd5c145..f4fabdd 100644 (file)
--- a/config.py
+++ b/config.py
@@ -17,7 +17,7 @@
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #
 # The original `Config` design model is unproudly borrowed from 
-# the rough gus of pypy: pypy: http://codespeak.net/svn/pypy/dist/pypy/config/
+# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
 # the whole pypy projet is under MIT licence
 # ____________________________________________________________
 from error import (HiddenOptionError, ConfigError, NotFoundError, 
@@ -25,16 +25,18 @@ from error import (HiddenOptionError, ConfigError, NotFoundError,
                             SpecialOwnersError, MandatoryError, MethodCallError, 
                                            DisabledOptionError, ModeOptionError)
 from option import (OptionDescription, Option, SymLinkOption, group_types, 
-                                                          apply_requires, modes)
-import autolib
+                    Multi, apply_requires, modes)
 from autolib import special_owners, special_owner_factory
+# ______________________________________________________________________
+# generic owner. 'default' is the general config owner after init time
+default_owner = 'user'
 # ____________________________________________________________
 class Config(object):
     _cfgimpl_hidden = True
     _cfgimpl_disabled = True
     _cfgimpl_mandatory = True
     _cfgimpl_frozen = False
-    _cfgimpl_owner = "user"
+    _cfgimpl_owner = default_owner
     _cfgimpl_toplevel = None
     _cfgimpl_mode = 'normal'
     
@@ -65,8 +67,15 @@ class Config(object):
         self._validate_duplicates(self._cfgimpl_descr._children)
         for child in self._cfgimpl_descr._children:
             if isinstance(child, Option):
-                self._cfgimpl_values[child._name] = child.getdefault()
-                self._cfgimpl_previous_values[child._name] = child.getdefault()
+                if child.is_multi():
+                    childdef = Multi(child.getdefault(), config=self, 
+                                     child=child)
+                    self._cfgimpl_values[child._name] = childdef
+                    self._cfgimpl_previous_values[child._name] = childdef
+                else:
+                    childdef = child.getdefault()
+                    self._cfgimpl_values[child._name] = childdef
+                    self._cfgimpl_previous_values[child._name] = childdef 
                 if child.getcallback() is not None:
                     if child._is_hidden():
                         self._cfgimpl_value_owners[child._name] = 'auto'
@@ -74,7 +83,8 @@ class Config(object):
                         self._cfgimpl_value_owners[child._name] = 'fill'
                 else:
                     if child.is_multi():
-                        self._cfgimpl_value_owners[child._name] = ['default']
+                        self._cfgimpl_value_owners[child._name] = ['default' \
+                            for i in range(len(child.getdefault() ))]
                     else:
                         self._cfgimpl_value_owners[child._name] = 'default'
             elif isinstance(child, OptionDescription):
@@ -154,17 +164,10 @@ class Config(object):
         if type(getattr(self._cfgimpl_descr, name)) != SymLinkOption:
             self._validate(name, getattr(self._cfgimpl_descr, name))
         self.setoption(name, value, self._cfgimpl_owner)
-
-#    def __setitem__(self, key, value):
-#        print "entering __setitem__"
-#        if '.' in name:
-#            homeconfig, name = self._cfgimpl_get_home_by_path(name)
-#            return "hello" #setattr(homeconfig, name, value)
-#        return "titi"
-                 
+        
     def _validate(self, name, opt_or_descr):
+        apply_requires(opt_or_descr, self) 
         if not type(opt_or_descr) == OptionDescription:
-            apply_requires(opt_or_descr, self) 
             # hidden options
             if self._cfgimpl_toplevel._cfgimpl_hidden and \
                 (opt_or_descr._is_hidden() or self._cfgimpl_descr._is_hidden()):
@@ -181,8 +184,6 @@ class Config(object):
                 if opt_or_descr.get_mode() != 'normal':
                     raise ModeOptionError("this option's mode is not normal:"
                                                             " {0}".format(name))
-        if type(opt_or_descr) == OptionDescription:
-            apply_requires(opt_or_descr, self) 
 
     def __getattr__(self, name):
         # attribute access by passing a path, 
@@ -206,7 +207,6 @@ class Config(object):
                                  (self.__class__, name))
         if name in self._cfgimpl_value_owners:
             owner = self._cfgimpl_value_owners[name]
-            # special owners
             if owner in special_owners:
                 value = self._cfgimpl_values[name]
                 if value != None:
@@ -223,16 +223,14 @@ class Config(object):
                             config=self._cfgimpl_get_toplevel())
                 # this result **shall not** be a list 
                 # for example, [1, 2, 3, None] -> [1, 2, 3, result]
-                #
                 if type(result) == list:
                     raise ConfigError('invalid calculated value returned'
                         ' for option {0} : shall not be a list'.format(name))
                 if result != None and not opt_or_descr._validate(result):
                     raise ConfigError('invalid calculated value returned'
                         ' for option {0}'.format(name))
-                
                 if opt_or_descr.is_multi():
-                    if value == None:
+                    if value == []:
                         _result = [result]
                     else:
                         _result = []
@@ -252,8 +250,19 @@ class Config(object):
                   and opt_or_descr.getdefault() == None:
                     raise MandatoryError("option: {0} is mandatory " 
                                           "and shall have a value".format(name))
+        # for multi types with None in the value (ex: ["egg", None, "spam"])
+        # None is replaced by default_multi
+        if not isinstance(opt_or_descr, OptionDescription):
+            if opt_or_descr.is_multi() and None in self._cfgimpl_values[name]:
+                newvalue = []
+                for val in self._cfgimpl_values[name]:
+                    if val is None:
+                        newvalue.append(opt_or_descr.default_multi)
+                    else:
+                        newvalue.append(val)
+                return newvalue
         return self._cfgimpl_values[name]
-
+        
     def __dir__(self):
         #from_type = dir(type(self))
         from_dict = list(self.__dict__)
@@ -325,11 +334,12 @@ class Config(object):
             if who == 'auto':
                 if not child._is_hidden():
                     child.hide()
-            if value is None and who != 'default':
-                if child.is_multi():
-                     child.setowner(self, ['default' for i in range(len(child.getdefault()))])
-                else:
-                    child.setowner(self, 'default')
+            if (value is None and who != 'default' and not child.is_multi()):
+                child.setowner(self, 'default')
+                self._cfgimpl_values[name] = child.getdefault()
+            elif (value == [] and who != 'default' and child.is_multi()):
+                child.setowner(self, ['default' for i in range(len(child.getdefault()))])
+                self._cfgimpl_values[name] = child.getdefault()
             else:         
                 child.setowner(self, newowner)
         else: