the value owner is a string now
authorgwen <gremond@cadoles.com>
Thu, 15 Nov 2012 09:55:14 +0000 (10:55 +0100)
committergwen <gremond@cadoles.com>
Thu, 15 Nov 2012 09:55:14 +0000 (10:55 +0100)
test/test_config.py
test/test_config_api.py
test/test_option_default.py
test/test_option_setting.py
tiramisu/config.py
tiramisu/option.py
tiramisu/tool.py

index 865ef70..e7c5192 100644 (file)
@@ -40,7 +40,9 @@ def test_reset_value():
     assert cfg.gc.dummy == False
     cfg.gc.dummy = True
     assert cfg.gc.dummy == True
-    cfg.gc.dummy = None
+#    dummy = cfg.unwrap_from_path("gc.dummy")
+#    dummy.reset()
+#    cfg.gc.dummy = False
 
 def test_base_config_and_groups():
     descr = make_description()
index 5d67413..3695049 100644 (file)
@@ -124,19 +124,19 @@ def test_make_dict():
     d2 = make_dict(config, flatten=True)
     assert d2 == {'a': True, 'int': 43}
 
-def test_delattr():
-    "delattr, means suppression of an option in a config"
-    descr = OptionDescription("opt", "", [
-    OptionDescription("s1", "", [
-        BoolOption("a", "", default=False)]),
-    IntOption("int", "", default=42)])
-    c = Config(descr)
-    c.int = 45
-    assert c.int == 45
-    del c.int
-    assert c.int == 42
-    c.int = 45
-    assert c.int == 45
+#def test_delattr():
+#    "delattr, means suppression of an option in a config"
+#    descr = OptionDescription("opt", "", [
+#    OptionDescription("s1", "", [
+#        BoolOption("a", "", default=False)]),
+#    IntOption("int", "", default=42)])
+#    c = Config(descr)
+#    c.int = 45
+#    assert c.int == 45
+#    del c.int
+#    assert c.int == 42
+#    c.int = 45
+#    assert c.int == 45
 
 def test_find_in_config():
     "finds option in config"
index 5b12d6c..3b48770 100644 (file)
@@ -115,20 +115,20 @@ def test_choice_with_default():
     config = Config(descr)
     assert config.backend == "cli"
 
-def test_arbitrary_option():
-    descr = OptionDescription("top", "", [
-        ArbitraryOption("a", "no help", default=None)
-    ])
-    config = Config(descr)
-    config.a = []
-    config.a.append(1)
-    assert config.a == [1]
+#def test_arbitrary_option():
+#    descr = OptionDescription("top", "", [
+#        ArbitraryOption("a", "no help", default=None)
+#    ])
+#    config = Config(descr)
+#    config.a = []
+#    config.a.append(1)
+#    assert config.a == [1]
 
-    descr = OptionDescription("top", "", [
-        ArbitraryOption("a", "no help", defaultfactory=list)
-    ])
-    c1 = Config(descr)
-    c2 = Config(descr)
-    c1.a.append(1)
-    assert c2.a == []
-    assert c1.a == [1]
+#    descr = OptionDescription("top", "", [
+#        ArbitraryOption("a", "no help", defaultfactory=list)
+#    ])
+#    c1 = Config(descr)
+#    c2 = Config(descr)
+#    c1.a.append(1)
+#    assert c2.a == []
+#    assert c1.a == [1]
index 9fdee42..f7a8903 100644 (file)
@@ -63,13 +63,13 @@ def test_reset_with_multi():
 #    config.string = []
     config.unwrap_from_path("string").reset(config)
     assert config.string == ["string"]
-    assert config._cfgimpl_value_owners['string'] == ['default']
+    assert config._cfgimpl_value_owners['string'] == 'default'
     config.string = ["eggs", "spam", "foo"]
-    assert config._cfgimpl_value_owners['string'] == ['user', 'user', 'user']
+    assert config._cfgimpl_value_owners['string'] == 'user'
     config.string = []
     config.unwrap_from_path("string").reset(config)
 #    assert config.string == ["string"]
