Merge branch 'master' into metaconfig

This commit is contained in:
2014-02-02 18:21:22 +01:00
25 changed files with 1453 additions and 670 deletions

View File

@ -9,7 +9,7 @@ from py.test import raises
from tiramisu.config import Config
from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \
BoolOption, UnicodeOption, OptionDescription
from tiramisu.error import ConflictError
from tiramisu.error import ConflictError, ConfigError
def make_description():
@ -131,8 +131,10 @@ def test_cfgimpl_get_home_by_path():
config.bool = False
assert config.cfgimpl_get_home_by_path('gc.dummy')[1] == 'dummy'
assert config.cfgimpl_get_home_by_path('dummy')[1] == 'dummy'
#assert config.getpaths(include_groups=False) == ['gc.name', 'gc.dummy', 'gc.float', 'bool', 'objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop']
#assert config.getpaths(include_groups=True) == ['gc', 'gc.name', 'gc.dummy', 'gc.float', 'bool', 'objspace', 'wantref', 'str', 'wantframework', 'int', 'boolop']
def test_not_valid_properties():
raises(TypeError, "stroption = StrOption('str', 'Test string option', default='abc', properties=['mandatory',])")
def test_information_config():
@ -142,6 +144,7 @@ def test_information_config():
config.impl_set_information('info', string)
assert config.impl_get_information('info') == string
raises(ValueError, "config.impl_get_information('noinfo')")
assert config.impl_get_information('noinfo', 'default') == 'default'
def test_config_impl_get_path_by_opt():
@ -149,8 +152,10 @@ def test_config_impl_get_path_by_opt():
config = Config(descr)
dummy = config.unwrap_from_path('gc.dummy')
boo = config.unwrap_from_path('bool')
unknown = IntOption('test', '')
assert config.cfgimpl_get_description().impl_get_path_by_opt(boo) == 'bool'
assert config.cfgimpl_get_description().impl_get_path_by_opt(dummy) == 'gc.dummy'
raises(AttributeError, "config.cfgimpl_get_description().impl_get_path_by_opt(unknown)")
def test_config_impl_get_opt_by_path():
@ -160,6 +165,7 @@ def test_config_impl_get_opt_by_path():
boo = config.unwrap_from_path('bool')
assert config.cfgimpl_get_description().impl_get_opt_by_path('bool') == boo
assert config.cfgimpl_get_description().impl_get_opt_by_path('gc.dummy') == dummy
raises(AttributeError, "config.cfgimpl_get_description().impl_get_opt_by_path('gc.unknown')")
def test_information_display():
@ -231,8 +237,60 @@ def test_duplicated_option():
#in different OptionDescription
raises(ConflictError, "config = Config(root)")
def test_cannot_assign_value_to_option_description():
descr = make_description()
cfg = Config(descr)
raises(TypeError, "cfg.gc = 3")
def test_config_multi():
i1 = IntOption('test1', '', multi=True)
i2 = IntOption('test2', '', multi=True, default_multi=1)
i3 = IntOption('test3', '', default=[2], multi=True, default_multi=1)
od = OptionDescription('test', '', [i1, i2, i3])
config = Config(od)
assert config.test1 == []
assert config.test2 == []
config.test2.append()
assert config.test2 == [1]
assert config.test3 == [2]
config.test3.append()
assert config.test3 == [2, 1]
def test_no_validation():
i1 = IntOption('test1', '')
od = OptionDescription('test', '', [i1])
c = Config(od)
setting = c.cfgimpl_get_settings()
c.test1 = 1
raises(ValueError, 'c.test1 = "yes"')
assert c.test1 == 1
setting.remove('validator')
c.test1 = "yes"
assert c.test1 == "yes"
setting.append('validator')
raises(ValueError, 'c.test1')
del(c.test1)
assert c.test1 is None
def test_delete_config_with_subconfig():
test = IntOption('test', '')
multi = IntOption('multi', '', multi=True)
od = OptionDescription('od', '', [test, multi])
odroot = OptionDescription('odroot', '', [od])
c = Config(odroot)
sub = c.od
val = c.cfgimpl_get_values()
setting = c.cfgimpl_get_settings()
val[test]
val[multi]
setting[test]
sub.make_dict()
del(c)
raises(ConfigError, 'val[test]')
raises(ConfigError, 'val[multi]')
raises(ConfigError, 'setting[test]')
raises(ConfigError, 'sub.make_dict()')

View File

