Merge branch 'master' into orm

Conflicts:
	test/test_config_api.py
	tiramisu/autolib.py
	tiramisu/config.py
	tiramisu/option.py
	tiramisu/value.py
This commit is contained in:
2014-04-13 10:30:42 +02:00
47 changed files with 3683 additions and 3215 deletions

View File

@ -4,7 +4,11 @@ from tiramisu import setting
setting.expires_time = 1
from tiramisu.option import IntOption, OptionDescription
from tiramisu.config import Config
from tiramisu.error import ConfigError
from time import sleep, time
from py.test import raises
def make_description():
@ -253,3 +257,25 @@ def test_reset_cache_only():
c.cfgimpl_reset_cache(only=('settings',))
assert 'u1' in values._p_.get_cached(c)
assert 'u1' not in settings._p_.get_cached(c)
def test_force_cache():
u1 = IntOption('u1', '', multi=True)
u2 = IntOption('u2', '')
u3 = IntOption('u3', '', multi=True)
u4 = IntOption('u4', '', properties=('disabled',))
od = OptionDescription('od1', '', [u1, u2, u3, u4])
c = Config(od)
c.cfgimpl_get_settings().remove('expire')
c.cfgimpl_get_values().force_cache()
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'u1': ([], None), 'u3': ([], None), 'u2': (None, None), 'u4': (None, None)}
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u4': (set(['disabled']), None), 'u1': (set([]), None), 'u3': (set([]), None), 'u2': (set([]), None)}
c.read_only()
c.cfgimpl_get_values().force_cache()
assert c.cfgimpl_get_values()._p_.get_cached(c) == {'u1': ([], None), 'u3': ([], None), 'u2': (None, None)}
assert c.cfgimpl_get_settings()._p_.get_cached(c) == {'u4': (set(['disabled']), None), 'u1': (set([]), None), 'u3': (set([]), None), 'u2': (set([]), None)}
c.cfgimpl_get_settings().remove('cache')
raises(ConfigError, "c.cfgimpl_get_values().force_cache()")

View File

@ -9,7 +9,7 @@ from py.test import raises
from tiramisu.config import Config, SubConfig
from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \
BoolOption, UnicodeOption, OptionDescription
from tiramisu.error import ConflictError, ConfigError
from tiramisu.error import ConflictError, ConfigError, PropertiesOptionError
import weakref
@ -22,7 +22,7 @@ def make_description():
intoption = IntOption('int', 'Test int option', default=0)
floatoption = FloatOption('float', 'Test float option', default=2.3)
stroption = StrOption('str', 'Test string option', default="abc", properties=('mandatory', ))
boolop = BoolOption('boolop', 'Test boolean option op', default=True)
boolop = BoolOption('boolop', 'Test boolean option op', default=True, properties=('hidden',))
wantref_option = BoolOption('wantref', 'Test requires', default=False)
wantframework_option = BoolOption('wantframework', 'Test requires',
default=False)
@ -90,6 +90,15 @@ def test_base_config_and_groups():
#assert nm.impl_getname() == 'name'
def test_base_config_force_permissive():
descr = make_description()
config = Config(descr)
config.read_write()
config.cfgimpl_get_settings().setpermissive(('hidden',))
raises(PropertiesOptionError, "config.getattr('boolop')")
assert config.getattr('boolop', force_permissive=True) is True
def test_base_config_in_a_tree():
"how options are organized into a tree, see :ref:`tree`"
descr = make_description()

View File