-    assert config._cfgimpl_value_owners['string'] == ['default']
+    assert config._cfgimpl_value_owners['string'] == 'default'
     raises(ConfigError, "config.string = None")
 
 def test_default_with_multi():
@@ -111,10 +111,10 @@ def test_access_with_multi_default():
     s = StrOption("string", "", default=["string"], multi=True)
     descr = OptionDescription("options", "", [s])
     config = Config(descr)
-    assert config._cfgimpl_value_owners["string"] == ['default']
+    assert config._cfgimpl_value_owners["string"] == 'default'
     config.string = ["foo", "bar"]
     assert config.string == ["foo", "bar"]
-    assert config._cfgimpl_value_owners["string"] == ['user', 'user']
+    assert config._cfgimpl_value_owners["string"] == 'user'
 
 #def test_attribute_access_with_multi2():
 #    s = StrOption("string", "", default="string", multi=True)
index 2a8aeee..e97323e 100644 (file)
@@ -25,7 +25,7 @@ from tiramisu.error import (PropertiesOptionError, ConfigError, NotFoundError,
     AmbigousOptionError, ConflictConfigError, NoMatchingOptionFound,
     MandatoryError, MethodCallError, NoValueReturned)
 from tiramisu.option import (OptionDescription, Option, SymLinkOption,
-    group_types, Multi, apply_requires, Owner)
+    group_types, Multi, apply_requires)
 
 # ______________________________________________________________________
 # generic owner. 'default' is the general config owner after init time
@@ -33,10 +33,11 @@ default_owner = 'user'
 
 # ____________________________________________________________
 class Config(object):
-    "properties attribute: the name of a property enables this property"
+    "main configuration management entry"
+    #properties attribute: the name of a property enables this property
     _cfgimpl_properties = ['hidden', 'disabled']
     _cfgimpl_permissive = []
-    "mandatory means: a mandatory option has to have a value that is not None"
+    #mandatory means: a mandatory option has to have a value that is not None
     _cfgimpl_mandatory = True
     _cfgimpl_frozen = True
     _cfgimpl_owner = default_owner
@@ -87,13 +88,11 @@ class Config(object):
                                      child=child)
                     self._cfgimpl_values[child._name] = childdef
                     self._cfgimpl_previous_values[child._name] = list(childdef)
-                    self._cfgimpl_value_owners[child._name] = ['default' \
-                        for i in range(len(child.getdefault() ))]
                 else:
                     childdef = child.getdefault()
                     self._cfgimpl_values[child._name] = childdef
                     self._cfgimpl_previous_values[child._name] = childdef
-                    self._cfgimpl_value_owners[child._name] = 'default'
+                self._cfgimpl_value_owners[child._name] = 'default'
             elif isinstance(child, OptionDescription):
                 self._validate_duplicates(child._children)
                 self._cfgimpl_values[child._name] = Config(child, parent=self)
@@ -115,24 +114,13 @@ class Config(object):
                     if child.is_multi():
                         self._cfgimpl_values[child._name] = Multi(
                                 copy(child.getdefault()), config=self, child=child)
-                        self._cfgimpl_value_owners[child._name] = ['default' \
-                                for i in range(len(child.getdefault() ))]
                     else:
                         self._cfgimpl_values[child._name] = copy(child.getdefault())
-                        self._cfgimpl_value_owners[child._name] = 'default'
+                    self._cfgimpl_value_owners[child._name] = 'default'
             elif isinstance(child, OptionDescription):
                 if child._name not in self._cfgimpl_values:
                     self._cfgimpl_values[child._name] = Config(child, parent=self)
 
-#    def override(self, overrides):
-#        """
-#        overrides default values. This marks the overridden values as defaults.
-#        :param overrides: is a dictionary of path strings to values.
-#        """
-#        for name, value in overrides.iteritems():
-#            homeconfig, name = self._cfgimpl_get_home_by_path(name)
-#            homeconfig.setoption(name, value, 'default')
-
     def cfgimpl_set_owner(self, owner):
         ":param owner: sets the default value for owner at the Config level"
         self._cfgimpl_owner = owner