@ -4,26 +4,31 @@ from py.test import raises
from tiramisu.config import Config
from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \
BoolOption, OptionDescription
BoolOption, FilenameOption, OptionDescription
def make_description():
gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
gcdummy = BoolOption('dummy', 'dummy', default=False)
prop = BoolOption('prop', '', properties=('disabled',))
prop2 = BoolOption('prop', '', properties=('hidden',))
objspaceoption = ChoiceOption('objspace', 'Object space',
('std', 'thunk'), 'std')
booloption = BoolOption('bool', 'Test boolean option', default=True)
booloption2 = BoolOption('bool', 'Test boolean option', default=False)
intoption = IntOption('int', 'Test int option', default=0)
floatoption2 = FloatOption('float', 'Test float option', default=2.3)
floatoption = FloatOption('float', 'Test float option', default=2.3)
stroption = StrOption('str', 'Test string option', default="abc")
boolop = BoolOption('boolop', 'Test boolean option op', default=True)
wantref_option = BoolOption('wantref', 'Tests', default=False)
wantframework_option = BoolOption('wantframework', 'Test', default=False)
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
gcgroup2 = OptionDescription('gc2', '', [booloption2, prop])
gcgroup = OptionDescription('gc', '', [gcgroup2, gcoption, gcdummy, floatoption, prop2])
descr = OptionDescription('tiramisu', '', [gcgroup, booloption, objspaceoption,
wantref_option, stroption,
wantframework_option,
intoption, boolop])
intoption, boolop, floatoption2])
return descr
@ -100,20 +105,40 @@ def test_find_in_config():
"finds option in config"
descr = make_description()
conf = Config(descr)
conf.read_only()
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')
assert conf.find_first(byname='bool', byvalue=True) == conf.unwrap_from_path('bool')
assert conf.find_first(byname='dummy') == conf.unwrap_from_path('gc.dummy')
assert conf.find_first(byname='float') == conf.unwrap_from_path('gc.float')
assert conf.find(bytype=ChoiceOption) == [conf.unwrap_from_path('gc.name'), conf.unwrap_from_path('objspace')]
assert conf.find_first(bytype=ChoiceOption) == conf.unwrap_from_path('gc.name')
assert conf.find(byvalue='ref') == [conf.unwrap_from_path('gc.name')]
assert conf.find_first(byvalue='ref') == conf.unwrap_from_path('gc.name')
assert conf.find(byname='prop') == [conf.unwrap_from_path('gc.prop')]
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_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')
assert conf.find(byvalue=False, byname='dummy') == [conf.unwrap_from_path('gc.dummy')]
assert conf.find_first(byvalue=False, byname='dummy') == conf.unwrap_from_path('gc.dummy')
## byattrs
#assert conf.find_first(byattrs= dict(default=2.3)) == conf.unwrap_from_path('gc.float')
#assert conf.find_first(byvalue=False, byname='dummy', byattrs=dict(default=False)) == conf.unwrap_from_path('gc.dummy')
#subconfig
assert conf.gc.find(byname='dummy') == [conf.unwrap_from_path('gc.dummy')]
assert conf.gc.find(byname='float') == [conf.unwrap_from_path('gc.float')]
assert conf.gc.find(byname='bool') == [conf.unwrap_from_path('gc.gc2.bool')]
assert conf.gc.find_first(byname='bool', byvalue=False) == conf.unwrap_from_path('gc.gc2.bool')
raises(AttributeError, "assert conf.gc.find_first(byname='bool', byvalue=True)")
raises(AttributeError, "conf.gc.find(byname='wantref').first()")
assert conf.gc.find(byname='prop', check_properties=False) == [conf.unwrap_from_path('gc.gc2.prop'), conf.unwrap_from_path('gc.prop')]
conf.read_only()
assert conf.gc.find(byname='prop') == [conf.unwrap_from_path('gc.prop')]
# not OptionDescription
raises(AttributeError, "conf.find_first(byname='gc')")
raises(AttributeError, "conf.gc.find_first(byname='gc2')")
def test_find_multi():
@ -137,3 +162,18 @@ def test_does_not_find_in_config():
descr = make_description()
conf = Config(descr)
raises(AttributeError, "conf.find(byname='IDontExist')")
def test_filename():
a = FilenameOption('a', '')
o = OptionDescription('o', '', [a])
c = Config(o)
c.a = u'/'
c.a = u'/tmp'
c.a = u'/tmp/'
c.a = u'/tmp/text.txt'
c.a = u'tmp'
c.a = u'tmp/'
c.a = u'tmp/text.txt'
raises(ValueError, "c.a = u'/tmp/with space.txt'")
raises(ValueError, "c.a = u'/tmp/with$.txt'")

View File

@ -2,23 +2,28 @@ import autopath
from py.test import raises
from tiramisu.config import Config
from tiramisu.option import DomainnameOption, OptionDescription
from tiramisu.option import DomainnameOption, EmailOption, URLOption, OptionDescription
def test_domainname():
d = DomainnameOption('d', '')
e = DomainnameOption('e', '', "toto.com")
od = OptionDescription('a', '', [d, e])
f = DomainnameOption('f', '', allow_without_dot=True)
od = OptionDescription('a', '', [d, f])
c = Config(od)
c.read_write()
c.d = 'toto.com'
raises(ValueError, "c.d = 'toto'")
c.d = 'toto3.com'
c.d = 'toto3.3la'
raises(ValueError, "c.d = 'toto3.3la'")
raises(ValueError, "c.d = '3toto.com'")
c.d = 'toto.co3'
raises(ValueError, "c.d = 'toto.co3'")
raises(ValueError, "c.d = 'toto_super.com'")
c.d = 'toto-.com'
raises(ValueError, "c.d = 'toto..com'")
#
c.f = 'toto.com'
c.f = 'toto'
def test_domainname_netbios():
@ -41,3 +46,33 @@ def test_domainname_hostname():
raises(ValueError, "c.d = 'toto.com'")
c.d = 'toto'
c.d = 'domainnametoolong'
def test_email():
e = EmailOption('e', '')
od = OptionDescription('a', '', [e])
c = Config(od)
c.read_write()
c.e = 'root@foo.com'
raises(ValueError, "c.e = 'root'")
raises(ValueError, "c.e = 'root@domain'")
def test_url():
u = URLOption('u', '')
od = OptionDescription('a', '', [u])
c = Config(od)
c.read_write()
c.u = 'http://foo.com'
c.u = 'https://foo.com'
c.u = 'https://foo.com/'
raises(ValueError, "c.u = 'ftp://foo.com'")
raises(ValueError, "c.u = 'foo.com'")
raises(ValueError, "c.u = ':/foo.com'")
raises(ValueError, "c.u = 'foo.com/http://'")
c.u = 'https://foo.com/index.html'
c.u = 'https://foo.com/index.html?var=value&var2=val2'
raises(ValueError, "c.u = 'https://foo.com/index\\n.html'")
c.u = 'https://foo.com:8443'
c.u = 'https://foo.com:8443/'
c.u = 'https://foo.com:8443/index.html'