@ -102,9 +102,12 @@ def test_make_dict():
"serialization of the whole config to a dict"
descr = OptionDescription("opt", "", [
OptionDescription("s1", "", [
BoolOption("a", "", default=False)]),
BoolOption("a", "", default=False),
BoolOption("b", "", default=False, properties=('hidden',))]),
IntOption("int", "", default=42)])
config = Config(descr)
config.read_write()
config.cfgimpl_get_settings().setpermissive(('hidden',))
d = config.make_dict()
assert d == {"s1.a": False, "int": 42}
config.int = 43
@ -114,6 +117,20 @@ def test_make_dict():
d2 = config.make_dict(flatten=True)
assert d2 == {'a': True, 'int': 43}
raises(ValueError, 'd2 = config.make_dict(withvalue="3")')
d = config.make_dict(force_permissive=True)
assert d == {"s1.a": True, "s1.b": False, "int": 43}
def test_make_dict_with_disabled():
descr = OptionDescription("opt", "", [
OptionDescription("s1", "", [
BoolOption("a", "", default=False),
BoolOption("b", "", default=False, properties=('disabled',))]),
IntOption("int", "", default=42)])
config = Config(descr)
config.read_only()
d = config.make_dict()
assert d == {"s1.a": False, "int": 42}
def test_find_in_config():
@ -121,6 +138,7 @@ def test_find_in_config():
descr = make_description()
conf = Config(descr)
conf.read_only()
conf.cfgimpl_get_settings().setpermissive(('hidden',))
assert conf.find(byname='dummy') == [conf.unwrap_from_path('gc.dummy')]
assert conf.find(byname='float') == [conf.unwrap_from_path('gc.float'), conf.unwrap_from_path('float')]
assert conf.find_first(byname='bool') == conf.unwrap_from_path('gc.gc2.bool')
@ -135,6 +153,9 @@ def test_find_in_config():
conf.read_write()
raises(AttributeError, "assert conf.find(byname='prop')")
assert conf.find(byname='prop', check_properties=False) == [conf.unwrap_from_path('gc.gc2.prop'), conf.unwrap_from_path('gc.prop')]
assert conf.find(byname='prop', force_permissive=True) == [conf.unwrap_from_path('gc.prop')]
assert conf.find_first(byname='prop', force_permissive=True) == conf.unwrap_from_path('gc.prop')
#assert conf.find_first(byname='prop') == conf.unwrap_from_path('gc.prop')
# combinaison of filters
assert conf.find(bytype=BoolOption, byname='dummy') == [conf.unwrap_from_path('gc.dummy')]
assert conf.find_first(bytype=BoolOption, byname='dummy') == conf.unwrap_from_path('gc.dummy')
@ -205,6 +226,20 @@ def test_iter_all():
break
def test_iter_all_force_permissive():
s = StrOption("string", "", default="string")
s2 = StrOption("string2", "", default="string2")
s3 = StrOption("string3", "", default="string3", properties=('hidden',))
descr = OptionDescription("options", "", [s, s2, s3])
config = Config(descr)
config.read_write()
config.cfgimpl_get_settings().setpermissive(('hidden',))
assert list(config.iter_all()) == [('string', 'string'), ('string2', 'string2')]
assert list(config.iter_all(force_permissive=True)) == [('string', 'string'),
('string2', 'string2'),
('string3', 'string3')]
def test_iter_all_prop():
s = StrOption("string", "", default="string", properties=('disabled',))
s2 = StrOption("string2", "", default="string2")

View File

@ -16,7 +16,7 @@ def test_domainname():
raises(ValueError, "c.d = 'toto'")
c.d = 'toto3.com'
raises(ValueError, "c.d = 'toto3.3la'")
raises(ValueError, "c.d = '3toto.com'")
#raises(ValueError, "c.d = '3toto.com'")
raises(ValueError, "c.d = 'toto.co3'")
raises(ValueError, "c.d = 'toto_super.com'")
c.d = 'toto-.com'
@ -31,6 +31,19 @@ def test_domainname():
c.g = '192.168.1.0'
c.g = '192.168.1.29'
def test_special_domain_name():
"""domain name option that starts with a number or not
"""
d = DomainnameOption('d', '')
e = DomainnameOption('e', '', type_='netbios')
od = OptionDescription('a', '', [d,e])
c = Config(od)
c.read_write()
c.d = '1toto.com'
c.d = '123toto.com'
c.e = 'toto'
raises(ValueError, "c.e = '1toto'")
def test_domainname_netbios():
d = DomainnameOption('d', '', type_='netbios')

View File

@ -22,13 +22,14 @@ def make_description_freeze():
boolop = BoolOption('boolop', 'Test boolean option op', default=[True], multi=True)
wantref_option = BoolOption('wantref', 'Test requires', default=False, properties=('force_store_value',),
requires=({'option': booloption, 'expected': True, 'action': 'hidden'},))
wantref2_option = BoolOption('wantref2', 'Test requires', default=False, properties=('force_store_value', 'hidden'))
wantframework_option = BoolOption('wantframework', 'Test requires',
default=False,
requires=({'option': booloption, 'expected': True, 'action': 'hidden'},))
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
descr = OptionDescription('tiramisu', '', [gcgroup, booloption, objspaceoption,
wantref_option, stroption,
wantref_option, wantref2_option, stroption,
wantframework_option,
intoption, boolop])
return descr
@ -141,15 +142,88 @@ def test_freeze_get_multi():
def test_force_store_value():
descr = make_description_freeze()
conf = Config(descr)
assert conf.getowner(conf.unwrap_from_path('wantref')) == 'default'
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
conf.wantref
assert conf.getowner(conf.unwrap_from_path('wantref')) == 'user'
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False)}
def test_force_store_value_no_requirement():
booloption = BoolOption('bool', 'Test boolean option', default=True)
try:
BoolOption('wantref', 'Test requires', default=False,
requires=({'option': booloption, 'expected': True, 'action': 'force_store_value'},))
except ValueError:
pass
def test_force_store_value_ro():
descr = make_description_freeze()
conf = Config(descr)
conf.read_only()
assert conf.getowner(conf.unwrap_from_path('wantref')) == 'default'
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
conf.wantref
assert conf.getowner(conf.unwrap_from_path('wantref')) == 'user'
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False)}
def test_force_store_value_hidden():
descr = make_description_freeze()
conf = Config(descr)
conf.cfgimpl_get_settings().setpermissive(('hidden',))
conf.read_write()
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
conf.getattr('wantref2', force_permissive=True)
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref2': ('user', False)}
def test_force_store_value_owner():
descr = make_description_freeze()
conf = Config(descr)
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
conf.getowner(conf.unwrap_from_path('wantref'))
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False)}
def test_force_store_value_owner_ro():
descr = make_description_freeze()
conf = Config(descr)
conf.read_only()
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
conf.getowner(conf.unwrap_from_path('wantref'))
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False)}
def test_force_store_value_owner_hidden():
descr = make_description_freeze()
conf = Config(descr)
conf.cfgimpl_get_settings().setpermissive(('hidden',))
conf.read_write()
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
conf.getowner(conf.unwrap_from_path('wantref2'), force_permissive=True)
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref2': ('user', False)}
def test_force_store_value_modified():
descr = make_description_freeze()
conf = Config(descr)
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
conf.cfgimpl_get_values().get_modified_values()
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False), 'wantref2': ('user', False)}
def test_force_store_value_modified_ro():
descr = make_description_freeze()
conf = Config(descr)
conf.read_only()
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
conf.cfgimpl_get_values().get_modified_values()
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False), 'wantref2': ('user', False)}
def test_force_store_value_modified_hidden():
descr = make_description_freeze()
conf = Config(descr)
conf.cfgimpl_get_settings().setpermissive(('hidden',))
conf.read_write()
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {}
conf.cfgimpl_get_values().get_modified_values()
assert conf.cfgimpl_get_values()._p_.get_modified_values() == {'wantref': ('user', False), 'wantref2': ('user', False)}