@@ -254,8 +242,7 @@ class Config(object):
                 value = self._cfgimpl_values[name]
                 if (not opt_or_descr.is_frozen() or \
                         not opt_or_descr.is_forced_on_freeze()) and \
-                        not opt_or_descr.is_default_owner(self, all_default=False):
-                        #not opt_or_descr.getowner(self) == 'default':
+                        not opt_or_descr.is_default_owner(self):
                     if opt_or_descr.is_multi():
                         if None not in value:
                             return value
@@ -268,42 +255,9 @@ class Config(object):
                     pass
                 else:
                     if opt_or_descr.is_multi():
-                        owners = copy(self._cfgimpl_value_owners[name])
-                        self._cfgimpl_value_owners[name] = []
                         if not isinstance(result, list):
-                            # for example, [1, 2, 3, None] -> [1, 2, 3, result]
-                            _result = Multi([result], value.config, value.child)
-                            for cpt in range(len(value)):
-                                val = value[cpt]
-                                if len(owners) > cpt:
-                                    if owners[cpt] == 'default':
-                                        _result.append(result)
-                                        self._cfgimpl_value_owners[name][cpt] = 'default'
-                                    else:
-                                        _result.append(val)
-                                else:
-                                    _result.append(val)
-                                    self._cfgimpl_value_owners[name][cpt] = 'default'
-                        else:
-                            # for example, [1, None, 2, None] + [a, b, c, d]
-                            # = [1, b, 2, d]
-                            _result = Multi([], value.config, value.child)
-                            for cpt in range(max(len(value), len(result))):
-                                if len(value) > cpt:
-                                    val = value[cpt]
-                                else:
-                                    val = ''
-                                if len(result) > cpt:
-                                    rval = result[cpt]
-                                if len(owners) > cpt:
-                                    if owners[cpt] == 'default':
-                                        _result.append(rval)
-                                        self._cfgimpl_value_owners[name][cpt] = 'default'
-                                    else:
-                                        _result.append(val)
-                                else:
-                                    _result.append(rval)
-                                    self._cfgimpl_value_owners[name][cpt] = 'default'
+                            result = [result]
+                        _result = Multi(result, value.config, value.child)
                     else:
                         # this result **shall not** be a list
                         if isinstance(result, list):
@@ -314,6 +268,7 @@ class Config(object):
                         raise ConfigError('invalid calculated value returned'
                             ' for option {0}'.format(name))
                     self._cfgimpl_values[name] = _result
+                    self._cfgimpl_value_owners[name] = 'default'
             self._test_mandatory(name, opt_or_descr)
             # frozen and force default
             if not opt_or_descr.has_callback() and opt_or_descr.is_forced_on_freeze():
@@ -347,16 +302,16 @@ class Config(object):
             return getattr(homeconfig._cfgimpl_descr, path)
         return getattr(self._cfgimpl_descr, path)
 
