Values validate now value
authorEmmanuel Garette <egarette@cadoles.com>
Thu, 11 Apr 2013 09:30:58 +0000 (11:30 +0200)
committerEmmanuel Garette <egarette@cadoles.com>
Thu, 11 Apr 2013 09:30:58 +0000 (11:30 +0200)
test/test_option_consistency.py
test/test_option_setting.py
test/test_tool.py [deleted file]
tiramisu/config.py
tiramisu/option.py
tiramisu/tool.py [deleted file]
tiramisu/value.py

index 8bc9b10..e241f29 100644 (file)
@@ -253,5 +253,5 @@ def test_freeze_and_has_callback_with_setoption():
     config.cfgimpl_get_settings().enable_property('freeze')
     dummy = config.unwrap_from_path('gc.dummy')
     config.cfgimpl_get_settings().add_property('frozen', dummy)
-    raises(TypeError, "config.gc.setoption('dummy', True, 'gen_config')")
+    raises(TypeError, "config.gc.setoption('dummy', descr.gc.dummy, True)")
 #____________________________________________________________
index 2d41cc2..e0af336 100644 (file)
@@ -250,13 +250,13 @@ def test_choice_access_with_multi():
     assert config.t1 == ["a", "b", "a", "b"]
 # ____________________________________________________________
 