View File

@ -1,7 +1,8 @@
import autopath
from time import sleep
#from py.test import raises
from tiramisu.config import Config, mandatory_warnings
from tiramisu.config import Config
from tiramisu.option import StrOption, UnicodeOption, OptionDescription
from tiramisu.error import PropertiesOptionError
@ -99,8 +100,8 @@ def test_mandatory_multi_none():
descr = make_description()
config = Config(descr)
config.str3 = [None]
config.read_only()
assert config.getowner(config.unwrap_from_path('str3')) == 'user'
config.read_only()
prop = []
try:
config.str3
@ -109,8 +110,8 @@ def test_mandatory_multi_none():
assert 'mandatory' in prop
config.read_write()
config.str3 = ['yes', None]
config.read_only()
assert config.getowner(config.unwrap_from_path('str3')) == 'user'
config.read_only()
prop = []
try:
config.str3
@ -123,8 +124,8 @@ def test_mandatory_multi_empty():
descr = make_description()
config = Config(descr)
config.str3 = ['']
config.read_only()
assert config.getowner(config.unwrap_from_path('str3')) == 'user'
config.read_only()
prop = []
try:
config.str3
@ -133,8 +134,8 @@ def test_mandatory_multi_empty():
assert 'mandatory' in prop
config.read_write()
config.str3 = ['yes', '']
config.read_only()
assert config.getowner(config.unwrap_from_path('str3')) == 'user'
config.read_only()
prop = []
try:
config.str3
@ -205,11 +206,12 @@ def test_mandatory_warnings_ro():
except PropertiesOptionError as err:
proc = err.proptype
assert proc == ['mandatory']
assert list(mandatory_warnings(config)) == ['str', 'str1', 'unicode2', 'str3']
assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
config.read_write()
config.str = 'a'
config.read_only()
assert list(mandatory_warnings(config)) == ['str1', 'unicode2', 'str3']
assert config.cfgimpl_get_values().mandatory_warnings() == ['str1', 'unicode2', 'str3']
sleep(.1)
def test_mandatory_warnings_rw():
@ -218,9 +220,10 @@ def test_mandatory_warnings_rw():
config.str = ''
config.read_write()
config.str
assert list(mandatory_warnings(config)) == ['str', 'str1', 'unicode2', 'str3']
assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
config.str = 'a'
assert list(mandatory_warnings(config)) == ['str1', 'unicode2', 'str3']
assert config.cfgimpl_get_values().mandatory_warnings() == ['str1', 'unicode2', 'str3']
sleep(.1)
def test_mandatory_warnings_disabled():
@ -230,9 +233,10 @@ def test_mandatory_warnings_disabled():
setting = config.cfgimpl_get_settings()
config.read_write()
config.str
assert list(mandatory_warnings(config)) == ['str', 'str1', 'unicode2', 'str3']
assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
setting[descr.str].append('disabled')
assert list(mandatory_warnings(config)) == ['str1', 'unicode2', 'str3']
assert config.cfgimpl_get_values().mandatory_warnings() == ['str1', 'unicode2', 'str3']
sleep(.1)
def test_mandatory_warnings_frozen():
@ -242,7 +246,8 @@ def test_mandatory_warnings_frozen():
setting = config.cfgimpl_get_settings()
config.read_write()
config.str
assert list(mandatory_warnings(config)) == ['str', 'str1', 'unicode2', 'str3']
assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
setting[descr.str].append('frozen')
config.read_only()
assert list(mandatory_warnings(config)) == ['str', 'str1', 'unicode2', 'str3']
assert config.cfgimpl_get_values().mandatory_warnings() == ['str', 'str1', 'unicode2', 'str3']
sleep(.1)