-    def __delattr__(self, name):
-        "if you use delattr you are responsible for all bad things happening"
-        if name.startswith('_cfgimpl_'):
-            del self.__dict__[name]
-            return
-        self._cfgimpl_value_owners[name] = 'default'
-        opt = getattr(self._cfgimpl_descr, name)
-        if isinstance(opt, OptionDescription):
-            raise AttributeError("can't option subgroup")
-        self._cfgimpl_values[name] = getattr(opt, 'default', None)
+    #def __delattr__(self, name):
+    #    "if you use delattr you are responsible for all bad things happening"
+    #    if name.startswith('_cfgimpl_'):
+    #        del self.__dict__[name]
+    #        return
+    #    self._cfgimpl_value_owners[name] = 'default'
+    #    opt = getattr(self._cfgimpl_descr, name)
+    #    if isinstance(opt, OptionDescription):
+    #        raise AttributeError("can't option subgroup")
+    #    self._cfgimpl_values[name] = getattr(opt, 'default', None)
 
     def setoption(self, name, value, who=None):
         """effectively modifies the value of an Option()
@@ -377,14 +332,8 @@ class Config(object):
                     else:
                         raise ConfigError("invalid value for option:"
                                    " {0} that is set to multi".format(name))
-                newowner = [who for i in range(len(value))]
-            else:
-                newowner = who
             child.setoption(self, value, who)
-            if child.is_multi() and value == [] and who != 'default':
-                child.setowner(self, Owner(who))
-            else:
-                child.setowner(self, newowner)
+            child.setowner(self, who)
         else:
             homeconfig = self._cfgimpl_get_toplevel()
             child.setoption(homeconfig, value, who)
index 3461bf5..fe0a619 100644 (file)
@@ -47,15 +47,6 @@ group_types = ['default', 'family', 'group', 'master']
 # ____________________________________________________________
 # multi types
 
-class Owner(str):
-    "an owner just for a multi Option that have no value set"
-    # we need a string that cannot be iterable
-    def __iter__(self):
-        raise StopIteration
-
-    def __len__(self):
-        return 0
-
 class Multi(list):
     "container that support items for the values of list (multi) options"
     def __init__(self, lst, config, child):
@@ -72,28 +63,21 @@ class Multi(list):
     def setoption(self, value, key=None, who=None):
         if who is None:
             who = self.config._cfgimpl_owner
-        if not self.child._validate(value):
-            raise ConfigError("invalid value {0} "
-                "for option {1}".format(str(value), self.child._name))
+        if value != None:
+            if not self.child._validate(value):
+                raise ConfigError("invalid value {0} "
+                    "for option {1}".format(str(value), self.child._name))
         oldvalue = list(self)
-        oldowner = self.child.getowner(self.config)
-        if isinstance(oldowner, Owner):
-            oldowner = []
         if key is None:
             ret = super(Multi, self).append(value)
-            oldvalue.append(None)
-            oldowner.append(who)
         else:
             ret = super(Multi, self).__setitem__(key, value)
-            oldowner[key] = who
+        self.child.setowner(self.config, who)
         self.config._cfgimpl_previous_values[self.child._name] = oldvalue
-        self.child.setowner(self.config, oldowner)
         return ret
 
     def pop(self, key):
-        oldowner = self.child.getowner(self.config)
-        oldowner.pop(key)
-        self.child.setowner(self.config, oldowner)
+        self.child.setowner(self.config, self.config._cfgimpl_owner)
         super(Multi, self).pop(key)
 # ____________________________________________________________
 #
@@ -219,10 +203,9 @@ class Option(HiddenBaseType, DisabledBaseType):
         which is allowable here
         """
         name = self._name
-        if self.is_multi():
-            if not type(owner) == list and not isinstance(owner, Owner):
-                raise ConfigError("invalid owner for multi "
-                    "option: {0}".format(name))
+        if not type(owner) == str:
+            raise ConfigError("invalid type for owner option: {0}".format(
+                    name))
         config._cfgimpl_value_owners[name] = owner
 
     def getowner(self, config):
@@ -236,13 +219,14 @@ class Option(HiddenBaseType, DisabledBaseType):
         if self.is_multi():
             if idx is not None:
                 defval = self.getdefault()
+                value = getattr(config, self._name)
                 # if the default is ['a', 'b', 'c']
                 if len(defval) > idx:
-                    # and idx = 4 -> there is actually no such value in the default
-                    value.setoption(default_multi, idx, who='default')
-                else:
                     # and idx = 2 -> there is a value in the default
                     value.setoption(defval[idx], idx, who='default')
+                else:
+                    # and idx = 4 -> there is actually no such value in the default
+                    value.setoption(self.default_multi, idx, who='default')
             else:
                 value = Multi(self.getdefault(), config, self)
                 config.setoption(self._name, value, 'default')
@@ -250,34 +234,13 @@ class Option(HiddenBaseType, DisabledBaseType):
             value = self.getdefault()
             config.setoption(self._name, value, 'default')
 
-    def is_default_owner(self, config, all_default=True, at_index=None):
+    def is_default_owner(self, config):
         """
         :param config: *must* be only the **parent** config
         (not the toplevel config)
-        :param all_default: only for multi options, if True and the owner list
-        has something else than "default" returns False, if False and the owner
-        list has at least one "default" owner, returns True
-        :param at_index: only for multi options, checks owner at specified
-        index
         :return: boolean
         """