-def test_setoption_from_option():
-    "a setoption directly from the option is **not** a good practice"
-    booloption = BoolOption('bool', 'Test boolean option', default=True)
-    descr = OptionDescription('descr', '', [booloption])
-    cfg = Config(descr)
-    booloption.setoption(cfg, False)
-    assert cfg.bool == False
+#def test_setoption_from_option():
+#    "a setoption directly from the option is **not** a good practice"
+#    booloption = BoolOption('bool', 'Test boolean option', default=True)
+#    descr = OptionDescription('descr', '', [booloption])
+#    cfg = Config(descr)
+#    booloption.setoption(cfg, False)
+#    assert cfg.bool == False
 #____________________________________________________________
 def test_dwim_set():
     descr = OptionDescription("opt", "", [
@@ -347,18 +347,18 @@ def test_set_symlink_option():
 ##    assert config.gc.dummy == True
 
 #____________________________________________________________
-def test_accepts_multiple_changes_from_option():
-    s = StrOption("string", "", default="string")
-    descr = OptionDescription("options", "", [s])
-    config = Config(descr)
-    config.string = "egg"
-    assert s.getdefault() == "string"
-    assert config.string == "egg"
-    s.setoption(config, 'blah')
-    assert s.getdefault() == "string"
-    assert config.string == "blah"
-    s.setoption(config, 'bol')
-    assert config.string == 'bol'
+#def test_accepts_multiple_changes_from_option():
+#    s = StrOption("string", "", default="string")
+#    descr = OptionDescription("options", "", [s])
+#    config = Config(descr)
+#    config.string = "egg"
+#    assert s.getdefault() == "string"
+#    assert config.string == "egg"
+#    s.setoption(config, 'blah')
+#    assert s.getdefault() == "string"
+#    assert config.string == "blah"
+#    s.setoption(config, 'bol')
+#    assert config.string == 'bol'
 
 def test_allow_multiple_changes_from_config():
     """
@@ -370,8 +370,8 @@ def test_allow_multiple_changes_from_config():
     suboption = OptionDescription("bip", "", [s2])
     descr = OptionDescription("options", "", [s, suboption])
     config = Config(descr)
-    config.setoption("string", 'blah', owners.user)
-    config.setoption("string", "oh", owners.user)
+    config.setoption("string", s, 'blah')
+    config.setoption("string", s, "oh")
     assert config.string == "oh"
     config.set(string2= 'blah')
     assert config.bip.string2 == 'blah'
diff --git a/test/test_tool.py b/test/test_tool.py
deleted file mode 100644 (file)
index 8620bc4..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#this test is much more to test that **it's there** and answers attribute access
-import autopath
-from py.test import raises
-
-from tool import extend
-
-class A:
-    a = 'titi'
-    def tarte(self):
-        return "tart"
-class B:
-    __metaclass__ = extend
-
-    def to_rst(self):
-        return "hello"
-
-B.extend(A)
-
-a = B()
-
-def test_extendable():
-    assert a.a == 'titi'
-    assert a.tarte() == 'tart'
-    assert a.to_rst() == "hello"
-
-
index 4440459..dfc3560 100644 (file)
@@ -24,7 +24,7 @@
 from tiramisu.error import (PropertiesOptionError, NotFoundError,
                             AmbigousOptionError, NoMatchingOptionFound, MandatoryError)
 from tiramisu.option import OptionDescription, Option, SymLinkOption
-from tiramisu.setting import groups, Setting
+from tiramisu.setting import groups, Setting, apply_requires
 from tiramisu.value import Values
 
 
@@ -71,9 +71,12 @@ class SubConfig(object):
         if '.' in name:
             homeconfig, name = self.cfgimpl_get_home_by_path(name)
             return homeconfig.__setattr__(name, value)
-        if type(getattr(self._cfgimpl_descr, name)) != SymLinkOption:
+        child = getattr(self._cfgimpl_descr, name)
+        if type(child) != SymLinkOption:
             self._validate(name, getattr(self._cfgimpl_descr, name), force_permissive=force_permissive)
-        self.setoption(name, value)
+            self.setoption(name, child, value)
+        else:
+            child.setoption(self.cfgimpl_get_context(), value)
 
     def _validate(self, name, opt_or_descr, force_permissive=False):
         "validation for the setattr and the getattr"
@@ -135,12 +138,26 @@ class SubConfig(object):
         return self.cfgimpl_get_values()._getitem(opt_or_descr,
                                                   force_properties=force_properties)
 
-    def setoption(self, name, value, who=None):
+    def setoption(self, name, child, value):
         """effectively modifies the value of an Option()
         (typically called by the __setattr__)
         """
-        child = getattr(self._cfgimpl_descr, name)
-        child.setoption(self, value)
+        setting = self.cfgimpl_get_settings()
+        #needed ?
+        apply_requires(child, self)
+        #needed to ?
+        if child not in self._cfgimpl_descr._children[1]:
+            raise AttributeError('unknown option %s' % (name))
+
+        if setting.has_property('everything_frozen'):
+            raise TypeError("cannot set a value to the option {} if the whole "
+                            "config has been frozen".format(name))
+
+        if setting.has_property('frozen') and setting.has_property('frozen',
+                                                                   child, is_apply_req=False):
+            raise TypeError('cannot change the value to %s for '
+                            'option %s this option is frozen' % (str(value), name))
+        self.cfgimpl_get_values()[child] = value
 
     def cfgimpl_get_home_by_path(self, path, force_permissive=False, force_properties=None):
         """:returns: tuple (config, name)"""
@@ -393,7 +410,6 @@ class Config(SubConfig):
         :param kwargs: dict of name strings to values.
         """
         #opts, paths = self.cfgimpl_get_description()._cache_paths
-        #FIXME _validate pour apply_requires ?
         all_paths = [p.split(".") for p in self.getpaths(allpaths=True)]
         for key, value in kwargs.iteritems():
             key_p = key.split('.')
@@ -407,7 +423,8 @@ class Config(SubConfig):
                     pass
                 except Exception, e:
                     raise e  # HiddenOptionError or DisabledOptionError
-                homeconfig.setoption(name, value)
+                child = getattr(homeconfig._cfgimpl_descr, name)
+                homeconfig.setoption(name, child, value)
             elif len(candidates) > 1:
                 raise AmbigousOptionError(
                     'more than one option that ends with %s' % (key, ))
index 9bdd4a5..befeec7 100644 (file)
@@ -221,28 +221,6 @@ class Option(BaseInformation):
         """
         config._cfgimpl_context._cfgimpl_values.reset(self)
 
-    def setoption(self, config, value):
-        """changes the option's value with the value_owner's who
-        :param config: the parent config is necessary here to store the value
-        """
-        name = self._name
-        setting = config.cfgimpl_get_settings()
-        if not self.validate(value, setting.has_property('validator')):
-            raise ConfigError('invalid value %s for option %s' % (value, name))
-        if self not in config._cfgimpl_descr._children[1]:
-            raise AttributeError('unknown option %s' % (name))
-
-        if setting.has_property('everything_frozen'):
-            raise TypeError("cannot set a value to the option {} if the whole "
-                            "config has been frozen".format(name))
-
-        if setting.has_property('frozen') and setting.has_property('frozen',
-                                                                   self, False):
-            raise TypeError('cannot change the value to %s for '
-                            'option %s this option is frozen' % (str(value), name))
-        #apply_requires(self, config)
-        config.cfgimpl_get_values()[self] = value
-
     def getkey(self, value):
         return value
 
@@ -330,8 +308,7 @@ class SymLinkOption(object):
         self._name = name
         self.opt = opt
 
-    def setoption(self, config, value):
-        context = config.cfgimpl_get_context()
+    def setoption(self, context, value):
         path = context.cfgimpl_get_description().get_path_by_opt(self.opt)
         setattr(context, path, value)
 
diff --git a/tiramisu/tool.py b/tiramisu/tool.py
deleted file mode 100644 (file)
index e10be70..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-# Copyright (C) 2012 Team tiramisu (see AUTHORS for all contributors)
-#
-# This program is free software; you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation; either version 2 of the License, or
-# (at your option) any later version.
-#
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-# GNU General Public License for more details.
-#
-# You should have received a copy of the GNU General Public License
-# 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 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,
-                    apply_requires)
-
-# ____________________________________________________________
-# reverse factory
-# XXX HAAAAAAAAAAAACK (but possibly a good one)
-#def reverse_from_paths(data):
-#    "rebuilds a (fake) data structure from an unflatten `make_dict()` result"
-#    # ____________________________________________________________
-#    _build_map = {
-#        bool: BoolOption,
-#        int: IntOption,
-#        float: FloatOption,
-#        str: StrOption,
-#    }
-#    def option_factory(name, value):
-#        "dummy -> Option('dummy')"
-#        if isinstance(value, list):
-#            return _build_map[type(value[0])](name, '', multi=True, default=value)
-#        else:
-#            return _build_map[type(value)](name, '', default=value)
-
-#    def build_options(data):
-#        "config.gc.dummy ->  Option('dummy')"
-#        for key, value in data.items():
-#            name = key.split('.')[-1]
-#            yield (key, option_factory(name, value))
-#    # ____________________________________________________________
-#    def parent(pathname):
-#        "config.gc.dummy -> config.gc"
-#        if "." in pathname:
-#            return ".".join(pathname.split('.')[:-1])
-#        # no parent except rootconfig, naturally returns None
-
-#    def subgroups(pathname):
-#        "config.gc.dummy.bool -> [config.gc, config.gc.dummy]"
-#        group = parent(pathname)
-#        parents =[]
-#        while group is not None:
-#            parents.append(group)
-#            group = parent(group)
-#        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
-#                if group not in all_groups:
-#                    all_groups.append(group)
-#        for group in all_groups:
-#            name = group.split('.')[-1]
-#            yield (group, OptionDescription(name, '', []))
-#    # ____________________________________________________________
-#    descr = OptionDescription('tiramisu', 'fake rebuild structure', [])
-#    cfg = Config(descr)
-#    # add descrs in cfg
-#    def compare(a, b):
-#        l1 = a.split(".")
-#        l2 = b.split(".")
-#        if len(l1) < len(l2):
-#            return -1
-#        elif len(l1) > len(l2):
-#            return 1
-#        else:
-#            return 0
-#    grps = list(build_option_descriptions(data))
-#    groups = dict(grps)
-#    grp_paths = [pathname for pathname, opt_descr in grps]
-#    grp_paths.sort(compare)
-#    for grp in grp_paths:
-#        if not "." in grp:
-#            cfg._cfgimpl_descr.add_child(groups[grp])
-#            cfg.cfgimpl_update()
-#        else:
-#            parentdescr = cfg.unwrap_from_path(parent(grp))
-#            parentdescr.add_child(groups[grp])
-#            getattr(cfg, parent(grp)).cfgimpl_update()
-#    # add options in descrs
-#    for pathname, opt in build_options(data):
-#        current_group_name = parent(pathname)
-#        if current_group_name == None:
-#            cfg._cfgimpl_descr.add_child(opt)
-#            cfg.cfgimpl_update()
-#        else:
-#            curr_grp = groups[current_group_name]
-#            curr_grp.add_child(opt)
-#            getattr(cfg, current_group_name).cfgimpl_update()
-
-#    return cfg
-# ____________________________________________________________
-# extendable type
-class extend(type):
-    """
-    A magic trick for classes, which lets you add methods or attributes to a
-    class
-    """
-    def extend(cls, extclass):
-        bases = list(extclass.__bases__)
-        bases.append(extclass)
-        for cl in bases:
-            for key, value in cl.__dict__.items():
-                if key == '__module__':
-                    continue
-                setattr(cls, key, value)
-
-# ____________________________________________________________
index 74022b3..1a7e9e2 100644 (file)
@@ -148,6 +148,10 @@ class Values(object):
         return value
 
     def __setitem__(self, opt, value):
+        if not opt.validate(value,
+                self.context.cfgimpl_get_settings().has_property('validator')):
+            raise ConfigError('invalid value {}'
+                    ' for option {}'.format(value, opt._name))
         if opt.is_multi():
             if opt.multitype == multitypes.master:
                 masterlen = len(value)