View File

@ -1,8 +1,8 @@
import autopath
from py.test import raises
from tiramisu.setting import groups
from tiramisu.config import Config
from tiramisu.setting import groups, owners
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
StrOption, OptionDescription, SymLinkOption
from tiramisu.error import PropertiesOptionError, ConflictError, SlaveError, ConfigError
@ -44,6 +44,13 @@ def return_calc(i, j, k):
return i + j + k
def is_config(config, **kwargs):
if isinstance(config, Config):
return 'yes'
else:
return 'no'
def make_description():
gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
gcdummy = BoolOption('dummy', 'dummy', default=False)
@ -254,6 +261,29 @@ def test_callback_invalid():
raises(ValueError, "StrOption('val2', '', callback=return_value, callback_params={'': 'string'})")
raises(ValueError, "StrOption('val4', '', callback=return_value, callback_params={'value': (('string', False),)})")
raises(ValueError, "StrOption('val4', '', callback=return_value, callback_params={'value': ((val1, 'string'),)})")
raises(ValueError, "StrOption('val4', '', callback=return_value, callback_params={'value': ((val1, False, 'unknown'),)})")
raises(ValueError, "StrOption('val4', '', callback=return_value, callback_params={'value': ((val1,),)})")
def test_callback_with_context():
val1 = StrOption("val1", "", callback=is_config, callback_params={'': ((None,),), 'value': ('string',)})
maconfig = OptionDescription('rootconfig', '', [val1])
cfg = Config(maconfig)
assert cfg.val1 == 'yes'
def test_callback_with_context_named():
val1 = StrOption("val1", "", callback=is_config, callback_params={'config': ((None,),)})
maconfig = OptionDescription('rootconfig', '', [val1])
cfg = Config(maconfig)
assert cfg.val1 == 'yes'
def test_callback_with_error():
val1 = StrOption("val1", "", callback=is_config, callback_params={'': ('string',), 'value': ('string',)})
maconfig = OptionDescription('rootconfig', '', [val1])
cfg = Config(maconfig)
assert cfg.val1 == 'no'
def test_callback_value():
@ -401,6 +431,17 @@ def test_callback_multi_list_extend():
assert cfg.val1 == ['1', '2', '3', '4', '5']
def test_callback_multi_callback():
val1 = StrOption('val1', "", multi=True, callback=return_val)
interface1 = OptionDescription('val1', '', [val1])
maconfig = OptionDescription('rootconfig', '', [interface1])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val1.val1 == ['val']
cfg.val1.val1.append()
assert cfg.val1.val1 == ['val', 'val']
def test_callback_master_and_slaves_master():
val1 = StrOption('val1', "", multi=True, callback=return_val)
val2 = StrOption('val2', "", multi=True)
@ -415,6 +456,22 @@ def test_callback_master_and_slaves_master():
assert cfg.val1.val2 == [None, None]
def test_callback_master_and_slaves_master2():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, default_multi='val2')
val3 = StrOption('val3', "", multi=True, callback=return_value, callback_params={'': ((val2, False),)})
val4 = StrOption('val4', "", multi=True, callback=return_value, callback_params={'': ((val3, False),)})
interface1 = OptionDescription('val1', '', [val1, val2, val3, val4])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1])
cfg = Config(maconfig)
cfg.read_write()
cfg.val1.val1.append('val')
assert cfg.val1.val4 == ['val2']
assert cfg.val1.val3 == ['val2']
assert cfg.val1.val2 == ['val2']
def test_callback_master_and_slaves_master_list():
val1 = StrOption('val1', "", multi=True, callback=return_list)
val2 = StrOption('val2', "", multi=True)
@ -470,6 +527,16 @@ def test_callback_master_and_slaves_slave():
assert cfg.val1.val2 == ['val2', 'val2', 'val']
def test_callback_master_and_slaves():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, callback=return_val)
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1])
cfg = Config(maconfig)
cfg.read_write()
def test_callback_master_and_slaves_slave_cal():
val3 = StrOption('val3', "", multi=True)
val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val3, False),)})
@ -486,8 +553,6 @@ def test_callback_master_and_slaves_slave_cal():
cfg.val3 = ['val1']
assert cfg.val1.val1 == ['val1']
assert cfg.val1.val2 == ['val']
assert cfg.val1.val1 == ['val1']
assert cfg.val1.val2 == ['val']
del(cfg.val1.val1)
cfg.val1.val2 = ['val']
cfg.val3 = ['val1', 'val2']
@ -516,8 +581,8 @@ def test_callback_master_and_slaves_slave_cal2():
assert cfg.val1.val1 == ['val', 'val']
assert cfg.val1.val2 == ['val2', 'val2']
cfg.val3.pop(1)
# # cannot remove slave's value because master is calculated
# # so raise
# cannot remove slave's value because master is calculated
# so raise
raises(SlaveError, "cfg.val1.val1")
raises(SlaveError, "cfg.val1.val2")
cfg.val3 = ['val', 'val']
@ -530,6 +595,88 @@ def test_callback_master_and_slaves_slave_cal2():
assert cfg.val1.val2 == ['val2', 'val2']
def test_callback_master_and_slaves_master_disabled():
#properties must be transitive
val1 = StrOption('val1', "", multi=True, properties=('disabled',))
val2 = StrOption('val2', "", multi=True)
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1])
cfg = Config(maconfig)
cfg.read_write()
raises(PropertiesOptionError, "cfg.val1.val1")
raises(PropertiesOptionError, "cfg.val1.val1.append('yes')")
raises(PropertiesOptionError, "cfg.val1.val2")
def test_callback_master_and_slaves_master_callback_disabled():
val0 = StrOption('val0', "", multi=True, properties=('disabled',))
val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val0, False),)})
val2 = StrOption('val2', "", multi=True)
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1, val0])
cfg = Config(maconfig)
cfg.read_write()
raises(ConfigError, "cfg.val1.val1")
raises(ConfigError, "cfg.val1.val2")
cfg.cfgimpl_get_settings().remove('disabled')
cfg.val1.val1 = []
cfg.cfgimpl_get_settings().append('disabled')
assert cfg.val1.val1 == []
assert cfg.val1.val2 == []
def test_callback_master_and_slaves_slave_disabled():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, properties=('disabled',))
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val1.val1 == []
raises(PropertiesOptionError, "cfg.val1.val2")
cfg.val1.val1.append('yes')
assert cfg.val1.val1 == ['yes']
cfg.cfgimpl_get_settings().remove('disabled')
assert cfg.val1.val2 == [None]
cfg.val1.val2 = ['no']
cfg.val1.val1.append('yes2')
cfg.val1.val1.append('yes3')
cfg.val1.val2[2] = 'no1'
assert cfg.val1.val2 == ['no', None, 'no1']
cfg.cfgimpl_get_settings().append('disabled')
cfg.val1.val1.pop(0)
assert cfg.val1.val1 == ['yes2', 'yes3']
cfg.cfgimpl_get_settings().remove('disabled')
assert cfg.val1.val2 == [None, 'no1']
def test_callback_master_and_slaves_slave_callback_disabled():
val0 = StrOption('val0', "", multi=True, properties=('disabled',))
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val0, False),)})
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1, val0])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val1.val1 == []
raises(ConfigError, "cfg.val1.val2")
cfg.val1.val1.append('yes')
assert cfg.val1.val1 == ['yes']
cfg.cfgimpl_get_settings().remove('disabled')
assert cfg.val1.val2 == [None]
cfg.val1.val2 = ['no']
cfg.val1.val1.append('yes1')
cfg.val1.val2[1] = 'no1'
cfg.cfgimpl_get_settings().append('disabled')
cfg.val1.val1.pop(0)
assert cfg.val1.val1 == ['yes1']
assert cfg.val1.val2 == ['no1']
def test_callback_master_and_slaves_slave_list():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, callback=return_list)
@ -538,20 +685,20 @@ def test_callback_master_and_slaves_slave_list():
maconfig = OptionDescription('rootconfig', '', [interface1])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val1.val2 == []
#len is equal to 2 for slave and 0 for master
raises(SlaveError, "cfg.val1.val2")
cfg.val1.val1 = ['val1', 'val2']
assert cfg.val1.val1 == ['val1', 'val2']
assert cfg.val1.val2 == ['val', 'val']
cfg.val1.val1 = ['val1']
#wrong len
raises(SlaveError, 'cfg.val1.val2')
raises(SlaveError, "cfg.val1.val1 = ['val1']")
def test_callback_master_and_slaves_value():
val4 = StrOption('val4', '', multi=True, default=['val10', 'val11'])
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
val3 = StrOption('val3', "", multi=True, callback=return_value, callback_params={'': ('yes',)})
val4 = StrOption('val4', '', multi=True, default=['val10', 'val11'])
val5 = StrOption('val5', "", multi=True, callback=return_value, callback_params={'': ((val4, False),)})
val6 = StrOption('val6', "", multi=True, callback=return_value, callback_params={'': ((val5, False),)})
interface1 = OptionDescription('val1', '', [val1, val2, val3, val5, val6])
@ -559,27 +706,24 @@ def test_callback_master_and_slaves_value():
maconfig = OptionDescription('rootconfig', '', [interface1, val4])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val1.val1 == []
assert cfg.val1.val2 == []
assert cfg.val1.val3 == []
assert cfg.val1.val5 == []
assert cfg.val1.val6 == []
cfg.val4 == ['val10', 'val11']
raises(SlaveError, "cfg.val1.val1")
raises(SlaveError, "cfg.val1.val2")
raises(SlaveError, "cfg.val1.val3")
raises(SlaveError, "cfg.val1.val5")
raises(SlaveError, "cfg.val1.val6")
#
cfg.val1.val1 = ['val1']
assert cfg.val1.val1 == ['val1']
assert cfg.val1.val2 == ['val1']
assert cfg.val1.val3 == ['yes']
assert cfg.val1.val5 == ['val10']
assert cfg.val1.val6 == ['val10']
#default calculation has greater length
raises(SlaveError, "cfg.val1.val1 = ['val1']")
#
cfg.val1.val1.append('val2')
cfg.val1.val1 = ['val1', 'val2']
assert cfg.val1.val1 == ['val1', 'val2']
assert cfg.val1.val2 == ['val1', 'val2']
assert cfg.val1.val3 == ['yes', 'yes']
assert cfg.val1.val5 == ['val10', 'val11']
assert cfg.val1.val6 == ['val10', 'val11']
#
cfg.val1.val1 = ['val1', 'val2', 'val3']
cfg.val1.val1.append('val3')
assert cfg.val1.val1 == ['val1', 'val2', 'val3']
assert cfg.val1.val2 == ['val1', 'val2', 'val3']
assert cfg.val1.val3 == ['yes', 'yes', 'yes']
@ -650,9 +794,16 @@ def test_callback_master_and_other_master_slave():
assert cfg.val4.val6 == ['no', None]
cfg.val1.val1 = ['yes', 'yes', 'yes']
cfg.val1.val2 = ['no', 'no', 'no']
assert cfg.val4.val4 == ['val10', 'val11']
assert cfg.val4.val5 == ['yes', 'yes']
assert cfg.val4.val6 == ['no', 'no']
raises(SlaveError, "cfg.val4.val4")
raises(SlaveError, "cfg.val4.val5")
raises(SlaveError, "cfg.val4.val6")
cfg.val4.getattr('val4', validate=False).append('val12')
assert cfg.val4.val4 == ['val10', 'val11', 'val12']
assert cfg.val4.val5 == ['yes', 'yes', 'yes']
assert cfg.val4.val6 == ['no', 'no', 'no']
#FIXME: slave est un symlink
def test_callback_different_type():
@ -702,6 +853,19 @@ def test_callback_two_disabled():
raises(PropertiesOptionError, 'cfg.od2.opt2')
def test_callback_two_disabled2():
opt1 = BoolOption('opt1', '', properties=('hidden',))
opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('hidden',))
od1 = OptionDescription('od1', '', [opt1])
od2 = OptionDescription('od2', '', [opt2])
maconfig = OptionDescription('rootconfig', '', [od1, od2])
cfg = Config(maconfig)
cfg.read_write()
cfg.cfgimpl_get_settings().setpermissive(('hidden',))
raises(PropertiesOptionError, 'cfg.od2.opt2')
assert cfg.getowner(opt2, force_permissive=True) == owners.default
def test_callback_calculating_disabled():
opt1 = BoolOption('opt1', '', properties=('disabled',))
opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)})
@ -724,6 +888,17 @@ def test_callback_calculating_mandatory():
raises(ConfigError, 'cfg.od2.opt2')
def test_callback_calculating_mandatory_multi():
opt1 = BoolOption('opt1', '', multi=True, properties=('disabled',))
opt2 = BoolOption('opt2', '', multi=True, callback=return_value, callback_params={'': ((opt1, False),)}, properties=('mandatory',))
od1 = OptionDescription('od1', '', [opt1])
od2 = OptionDescription('od2', '', [opt2])
maconfig = OptionDescription('rootconfig', '', [od1, od2])
cfg = Config(maconfig)
cfg.read_only()
raises(ConfigError, 'cfg.od2.opt2')
def test_callback_two_disabled_multi():
opt1 = BoolOption('opt1', '', properties=('disabled',))
opt2 = BoolOption('opt2', '', callback=return_value, callback_params={'': ((opt1, False),)}, properties=('disabled',), multi=True)