View File

@ -21,6 +21,11 @@ def test_ip():
c.b = '0.0.0.0'
raises(ValueError, "c.b = '255.255.255.0'")
raises(ValueError, "IPOption('a', 'ip', default='192.000.023.01')")
d = IPOption('a', 'ip', default='192.0.23.1')
od = OptionDescription('od', '', [d])
c = Config(od)
raises(ValueError, "c.a = '192.000.023.01'")
def test_ip_default():
a = IPOption('a', '', '88.88.88.88')

21
test/test_multi.py Normal file
View File

@ -0,0 +1,21 @@
# coding: utf-8
import autopath
from tiramisu.value import Multi
from tiramisu.option import IntOption, OptionDescription
from tiramisu.config import Config
from tiramisu.error import ConfigError
import weakref
from py.test import raises
def test_multi():
i = IntOption('int', '', multi=True)
o = OptionDescription('od', '', [i])
c = Config(o)
multi = Multi([1,2,3], weakref.ref(c), i, 'int')
raises(ValueError, "Multi([1,2,3], c, i, 'int')")
raises(ValueError, "Multi(multi, weakref.ref(c), i, 'int')")
assert c is multi._getcontext()
del(c)
raises(ConfigError, "multi._getcontext()")

View File

@ -2,8 +2,13 @@
and to compare them
"""
import autopath
from py.test import raises
from tiramisu.option import BoolOption, IntOption
from tiramisu.option import IntOption, OptionDescription
def a_func():
return None
#def test_option_comparison():
@ -36,3 +41,60 @@ from tiramisu.option import BoolOption, IntOption
# assert dummy1 != dummy5
# assert dummy1 == dummy6
# assert dummy1 != dummy7
def test_option_valid_name():
IntOption('test', '')
raises(ValueError, 'IntOption(1, "")')
raises(ValueError, 'IntOption("impl_test", "")')
raises(ValueError, 'IntOption("_test", "")')
raises(ValueError, 'IntOption("unwrap_from_path", "")')
def test_option_with_callback():
#no default value with callback
raises(ValueError, "IntOption('test', '', default=1, callback=a_func)")
def test_option_get_information():
description = "it's ok"
string = 'some informations'
i = IntOption('test', description)
i.impl_set_information('info', string)
assert i.impl_get_information('info') == string
raises(ValueError, "i.impl_get_information('noinfo')")
assert i.impl_get_information('noinfo', 'default') == 'default'
assert i.impl_get_information('doc') == description
assert i.impl_getdoc() == description
def test_optiondescription_get_information():
description = "it's ok"
string = 'some informations'
o = OptionDescription('test', description, [])
o.impl_set_information('info', string)
assert o.impl_get_information('info') == string
raises(ValueError, "o.impl_get_information('noinfo')")
assert o.impl_get_information('noinfo', 'default') == 'default'
assert o.impl_get_information('doc') == description
assert o.impl_getdoc() == description
def test_option_multi():
IntOption('test', '', multi=True)
IntOption('test', '', multi=True, default_multi=1)
IntOption('test', '', default=[1], multi=True, default_multi=1)
#add default_multi to not multi's option
raises(ValueError, "IntOption('test', '', default_multi=1)")
#unvalid default_multi
raises(ValueError, "IntOption('test', '', multi=True, default_multi='yes')")
#not default_multi with callback
raises(ValueError, "IntOption('test', '', multi=True, default_multi=1, callback=a_func)")
def test_option_is_multi_by_default():
assert IntOption('test', '').impl_is_empty_by_default() is True
assert IntOption('test', '', 1).impl_is_empty_by_default() is False
assert IntOption('test', '', multi=True).impl_is_empty_by_default() is True
assert IntOption('test', '', [1], multi=True).impl_is_empty_by_default() is False
assert IntOption('test', '', multi=True, default_multi=1).impl_is_empty_by_default() is True

View File

@ -21,7 +21,13 @@ def return_list(value=None):
def return_list2(*args):
return list(args)
l = []
for arg in args:
if isinstance(arg, list):
l.extend(arg)
else:
l.append(arg)
return l
def return_value(value=None):
@ -34,6 +40,10 @@ def return_value2(*args, **kwargs):
return value
def return_calc(i, j, k):
return i + j + k
def make_description():
gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
gcdummy = BoolOption('dummy', 'dummy', default=False)
@ -93,83 +103,6 @@ def test_identical_paths():
raises(ConflictError, "make_description_duplicates()")
def make_description2():
gcoption = ChoiceOption('name', 'GC name', ['ref', 'framework'], 'ref')
gcdummy = BoolOption('dummy', 'dummy', default=False)
floatoption = FloatOption('float', 'Test float option', default=2.3)
objspaceoption = ChoiceOption('objspace', 'Object space',
['std', 'thunk'], 'std')
booloption = BoolOption('bool', 'Test boolean option', default=True)
intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default="abc")
# first multi
boolop = BoolOption('boolop', 'Test boolean option op', default=True)
boolop.enable_multi()
wantref_option = BoolOption('wantref', 'Test requires', default=False,
requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
# second multi
wantframework_option = BoolOption('wantframework', 'Test requires',
default=False,
requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
wantframework_option.enable_multi()
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
wantref_option, stroption,
wantframework_option,
intoption, boolop])
return descr
# FIXME: il faudra tester les validations sur les multis
#def test_multi_constraints():
# "a multi in a constraint has to have the same length"
# descr = make_description2()
# cfg = Config(descr)
# cfg.boolop = [True, True, False]
# cfg.wantframework = [False, False, True]
#
#def test_multi_raise():
# "a multi in a constraint has to have the same length"
# # FIXME fusionner les deux tests, MAIS PROBLEME :
# # il ne devrait pas etre necessaire de refaire une config
# # si la valeur est modifiee une deuxieme fois ->
# #raises(ConflictConfigError, "cfg.wantframework = [False, False, True]")
# # ExceptionFailure: 'DID NOT RAISE'
# descr = make_description2()
# cfg = Config(descr)
# cfg.boolop = [True]
# raises(ConflictConfigError, "cfg.wantframework = [False, False, True]")
# ____________________________________________________________
# adding dynamically new options description schema
#def test_newoption_add_in_descr():
# descr = make_description()
# newoption = BoolOption('newoption', 'dummy twoo', default=False)
# descr.add_child(newoption)
# config = Config(descr)
# assert config.newoption == False
#def test_newoption_add_in_subdescr():
# descr = make_description()
# newoption = BoolOption('newoption', 'dummy twoo', default=False)
# descr.gc.add_child(newoption)
# config = Config(descr)
# config.bool = False
# assert config.gc.newoption == False
#def test_newoption_add_in_config():
# descr = make_description()
# config = Config(descr)
# config.bool = False
# newoption = BoolOption('newoption', 'dummy twoo', default=False)
# descr.add_child(newoption)
# config.cfgimpl_update()
# assert config.newoption == False
# ____________________________________________________________
def make_description_requires():
gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
gcdummy = BoolOption('dummy', 'dummy', default=False)
@ -310,6 +243,19 @@ def test_callback():
assert cfg.val1 == 'val'
def test_callback_params_without_callback():
raises(ValueError, "StrOption('val2', '', callback_params={'': ('yes',)})")
def test_callback_invalid():
raises(ValueError, 'val1 = StrOption("val1", "", callback="string")')
raises(ValueError, 'val1 = StrOption("val1", "", callback=return_val, callback_params="string")')
val1 = StrOption('val1', "", 'val')
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'),)})")
def test_callback_value():
val1 = StrOption('val1', "", 'val')
val2 = StrOption('val2', "", callback=return_value, callback_params={'': ((val1, False),)})
@ -421,12 +367,15 @@ def test_callback_multi_value():
cfg.val1.append('new-val2')
assert cfg.val1 == ['new-val', 'new-val2']
assert cfg.val2 == ['new-val', 'new-val2']
assert cfg.val4 == ['new-val', 'yes', 'new-val2', 'yes']
assert cfg.val4 == ['new-val', 'new-val2', 'yes']
del(cfg.val1)
assert cfg.val1 == ['val']
assert cfg.val2 == ['val']
assert cfg.val3 == ['yes']
assert cfg.val4 == ['val', 'yes']
cfg.val2.append('new')
assert cfg.val1 == ['val']
assert cfg.val2 == ['val', 'new']
def test_callback_multi_list():
@ -443,6 +392,14 @@ def test_callback_multi_list():
assert cfg.val1 == ['val', 'val']
def test_callback_multi_list_extend():
val1 = StrOption('val1', "", callback=return_list2, callback_params={'': (['1', '2', '3'], ['4', '5'])}, multi=True)
maconfig = OptionDescription('rootconfig', '', [val1])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val1 == ['1', '2', '3', '4', '5']
def test_callback_master_and_slaves_master():
val1 = StrOption('val1', "", multi=True, callback=return_val)
val2 = StrOption('val2', "", multi=True)
@ -452,7 +409,7 @@ def test_callback_master_and_slaves_master():
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val1.val1 == ['val']
cfg.val1.val1.append(None)
cfg.val1.val1.append()
assert cfg.val1.val1 == ['val', 'val']
assert cfg.val1.val2 == [None, None]
@ -467,7 +424,7 @@ def test_callback_master_and_slaves_master_list():
cfg.read_write()
assert cfg.val1.val1 == ['val', 'val']
assert cfg.val1.val2 == [None, None]
cfg.val1.val1.append(None)
cfg.val1.val1.append()
assert cfg.val1.val1 == ['val', 'val', None]
assert cfg.val1.val2 == [None, None, None]
del(cfg.val1.val1)
@ -512,6 +469,66 @@ def test_callback_master_and_slaves_slave():
assert cfg.val1.val2 == ['val2', 'val2', 'val']
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),)})
val2 = StrOption('val2', "", multi=True, callback=return_val)
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1, val3])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val3 == []
assert cfg.val1.val1 == []
assert cfg.val1.val2 == []
cfg.val1.val1 = ['val1']
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']
assert cfg.val1.val2 == ['val', 'val']
assert cfg.val1.val1 == ['val1', 'val2']
cfg.val1.val2 = ['val1', 'val2']
cfg.val3.pop(1)
# cannot remove slave's value because master is calculated
# so raise
raises(SlaveError, "cfg.val1.val1")
raises(SlaveError, "cfg.val1.val2")
cfg.val3 = ['val1', 'val2', 'val3']
assert cfg.val1.val2 == ['val1', 'val2', 'val']
def test_callback_master_and_slaves_slave_cal2():
val3 = StrOption('val3', "", ['val', 'val'], multi=True)
val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val3, False),)})
val2 = StrOption('val2', "", ['val2', 'val2'], multi=True)
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1, val3])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val3 == ['val', 'val']
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
raises(SlaveError, "cfg.val1.val1")
raises(SlaveError, "cfg.val1.val2")
cfg.val3 = ['val', 'val']
assert cfg.val3 == ['val', 'val']
assert cfg.val1.val1 == ['val', 'val']
assert cfg.val1.val2 == ['val2', 'val2']
raises(SlaveError, "cfg.val1.val1 = ['val']")
assert cfg.val3 == ['val', 'val']
assert cfg.val1.val1 == ['val', 'val']
assert cfg.val1.val2 == ['val2', 'val2']
def test_callback_master_and_slaves_slave_list():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True, callback=return_list)
@ -535,7 +552,8 @@ def test_callback_master_and_slaves_value():
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),)})
interface1 = OptionDescription('val1', '', [val1, val2, val3, val5])
val6 = StrOption('val6', "", multi=True, callback=return_value, callback_params={'': ((val5, False),)})
interface1 = OptionDescription('val1', '', [val1, val2, val3, val5, val6])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1, val4])
cfg = Config(maconfig)
@ -544,30 +562,35 @@ def test_callback_master_and_slaves_value():
assert cfg.val1.val2 == []
assert cfg.val1.val3 == []
assert cfg.val1.val5 == []
assert 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']
#
cfg.val1.val1.append('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']
assert cfg.val1.val1 == ['val1', 'val2', 'val3']
assert cfg.val1.val2 == ['val1', 'val2', 'val3']
assert cfg.val1.val3 == ['yes', 'yes', 'yes']
assert cfg.val1.val5 == ['val10', 'val11', None]
assert cfg.val1.val6 == ['val10', 'val11', None]
#
cfg.val1.val1.pop(2)
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.val2 = ['val2', 'val2']
cfg.val1.val3 = ['val2', 'val2']
@ -575,11 +598,13 @@ def test_callback_master_and_slaves_value():
assert cfg.val1.val2 == ['val2', 'val2']
assert cfg.val1.val3 == ['val2', 'val2']
assert cfg.val1.val5 == ['val2', 'val2']
assert cfg.val1.val6 == ['val2', 'val2']
#
cfg.val1.val1.append('val3')
assert cfg.val1.val2 == ['val2', 'val2', 'val3']
assert cfg.val1.val3 == ['val2', 'val2', 'yes']
assert cfg.val1.val5 == ['val2', 'val2', None]
assert cfg.val1.val6 == ['val2', 'val2', None]
cfg.cfgimpl_get_settings().remove('cache')
cfg.val4 = ['val10', 'val11', 'val12']
#if value is already set, not updated !
@ -587,6 +612,69 @@ def test_callback_master_and_slaves_value():
cfg.val1.val1.append('val3')
cfg.val1.val1 = ['val1', 'val2', 'val3']
assert cfg.val1.val5 == ['val2', 'val2', 'val12']
assert cfg.val1.val6 == ['val2', 'val2', 'val12']
def test_callback_master():
val2 = StrOption('val2', "", multi=True, callback=return_value)
val1 = StrOption('val1', "", multi=True, callback=return_value, callback_params={'': ((val2, False),)})
interface1 = OptionDescription('val1', '', [val1, val2])
raises(ValueError, "interface1.impl_set_group_type(groups.master)")
def test_callback_master_and_other_master_slave():
val1 = StrOption('val1', "", multi=True)
val2 = StrOption('val2', "", multi=True)
val3 = StrOption('val3', "", multi=True)
val4 = StrOption('val4', '', multi=True, default=['val10', 'val11'])
val5 = StrOption('val5', "", multi=True, callback=return_value, callback_params={'': ((val1, False),)})
val6 = StrOption('val6', "", multi=True, callback=return_value, callback_params={'': ((val2, False),)})
interface1 = OptionDescription('val1', '', [val1, val2, val3])
interface1.impl_set_group_type(groups.master)
interface2 = OptionDescription('val4', '', [val4, val5, val6])
interface2.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1, interface2])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val4.val4 == ['val10', 'val11']
assert cfg.val4.val5 == [None, None]
assert cfg.val4.val6 == [None, None]
cfg.val1.val1 = ['yes']
assert cfg.val4.val4 == ['val10', 'val11']
assert cfg.val4.val5 == ['yes', None]
assert cfg.val4.val6 == [None, None]
cfg.val1.val2 = ['no']
assert cfg.val4.val4 == ['val10', 'val11']
assert cfg.val4.val5 == ['yes', None]
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']
def test_callback_different_type():
val = IntOption('val', "", default=2)
val_ = IntOption('val_', "", default=3)
val1 = IntOption('val1', "", multi=True)
val2 = IntOption('val2', "", multi=True, callback=return_calc, callback_params={'': ((val, False), (val1, False)), 'k': ((val_, False),)})
interface1 = OptionDescription('val1', '', [val1, val2])
interface1.impl_set_group_type(groups.master)
maconfig = OptionDescription('rootconfig', '', [interface1, val, val_])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val1.val1 == []
assert cfg.val1.val2 == []
cfg.val1.val1 = [1]
assert cfg.val1.val1 == [1]
assert cfg.val1.val2 == [6]
cfg.val1.val1 = [1, 3]
assert cfg.val1.val1 == [1, 3]
assert cfg.val1.val2 == [6, 8]
cfg.val1.val1 = [1, 3, 5]
assert cfg.val1.val1 == [1, 3, 5]
assert cfg.val1.val2 == [6, 8, 10]
def test_callback_hidden():
@ -653,7 +741,7 @@ def test_callback_multi_list_params():
maconfig = OptionDescription('rootconfig', '', [val1, oval2])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val2.val2 == ['val', 'val', 'val', 'val']
assert cfg.val2.val2 == ['val', 'val']
def test_callback_multi_list_params_key():
@ -663,31 +751,4 @@ def test_callback_multi_list_params_key():
maconfig = OptionDescription('rootconfig', '', [val1, oval2])
cfg = Config(maconfig)
cfg.read_write()
assert cfg.val2.val2 == ['val', 'val', 'val', 'val']
def test_callback_multi_multi():
val1 = StrOption('val1', "", multi=True, default=['val1', 'val2', 'val3'])
val2 = StrOption('val2', "", multi=True, default=['val11', 'val12'])
val3 = StrOption('val3', "", default='val4')
val4 = StrOption('val4', "", multi=True, callback=return_list2, callback_params={'': ((val1, False), (val2, False))})
val5 = StrOption('val5', "", multi=True, callback=return_list2, callback_params={'': ((val1, False), (val3, False))})
val6 = StrOption('val6', "", multi=True, default=['val21', 'val22', 'val23'])
val7 = StrOption('val7', "", multi=True, callback=return_list2, callback_params={'': ((val1, False), (val6, False))})
raises(ValueError, "StrOption('val8', '', multi=True, callback=return_list2, callback_params={'value': ((val1, False), (val6, False))})")
maconfig = OptionDescription('rootconfig', '', [val1, val2, val3, val4, val5, val6, val7])
cfg = Config(maconfig)
cfg.read_write()
raises(ConfigError, "cfg.val4")
assert cfg.val5 == ['val1', 'val4', 'val2', 'val4', 'val3', 'val4']
assert cfg.val7 == ['val1', 'val21', 'val2', 'val22', 'val3', 'val23']
def test_multi_with_no_value():
#First option return [] (so without value)
val1 = StrOption('val1', "", ['val'], multi=True)
val2 = StrOption('val2', "", multi=True)
val3 = StrOption('val3', '', multi=True, callback=return_value, callback_params={'': ((val2, False),), 'value': ((val1, False),)})
od = OptionDescription('od', '', [val1, val2, val3])
c = Config(od)
raises(ConfigError, "c.val3")
assert cfg.val2.val2 == ['val', 'val']

View File

@ -8,6 +8,17 @@ from tiramisu.option import IPOption, NetworkOption, NetmaskOption, IntOption,\
from tiramisu.error import ConfigError
def test_consistency():
a = IntOption('a', '')
b = IntOption('b', '')
od = OptionDescription('od', '', [a, b])
a.impl_add_consistency('not_equal', b)
#consistency to itself
raises(ConfigError, "a.impl_add_consistency('not_equal', a)")
#consistency with string
raises(ConfigError, "a.impl_add_consistency('not_equal', 'a')")
def test_consistency_not_equal():
a = IntOption('a', '')
b = IntOption('b', '')

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
from tiramisu.error import ConfigError, ConstError
def make_description():
@ -52,6 +52,17 @@ def test_addowner():
assert cfg.getowner(gcdummy) == owners.gen_config
def test_addowner_multiple_time():
owners.addowner("testowner")
raises(ConstError, 'owners.addowner("testowner")')
def test_delete_owner():
owners.addowner('deleted')
raises(ConstError, 'del(owners.deleted)')
raises(ValueError, 'del(owners.deleted2)')
def test_owner_is_not_a_string():
gcdummy = BoolOption('dummy', 'dummy', default=False)
descr = OptionDescription('tiramisu', '', [gcdummy])

View File

@ -75,6 +75,16 @@ def test_group_is_hidden():
prop = err.proptype
assert 'hidden' in prop
def test_extend_properties():
descr = make_description()
config = Config(descr)
setting = config.cfgimpl_get_settings()
config.read_write()
gc = config.unwrap_from_path('gc')
config.unwrap_from_path('gc.dummy')
setting[gc].extend(['hidden', 'user_defined_property'])
assert 'hidden' in setting[gc]
assert 'user_defined_property' in setting[gc]
def test_group_is_hidden_multi():
descr = make_description()

View File

@ -6,6 +6,7 @@ from tiramisu.config import Config
from tiramisu.option import StrOption, OptionDescription
from tiramisu.setting import groups
from tiramisu.error import ValueWarning
from tiramisu.i18n import _
def return_true(value, param=None):
@ -87,7 +88,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 val for option opt2: error'
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('opt2', 'error')
#
with warnings.catch_warnings(record=True) as w:
cfg.opt3.append('val')
@ -97,7 +98,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 val1 for option opt3: error'
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('opt3', 'error')
raises(ValueError, "cfg.opt2 = 1")
#
with warnings.catch_warnings(record=True) as w:
@ -105,9 +106,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 val for option opt2: error'
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('opt2', 'error')
assert w[1].message.opt == opt3
assert str(w[1].message) == 'invalid value val1 for option opt3: error'
assert str(w[1].message) == _('invalid value for option {0}: {1}').format('opt3', 'error')
def test_validator_warning_master_slave():
@ -127,29 +128,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 val1 for option netmask_admin_eth0: error'
assert str(w[0].message) == _('invalid value for 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 val for option ip_admin_eth0: error'
assert str(w[0].message) == _('invalid value for 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 val for option ip_admin_eth0: error'
assert str(w[0].message) == _('invalid value for 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 val for option ip_admin_eth0: error'
assert str(w[0].message) == _('invalid value for 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 val for option ip_admin_eth0: error'
assert str(w[0].message) == _('invalid value for option {0}: {1}').format('ip_admin_eth0', 'error')

View File

@ -9,7 +9,8 @@ from tiramisu.error import PropertiesOptionError
def make_description():
u1 = IntOption('u1', '', properties=('frozen', 'mandatory', 'disabled', ))
return OptionDescription('od1', '', [u1])
u2 = IntOption('u2', '', properties=('frozen', 'mandatory', 'disabled', ))
return OptionDescription('od1', '', [u1, u2])
def test_permissive():
@ -91,3 +92,108 @@ def test_invalid_permissive():
setting = config.cfgimpl_get_settings()
config.read_write()
raises(TypeError, "setting.setpermissive(['frozen', 'disabled',])")
def test_permissive_option():
descr = make_description()
u1 = descr.u1
config = Config(descr)
setting = config.cfgimpl_get_settings()
config.read_write()
props = []
try:
config.u1
except PropertiesOptionError as err:
props = err.proptype
assert props == ['disabled']
props = []
try:
config.u2
except PropertiesOptionError as err:
props = err.proptype
assert props == ['disabled']
setting.setpermissive(('disabled',), u1)
props = []
try:
config.u1
except PropertiesOptionError as err:
props = err.proptype
assert props == []
props = []
try:
config.u2
except PropertiesOptionError as err:
props = err.proptype
assert props == ['disabled']
setting.append('permissive')
config.u1
props = []
try:
config.u2
except PropertiesOptionError as err:
props = err.proptype
assert props == ['disabled']
setting.remove('permissive')
props = []
try:
config.u1
except PropertiesOptionError as err:
props = err.proptype
assert props == []
props = []
try:
config.u2
except PropertiesOptionError as err:
props = err.proptype
assert props == ['disabled']
def test_permissive_option_mandatory():
descr = make_description()
u1 = descr.u1
config = Config(descr)
setting = config.cfgimpl_get_settings()
config.read_only()
props = []
try:
config.u1
except PropertiesOptionError as err:
props = err.proptype
assert set(props) == set(['disabled', 'mandatory'])
setting.setpermissive(('mandatory', 'disabled',), u1)
setting.append('permissive')
config.u1
setting.remove('permissive')
try:
config.u1
except PropertiesOptionError as err:
props = err.proptype
assert set(props) == set(['disabled', 'mandatory'])
def test_permissive_option_frozen():
descr = make_description()
config = Config(descr)
u1 = descr.u1
setting = config.cfgimpl_get_settings()
config.read_write()
setting.setpermissive(('frozen', 'disabled'), u1)
config.u1 = 1
assert config.u1 == 1
setting.append('permissive')
assert config.u1 == 1
setting.remove('permissive')
assert config.u1 == 1
def test_invalid_option_permissive():
descr = make_description()
u1 = descr.u1
config = Config(descr)
setting = config.cfgimpl_get_settings()
config.read_write()
raises(TypeError, "setting.setpermissive(['frozen', 'disabled',], u1)")

View File

@ -26,6 +26,20 @@ def test_requires():
assert props == ['disabled']
def test_requires_invalid():
a = BoolOption('activate_service', '', True)
raises(ValueError, "IPOption('ip_address_service', '', requires='string')")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'unknown': True}])")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False}])")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'action': 'disabled'}])")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'expected': False, 'action': 'disabled'}])")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'inverse': 'string'}])")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'transitive': 'string'}])")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': False, 'action': 'disabled', 'same_action': 'string'}])")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': 'string', 'expected': False, 'action': 'disabled'}])")
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': 'string', 'action': 'disabled'}])")
def test_requires_same_action():
a = BoolOption('activate_service', '', True)
b = BoolOption('activate_service_web', '', True,
@ -504,6 +518,11 @@ def test_requires_requirement_append():
c.cfgimpl_get_settings()[b].append("test")
def test_requires_different_inverse():
a = BoolOption('activate_service', '', True)
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}, {'option': a, 'expected': True, 'action': 'disabled', 'inverse': False}])")
def test_requires_recursive_path():
a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '',

View File

@ -3,9 +3,10 @@ import autopath
from py.test import raises
from tiramisu.config import Config, SubConfig
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption, \
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption,\
StrOption, SymLinkOption, UnicodeOption, IPOption, OptionDescription, \
PortOption, NetworkOption, NetmaskOption, DomainnameOption
PortOption, NetworkOption, NetmaskOption, DomainnameOption, EmailOption, \
URLOption, FilenameOption
def test_slots_option():
@ -35,6 +36,12 @@ def test_slots_option():
raises(AttributeError, "c.x = 1")
c = DomainnameOption('a', '')
raises(AttributeError, "c.x = 1")
c = EmailOption('a', '')
raises(AttributeError, "c.x = 1")
c = URLOption('a', '')
raises(AttributeError, "c.x = 1")
c = FilenameOption('a', '')
raises(AttributeError, "c.x = 1")
def test_slots_option_readonly():
@ -49,7 +56,10 @@ def test_slots_option_readonly():
j = NetworkOption('j', '')
k = NetmaskOption('k', '')
l = DomainnameOption('l', '')
m = OptionDescription('m', '', [a, b, c, d, e, g, h, i, j, k, l])
o = EmailOption('o', '')
p = URLOption('p', '')
q = FilenameOption('q', '')
m = OptionDescription('m', '', [a, b, c, d, e, g, h, i, j, k, l, o, p, q])
a._requires = 'a'
b._requires = 'b'
c._requires = 'c'
@ -62,6 +72,9 @@ def test_slots_option_readonly():
k._requires = 'k'
l._requires = 'l'
m._requires = 'm'
o._requires = 'o'
p._requires = 'p'
q._requires = 'q'
Config(m)
raises(AttributeError, "a._requires = 'a'")
raises(AttributeError, "b._requires = 'b'")
@ -75,6 +88,9 @@ def test_slots_option_readonly():
raises(AttributeError, "k._requires = 'k'")
raises(AttributeError, "l._requires = 'l'")
raises(AttributeError, "m._requires = 'm'")
raises(AttributeError, "o._requires = 'o'")
raises(AttributeError, "p._requires = 'p'")
raises(AttributeError, "q._requires = 'q'")
def test_slots_option_readonly_name():
@ -90,7 +106,10 @@ def test_slots_option_readonly_name():
j = NetworkOption('j', '')
k = NetmaskOption('k', '')
l = DomainnameOption('l', '')
m = OptionDescription('m', '', [a, b, c, d, e, f, g, h, i, j, k, l])
o = DomainnameOption('o', '')
p = DomainnameOption('p', '')
q = DomainnameOption('q', '')
m = OptionDescription('m', '', [a, b, c, d, e, f, g, h, i, j, k, l, o, p, q])
raises(AttributeError, "a._name = 'a'")
raises(AttributeError, "b._name = 'b'")
raises(AttributeError, "c._name = 'c'")
@ -104,6 +123,9 @@ def test_slots_option_readonly_name():
raises(AttributeError, "k._name = 'k'")
raises(AttributeError, "l._name = 'l'")
raises(AttributeError, "m._name = 'm'")
raises(AttributeError, "o._name = 'o'")
raises(AttributeError, "p._name = 'p'")
raises(AttributeError, "q._name = 'q'")
def test_slots_description():

View File

@ -318,3 +318,46 @@ def test_state_groupconfig():
delete_session('29090937')
except ConfigError:
pass
def test_state_unkown_setting_owner():
"""load an unknow _owner, should create it"""
assert not 'supernewuser' in owners.__dict__
loads("""ccopy_reg
_reconstructor
p0
(ctiramisu.setting
Settings
p1
c__builtin__
object
p2
Ntp3
Rp4
(dp5
S'_owner'
p6
S'supernewuser'
p7
sS'_p_'
p8
g0
(ctiramisu.storage.dictionary.setting
Settings
p9
g2
Ntp10
Rp11
(dp12
S'_cache'
p13
(dp14
sS'_permissives'
p15
(dp16
sS'_properties'
p17
(dp18
sbsb.
.""")
assert 'supernewuser' in owners.__dict__