Merge branch 'master' into orm
Conflicts: tiramisu/config.py tiramisu/option.py
This commit is contained in:
commit
98bd35ad36
|
@ -4,7 +4,8 @@ from py.test import raises
|
||||||
|
|
||||||
from tiramisu.config import Config
|
from tiramisu.config import Config
|
||||||
from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \
|
from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \
|
||||||
BoolOption, FilenameOption, OptionDescription
|
BoolOption, FilenameOption, UnicodeOption, SymLinkOption, IPOption, \
|
||||||
|
PortOption, OptionDescription
|
||||||
|
|
||||||
|
|
||||||
def make_description():
|
def make_description():
|
||||||
|
@ -150,6 +151,7 @@ def test_find_in_config():
|
||||||
# not OptionDescription
|
# not OptionDescription
|
||||||
raises(AttributeError, "conf.find_first(byname='gc')")
|
raises(AttributeError, "conf.find_first(byname='gc')")
|
||||||
raises(AttributeError, "conf.gc.find_first(byname='gc2')")
|
raises(AttributeError, "conf.gc.find_first(byname='gc2')")
|
||||||
|
raises(ValueError, "conf.find(byname='bool', type_='unknown')")
|
||||||
|
|
||||||
|
|
||||||
def test_find_multi():
|
def test_find_multi():
|
||||||
|
@ -208,3 +210,18 @@ def test_iter_all_prop():
|
||||||
config = Config(descr)
|
config = Config(descr)
|
||||||
config.read_only()
|
config.read_only()
|
||||||
assert list(config.iter_all()) == [('string2', 'string2')]
|
assert list(config.iter_all()) == [('string2', 'string2')]
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_option():
|
||||||
|
raises(TypeError, "ChoiceOption('a', '', [1, 2])")
|
||||||
|
raises(TypeError, "ChoiceOption('a', '', 1)")
|
||||||
|
raises(TypeError, "ChoiceOption('a', '', (1,), open_values='string')")
|
||||||
|
raises(ValueError, "ChoiceOption('a', '', (1,), 3)")
|
||||||
|
raises(ValueError, "FloatOption('a', '', 'string')")
|
||||||
|
raises(ValueError, "UnicodeOption('a', '', 1)")
|
||||||
|
raises(ValueError, "SymLinkOption('a', 'string')")
|
||||||
|
raises(ValueError, "IPOption('a', '', 1)")
|
||||||
|
raises(ValueError, "IPOption('a', '', 'string')")
|
||||||
|
raises(ValueError, "PortOption('a', '', 'string')")
|
||||||
|
raises(ValueError, "PortOption('a', '', '11:12:13', allow_range=True)")
|
||||||
|
raises(ValueError, "PortOption('a', '', 11111111111111111111)")
|
||||||
|
|
|
@ -5,7 +5,7 @@ from py.test import raises
|
||||||
from tiramisu.setting import owners
|
from tiramisu.setting import owners
|
||||||
from tiramisu.config import Config, GroupConfig, MetaConfig
|
from tiramisu.config import Config, GroupConfig, MetaConfig
|
||||||
from tiramisu.option import IntOption, OptionDescription
|
from tiramisu.option import IntOption, OptionDescription
|
||||||
from tiramisu.error import ConfigError
|
from tiramisu.error import ConfigError, PropertiesOptionError
|
||||||
|
|
||||||
owners.addowner('meta')
|
owners.addowner('meta')
|
||||||
|
|
||||||
|
@ -15,10 +15,14 @@ def make_description():
|
||||||
i2 = IntOption('i2', '', default=1)
|
i2 = IntOption('i2', '', default=1)
|
||||||
i3 = IntOption('i3', '')
|
i3 = IntOption('i3', '')
|
||||||
i4 = IntOption('i4', '', default=2)
|
i4 = IntOption('i4', '', default=2)
|
||||||
od1 = OptionDescription('od1', '', [i1, i2, i3, i4])
|
i5 = IntOption('i5', '', default=[2], multi=True)
|
||||||
|
i6 = IntOption('i6', '', properties=('disabled',))
|
||||||
|
od1 = OptionDescription('od1', '', [i1, i2, i3, i4, i5, i6])
|
||||||
od2 = OptionDescription('od2', '', [od1])
|
od2 = OptionDescription('od2', '', [od1])
|
||||||
conf1 = Config(od2)
|
conf1 = Config(od2)
|
||||||
conf2 = Config(od2)
|
conf2 = Config(od2)
|
||||||
|
conf1.read_write()
|
||||||
|
conf2.read_write()
|
||||||
meta = MetaConfig([conf1, conf2])
|
meta = MetaConfig([conf1, conf2])
|
||||||
meta.cfgimpl_get_settings().setowner(owners.meta)
|
meta.cfgimpl_get_settings().setowner(owners.meta)
|
||||||
return meta
|
return meta
|
||||||
|
@ -29,7 +33,7 @@ def make_description():
|
||||||
#FIXME serialization
|
#FIXME serialization
|
||||||
def test_none():
|
def test_none():
|
||||||
meta = make_description()
|
meta = make_description()
|
||||||
conf1, conf2 = meta._impl_children
|
conf1, conf2 = meta.cfgimpl_get_children()
|
||||||
assert conf1.od1.i3 is conf2.od1.i3 is None
|
assert conf1.od1.i3 is conf2.od1.i3 is None
|
||||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.default
|
assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.default
|
||||||
meta.od1.i3 = 3
|
meta.od1.i3 = 3
|
||||||
|
@ -58,7 +62,7 @@ def test_none():
|
||||||
|
|
||||||
def test_default():
|
def test_default():
|
||||||
meta = make_description()
|
meta = make_description()
|
||||||
conf1, conf2 = meta._impl_children
|
conf1, conf2 = meta.cfgimpl_get_children()
|
||||||
assert conf1.od1.i2 == conf2.od1.i2 == 1
|
assert conf1.od1.i2 == conf2.od1.i2 == 1
|
||||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
|
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
|
||||||
meta.od1.i2 = 3
|
meta.od1.i2 = 3
|
||||||
|
@ -87,7 +91,7 @@ def test_default():
|
||||||
|
|
||||||
def test_contexts():
|
def test_contexts():
|
||||||
meta = make_description()
|
meta = make_description()
|
||||||
conf1, conf2 = meta._impl_children
|
conf1, conf2 = meta.cfgimpl_get_children()
|
||||||
assert conf1.od1.i2 == conf2.od1.i2 == 1
|
assert conf1.od1.i2 == conf2.od1.i2 == 1
|
||||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
|
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
|
||||||
meta.setattrs('od1.i2', 6)
|
meta.setattrs('od1.i2', 6)
|
||||||
|
@ -101,14 +105,15 @@ def test_find():
|
||||||
i2 = meta.unwrap_from_path('od1.i2')
|
i2 = meta.unwrap_from_path('od1.i2')
|
||||||
assert [i2] == meta.find(byname='i2')
|
assert [i2] == meta.find(byname='i2')
|
||||||
assert i2 == meta.find_first(byname='i2')
|
assert i2 == meta.find_first(byname='i2')
|
||||||
assert meta.make_dict() == {'od1.i4': 2, 'od1.i1': None, 'od1.i3': None, 'od1.i2': 1}
|
assert meta.make_dict() == {'od1.i4': 2, 'od1.i1': None, 'od1.i3': None,
|
||||||
|
'od1.i2': 1, 'od1.i5': [2], 'od1.i6': None}
|
||||||
|
|
||||||
|
|
||||||
def test_meta_meta():
|
def test_meta_meta():
|
||||||
meta1 = make_description()
|
meta1 = make_description()
|
||||||
meta2 = MetaConfig([meta1])
|
meta2 = MetaConfig([meta1])
|
||||||
meta2.cfgimpl_get_settings().setowner(owners.meta)
|
meta2.cfgimpl_get_settings().setowner(owners.meta)
|
||||||
conf1, conf2 = meta1._impl_children
|
conf1, conf2 = meta1.cfgimpl_get_children()
|
||||||
assert conf1.od1.i2 == conf2.od1.i2 == 1
|
assert conf1.od1.i2 == conf2.od1.i2 == 1
|
||||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
|
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
|
||||||
meta2.od1.i2 = 3
|
meta2.od1.i2 = 3
|
||||||
|
@ -142,15 +147,21 @@ def test_meta_meta_set():
|
||||||
meta1 = make_description()
|
meta1 = make_description()
|
||||||
meta2 = MetaConfig([meta1])
|
meta2 = MetaConfig([meta1])
|
||||||
meta2.cfgimpl_get_settings().setowner(owners.meta)
|
meta2.cfgimpl_get_settings().setowner(owners.meta)
|
||||||
conf1, conf2 = meta1._impl_children
|
conf1, conf2 = meta1.cfgimpl_get_children()
|
||||||
meta2.setattrs('od1.i1', 7)
|
meta2.setattrs('od1.i1', 7)
|
||||||
|
#PropertiesOptionError
|
||||||
|
meta2.setattrs('od1.i6', 7)
|
||||||
assert conf1.od1.i1 == conf2.od1.i1 == 7
|
assert conf1.od1.i1 == conf2.od1.i1 == 7
|
||||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i1')) is conf2.getowner(conf2.unwrap_from_path('od1.i1')) is owners.user
|
assert conf1.getowner(conf1.unwrap_from_path('od1.i1')) is conf2.getowner(conf2.unwrap_from_path('od1.i1')) is owners.user
|
||||||
assert [conf1, conf2] == meta2.find_firsts(byname='i1', byvalue=7)
|
assert [conf1, conf2] == meta2.find_firsts(byname='i1', byvalue=7)
|
||||||
conf1.od1.i1 = 8
|
conf1.od1.i1 = 8
|
||||||
|
assert [conf1, conf2] == meta2.find_firsts(byname='i1')
|
||||||
assert [conf2] == meta2.find_firsts(byname='i1', byvalue=7)
|
assert [conf2] == meta2.find_firsts(byname='i1', byvalue=7)
|
||||||
assert [conf1] == meta2.find_firsts(byname='i1', byvalue=8)
|
assert [conf1] == meta2.find_firsts(byname='i1', byvalue=8)
|
||||||
|
assert [conf1, conf2] == meta2.find_firsts(byname='i5', byvalue=2)
|
||||||
raises(AttributeError, "meta2.find_firsts(byname='i1', byvalue=10)")
|
raises(AttributeError, "meta2.find_firsts(byname='i1', byvalue=10)")
|
||||||
|
raises(AttributeError, "meta2.find_firsts(byname='not', byvalue=10)")
|
||||||
|
raises(AttributeError, "meta2.find_firsts(byname='i6')")
|
||||||
|
|
||||||
|
|
||||||
def test_not_meta():
|
def test_not_meta():
|
||||||
|
@ -159,9 +170,10 @@ def test_not_meta():
|
||||||
od2 = OptionDescription('od2', '', [od1])
|
od2 = OptionDescription('od2', '', [od1])
|
||||||
conf1 = Config(od2)
|
conf1 = Config(od2)
|
||||||
conf2 = Config(od2)
|
conf2 = Config(od2)
|
||||||
|
raises(ValueError, "GroupConfig(conf1)")
|
||||||
meta = GroupConfig([conf1, conf2])
|
meta = GroupConfig([conf1, conf2])
|
||||||
raises(ConfigError, 'meta.od1.i1')
|
raises(ConfigError, 'meta.od1.i1')
|
||||||
conf1, conf2 = meta._impl_children
|
conf1, conf2 = meta.cfgimpl_get_children()
|
||||||
meta.setattrs('od1.i1', 7)
|
meta.setattrs('od1.i1', 7)
|
||||||
assert conf1.od1.i1 == conf2.od1.i1 == 7
|
assert conf1.od1.i1 == conf2.od1.i1 == 7
|
||||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i1')) is conf2.getowner(conf2.unwrap_from_path('od1.i1')) is owners.user
|
assert conf1.getowner(conf1.unwrap_from_path('od1.i1')) is conf2.getowner(conf2.unwrap_from_path('od1.i1')) is owners.user
|
||||||
|
|
|
@ -36,6 +36,7 @@ def test_default_owner():
|
||||||
cfg = Config(descr)
|
cfg = Config(descr)
|
||||||
assert cfg.dummy is False
|
assert cfg.dummy is False
|
||||||
assert cfg.getowner(gcdummy) == 'default'
|
assert cfg.getowner(gcdummy) == 'default'
|
||||||
|
raises(TypeError, "cfg.getowner('gcdummy')")
|
||||||
cfg.dummy = True
|
cfg.dummy = True
|
||||||
assert cfg.getowner(gcdummy) == owners.user
|
assert cfg.getowner(gcdummy) == owners.user
|
||||||
|
|
||||||
|
|
|
@ -24,6 +24,28 @@ def test_requires():
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
props = err.proptype
|
props = err.proptype
|
||||||
assert props == ['disabled']
|
assert props == ['disabled']
|
||||||
|
c.activate_service = True
|
||||||
|
c.ip_address_service
|
||||||
|
|
||||||
|
|
||||||
|
def test_requires_with_requires():
|
||||||
|
a = BoolOption('activate_service', '', True)
|
||||||
|
b = IPOption('ip_address_service', '',
|
||||||
|
requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
|
||||||
|
od = OptionDescription('service', '', [a, b])
|
||||||
|
c = Config(od)
|
||||||
|
c.read_write()
|
||||||
|
c.cfgimpl_get_settings()[b].append('test')
|
||||||
|
c.ip_address_service
|
||||||
|
c.activate_service = False
|
||||||
|
props = []
|
||||||
|
try:
|
||||||
|
c.ip_address_service
|
||||||
|
except PropertiesOptionError as err:
|
||||||
|
props = err.proptype
|
||||||
|
assert props == ['disabled']
|
||||||
|
c.activate_service = True
|
||||||
|
c.ip_address_service
|
||||||
|
|
||||||
|
|
||||||
def test_requires_invalid():
|
def test_requires_invalid():
|
||||||
|
|
|
@ -434,12 +434,9 @@ class SubConfig(object):
|
||||||
|
|
||||||
def _make_sub_dict(self, opt, path, pathsvalues, _currpath, flatten):
|
def _make_sub_dict(self, opt, path, pathsvalues, _currpath, flatten):
|
||||||
if isinstance(opt, OptionDescription):
|
if isinstance(opt, OptionDescription):
|
||||||
try:
|
pathsvalues += getattr(self, path).make_dict(flatten,
|
||||||
pathsvalues += getattr(self, path).make_dict(flatten,
|
_currpath +
|
||||||
_currpath +
|
path.split('.'))
|
||||||
path.split('.'))
|
|
||||||
except PropertiesOptionError:
|
|
||||||
pass # this just a hidden or disabled option
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
value = self._getattr(opt.impl_getname())
|
value = self._getattr(opt.impl_getname())
|
||||||
|
|
|
@ -715,7 +715,7 @@ class ChoiceOption(Option):
|
||||||
return self._choice_open_values
|
return self._choice_open_values
|
||||||
|
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
if not self._choice_open_values and not value in self._choice_values:
|
if not self.impl_is_openvalues() and not value in self.impl_get_values():
|
||||||
raise ValueError(_('value {0} is not permitted, '
|
raise ValueError(_('value {0} is not permitted, '
|
||||||
'only {1} is allowed'
|
'only {1} is allowed'
|
||||||
'').format(value, self._choice_values))
|
'').format(value, self._choice_values))
|
||||||
|
@ -832,9 +832,13 @@ class IPOption(Option):
|
||||||
def _validate(self, value):
|
def _validate(self, value):
|
||||||
# sometimes an ip term starts with a zero
|
# sometimes an ip term starts with a zero
|
||||||
# but this does not fit in some case, for example bind does not like it
|
# but this does not fit in some case, for example bind does not like it
|
||||||
for val in value.split('.'):
|
try:
|
||||||
if val.startswith("0") and len(val) > 1:
|
for val in value.split('.'):
|
||||||
raise ValueError(_('invalid IP'))
|
if val.startswith("0") and len(val) > 1:
|
||||||
|
raise ValueError(_('invalid IP'))
|
||||||
|
except AttributeError:
|
||||||
|
#if integer for example
|
||||||
|
raise ValueError(_('invalid IP'))
|
||||||
# 'standard' validation
|
# 'standard' validation
|
||||||
try:
|
try:
|
||||||
IP('{0}/32'.format(value))
|
IP('{0}/32'.format(value))
|
||||||
|
@ -905,18 +909,23 @@ class PortOption(Option):
|
||||||
if self._extra['_allow_range'] and ":" in str(value):
|
if self._extra['_allow_range'] and ":" in str(value):
|
||||||
value = str(value).split(':')
|
value = str(value).split(':')
|
||||||
if len(value) != 2:
|
if len(value) != 2:
|
||||||
raise ValueError('invalid part, range must have two values '
|
raise ValueError(_('invalid part, range must have two values '
|
||||||
'only')
|
'only'))
|
||||||
if not value[0] < value[1]:
|
if not value[0] < value[1]:
|
||||||
raise ValueError('invalid port, first port in range must be'
|
raise ValueError(_('invalid port, first port in range must be'
|
||||||
' smaller than the second one')
|
' smaller than the second one'))
|
||||||
else:
|
else:
|
||||||
value = [value]
|
value = [value]
|
||||||
|
|
||||||
for val in value:
|
for val in value:
|
||||||
if not self._extra['_min_value'] <= int(val) <= self._extra['_max_value']:
|
try:
|
||||||
raise ValueError('invalid port, must be an between {0} and {1}'
|
if not self._extra['_min_value'] <= int(val) <= self._extra['_max_value']:
|
||||||
''.format(self._extra['_min_value'], self._extra['_max_value']))
|
raise ValueError('invalid port, must be an between {0} '
|
||||||
|
'and {1}'.format(
|
||||||
|
self._extra['_min_value'],
|
||||||
|
self._extra['_max_value']))
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError(_('invalid port'))
|
||||||
|
|
||||||
|
|
||||||
class NetworkOption(Option):
|
class NetworkOption(Option):
|
||||||
|
|
|
@ -372,7 +372,7 @@ class Settings(object):
|
||||||
|
|
||||||
def _getproperties(self, opt=None, path=None, is_apply_req=True):
|
def _getproperties(self, opt=None, path=None, is_apply_req=True):
|
||||||
if opt is None:
|
if opt is None:
|
||||||
props = self._p_.getproperties(path, default_properties)
|
props = copy(self._p_.getproperties(path, default_properties))
|
||||||
else:
|
else:
|
||||||
if path is None:
|
if path is None:
|
||||||
raise ValueError(_('if opt is not None, path should not be'
|
raise ValueError(_('if opt is not None, path should not be'
|
||||||
|
@ -383,8 +383,8 @@ class Settings(object):
|
||||||
ntime = int(time())
|
ntime = int(time())
|
||||||
is_cached, props = self._p_.getcache(path, ntime)
|
is_cached, props = self._p_.getcache(path, ntime)
|
||||||
if is_cached:
|
if is_cached:
|
||||||
return props
|
return copy(props)
|
||||||
props = self._p_.getproperties(path, opt._properties)
|
props = copy(self._p_.getproperties(path, opt._properties))
|
||||||
if is_apply_req:
|
if is_apply_req:
|
||||||
props |= self.apply_requires(opt, path)
|
props |= self.apply_requires(opt, path)
|
||||||
if 'cache' in self:
|
if 'cache' in self:
|
||||||
|
@ -447,8 +447,8 @@ class Settings(object):
|
||||||
(typically with the `frozen` property)
|
(typically with the `frozen` property)
|
||||||
"""
|
"""
|
||||||
# opt properties
|
# opt properties
|
||||||
properties = copy(self._getproperties(opt_or_descr, path))
|
properties = self._getproperties(opt_or_descr, path)
|
||||||
self_properties = copy(self._getproperties())
|
self_properties = self._getproperties()
|
||||||
# remove opt permissive
|
# remove opt permissive
|
||||||
# permissive affect option's permission with or without permissive
|
# permissive affect option's permission with or without permissive
|
||||||
# global property
|
# global property
|
||||||
|
|
|
@ -66,6 +66,8 @@ class Values(object):
|
||||||
meta = self._getcontext().cfgimpl_get_meta()
|
meta = self._getcontext().cfgimpl_get_meta()
|
||||||
if meta is not None:
|
if meta is not None:
|
||||||
value = meta.cfgimpl_get_values()[opt]
|
value = meta.cfgimpl_get_values()[opt]
|
||||||
|
if isinstance(value, Multi):
|
||||||
|
value = list(value)
|
||||||
else:
|
else:
|
||||||
value = opt.impl_getdefault()
|
value = opt.impl_getdefault()
|
||||||
if opt.impl_is_multi():
|
if opt.impl_is_multi():
|
||||||
|
|
Loading…
Reference in New Issue