View File

@ -5,7 +5,8 @@ from tiramisu.setting import owners, groups
from tiramisu.config import Config
from tiramisu.option import IPOption, NetworkOption, NetmaskOption, IntOption,\
BroadcastOption, SymLinkOption, OptionDescription
from tiramisu.error import ConfigError
from tiramisu.error import ConfigError, ValueWarning
import warnings
def test_consistency():
@ -19,6 +20,19 @@ def test_consistency():
raises(ConfigError, "a.impl_add_consistency('not_equal', 'a')")
def test_consistency_warnings_only():
a = IntOption('a', '')
b = IntOption('b', '')
od = OptionDescription('od', '', [a, b])
a.impl_add_consistency('not_equal', b, warnings_only=True)
c = Config(od)
c.a = 1
warnings.simplefilter("always", ValueWarning)
with warnings.catch_warnings(record=True) as w:
c.b = 1
assert w != []
def test_consistency_not_equal():
a = IntOption('a', '')
b = IntOption('b', '')
@ -186,6 +200,29 @@ def test_consistency_network_netmask():
raises(ValueError, "c.a = '192.168.1.1'")
def test_consistency_ip_in_network():
a = NetworkOption('a', '')
b = NetmaskOption('b', '')
c = IPOption('c', '')
od = OptionDescription('od', '', [a, b, c])
c.impl_add_consistency('in_network', a, b)
cfg = Config(od)
cfg.a = '192.168.1.0'
cfg.b = '255.255.255.0'
cfg.c = '192.168.1.1'
raises(ValueError, "cfg.c = '192.168.2.1'")
def test_consistency_ip_in_network_len_error():
a = NetworkOption('a', '')
b = NetmaskOption('b', '')
c = IPOption('c', '')
od = OptionDescription('od', '', [a, b, c])
c.impl_add_consistency('in_network', a)
cfg = Config(od)
raises(ConfigError, "cfg.a = '192.168.2.0'")
def test_consistency_ip_netmask_network_error():
a = IPOption('a', '')
b = NetworkOption('b', '')
@ -301,7 +338,7 @@ def test_consistency_broadcast_error():
c.impl_add_consistency('broadcast', a)
c = Config(od)
c.a = ['192.168.1.0']
c.b = ['255.255.255.0']
raises(ConfigError, "c.b = ['255.255.255.0']")
raises(ConfigError, "c.c = ['192.168.1.255']")
@ -346,3 +383,17 @@ def test_consistency_permissive():
c.cfgimpl_get_settings().setpermissive(('hidden',))
c.read_write()
c.a = 1
def return_val(*args, **kwargs):
return '192.168.1.1'
def test_consistency_with_callback():
a = NetworkOption('a', '', default='192.168.1.0')
b = NetmaskOption('b', '', default='255.255.255.0')
c = IPOption('c', '', callback=return_val, callback_params={'': ((a, False),)})
od = OptionDescription('od', '', [a, b, c])
c.impl_add_consistency('in_network', a, b)
cfg = Config(od)
cfg.c