-        if self.is_multi():
-            owners = self.getowner(config)
-            if at_index:
-                return owners[at_index] == 'default'
-            for owner in owners:
-                if all_default and owner != 'default':
-                    return False
-                if not all_default and owner == 'default':
-                    return True
-            if all_default or owners == []:
-                return True
-            else:
-                return False
-        else:
-            if at_index:
-                raise ValueError('index specified for a not multi option')
-            return self.getowner(config) == 'default'
+        return self.getowner(config) == 'default'
 
     def setoption(self, config, value, who):
         """changes the option's value with the value_owner's who
@@ -405,22 +368,17 @@ class NetmaskOption(Option):
         # by now the validation is nothing but a string, use IPy instead
         return isinstance(value, str)
 
-class ArbitraryOption(Option):
-    def __init__(self, name, doc, default=None, defaultfactory=None,
-                                   requires=None, multi=False, mandatory=False):
-        super(ArbitraryOption, self).__init__(name, doc, requires=requires,
-                                               multi=multi, mandatory=mandatory)
-        self.defaultfactory = defaultfactory
-        if defaultfactory is not None:
-            assert default is None
-
-    def _validate(self, value):
-        return True
-
-    def getdefault(self):
-        if self.defaultfactory is not None:
-            return self.defaultfactory()
-        return self.default
+#class ArbitraryOption(Option):
+#    def __init__(self, name, doc, default=None, defaultfactory=None,
+#                                   requires=None, multi=False, mandatory=False):
+#        super(ArbitraryOption, self).__init__(name, doc, requires=requires,
+#                                               multi=multi, mandatory=mandatory)
+#        self.defaultfactory = defaultfactory
+#        if defaultfactory is not None:
+#            assert default is None
+
+#    def _validate(self, value):
+#        return True
 
 class OptionDescription(HiddenBaseType, DisabledBaseType):
     "Config's schema (organisation) and container of Options"
index b535e90..9f082bf 100644 (file)
 # along with this program; if not, write to the Free Software
 # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 #
-# The original `Config` design model is unproudly borrowed from 
+# The original `Config` design model is unproudly borrowed from
 # the rough gus of pypy: pypy: http://codespeak.net/svn/pypy/dist/pypy/config/
 # the whole pypy projet is under MIT licence
 from tiramisu.config import Config
-from tiramisu.option import (OptionDescription, Option, ChoiceOption, BoolOption, 
-                    FloatOption, StrOption, IntOption, IPOption, NetmaskOption, 
-                    ArbitraryOption, group_types, apply_requires)
+from tiramisu.option import (OptionDescription, Option, ChoiceOption, BoolOption,
+                    FloatOption, StrOption, IntOption, IPOption, NetmaskOption,
+                    group_types, apply_requires)
 
 # ____________________________________________________________
 # reverse factory
@@ -38,7 +38,7 @@ def reverse_from_paths(data):
         "dummy -> Option('dummy')"
         if isinstance(value, list):
             return _build_map[type(value[0])](name, '', multi=True, default=value)
-        else:            
+        else:
             return _build_map[type(value)](name, '', default=value)
 
     def build_options(data):
@@ -51,7 +51,7 @@ def reverse_from_paths(data):
         "config.gc.dummy -> config.gc"
         if "." in pathname:
             return ".".join(pathname.split('.')[:-1])
-        # no parent except rootconfig, naturally returns None    
+        # no parent except rootconfig, naturally returns None
 
     def subgroups(pathname):
         "config.gc.dummy.bool -> [config.gc, config.gc.dummy]"
@@ -60,13 +60,13 @@ def reverse_from_paths(data):
         while group is not None:
             parents.append(group)
             group = parent(group)
-        return parents 
+        return parents
 
     def build_option_descriptions(data):
         all_groups = []
         for key in data.keys():
             for group in subgroups(key):
-                # so group is unique in the list 
+                # so group is unique in the list
                 if group not in all_groups:
                     all_groups.append(group)
         for group in all_groups:
@@ -126,4 +126,3 @@ class extend(type):
                 setattr(cls, key, value)
 
 # ____________________________________________________________
-