Values validate now value
This commit is contained in:
parent
0c5ab9df18
commit
26568dc45a
|
@ -253,5 +253,5 @@ def test_freeze_and_has_callback_with_setoption():
|
||||||
config.cfgimpl_get_settings().enable_property('freeze')
|
config.cfgimpl_get_settings().enable_property('freeze')
|
||||||
dummy = config.unwrap_from_path('gc.dummy')
|
dummy = config.unwrap_from_path('gc.dummy')
|
||||||
config.cfgimpl_get_settings().add_property('frozen', 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)")
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
|
|
|
@ -250,13 +250,13 @@ def test_choice_access_with_multi():
|
||||||
assert config.t1 == ["a", "b", "a", "b"]
|
assert config.t1 == ["a", "b", "a", "b"]
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
|
|
||||||
def test_setoption_from_option():
|
#def test_setoption_from_option():
|
||||||
"a setoption directly from the option is **not** a good practice"
|
# "a setoption directly from the option is **not** a good practice"
|
||||||
booloption = BoolOption('bool', 'Test boolean option', default=True)
|
# booloption = BoolOption('bool', 'Test boolean option', default=True)
|
||||||
descr = OptionDescription('descr', '', [booloption])
|
# descr = OptionDescription('descr', '', [booloption])
|
||||||
cfg = Config(descr)
|
# cfg = Config(descr)
|
||||||
booloption.setoption(cfg, False)
|
# booloption.setoption(cfg, False)
|
||||||
assert cfg.bool == False
|
# assert cfg.bool == False
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
def test_dwim_set():
|
def test_dwim_set():
|
||||||
descr = OptionDescription("opt", "", [
|
descr = OptionDescription("opt", "", [
|
||||||
|
@ -347,18 +347,18 @@ def test_set_symlink_option():
|
||||||
## assert config.gc.dummy == True
|
## assert config.gc.dummy == True
|
||||||
|
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
def test_accepts_multiple_changes_from_option():
|
#def test_accepts_multiple_changes_from_option():
|
||||||
s = StrOption("string", "", default="string")
|
# s = StrOption("string", "", default="string")
|
||||||
descr = OptionDescription("options", "", [s])
|
# descr = OptionDescription("options", "", [s])
|
||||||
config = Config(descr)
|
# config = Config(descr)
|
||||||
config.string = "egg"
|
# config.string = "egg"
|
||||||
assert s.getdefault() == "string"
|
# assert s.getdefault() == "string"
|
||||||
assert config.string == "egg"
|
# assert config.string == "egg"
|
||||||
s.setoption(config, 'blah')
|
# s.setoption(config, 'blah')
|
||||||
assert s.getdefault() == "string"
|
# assert s.getdefault() == "string"
|
||||||
assert config.string == "blah"
|
# assert config.string == "blah"
|
||||||
s.setoption(config, 'bol')
|
# s.setoption(config, 'bol')
|
||||||
assert config.string == 'bol'
|
# assert config.string == 'bol'
|
||||||
|
|
||||||
def test_allow_multiple_changes_from_config():
|
def test_allow_multiple_changes_from_config():
|
||||||
"""
|
"""
|
||||||
|
@ -370,8 +370,8 @@ def test_allow_multiple_changes_from_config():
|
||||||
suboption = OptionDescription("bip", "", [s2])
|
suboption = OptionDescription("bip", "", [s2])
|
||||||
descr = OptionDescription("options", "", [s, suboption])
|
descr = OptionDescription("options", "", [s, suboption])
|
||||||
config = Config(descr)
|
config = Config(descr)
|
||||||
config.setoption("string", 'blah', owners.user)
|
config.setoption("string", s, 'blah')
|
||||||
config.setoption("string", "oh", owners.user)
|
config.setoption("string", s, "oh")
|
||||||
assert config.string == "oh"
|
assert config.string == "oh"
|
||||||
config.set(string2= 'blah')
|
config.set(string2= 'blah')
|
||||||
assert config.bip.string2 == 'blah'
|
assert config.bip.string2 == 'blah'
|
||||||
|
|
|
@ -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"
|
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
from tiramisu.error import (PropertiesOptionError, NotFoundError,
|
from tiramisu.error import (PropertiesOptionError, NotFoundError,
|
||||||
AmbigousOptionError, NoMatchingOptionFound, MandatoryError)
|
AmbigousOptionError, NoMatchingOptionFound, MandatoryError)
|
||||||
from tiramisu.option import OptionDescription, Option, SymLinkOption
|
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
|
from tiramisu.value import Values
|
||||||
|
|
||||||
|
|
||||||
|
@ -71,9 +71,12 @@ class SubConfig(object):
|
||||||
if '.' in name:
|
if '.' in name:
|
||||||
homeconfig, name = self.cfgimpl_get_home_by_path(name)
|
homeconfig, name = self.cfgimpl_get_home_by_path(name)
|
||||||
return homeconfig.__setattr__(name, value)
|
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._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):
|
def _validate(self, name, opt_or_descr, force_permissive=False):
|
||||||
"validation for the setattr and the getattr"
|
"validation for the setattr and the getattr"
|
||||||
|
@ -135,12 +138,26 @@ class SubConfig(object):
|
||||||
return self.cfgimpl_get_values()._getitem(opt_or_descr,
|
return self.cfgimpl_get_values()._getitem(opt_or_descr,
|
||||||
force_properties=force_properties)
|
force_properties=force_properties)
|
||||||
|
|
||||||
def setoption(self, name, value, who=None):
|
def setoption(self, name, child, value):
|
||||||
"""effectively modifies the value of an Option()
|
"""effectively modifies the value of an Option()
|
||||||
(typically called by the __setattr__)
|
(typically called by the __setattr__)
|
||||||
"""
|
"""
|
||||||
child = getattr(self._cfgimpl_descr, name)
|
setting = self.cfgimpl_get_settings()
|
||||||
child.setoption(self, value)
|
#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):
|
def cfgimpl_get_home_by_path(self, path, force_permissive=False, force_properties=None):
|
||||||
""":returns: tuple (config, name)"""
|
""":returns: tuple (config, name)"""
|
||||||
|
@ -393,7 +410,6 @@ class Config(SubConfig):
|
||||||
:param kwargs: dict of name strings to values.
|
:param kwargs: dict of name strings to values.
|
||||||
"""
|
"""
|
||||||
#opts, paths = self.cfgimpl_get_description()._cache_paths
|
#opts, paths = self.cfgimpl_get_description()._cache_paths
|
||||||
#FIXME _validate pour apply_requires ?
|
|
||||||
all_paths = [p.split(".") for p in self.getpaths(allpaths=True)]
|
all_paths = [p.split(".") for p in self.getpaths(allpaths=True)]
|
||||||
for key, value in kwargs.iteritems():
|
for key, value in kwargs.iteritems():
|
||||||
key_p = key.split('.')
|
key_p = key.split('.')
|
||||||
|
@ -407,7 +423,8 @@ class Config(SubConfig):
|
||||||
pass
|
pass
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise e # HiddenOptionError or DisabledOptionError
|
raise e # HiddenOptionError or DisabledOptionError
|
||||||
homeconfig.setoption(name, value)
|
child = getattr(homeconfig._cfgimpl_descr, name)
|
||||||
|
homeconfig.setoption(name, child, value)
|
||||||
elif len(candidates) > 1:
|
elif len(candidates) > 1:
|
||||||
raise AmbigousOptionError(
|
raise AmbigousOptionError(
|
||||||
'more than one option that ends with %s' % (key, ))
|
'more than one option that ends with %s' % (key, ))
|
||||||
|
|
|
@ -221,28 +221,6 @@ class Option(BaseInformation):
|
||||||
"""
|
"""
|
||||||
config._cfgimpl_context._cfgimpl_values.reset(self)
|
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):
|
def getkey(self, value):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
@ -330,8 +308,7 @@ class SymLinkOption(object):
|
||||||
self._name = name
|
self._name = name
|
||||||
self.opt = opt
|
self.opt = opt
|
||||||
|
|
||||||
def setoption(self, config, value):
|
def setoption(self, context, value):
|
||||||
context = config.cfgimpl_get_context()
|
|
||||||
path = context.cfgimpl_get_description().get_path_by_opt(self.opt)
|
path = context.cfgimpl_get_description().get_path_by_opt(self.opt)
|
||||||
setattr(context, path, value)
|
setattr(context, path, value)
|
||||||
|
|
||||||
|
|
128
tiramisu/tool.py
128
tiramisu/tool.py
|
@ -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)
|
|
||||||
|
|
||||||
# ____________________________________________________________
|
|
|
@ -148,6 +148,10 @@ class Values(object):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def __setitem__(self, opt, 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.is_multi():
|
||||||
if opt.multitype == multitypes.master:
|
if opt.multitype == multitypes.master:
|
||||||
masterlen = len(value)
|
masterlen = len(value)
|
||||||
|
|
Loading…
Reference in New Issue