View File

@ -5,7 +5,7 @@ from tiramisu.setting import owners
from tiramisu.config import Config
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
StrOption, OptionDescription
from tiramisu.error import ConfigError, ConstError
from tiramisu.error import ConfigError, ConstError, PropertiesOptionError
def make_description():
@ -41,6 +41,14 @@ def test_default_owner():
assert cfg.getowner(gcdummy) == owners.user
def test_hidden_owner():
gcdummy = BoolOption('dummy', 'dummy', default=False, properties=('hidden',))
descr = OptionDescription('tiramisu', '', [gcdummy])
cfg = Config(descr)
cfg.read_write()
raises(PropertiesOptionError, "cfg.getowner(gcdummy)")
def test_addowner():
gcdummy = BoolOption('dummy', 'dummy', default=False)
descr = OptionDescription('tiramisu', '', [gcdummy])

View File

@ -306,6 +306,15 @@ def test_access_by_get_whith_hide():
raises(AttributeError, "c.find(byname='b1')")
def test_extend_config_properties():
descr = make_description()
cfg = Config(descr)
setting = cfg.cfgimpl_get_settings()
assert str(setting) == str(['cache', 'expire', 'validator'])
setting.extend(['test', 'test2'])
assert str(setting) == str(['test', 'cache', 'test2', 'expire', 'validator'])
def test_append_properties():
descr = make_description()
cfg = Config(descr)
@ -363,3 +372,14 @@ def test_reset_multiple():
setting[option].append('test')
setting.reset(all_properties=True)
setting.reset(all_properties=True)
def test_properties_cached():
b1 = BoolOption("b1", "", properties=('test',))
descr = OptionDescription("opt", "", [OptionDescription("sub", "", [b1])])
c = Config(descr)
c.read_write()
setting = c.cfgimpl_get_settings()
option = c.cfgimpl_get_description().sub.b1
c._setattr('sub.b1', True, force_permissive=True)
assert str(setting[b1]) == "['test']"

View File

@ -0,0 +1,25 @@
"configuration objects global API"
import autopath
from py.test import raises
from tiramisu.config import Config
from tiramisu.option import UsernameOption
def test_username():
UsernameOption('a', '', 'string')
UsernameOption('a', '', '_string')
UsernameOption('a', '', 's_tring')
UsernameOption('a', '', 'string_')
UsernameOption('a', '', 'string$')
UsernameOption('a', '', '_string$')
raises(ValueError, "UsernameOption('a', '', 'strin$g')")
UsernameOption('a', '', 's-tring')
raises(ValueError, "UsernameOption('a', '', '-string')")
UsernameOption('a', '', 's9tring')
raises(ValueError, "UsernameOption('a', '', '9string')")
raises(ValueError, "UsernameOption('a', '', '')")
UsernameOption('a', '', 's')
UsernameOption('a', '', 's2345678901234567890123456789012')
raises(ValueError, "UsernameOption('a', '', 's23456789012345678901234567890123')")
UsernameOption('a', '', 's234567890123456789012345678901$')
raises(ValueError, "UsernameOption('a', '', 's2345678901234567890123456789012$')")

View File

@ -90,7 +90,7 @@ def test_validator_warning():
cfg.opt2 = 'val'
assert len(w) == 1
assert w[0].message.opt == opt2
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('opt2', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('opt2', 'error')
#
with warnings.catch_warnings(record=True) as w:
cfg.opt3.append('val')
@ -100,7 +100,7 @@ def test_validator_warning():
cfg.opt3.append('val1')
assert len(w) == 1
assert w[0].message.opt == opt3
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('opt3', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('opt3', 'error')
raises(ValueError, "cfg.opt2 = 1")
#
with warnings.catch_warnings(record=True) as w:
@ -108,9 +108,9 @@ def test_validator_warning():
cfg.opt3.append('val')
assert len(w) == 2
assert w[0].message.opt == opt2
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('opt2', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('opt2', 'error')
assert w[1].message.opt == opt3
assert str(w[1].message) == _('invalid value for option {0}: {1}').format('opt3', 'error')
assert str(w[1].message) == _("warning on the value of the option {0}: {1}").format('opt3', 'error')
def test_validator_warning_master_slave():
@ -130,29 +130,29 @@ def test_validator_warning_master_slave():
cfg.ip_admin_eth0.netmask_admin_eth0 = ['val1']
assert len(w) == 1
assert w[0].message.opt == netmask_admin_eth0
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('netmask_admin_eth0', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('netmask_admin_eth0', 'error')
#
with warnings.catch_warnings(record=True) as w:
cfg.ip_admin_eth0.ip_admin_eth0 = ['val']
assert len(w) == 1
assert w[0].message.opt == ip_admin_eth0
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('ip_admin_eth0', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('ip_admin_eth0', 'error')
#
with warnings.catch_warnings(record=True) as w:
cfg.ip_admin_eth0.ip_admin_eth0 = ['val', 'val1', 'val1']
assert len(w) == 1
assert w[0].message.opt == ip_admin_eth0
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('ip_admin_eth0', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('ip_admin_eth0', 'error')
#
with warnings.catch_warnings(record=True) as w:
cfg.ip_admin_eth0.ip_admin_eth0 = ['val1', 'val', 'val1']
assert len(w) == 1
assert w[0].message.opt == ip_admin_eth0
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('ip_admin_eth0', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('ip_admin_eth0', 'error')
#
warnings.resetwarnings()
with warnings.catch_warnings(record=True) as w:
cfg.ip_admin_eth0.ip_admin_eth0 = ['val1', 'val1', 'val']
assert len(w) == 1
assert w[0].message.opt == ip_admin_eth0
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('ip_admin_eth0', 'error')
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('ip_admin_eth0', 'error')

View File

@ -34,7 +34,9 @@ def make_description():
mode_conteneur_actif, adresse_serveur_ntp,
time_zone])
general.impl_set_group_type(groups.family)
creole = OptionDescription('creole', 'first tiramisu configuration', [general, interface1])
new = OptionDescription('new', '', [], properties=('hidden',))
new.impl_set_group_type(groups.family)
creole = OptionDescription('creole', 'first tiramisu configuration', [general, interface1, new])
descr = OptionDescription('baseconfig', 'baseconifgdescr', [creole])
return descr
@ -99,6 +101,17 @@ def test_iter_on_groups():
break
def test_iter_on_groups_force_permissive():
descr = make_description()
config = Config(descr)
config.read_write()
config.cfgimpl_get_settings().setpermissive(('hidden',))
result = list(config.creole.iter_groups(group_type=groups.family,
force_permissive=True))
group_names = [res[0] for res in result]
assert group_names == ['general', 'interface1', 'new']
def test_iter_on_groups_props():
descr = make_description()
config = Config(descr)

View File

@ -242,6 +242,30 @@ def test_requires_transitive():
assert props == ['disabled']
def test_requires_transitive_owner():
a = BoolOption('activate_service', '', True)
b = BoolOption('activate_service_web', '', True,
requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
d = IPOption('ip_address_service_web', '',
requires=[{'option': b, 'expected': False, 'action': 'disabled'}])
od = OptionDescription('service', '', [a, b, d])
c = Config(od)
c.read_write()
c.activate_service
c.activate_service_web
c.ip_address_service_web
#no more default value
c.ip_address_service_web = '1.1.1.1'
c.activate_service = False
props = []
try:
c.ip_address_service_web
except PropertiesOptionError as err:
props = err.proptype
assert props == ['disabled']
def test_requires_transitive_bis():
a = BoolOption('activate_service', '', True)
abis = BoolOption('activate_service_bis', '', True)