Merge branch 'master' into lgpl
This commit is contained in:
commit
a04a61f1a4
@ -10,8 +10,6 @@ Tiramisu is made of almost three main objects :
|
||||
- :class:`tiramisu.option.OptionDescription` is the shema, the option's structure
|
||||
- :class:`tiramisu.config.Config` which is the whole configuration entry point
|
||||
|
||||
.. image:: config.png
|
||||
|
||||
Accessing the `Option`'s
|
||||
-------------------------
|
||||
|
||||
@ -47,9 +45,13 @@ object is returned, and if no `Option` has been declared in the
|
||||
|
||||
The `Option` objects (in this case the :class:`~tiramisu.option.BoolOption`),
|
||||
are organized into a tree into nested
|
||||
:class:`~tiramisu.option.OptionDescription` objects. Every option has a name,
|
||||
as does every option group. The parts of the full name of the option are
|
||||
separated by dots: e.g. ``cfg.optgroup.optname``.
|
||||
:class:`~tiramisu.option.OptionDescription` objects.
|
||||
|
||||
.. image:: config.png
|
||||
|
||||
Every option has a name, as does every option group. The parts
|
||||
of the full name of the option are separated by dots: e.g.
|
||||
``cfg.optgroup.optname``.
|
||||
|
||||
Let's make the protocol of accessing a `Config`'s attribute explicit
|
||||
(because explicit is better than implicit):
|
||||
@ -362,6 +364,10 @@ read/write or read only mode::
|
||||
>>> c.cfgimpl_get_settings().remove('unknown')
|
||||
>>> print c.od1.var3
|
||||
value
|
||||
|
||||
Many properties can be defined at the same time on an option::
|
||||
|
||||
>>> c.cfgimpl_get_settings().extend(['unknown1', 'unknown2'])
|
||||
|
||||
Properties can also be defined on an option group (that is, on an
|
||||
:term:`option description`) let's hide a group and try to access to it::
|
||||
|
@ -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()")
|
||||
|
@ -6,10 +6,11 @@
|
||||
import autopath
|
||||
from py.test import raises
|
||||
|
||||
from tiramisu.config import Config
|
||||
from tiramisu.config import Config, SubConfig
|
||||
from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \
|
||||
BoolOption, UnicodeOption, OptionDescription
|
||||
from tiramisu.error import ConflictError
|
||||
from tiramisu.error import ConflictError, ConfigError
|
||||
import weakref
|
||||
|
||||
|
||||
def make_description():
|
||||
@ -131,8 +132,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 +145,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 +153,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 +166,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 +238,83 @@ 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()')
|
||||
|
||||
|
||||
def test_config_weakref():
|
||||
o = OptionDescription('val', '', [])
|
||||
o2 = OptionDescription('val', '', [o])
|
||||
c = Config(o2)
|
||||
SubConfig(o, weakref.ref(c))
|
||||
raises(ValueError, "SubConfig(o, c)")
|
||||
s = SubConfig(o, weakref.ref(c))
|
||||
assert s._cfgimpl_get_context() == c
|
||||
del(c)
|
||||
raises(ConfigError, "s._cfgimpl_get_context()")
|
||||
|
||||
|
||||
def test_config_str():
|
||||
gcdummy = BoolOption('dummy', 'dummy', default=False)
|
||||
gcdummy1 = BoolOption('dummy1', 'dummy', default=False, properties=('disabled',))
|
||||
o = OptionDescription('o', '', [gcdummy, gcdummy1])
|
||||
descr = OptionDescription('tiramisu', '', [o])
|
||||
cfg = Config(descr)
|
||||
cfg.read_only()
|
||||
str(cfg)
|
||||
str(cfg.o)
|
||||
|
@ -4,26 +4,34 @@ from py.test import raises
|
||||
|
||||
from tiramisu.config import Config
|
||||
from tiramisu.option import IntOption, FloatOption, StrOption, ChoiceOption, \
|
||||
BoolOption, OptionDescription
|
||||
BoolOption, FilenameOption, UnicodeOption, SymLinkOption, IPOption, \
|
||||
PortOption, NetworkOption, NetmaskOption, BroadcastOption, \
|
||||
DomainnameOption, OptionDescription
|
||||
from tiramisu.error import PropertiesOptionError
|
||||
|
||||
|
||||
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
|
||||
|
||||
|
||||
@ -62,6 +70,17 @@ def test_iter_config():
|
||||
[('string', 'string'), ('string2', 'string2')]
|
||||
|
||||
|
||||
def test_iter_config_property():
|
||||
"iteration on config object"
|
||||
s = StrOption("string", "", default="string", properties=('disabled',))
|
||||
s2 = StrOption("string2", "", default="string2")
|
||||
descr = OptionDescription("options", "", [s, s2])
|
||||
config = Config(descr)
|
||||
config.read_only()
|
||||
assert [(name, value) for name, value in config] == \
|
||||
[('string2', 'string2')]
|
||||
|
||||
|
||||
def test_iter_subconfig():
|
||||
"iteration on config sub object"
|
||||
descr = make_description()
|
||||
@ -96,24 +115,57 @@ def test_make_dict():
|
||||
raises(ValueError, 'd2 = config.make_dict(withvalue="3")')
|
||||
|
||||
|
||||
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():
|
||||
"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')")
|
||||
raises(ValueError, "conf.find(byname='bool', type_='unknown')")
|
||||
|
||||
|
||||
def test_find_multi():
|
||||
@ -137,3 +189,81 @@ 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'")
|
||||
|
||||
|
||||
def test_iter_all():
|
||||
s = StrOption("string", "", default="string")
|
||||
s2 = StrOption("string2", "", default="string2")
|
||||
descr = OptionDescription("options", "", [s, s2])
|
||||
config = Config(descr)
|
||||
assert list(config.iter_all()) == [('string', 'string'), ('string2', 'string2')]
|
||||
for i in config.iter_all():
|
||||
#test StopIteration
|
||||
break
|
||||
|
||||
|
||||
def test_iter_all_prop():
|
||||
s = StrOption("string", "", default="string", properties=('disabled',))
|
||||
s2 = StrOption("string2", "", default="string2")
|
||||
descr = OptionDescription("options", "", [s, s2])
|
||||
config = Config(descr)
|
||||
config.read_only()
|
||||
assert list(config.iter_all()) == [('string2', 'string2')]
|
||||
|
||||
|
||||
def test_impl_getpaths():
|
||||
s = StrOption("string", "", default="string", properties=('disabled',))
|
||||
s2 = StrOption("string2", "", default="string2")
|
||||
s3 = StrOption("string3", "", default="string3")
|
||||
s4 = StrOption("string4", "", default="string4", properties=('hidden',))
|
||||
od = OptionDescription('od', '', [s3, s4])
|
||||
descr = OptionDescription("options", "", [s, s2, od])
|
||||
config = Config(descr)
|
||||
assert ['string', 'string2', 'od.string3', 'od.string4'] == config.cfgimpl_get_description().impl_getpaths()
|
||||
assert ['string', 'string2', 'od', 'od.string3', 'od.string4'] == config.cfgimpl_get_description().impl_getpaths(include_groups=True)
|
||||
config.read_write()
|
||||
raises(PropertiesOptionError, "config.od.string4")
|
||||
assert ['string', 'string2', 'od.string3', 'od.string4'] == config.cfgimpl_get_description().impl_getpaths()
|
||||
assert ['string', 'string2', 'od', 'od.string3', 'od.string4'] == config.cfgimpl_get_description().impl_getpaths(include_groups=True)
|
||||
|
||||
|
||||
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)")
|
||||
raises(ValueError, "PortOption('a', '', allow_zero=True, allow_wellknown=False, allow_registred=True, allow_private=False)")
|
||||
raises(ValueError, "PortOption('a', '', allow_zero=True, allow_wellknown=True, allow_registred=False, allow_private=True)")
|
||||
raises(ValueError, "PortOption('a', '', allow_zero=True, allow_wellknown=False, allow_registred=False, allow_private=True)")
|
||||
raises(ValueError, "PortOption('a', '', allow_zero=True, allow_wellknown=False, allow_registred=True, allow_private=True)")
|
||||
raises(ValueError, "PortOption('a', '', allow_zero=False, allow_wellknown=False, allow_registred=False, allow_private=False)")
|
||||
raises(ValueError, "NetworkOption('a', '', 'string')")
|
||||
raises(ValueError, "NetmaskOption('a', '', 'string')")
|
||||
raises(ValueError, "BroadcastOption('a', '', 'string')")
|
||||
raises(ValueError, "DomainnameOption('a', '', 'string')")
|
||||
raises(ValueError, "DomainnameOption('a', '', type_='string')")
|
||||
raises(ValueError, "DomainnameOption('a', '', allow_ip='string')")
|
||||
raises(ValueError, "DomainnameOption('a', '', allow_without_dot='string')")
|
||||
|
@ -2,23 +2,47 @@ 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)
|
||||
g = DomainnameOption('g', '', allow_ip=True)
|
||||
od = OptionDescription('a', '', [d, f, g])
|
||||
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 = '3toto.com'")
|
||||
c.d = 'toto.co3'
|
||||
raises(ValueError, "c.d = 'toto3.3la'")
|
||||
#raises(ValueError, "c.d = '3toto.com'")
|
||||
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'
|
||||
raises(ValueError, "c.f = 'domainnametoolongthathavemorethanmaximumsizeforatruedomainnameanditsnoteasytogeneratesolongdomainnamewithoutrepeatdomainnametoolongthathavemorethanmaximumsizeforatruedomainnameanditsnoteasytogeneratesolongdomainnamewithoutrepeatbutimnotabletodoitnowiendityeah'")
|
||||
raises(ValueError, "c.f = 'd'")
|
||||
#
|
||||
c.g = 'toto.com'
|
||||
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():
|
||||
@ -41,3 +65,35 @@ 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'")
|
||||
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'
|
||||
raises(ValueError, "c.u = 'https://foo.com:84438989'")
|
||||
|
@ -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')
|
||||
|
@ -2,8 +2,8 @@
|
||||
import autopath
|
||||
#from py.test import raises
|
||||
|
||||
from tiramisu.config import Config
|
||||
from tiramisu.option import BoolOption, OptionDescription
|
||||
from tiramisu.config import Config, GroupConfig, MetaConfig
|
||||
from tiramisu.option import BoolOption, IntOption, OptionDescription
|
||||
import weakref
|
||||
|
||||
|
||||
@ -109,3 +109,31 @@ def test_deref_optiondescription_config():
|
||||
assert w() is not None
|
||||
del(c)
|
||||
assert w() is None
|
||||
|
||||
|
||||
def test_deref_groupconfig():
|
||||
i1 = IntOption('i1', '')
|
||||
od1 = OptionDescription('od1', '', [i1])
|
||||
od2 = OptionDescription('od2', '', [od1])
|
||||
conf1 = Config(od2)
|
||||
conf2 = Config(od2)
|
||||
meta = GroupConfig([conf1, conf2])
|
||||
w = weakref.ref(conf1)
|
||||
del(conf1)
|
||||
assert w() is not None
|
||||
del(meta)
|
||||
assert w() is None
|
||||
|
||||
|
||||
def test_deref_metaconfig():
|
||||
i1 = IntOption('i1', '')
|
||||
od1 = OptionDescription('od1', '', [i1])
|
||||
od2 = OptionDescription('od2', '', [od1])
|
||||
conf1 = Config(od2)
|
||||
conf2 = Config(od2)
|
||||
meta = MetaConfig([conf1, conf2])
|
||||
w = weakref.ref(conf1)
|
||||
del(conf1)
|
||||
assert w() is not None
|
||||
del(meta)
|
||||
assert w() is None
|
||||
|
@ -1,7 +1,7 @@
|
||||
import autopath
|
||||
|
||||
#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
|
||||
|
||||
@ -205,11 +205,11 @@ 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 list(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 list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
|
||||
|
||||
|
||||
def test_mandatory_warnings_rw():
|
||||
@ -218,9 +218,9 @@ def test_mandatory_warnings_rw():
|
||||
config.str = ''
|
||||
config.read_write()
|
||||
config.str
|
||||
assert list(mandatory_warnings(config)) == ['str', 'str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3']
|
||||
config.str = 'a'
|
||||
assert list(mandatory_warnings(config)) == ['str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
|
||||
|
||||
|
||||
def test_mandatory_warnings_disabled():
|
||||
@ -230,9 +230,9 @@ 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 list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3']
|
||||
setting[descr.str].append('disabled')
|
||||
assert list(mandatory_warnings(config)) == ['str1', 'unicode2', 'str3']
|
||||
assert list(config.cfgimpl_get_values().mandatory_warnings()) == ['str1', 'unicode2', 'str3']
|
||||
|
||||
|
||||
def test_mandatory_warnings_frozen():
|
||||
@ -242,7 +242,7 @@ 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 list(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 list(config.cfgimpl_get_values().mandatory_warnings()) == ['str', 'str1', 'unicode2', 'str3']
|
||||
|
@ -1,172 +1,203 @@
|
||||
#import autopath
|
||||
import autopath
|
||||
|
||||
#from py.test import raises
|
||||
from py.test import raises
|
||||
|
||||
#from tiramisu.setting import owners
|
||||
#from tiramisu.config import Config, MetaConfig
|
||||
#from tiramisu.option import IntOption, OptionDescription
|
||||
#from tiramisu.error import ConfigError
|
||||
from tiramisu.setting import owners
|
||||
from tiramisu.config import Config, GroupConfig, MetaConfig
|
||||
from tiramisu.option import IntOption, OptionDescription
|
||||
from tiramisu.error import ConfigError, PropertiesOptionError
|
||||
|
||||
#owners.addowner('meta')
|
||||
owners.addowner('meta')
|
||||
|
||||
|
||||
#def make_description():
|
||||
# i1 = IntOption('i1', '')
|
||||
# i2 = IntOption('i2', '', default=1)
|
||||
# i3 = IntOption('i3', '')
|
||||
# i4 = IntOption('i4', '', default=2)
|
||||
# od1 = OptionDescription('od1', '', [i1, i2, i3, i4])
|
||||
# od2 = OptionDescription('od2', '', [od1])
|
||||
# conf1 = Config(od2)
|
||||
# conf2 = Config(od2)
|
||||
# meta = MetaConfig([conf1, conf2])
|
||||
# meta.cfgimpl_get_settings().setowner(owners.meta)
|
||||
# return meta
|
||||
def make_description():
|
||||
i1 = IntOption('i1', '')
|
||||
i2 = IntOption('i2', '', default=1)
|
||||
i3 = IntOption('i3', '')
|
||||
i4 = IntOption('i4', '', default=2)
|
||||
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])
|
||||
conf1 = Config(od2)
|
||||
conf2 = Config(od2)
|
||||
conf1.read_write()
|
||||
conf2.read_write()
|
||||
meta = MetaConfig([conf1, conf2])
|
||||
meta.cfgimpl_get_settings().setowner(owners.meta)
|
||||
return meta
|
||||
|
||||
|
||||
##FIXME ne pas mettre 2 meta dans une config
|
||||
##FIXME ne pas mettre 2 OD differents dans un meta
|
||||
#def test_none():
|
||||
# meta = make_description()
|
||||
# conf1, conf2 = meta._impl_children
|
||||
# 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
|
||||
# meta.od1.i3 = 3
|
||||
# assert conf1.od1.i3 == conf2.od1.i3 == 3
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.meta
|
||||
# meta.od1.i3 = 3
|
||||
# conf1.od1.i3 = 2
|
||||
# assert conf1.od1.i3 == 2
|
||||
# assert conf2.od1.i3 == 3
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is owners.user
|
||||
# assert conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.meta
|
||||
# meta.od1.i3 = 4
|
||||
# assert conf1.od1.i3 == 2
|
||||
# assert conf2.od1.i3 == 4
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is owners.user
|
||||
# assert conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.meta
|
||||
# del(meta.od1.i3)
|
||||
# assert conf1.od1.i3 == 2
|
||||
# assert conf2.od1.i3 is None
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is owners.user
|
||||
# assert conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.default
|
||||
# del(conf1.od1.i3)
|
||||
# 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
|
||||
#FIXME ne pas mettre 2 meta dans une config
|
||||
#FIXME ne pas mettre 2 OD differents dans un meta
|
||||
#FIXME serialization
|
||||
def test_none():
|
||||
meta = make_description()
|
||||
conf1, conf2 = meta.cfgimpl_get_children()
|
||||
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
|
||||
meta.od1.i3 = 3
|
||||
assert conf1.od1.i3 == conf2.od1.i3 == 3
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.meta
|
||||
meta.od1.i3 = 3
|
||||
conf1.od1.i3 = 2
|
||||
assert conf1.od1.i3 == 2
|
||||
assert conf2.od1.i3 == 3
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is owners.user
|
||||
assert conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.meta
|
||||
meta.od1.i3 = 4
|
||||
assert conf1.od1.i3 == 2
|
||||
assert conf2.od1.i3 == 4
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is owners.user
|
||||
assert conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.meta
|
||||
del(meta.od1.i3)
|
||||
assert conf1.od1.i3 == 2
|
||||
assert conf2.od1.i3 is None
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i3')) is owners.user
|
||||
assert conf2.getowner(conf2.unwrap_from_path('od1.i3')) is owners.default
|
||||
del(conf1.od1.i3)
|
||||
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
|
||||
|
||||
|
||||
#def test_default():
|
||||
# meta = make_description()
|
||||
# conf1, conf2 = meta._impl_children
|
||||
# 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
|
||||
# meta.od1.i2 = 3
|
||||
# assert conf1.od1.i2 == conf2.od1.i2 == 3
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
# meta.od1.i2 = 3
|
||||
# conf1.od1.i2 = 2
|
||||
# assert conf1.od1.i2 == 2
|
||||
# assert conf2.od1.i2 == 3
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
|
||||
# assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
# meta.od1.i2 = 4
|
||||
# assert conf1.od1.i2 == 2
|
||||
# assert conf2.od1.i2 == 4
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
|
||||
# assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
# del(meta.od1.i2)
|
||||
# assert conf1.od1.i2 == 2
|
||||
# assert conf2.od1.i2 == 1
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
|
||||
# assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
|
||||
# del(conf1.od1.i2)
|
||||
# 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
|
||||
def test_default():
|
||||
meta = make_description()
|
||||
conf1, conf2 = meta.cfgimpl_get_children()
|
||||
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
|
||||
meta.od1.i2 = 3
|
||||
assert conf1.od1.i2 == conf2.od1.i2 == 3
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
meta.od1.i2 = 3
|
||||
conf1.od1.i2 = 2
|
||||
assert conf1.od1.i2 == 2
|
||||
assert conf2.od1.i2 == 3
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
|
||||
assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
meta.od1.i2 = 4
|
||||
assert conf1.od1.i2 == 2
|
||||
assert conf2.od1.i2 == 4
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
|
||||
assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
del(meta.od1.i2)
|
||||
assert conf1.od1.i2 == 2
|
||||
assert conf2.od1.i2 == 1
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
|
||||
assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
|
||||
del(conf1.od1.i2)
|
||||
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
|
||||
|
||||
|
||||
#def test_contexts():
|
||||
# meta = make_description()
|
||||
# conf1, conf2 = meta._impl_children
|
||||
# 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
|
||||
# meta.set_contexts('od1.i2', 6)
|
||||
# assert meta.od1.i2 == 1
|
||||
# assert conf1.od1.i2 == conf2.od1.i2 == 6
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.user
|
||||
def test_contexts():
|
||||
meta = make_description()
|
||||
conf1, conf2 = meta.cfgimpl_get_children()
|
||||
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
|
||||
meta.setattrs('od1.i2', 6)
|
||||
assert meta.od1.i2 == 1
|
||||
assert conf1.od1.i2 == conf2.od1.i2 == 6
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.user
|
||||
|
||||
|
||||
#def test_find():
|
||||
# meta = make_description()
|
||||
# i2 = meta.unwrap_from_path('od1.i2')
|
||||
# assert [i2] == meta.find(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}
|
||||
def test_find():
|
||||
meta = make_description()
|
||||
i2 = meta.unwrap_from_path('od1.i2')
|
||||
assert [i2] == meta.find(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, 'od1.i5': [2], 'od1.i6': None}
|
||||
|
||||
|
||||
#def test_meta_meta():
|
||||
# meta1 = make_description()
|
||||
# meta2 = MetaConfig([meta1])
|
||||
# meta2.cfgimpl_get_settings().setowner(owners.meta)
|
||||
# conf1, conf2 = meta1._impl_children
|
||||
# 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
|
||||
# meta2.od1.i2 = 3
|
||||
# assert conf1.od1.i2 == conf2.od1.i2 == 3
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
# meta2.od1.i2 = 3
|
||||
# conf1.od1.i2 = 2
|
||||
# assert conf1.od1.i2 == 2
|
||||
# assert conf2.od1.i2 == 3
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
|
||||
# assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
# meta2.od1.i2 = 4
|
||||
# assert conf1.od1.i2 == 2
|
||||
# assert conf2.od1.i2 == 4
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
|
||||
# assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
# del(meta2.od1.i2)
|
||||
# assert conf1.od1.i2 == 2
|
||||
# assert conf2.od1.i2 == 1
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
|
||||
# assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
|
||||
# del(conf1.od1.i2)
|
||||
# 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
|
||||
# meta1.od1.i2 = 6
|
||||
# assert conf1.od1.i2 == conf2.od1.i2 == 6
|
||||
# assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
def test_meta_meta():
|
||||
meta1 = make_description()
|
||||
meta2 = MetaConfig([meta1])
|
||||
meta2.cfgimpl_get_settings().setowner(owners.meta)
|
||||
conf1, conf2 = meta1.cfgimpl_get_children()
|
||||
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
|
||||
meta2.od1.i2 = 3
|
||||
assert conf1.od1.i2 == conf2.od1.i2 == 3
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
meta2.od1.i2 = 3
|
||||
conf1.od1.i2 = 2
|
||||
assert conf1.od1.i2 == 2
|
||||
assert conf2.od1.i2 == 3
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
|
||||
assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
meta2.od1.i2 = 4
|
||||
assert conf1.od1.i2 == 2
|
||||
assert conf2.od1.i2 == 4
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
|
||||
assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
del(meta2.od1.i2)
|
||||
assert conf1.od1.i2 == 2
|
||||
assert conf2.od1.i2 == 1
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is owners.user
|
||||
assert conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.default
|
||||
del(conf1.od1.i2)
|
||||
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
|
||||
meta1.od1.i2 = 6
|
||||
assert conf1.od1.i2 == conf2.od1.i2 == 6
|
||||
assert conf1.getowner(conf1.unwrap_from_path('od1.i2')) is conf2.getowner(conf2.unwrap_from_path('od1.i2')) is owners.meta
|
||||
|
||||
|
||||
#def test_meta_meta_set():
|
||||
# meta1 = make_description()
|
||||
# meta2 = MetaConfig([meta1])
|
||||
# meta2.cfgimpl_get_settings().setowner(owners.meta)
|
||||
# conf1, conf2 = meta1._impl_children
|
||||
# meta2.set_contexts('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, conf2] == meta2.find_first_contexts(byname='i1', byvalue=7)
|
||||
# conf1.od1.i1 = 8
|
||||
# assert [conf2] == meta2.find_first_contexts(byname='i1', byvalue=7)
|
||||
# assert [conf1] == meta2.find_first_contexts(byname='i1', byvalue=8)
|
||||
# raises(AttributeError, "meta2.find_first_contexts(byname='i1', byvalue=10)")
|
||||
def test_meta_meta_set():
|
||||
meta1 = make_description()
|
||||
meta2 = MetaConfig([meta1])
|
||||
meta2.cfgimpl_get_settings().setowner(owners.meta)
|
||||
conf1, conf2 = meta1.cfgimpl_get_children()
|
||||
meta2.setattrs('od1.i1', 7)
|
||||
#PropertiesOptionError
|
||||
meta2.setattrs('od1.i6', 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, conf2] == meta2.find_firsts(byname='i1', byvalue=7)
|
||||
conf1.od1.i1 = 8
|
||||
assert [conf1, conf2] == meta2.find_firsts(byname='i1')
|
||||
assert [conf2] == meta2.find_firsts(byname='i1', byvalue=7)
|
||||
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='not', byvalue=10)")
|
||||
raises(AttributeError, "meta2.find_firsts(byname='i6')")
|
||||
|
||||
|
||||
#def test_not_meta():
|
||||
# i1 = IntOption('i1', '')
|
||||
# od1 = OptionDescription('od1', '', [i1])
|
||||
# od2 = OptionDescription('od2', '', [od1])
|
||||
# conf1 = Config(od2)
|
||||
# conf2 = Config(od2)
|
||||
# meta = MetaConfig([conf1, conf2], False)
|
||||
# raises(ConfigError, 'meta.od1.i1')
|
||||
# conf1, conf2 = meta._impl_children
|
||||
# meta.set_contexts('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
|
||||
def test_not_meta():
|
||||
i1 = IntOption('i1', '')
|
||||
od1 = OptionDescription('od1', '', [i1])
|
||||
od2 = OptionDescription('od2', '', [od1])
|
||||
conf1 = Config(od2)
|
||||
conf2 = Config(od2)
|
||||
raises(ValueError, "GroupConfig(conf1)")
|
||||
meta = GroupConfig([conf1, conf2])
|
||||
raises(ConfigError, 'meta.od1.i1')
|
||||
conf1, conf2 = meta.cfgimpl_get_children()
|
||||
meta.setattrs('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
|
||||
|
||||
|
||||
#def test_meta_path():
|
||||
# meta = make_description()
|
||||
# assert meta._impl_path is None
|
||||
# assert meta.od1._impl_path == 'od1'
|
||||
def test_meta_path():
|
||||
meta = make_description()
|
||||
assert meta._impl_path is None
|
||||
assert meta.od1._impl_path == 'od1'
|
||||
|
||||
|
||||
def test_meta_unconsistent():
|
||||
i1 = IntOption('i1', '')
|
||||
i2 = IntOption('i2', '', default=1)
|
||||
i3 = IntOption('i3', '')
|
||||
i4 = IntOption('i4', '', default=2)
|
||||
od1 = OptionDescription('od1', '', [i1, i2, i3, i4])
|
||||
od2 = OptionDescription('od2', '', [od1])
|
||||
conf1 = Config(od2)
|
||||
conf2 = Config(od2)
|
||||
conf3 = Config(od2)
|
||||
conf4 = Config(od1)
|
||||
meta = MetaConfig([conf1, conf2])
|
||||
meta.cfgimpl_get_settings().setowner(owners.meta)
|
||||
raises(TypeError, 'MetaConfig("string")')
|
||||
raises(ValueError, "MetaConfig([conf1, conf3])")
|
||||
raises(ValueError, "MetaConfig([conf3, conf4])")
|
||||
|
21
test/test_multi.py
Normal file
21
test/test_multi.py
Normal 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()")
|
@ -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
|
||||
|
@ -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']
|
||||
|
@ -5,7 +5,32 @@ 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():
|
||||
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_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():
|
||||
@ -158,6 +183,41 @@ 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', '')
|
||||
c = NetmaskOption('c', '')
|
||||
od = OptionDescription('od', '', [a, b, c])
|
||||
c.impl_add_consistency('ip_netmask', a, b)
|
||||
c = Config(od)
|
||||
c.a = '192.168.1.1'
|
||||
c.b = '192.168.1.0'
|
||||
raises(ConfigError, "c.c = '255.255.255.0'")
|
||||
|
||||
|
||||
def test_consistency_ip_netmask_error_multi():
|
||||
a = IPOption('a', '', multi=True)
|
||||
b = NetmaskOption('b', '')
|
||||
@ -206,6 +266,8 @@ def test_consistency_ip_netmask_multi_master():
|
||||
c.b = ['255.255.255.255']
|
||||
c.b = ['255.255.255.0']
|
||||
raises(ValueError, "c.a = ['192.168.1.0']")
|
||||
c.a = ['192.168.1.128']
|
||||
raises(ValueError, "c.b = ['255.255.255.128']")
|
||||
c.a = ['192.168.1.2', '192.168.1.3']
|
||||
|
||||
|
||||
@ -249,6 +311,20 @@ def test_consistency_broadcast():
|
||||
c.c[1] = '192.168.2.255'
|
||||
|
||||
|
||||
def test_consistency_broadcast_error():
|
||||
a = NetworkOption('a', '', multi=True)
|
||||
b = NetmaskOption('b', '', multi=True)
|
||||
c = BroadcastOption('c', '', multi=True)
|
||||
od = OptionDescription('a', '', [a, b, c])
|
||||
od.impl_set_group_type(groups.master)
|
||||
b.impl_add_consistency('network_netmask', a)
|
||||
c.impl_add_consistency('broadcast', a)
|
||||
c = Config(od)
|
||||
c.a = ['192.168.1.0']
|
||||
c.b = ['255.255.255.0']
|
||||
raises(ConfigError, "c.c = ['192.168.1.255']")
|
||||
|
||||
|
||||
def test_consistency_broadcast_default():
|
||||
a = NetworkOption('a', '', '192.168.1.0')
|
||||
b = NetmaskOption('b', '', '255.255.255.128')
|
||||
@ -272,3 +348,28 @@ def test_consistency_not_all():
|
||||
c.a = ['192.168.1.0']
|
||||
c.b = ['255.255.255.0']
|
||||
c.c = ['192.168.1.255']
|
||||
|
||||
|
||||
def test_consistency_permissive():
|
||||
a = IntOption('a', '', 1)
|
||||
b = IntOption('b', '', 2, properties=('hidden',))
|
||||
od = OptionDescription('od', '', [a, b])
|
||||
a.impl_add_consistency('not_equal', b)
|
||||
c = Config(od)
|
||||
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
|
||||
|
@ -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():
|
||||
@ -36,6 +36,7 @@ def test_default_owner():
|
||||
cfg = Config(descr)
|
||||
assert cfg.dummy is False
|
||||
assert cfg.getowner(gcdummy) == 'default'
|
||||
raises(TypeError, "cfg.getowner('gcdummy')")
|
||||
cfg.dummy = True
|
||||
assert cfg.getowner(gcdummy) == owners.user
|
||||
|
||||
@ -52,6 +53,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])
|
||||
|
@ -310,6 +310,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)
|
||||
@ -367,3 +376,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']"
|
||||
|
@ -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()
|
||||
|
25
test/test_option_username.py
Normal file
25
test/test_option_username.py
Normal 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$')")
|
@ -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) == _("warning on the value of the 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) == _("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:
|
||||
@ -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) == _("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 val1 for option 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():
|
||||
@ -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) == _("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 val for option 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 val for option 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 val for option 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 val for option ip_admin_eth0: error'
|
||||
assert str(w[0].message) == _("warning on the value of the option {0}: {1}").format('ip_admin_eth0', 'error')
|
||||
|
@ -94,6 +94,19 @@ def test_iter_on_groups():
|
||||
result = list(config.creole.iter_groups(group_type=groups.family))
|
||||
group_names = [res[0] for res in result]
|
||||
assert group_names == ['general', 'interface1']
|
||||
for i in config.creole.iter_groups(group_type=groups.family):
|
||||
#test StopIteration
|
||||
break
|
||||
|
||||
|
||||
def test_iter_on_groups_props():
|
||||
descr = make_description()
|
||||
config = Config(descr)
|
||||
config.read_write()
|
||||
config.cfgimpl_get_settings()[descr.creole.interface1].append('disabled')
|
||||
result = list(config.creole.iter_groups(group_type=groups.family))
|
||||
group_names = [res[0] for res in result]
|
||||
assert group_names == ['general']
|
||||
|
||||
|
||||
def test_iter_on_empty_group():
|
||||
|
@ -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)")
|
||||
|
@ -24,6 +24,42 @@ def test_requires():
|
||||
except PropertiesOptionError as err:
|
||||
props = err.proptype
|
||||
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():
|
||||
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():
|
||||
@ -504,6 +540,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', '',
|
||||
|
@ -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():
|
||||
|
@ -1,10 +1,13 @@
|
||||
import autopath
|
||||
|
||||
from tiramisu.option import BoolOption, UnicodeOption, SymLinkOption, \
|
||||
OptionDescription
|
||||
from tiramisu.config import Config
|
||||
IntOption, OptionDescription
|
||||
from tiramisu.config import Config, GroupConfig, MetaConfig
|
||||
from tiramisu.setting import owners
|
||||
from tiramisu.storage import delete_session
|
||||
from tiramisu.error import ConfigError
|
||||
from pickle import dumps, loads
|
||||
from py.test import raises
|
||||
|
||||
|
||||
def return_value(value=None):
|
||||
@ -90,10 +93,48 @@ def _diff_opt(opt1, opt2):
|
||||
assert val1 == val2
|
||||
|
||||
|
||||
def _diff_conf(cfg1, cfg2):
|
||||
attr1 = set(_get_slots(cfg1))
|
||||
attr2 = set(_get_slots(cfg2))
|
||||
diff1 = attr1 - attr2
|
||||
diff2 = attr2 - attr1
|
||||
if diff1 != set():
|
||||
raise Exception('more attribute in cfg1 {0}'.format(list(diff1)))
|
||||
if diff2 != set():
|
||||
raise Exception('more attribute in cfg2 {0}'.format(list(diff2)))
|
||||
for attr in attr1:
|
||||
if attr in ('_impl_context', '__weakref__'):
|
||||
continue
|
||||
err1 = False
|
||||
err2 = False
|
||||
val1 = None
|
||||
val2 = None
|
||||
try:
|
||||
val1 = getattr(cfg1, attr)
|
||||
except:
|
||||
err1 = True
|
||||
|
||||
try:
|
||||
val2 = getattr(cfg2, attr)
|
||||
except:
|
||||
err2 = True
|
||||
assert err1 == err2
|
||||
if val1 is None:
|
||||
assert val1 == val2
|
||||
elif attr == '_impl_values':
|
||||
assert cfg1.cfgimpl_get_values().get_modified_values() == cfg2.cfgimpl_get_values().get_modified_values()
|
||||
elif attr == '_impl_settings':
|
||||
assert cfg1.cfgimpl_get_settings().get_modified_properties() == cfg2.cfgimpl_get_settings().get_modified_properties()
|
||||
assert cfg1.cfgimpl_get_settings().get_modified_permissives() == cfg2.cfgimpl_get_settings().get_modified_permissives()
|
||||
elif attr == '_impl_descr':
|
||||
_diff_opt(cfg1.cfgimpl_get_description(), cfg2.cfgimpl_get_description())
|
||||
else:
|
||||
assert val1 == val2
|
||||
|
||||
|
||||
def test_diff_opt():
|
||||
b = BoolOption('b', '')
|
||||
u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
|
||||
#u.impl_add_consistency('not_equal', b)
|
||||
s = SymLinkOption('s', u)
|
||||
o = OptionDescription('o', '', [b, u, s])
|
||||
o1 = OptionDescription('o1', '', [o])
|
||||
@ -107,6 +148,11 @@ def test_diff_opt():
|
||||
_diff_opt(o1.o.s, q.o.s)
|
||||
|
||||
|
||||
def test_only_optiondescription():
|
||||
b = BoolOption('b', '')
|
||||
raises(SystemError, "a = dumps(b)")
|
||||
|
||||
|
||||
def test_diff_opt_cache():
|
||||
b = BoolOption('b', '')
|
||||
u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}])
|
||||
@ -169,10 +215,7 @@ def test_state_config():
|
||||
cfg._impl_test = True
|
||||
a = dumps(cfg)
|
||||
q = loads(a)
|
||||
_diff_opt(maconfig, q.cfgimpl_get_description())
|
||||
assert cfg.cfgimpl_get_values().get_modified_values() == q.cfgimpl_get_values().get_modified_values()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_properties() == q.cfgimpl_get_settings().get_modified_properties()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_permissives() == q.cfgimpl_get_settings().get_modified_permissives()
|
||||
_diff_conf(cfg, q)
|
||||
try:
|
||||
delete_session('29090931')
|
||||
except ConfigError:
|
||||
@ -191,12 +234,9 @@ def test_state_properties():
|
||||
cfg.cfgimpl_get_settings()[val1].append('test')
|
||||
a = dumps(cfg)
|
||||
q = loads(a)
|
||||
_diff_opt(maconfig, q.cfgimpl_get_description())
|
||||
assert cfg.cfgimpl_get_values().get_modified_values() == q.cfgimpl_get_values().get_modified_values()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_properties() == q.cfgimpl_get_settings().get_modified_properties()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_permissives() == q.cfgimpl_get_settings().get_modified_permissives()
|
||||
_diff_conf(cfg, q)
|
||||
try:
|
||||
delete_session('29090931')
|
||||
delete_session('29090932')
|
||||
except ConfigError:
|
||||
pass
|
||||
|
||||
@ -212,15 +252,12 @@ def test_state_values():
|
||||
cfg.val1 = True
|
||||
a = dumps(cfg)
|
||||
q = loads(a)
|
||||
_diff_opt(maconfig, q.cfgimpl_get_description())
|
||||
assert cfg.cfgimpl_get_values().get_modified_values() == q.cfgimpl_get_values().get_modified_values()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_properties() == q.cfgimpl_get_settings().get_modified_properties()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_permissives() == q.cfgimpl_get_settings().get_modified_permissives()
|
||||
_diff_conf(cfg, q)
|
||||
q.val1 = False
|
||||
#assert cfg.val1 is True
|
||||
assert q.val1 is False
|
||||
try:
|
||||
delete_session('29090931')
|
||||
delete_session('29090933')
|
||||
except ConfigError:
|
||||
pass
|
||||
|
||||
@ -238,14 +275,94 @@ def test_state_values_owner():
|
||||
cfg.val1 = True
|
||||
a = dumps(cfg)
|
||||
q = loads(a)
|
||||
_diff_opt(maconfig, q.cfgimpl_get_description())
|
||||
assert cfg.cfgimpl_get_values().get_modified_values() == q.cfgimpl_get_values().get_modified_values()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_properties() == q.cfgimpl_get_settings().get_modified_properties()
|
||||
assert cfg.cfgimpl_get_settings().get_modified_permissives() == q.cfgimpl_get_settings().get_modified_permissives()
|
||||
_diff_conf(cfg, q)
|
||||
q.val1 = False
|
||||
nval1 = q.cfgimpl_get_description().val1
|
||||
assert q.getowner(nval1) == owners.newowner
|
||||
try:
|
||||
delete_session('29090931')
|
||||
delete_session('29090934')
|
||||
except ConfigError:
|
||||
pass
|
||||
|
||||
|
||||
def test_state_metaconfig():
|
||||
i1 = IntOption('i1', '')
|
||||
od1 = OptionDescription('od1', '', [i1])
|
||||
od2 = OptionDescription('od2', '', [od1])
|
||||
conf1 = Config(od2, session_id='29090935')
|
||||
conf1._impl_test = True
|
||||
conf2 = Config(od2, session_id='29090936')
|
||||
conf2._impl_test = True
|
||||
meta = MetaConfig([conf1, conf2], session_id='29090937')
|
||||
meta._impl_test = True
|
||||
raises(ConfigError, "dumps(meta)")
|
||||
try:
|
||||
delete_session('29090935')
|
||||
delete_session('29090936')
|
||||
delete_session('29090937')
|
||||
except ConfigError:
|
||||
pass
|
||||
|
||||
|
||||
def test_state_groupconfig():
|
||||
i1 = IntOption('i1', '')
|
||||
od1 = OptionDescription('od1', '', [i1])
|
||||
od2 = OptionDescription('od2', '', [od1])
|
||||
conf1 = Config(od2, session_id='29090935')
|
||||
conf1._impl_test = True
|
||||
conf2 = Config(od2, session_id='29090936')
|
||||
conf2._impl_test = True
|
||||
meta = GroupConfig([conf1, conf2], session_id='29090937')
|
||||
meta._impl_test = True
|
||||
a = dumps(meta)
|
||||
q = loads(a)
|
||||
_diff_conf(meta, q)
|
||||
try:
|
||||
delete_session('29090935')
|
||||
delete_session('29090936')
|
||||
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__
|
||||
|
@ -19,15 +19,16 @@
|
||||
# ____________________________________________________________
|
||||
"enables us to carry out a calculation and return an option's value"
|
||||
from tiramisu.error import PropertiesOptionError, ConfigError
|
||||
from tiramisu.setting import multitypes
|
||||
from tiramisu.i18n import _
|
||||
# ____________________________________________________________
|
||||
|
||||
|
||||
def carry_out_calculation(name, config, callback, callback_params,
|
||||
def carry_out_calculation(option, config, callback, callback_params,
|
||||
index=None, max_len=None):
|
||||
"""a function that carries out a calculation for an option's value
|
||||
|
||||
:param name: the option name (`opt._name`)
|
||||
:param name: the option
|
||||
:param config: the context config in order to have
|
||||
the whole options available
|
||||
:param callback: the name of the callback function
|
||||
@ -48,13 +49,13 @@ def carry_out_calculation(name, config, callback, callback_params,
|
||||
Values could have multiple values only when key is ''.
|
||||
|
||||
* if no callback_params:
|
||||
=> calculate()
|
||||
=> calculate(<function func at 0x2092320>, [], {})
|
||||
|
||||
* if callback_params={'': ('yes',)}
|
||||
=> calculate('yes')
|
||||
=> calculate(<function func at 0x2092320>, ['yes'], {})
|
||||
|
||||
* if callback_params={'value': ('yes',)}
|
||||
=> calculate(value='yes')
|
||||
=> calculate(<function func at 0x165b320>, [], {'value': 'yes'})
|
||||
|
||||
* if callback_params={'': ('yes', 'no')}
|
||||
=> calculate('yes', 'no')
|
||||
@ -62,58 +63,71 @@ def carry_out_calculation(name, config, callback, callback_params,
|
||||
* if callback_params={'value': ('yes', 'no')}
|
||||
=> ValueError()
|
||||
|
||||
* if callback_params={'': (['yes', 'no'],)}
|
||||
=> calculate(<function func at 0x176b320>, ['yes', 'no'], {})
|
||||
|
||||
* if callback_params={'value': ('yes', 'no')}
|
||||
=> raises ValueError()
|
||||
|
||||
* if callback_params={'': ((opt1, False),)}
|
||||
|
||||
- a simple option:
|
||||
opt1 == 11
|
||||
=> calculate(11)
|
||||
=> calculate(<function func at 0x1cea320>, [11], {})
|
||||
|
||||
- a multi option:
|
||||
- a multi option and not master/slave:
|
||||
opt1 == [1, 2, 3]
|
||||
=> calculate(1)
|
||||
=> calculate(2)
|
||||
=> calculate(3)
|
||||
=> calculate(<function func at 0x223c320>, [[1, 2, 3]], {})
|
||||
|
||||
- option is master or slave of opt1:
|
||||
opt1 == [1, 2, 3]
|
||||
=> calculate(<function func at 0x223c320>, [1], {})
|
||||
=> calculate(<function func at 0x223c320>, [2], {})
|
||||
=> calculate(<function func at 0x223c320>, [3], {})
|
||||
|
||||
- opt is a master or slave but not related to option:
|
||||
opt1 == [1, 2, 3]
|
||||
=> calculate(<function func at 0x11b0320>, [[1, 2, 3]], {})
|
||||
|
||||
* if callback_params={'value': ((opt1, False),)}
|
||||
|
||||
- a simple option:
|
||||
opt1 == 11
|
||||
=> calculate(value=11)
|
||||
=> calculate(<function func at 0x17ff320>, [], {'value': 11})
|
||||
|
||||
- a multi option:
|
||||
opt1 == [1, 2, 3]
|
||||
=> calculate(value=1)
|
||||
=> calculate(value=2)
|
||||
=> calculate(value=3)
|
||||
=> calculate(<function func at 0x1262320>, [], {'value': [1, 2, 3]})
|
||||
|
||||
* if callback_params={'': ((opt1, False), (opt2, False))}
|
||||
|
||||
- two single options
|
||||
opt1 = 11
|
||||
opt2 = 12
|
||||
=> calculate(<function func at 0x217a320>, [11, 12], {})
|
||||
|
||||
- a multi option with a simple option
|
||||
opt1 == [1, 2, 3]
|
||||
opt2 == 11
|
||||
=> calculate(1, 11)
|
||||
=> calculate(2, 11)
|
||||
=> calculate(3, 11)
|
||||
opt2 == 12
|
||||
=> calculate(<function func at 0x2153320>, [[1, 2, 3], 12], {})
|
||||
|
||||
- a multi option with an other multi option but with same length
|
||||
opt1 == [1, 2, 3]
|
||||
opt2 == [11, 12, 13]
|
||||
=> calculate(1, 11)
|
||||
=> calculate(2, 12)
|
||||
=> calculate(3, 13)
|
||||
=> calculate(<function func at 0x1981320>, [[1, 2, 3], [11, 12, 13]], {})
|
||||
|
||||
- a multi option with an other multi option but with different length
|
||||
opt1 == [1, 2, 3]
|
||||
opt2 == [11, 12]
|
||||
=> ConfigError()
|
||||
=> calculate(<function func at 0x2384320>, [[1, 2, 3], [11, 12]], {})
|
||||
|
||||
- a multi option without value with a simple option
|
||||
opt1 == []
|
||||
opt2 == 11
|
||||
=> []
|
||||
=> calculate(<function func at 0xb65320>, [[], 12], {})
|
||||
|
||||
* if callback_params={'value': ((opt1, False), (opt2, False))}
|
||||
=> ConfigError()
|
||||
=> raises ValueError()
|
||||
|
||||
If index is not None, return a value, otherwise return:
|
||||
|
||||
@ -132,29 +146,36 @@ def carry_out_calculation(name, config, callback, callback_params,
|
||||
for callbk in callbacks:
|
||||
if isinstance(callbk, tuple):
|
||||
# callbk is something link (opt, True|False)
|
||||
option, force_permissive = callbk
|
||||
opt, force_permissive = callbk
|
||||
path = config.cfgimpl_get_description().impl_get_path_by_opt(
|
||||
option)
|
||||
opt)
|
||||
# get value
|
||||
try:
|
||||
value = config._getattr(path, force_permissive=True)
|
||||
value = config._getattr(path, force_permissive=True, validate=False)
|
||||
# convert to list, not modifie this multi
|
||||
if value.__class__.__name__ == 'Multi':
|
||||
value = list(value)
|
||||
except PropertiesOptionError as err:
|
||||
if force_permissive:
|
||||
continue
|
||||
raise ConfigError(_('unable to carry out a calculation, '
|
||||
'option {0} has properties: {1} for: '
|
||||
'{2}').format(option._name,
|
||||
'{2}').format(opt._name,
|
||||
err.proptype,
|
||||
name))
|
||||
is_multi = option.impl_is_multi()
|
||||
option._name))
|
||||
|
||||
is_multi = False
|
||||
if opt.impl_is_multi():
|
||||
#opt is master, search if option is a slave
|
||||
if opt.impl_get_multitype() == multitypes.master:
|
||||
if option in opt.impl_get_master_slaves():
|
||||
is_multi = True
|
||||
#opt is slave, search if option is an other slaves
|
||||
elif opt.impl_get_multitype() == multitypes.slave:
|
||||
if option in opt.impl_get_master_slaves().impl_get_master_slaves():
|
||||
is_multi = True
|
||||
if is_multi:
|
||||
len_value = len(value)
|
||||
if len_multi is not None and len_multi != len_value:
|
||||
raise ConfigError(_('unable to carry out a '
|
||||
'calculation, option value with'
|
||||
' multi types must have same '
|
||||
'length for: {0}').format(name))
|
||||
len_multi = len_value
|
||||
len_multi = len(value)
|
||||
one_is_multi = True
|
||||
tcparams.setdefault(key, []).append((value, is_multi))
|
||||
else:
|
||||
@ -167,16 +188,9 @@ def carry_out_calculation(name, config, callback, callback_params,
|
||||
if one_is_multi:
|
||||
ret = []
|
||||
if index:
|
||||
if index < len_multi:
|
||||
range_ = [index]
|
||||
else:
|
||||
range_ = []
|
||||
ret = None
|
||||
range_ = [index]
|
||||
else:
|
||||
if max_len and max_len < len_multi:
|
||||
range_ = range(max_len)
|
||||
else:
|
||||
range_ = range(len_multi)
|
||||
range_ = range(len_multi)
|
||||
for incr in range_:
|
||||
args = []
|
||||
kwargs = {}
|
||||
@ -195,10 +209,7 @@ def carry_out_calculation(name, config, callback, callback_params,
|
||||
if index:
|
||||
ret = calc
|
||||
else:
|
||||
if isinstance(calc, list):
|
||||
ret.extend(calc)
|
||||
else:
|
||||
ret.append(calc)
|
||||
ret.append(calc)
|
||||
return ret
|
||||
else:
|
||||
# no value is multi
|
||||
@ -212,7 +223,18 @@ def carry_out_calculation(name, config, callback, callback_params,
|
||||
args.append(couple[0])
|
||||
else:
|
||||
kwargs[key] = couple[0]
|
||||
return calculate(callback, args, kwargs)
|
||||
ret = calculate(callback, args, kwargs)
|
||||
if callback_params != {}:
|
||||
if isinstance(ret, list) and max_len:
|
||||
ret = ret[:max_len]
|
||||
if len(ret) < max_len:
|
||||
ret = ret + [None] * (max_len - len(ret))
|
||||
if isinstance(ret, list) and index:
|
||||
if len(ret) < index + 1:
|
||||
ret = None
|
||||
else:
|
||||
ret = ret[index]
|
||||
return ret
|
||||
|
||||
|
||||
def calculate(callback, args, kwargs):
|
||||
|
@ -47,7 +47,7 @@ class SubConfig(object):
|
||||
:type subpath: `str` with the path name
|
||||
"""
|
||||
# main option description
|
||||
if not isinstance(descr, OptionDescription):
|
||||
if descr is not None and not isinstance(descr, OptionDescription):
|
||||
raise TypeError(_('descr must be an optiondescription, not {0}'
|
||||
).format(type(descr)))
|
||||
self._impl_descr = descr
|
||||
@ -148,19 +148,25 @@ class SubConfig(object):
|
||||
except UnicodeEncodeError:
|
||||
lines.append("{0} = {1}".format(name,
|
||||
value.encode(default_encoding)))
|
||||
except PropertiesOptionError:
|
||||
pass
|
||||
return '\n'.join(lines)
|
||||
|
||||
__repr__ = __str__
|
||||
|
||||
def _cfgimpl_get_context(self):
|
||||
return self._impl_context()
|
||||
"""context could be None, we need to test it
|
||||
context is None only if all reference to `Config` object is deleted
|
||||
(for example we delete a `Config` and we manipulate a reference to
|
||||
old `SubConfig`, `Values`, `Multi` or `Settings`)
|
||||
"""
|
||||
context = self._impl_context()
|
||||
if context is None:
|
||||
raise ConfigError(_('the context does not exist anymore'))
|
||||
return context
|
||||
|
||||
def cfgimpl_get_description(self):
|
||||
if self._impl_descr is None:
|
||||
raise ConfigError(_('no option description found for this config'
|
||||
' (may be metaconfig without meta)'))
|
||||
' (may be GroupConfig)'))
|
||||
else:
|
||||
return self._impl_descr
|
||||
|
||||
@ -249,7 +255,8 @@ class SubConfig(object):
|
||||
force_properties=force_properties,
|
||||
force_permissive=force_permissive)
|
||||
|
||||
def find(self, bytype=None, byname=None, byvalue=None, type_='option'):
|
||||
def find(self, bytype=None, byname=None, byvalue=None, type_='option',
|
||||
check_properties=True):
|
||||
"""
|
||||
finds a list of options recursively in the config
|
||||
|
||||
@ -261,11 +268,11 @@ class SubConfig(object):
|
||||
return self._cfgimpl_get_context()._find(bytype, byname, byvalue,
|
||||
first=False,
|
||||
type_=type_,
|
||||
_subpath=self.cfgimpl_get_path()
|
||||
)
|
||||
_subpath=self.cfgimpl_get_path(),
|
||||
check_properties=check_properties)
|
||||
|
||||
def find_first(self, bytype=None, byname=None, byvalue=None,
|
||||
type_='option', display_error=True):
|
||||
type_='option', display_error=True, check_properties=True):
|
||||
"""
|
||||
finds an option recursively in the config
|
||||
|
||||
@ -276,7 +283,8 @@ class SubConfig(object):
|
||||
"""
|
||||
return self._cfgimpl_get_context()._find(
|
||||
bytype, byname, byvalue, first=True, type_=type_,
|
||||
_subpath=self.cfgimpl_get_path(), display_error=display_error)
|
||||
_subpath=self.cfgimpl_get_path(), display_error=display_error,
|
||||
check_properties=check_properties)
|
||||
|
||||
def _find(self, bytype, byname, byvalue, first, type_='option',
|
||||
_subpath=None, check_properties=True, display_error=True):
|
||||
@ -287,12 +295,9 @@ class SubConfig(object):
|
||||
:return: find list or an exception if nothing has been found
|
||||
"""
|
||||
def _filter_by_name():
|
||||
try:
|
||||
if byname is None or path == byname or \
|
||||
path.endswith('.' + byname):
|
||||
return True
|
||||
except IndexError:
|
||||
pass
|
||||
if byname is None or path == byname or \
|
||||
path.endswith('.' + byname):
|
||||
return True
|
||||
return False
|
||||
|
||||
def _filter_by_value():
|
||||
@ -442,23 +447,20 @@ class SubConfig(object):
|
||||
return pathsvalues
|
||||
|
||||
def _make_sub_dict(self, opt, path, pathsvalues, _currpath, flatten):
|
||||
if isinstance(opt, OptionDescription):
|
||||
try:
|
||||
try:
|
||||
if isinstance(opt, OptionDescription):
|
||||
pathsvalues += getattr(self, path).make_dict(flatten,
|
||||
_currpath +
|
||||
path.split('.'))
|
||||
except PropertiesOptionError:
|
||||
pass # this just a hidden or disabled option
|
||||
else:
|
||||
try:
|
||||
else:
|
||||
value = self._getattr(opt._name)
|
||||
if flatten:
|
||||
name = opt._name
|
||||
else:
|
||||
name = '.'.join(_currpath + [opt._name])
|
||||
pathsvalues.append((name, value))
|
||||
except PropertiesOptionError:
|
||||
pass # this just a hidden or disabled option
|
||||
except PropertiesOptionError:
|
||||
pass
|
||||
|
||||
def cfgimpl_get_path(self):
|
||||
descr = self.cfgimpl_get_description()
|
||||
@ -466,9 +468,9 @@ class SubConfig(object):
|
||||
return context_descr.impl_get_path_by_opt(descr)
|
||||
|
||||
|
||||
class CommonConfig(SubConfig):
|
||||
"abstract base class for the Config and the MetaConfig"
|
||||
__slots__ = ('_impl_values', '_impl_settings', '_impl_meta')
|
||||
class _CommonConfig(SubConfig):
|
||||
"abstract base class for the Config, GroupConfig and the MetaConfig"
|
||||
__slots__ = ('_impl_values', '_impl_settings', '_impl_meta', '_impl_test')
|
||||
|
||||
def _impl_build_all_paths(self):
|
||||
self.cfgimpl_get_description().impl_build_cache()
|
||||
@ -507,7 +509,8 @@ class CommonConfig(SubConfig):
|
||||
return None
|
||||
|
||||
def cfgimpl_get_meta(self):
|
||||
return self._impl_meta
|
||||
if self._impl_meta is not None:
|
||||
return self._impl_meta()
|
||||
|
||||
# information
|
||||
def impl_set_information(self, key, value):
|
||||
@ -525,11 +528,48 @@ class CommonConfig(SubConfig):
|
||||
"""
|
||||
return self._impl_values.get_information(key, default)
|
||||
|
||||
# ----- state
|
||||
def __getstate__(self):
|
||||
if self._impl_meta is not None:
|
||||
raise ConfigError(_('cannot serialize Config with MetaConfig'))
|
||||
slots = set()
|
||||
for subclass in self.__class__.__mro__:
|
||||
if subclass is not object:
|
||||
slots.update(subclass.__slots__)
|
||||
slots -= frozenset(['_impl_context', '_impl_meta', '__weakref__'])
|
||||
state = {}
|
||||
for slot in slots:
|
||||
try:
|
||||
state[slot] = getattr(self, slot)
|
||||
except AttributeError:
|
||||
pass
|
||||
storage = self._impl_values._p_._storage
|
||||
if not storage.serializable:
|
||||
raise ConfigError(_('this storage is not serialisable, could be a '
|
||||
'none persistent storage'))
|
||||
state['_storage'] = {'session_id': storage.session_id,
|
||||
'persistent': storage.persistent}
|
||||
state['_impl_setting'] = _impl_getstate_setting()
|
||||
return state
|
||||
|
||||
def __setstate__(self, state):
|
||||
for key, value in state.items():
|
||||
if key not in ['_storage', '_impl_setting']:
|
||||
setattr(self, key, value)
|
||||
set_storage(**state['_impl_setting'])
|
||||
self._impl_context = weakref.ref(self)
|
||||
self._impl_settings.context = weakref.ref(self)
|
||||
self._impl_values.context = weakref.ref(self)
|
||||
storage = get_storage(test=self._impl_test, **state['_storage'])
|
||||
self._impl_values._impl_setstate(storage)
|
||||
self._impl_settings._impl_setstate(storage)
|
||||
self._impl_meta = None
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
class Config(CommonConfig):
|
||||
class Config(_CommonConfig):
|
||||
"main configuration management entry"
|
||||
__slots__ = ('__weakref__', '_impl_test')
|
||||
__slots__ = ('__weakref__',)
|
||||
|
||||
def __init__(self, descr, session_id=None, persistent=False):
|
||||
""" Configuration option management master class
|
||||
@ -553,41 +593,6 @@ class Config(CommonConfig):
|
||||
#undocumented option used only in test script
|
||||
self._impl_test = False
|
||||
|
||||
def __getstate__(self):
|
||||
if self._impl_meta is not None:
|
||||
raise ConfigError('cannot serialize Config with meta')
|
||||
slots = set()
|
||||
for subclass in self.__class__.__mro__:
|
||||
if subclass is not object:
|
||||
slots.update(subclass.__slots__)
|
||||
slots -= frozenset(['_impl_context', '__weakref__'])
|
||||
state = {}
|
||||
for slot in slots:
|
||||
try:
|
||||
state[slot] = getattr(self, slot)
|
||||
except AttributeError:
|
||||
pass
|
||||
storage = self._impl_values._p_._storage
|
||||
if not storage.serializable:
|
||||
raise ConfigError('this storage is not serialisable, could be a '
|
||||
'none persistent storage')
|
||||
state['_storage'] = {'session_id': storage.session_id,
|
||||
'persistent': storage.persistent}
|
||||
state['_impl_setting'] = _impl_getstate_setting()
|
||||
return state
|
||||
|
||||
def __setstate__(self, state):
|
||||
for key, value in state.items():
|
||||
if key not in ['_storage', '_impl_setting']:
|
||||
setattr(self, key, value)
|
||||
set_storage(**state['_impl_setting'])
|
||||
self._impl_context = weakref.ref(self)
|
||||
self._impl_settings.context = weakref.ref(self)
|
||||
self._impl_values.context = weakref.ref(self)
|
||||
storage = get_storage(test=self._impl_test, **state['_storage'])
|
||||
self._impl_values._impl_setstate(storage)
|
||||
self._impl_settings._impl_setstate(storage)
|
||||
|
||||
def cfgimpl_reset_cache(self,
|
||||
only_expired=False,
|
||||
only=('values', 'settings')):
|
||||
@ -597,115 +602,121 @@ class Config(CommonConfig):
|
||||
self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
|
||||
|
||||
|
||||
#class MetaConfig(CommonConfig):
|
||||
# __slots__ = ('_impl_children',)
|
||||
class GroupConfig(_CommonConfig):
|
||||
__slots__ = ('_impl_children', '__weakref__')
|
||||
|
||||
# def __init__(self, children, meta=True, session_id=None, persistent=False):
|
||||
# if not isinstance(children, list):
|
||||
# raise ValueError(_("metaconfig's children must be a list"))
|
||||
# self._impl_descr = None
|
||||
# self._impl_path = None
|
||||
# if meta:
|
||||
# for child in children:
|
||||
# if not isinstance(child, CommonConfig):
|
||||
# raise TypeError(_("metaconfig's children "
|
||||
# "must be config, not {0}"
|
||||
# ).format(type(child)))
|
||||
# if self._impl_descr is None:
|
||||
# self._impl_descr = child.cfgimpl_get_description()
|
||||
# elif not self._impl_descr is child.cfgimpl_get_description():
|
||||
# raise ValueError(_('all config in metaconfig must '
|
||||
# 'have the same optiondescription'))
|
||||
# if child.cfgimpl_get_meta() is not None:
|
||||
# raise ValueError(_("child has already a metaconfig's"))
|
||||
# child._impl_meta = self
|
||||
def __init__(self, children, session_id=None, persistent=False,
|
||||
_descr=None):
|
||||
if not isinstance(children, list):
|
||||
raise ValueError(_("metaconfig's children must be a list"))
|
||||
self._impl_children = children
|
||||
settings, values = get_storages(self, session_id, persistent)
|
||||
self._impl_settings = Settings(self, settings)
|
||||
self._impl_values = Values(self, values)
|
||||
super(GroupConfig, self).__init__(_descr, weakref.ref(self))
|
||||
self._impl_meta = None
|
||||
#undocumented option used only in test script
|
||||
self._impl_test = False
|
||||
|
||||
# self._impl_children = children
|
||||
# settings, values = get_storages(self, session_id, persistent)
|
||||
# self._impl_settings = Settings(self, settings)
|
||||
# self._impl_values = Values(self, values)
|
||||
# self._impl_meta = None
|
||||
def cfgimpl_get_children(self):
|
||||
return self._impl_children
|
||||
|
||||
# def cfgimpl_get_children(self):
|
||||
# return self._impl_children
|
||||
#def cfgimpl_get_context(self):
|
||||
# "a meta config is a config which has a setting, that is itself"
|
||||
# return self
|
||||
#
|
||||
def cfgimpl_reset_cache(self,
|
||||
only_expired=False,
|
||||
only=('values', 'settings')):
|
||||
if 'values' in only:
|
||||
self.cfgimpl_get_values().reset_cache(only_expired=only_expired)
|
||||
if 'settings' in only:
|
||||
self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
|
||||
for child in self._impl_children:
|
||||
child.cfgimpl_reset_cache(only_expired=only_expired, only=only)
|
||||
|
||||
# def cfgimpl_get_context(self):
|
||||
# "a meta config is a config wich has a setting, that is itself"
|
||||
# return self
|
||||
def setattrs(self, path, value):
|
||||
"""Setattr not in current GroupConfig, but in each children
|
||||
"""
|
||||
for child in self._impl_children:
|
||||
try:
|
||||
if not isinstance(child, GroupConfig):
|
||||
setattr(child, path, value)
|
||||
else:
|
||||
child.setattrs(path, value)
|
||||
except PropertiesOptionError:
|
||||
pass
|
||||
|
||||
# def cfgimpl_reset_cache(self,
|
||||
# only_expired=False,
|
||||
# only=('values', 'settings')):
|
||||
# if 'values' in only:
|
||||
# self.cfgimpl_get_values().reset_cache(only_expired=only_expired)
|
||||
# if 'settings' in only:
|
||||
# self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
|
||||
# for child in self._impl_children:
|
||||
# child.cfgimpl_reset_cache(only_expired=only_expired, only=only)
|
||||
def find_firsts(self, byname=None, bypath=None, byvalue=None,
|
||||
type_='path', display_error=True):
|
||||
"""Find first not in current GroupConfig, but in each children
|
||||
"""
|
||||
ret = []
|
||||
#if MetaConfig, all children have same OptionDescription as context
|
||||
#so search only one time for all children
|
||||
try:
|
||||
if bypath is None and byname is not None and \
|
||||
isinstance(self, MetaConfig):
|
||||
bypath = self._find(bytype=None, byvalue=None, byname=byname,
|
||||
first=True, type_='path',
|
||||
check_properties=False,
|
||||
display_error=display_error)
|
||||
byname = None
|
||||
except AttributeError:
|
||||
pass
|
||||
for child in self._impl_children:
|
||||
try:
|
||||
if not isinstance(child, MetaConfig):
|
||||
if bypath is not None:
|
||||
#if byvalue is None, try if not raise
|
||||
value = getattr(child, bypath)
|
||||
if byvalue is not None:
|
||||
if isinstance(value, Multi):
|
||||
if byvalue in value:
|
||||
ret.append(child)
|
||||
else:
|
||||
if value == byvalue:
|
||||
ret.append(child)
|
||||
else:
|
||||
ret.append(child)
|
||||
else:
|
||||
ret.append(child.find_first(byname=byname,
|
||||
byvalue=byvalue,
|
||||
type_=type_,
|
||||
display_error=False))
|
||||
else:
|
||||
ret.extend(child.find_firsts(byname=byname,
|
||||
bypath=bypath,
|
||||
byvalue=byvalue,
|
||||
type_=type_,
|
||||
display_error=False))
|
||||
except AttributeError:
|
||||
pass
|
||||
return self._find_return_results(ret, display_error)
|
||||
|
||||
# def set_contexts(self, path, value):
|
||||
# for child in self._impl_children:
|
||||
# try:
|
||||
# if not isinstance(child, MetaConfig):
|
||||
# setattr(child, path, value)
|
||||
# else:
|
||||
# child.set_contexts(path, value)
|
||||
# except PropertiesOptionError:
|
||||
# pass
|
||||
|
||||
# def find_first_contexts(self, byname=None, bypath=None, byvalue=None,
|
||||
# type_='path', display_error=True):
|
||||
# ret = []
|
||||
# try:
|
||||
# if bypath is None and byname is not None and \
|
||||
# self.cfgimpl_get_description() is not None:
|
||||
# bypath = self._find(bytype=None, byvalue=None, byname=byname,
|
||||
# first=True, type_='path',
|
||||
# check_properties=False,
|
||||
# display_error=display_error)
|
||||
# except ConfigError:
|
||||
# pass
|
||||
# for child in self._impl_children:
|
||||
# try:
|
||||
# if not isinstance(child, MetaConfig):
|
||||
# if bypath is not None:
|
||||
# if byvalue is not None:
|
||||
# if getattr(child, bypath) == byvalue:
|
||||
# ret.append(child)
|
||||
# else:
|
||||
# #not raise
|
||||
# getattr(child, bypath)
|
||||
# ret.append(child)
|
||||
# else:
|
||||
# ret.append(child.find_first(byname=byname,
|
||||
# byvalue=byvalue,
|
||||
# type_=type_,
|
||||
# display_error=False))
|
||||
# else:
|
||||
# ret.extend(child.find_first_contexts(byname=byname,
|
||||
# bypath=bypath,
|
||||
# byvalue=byvalue,
|
||||
# type_=type_,
|
||||
# display_error=False))
|
||||
# except AttributeError:
|
||||
# pass
|
||||
# return self._find_return_results(ret, display_error)
|
||||
class MetaConfig(GroupConfig):
|
||||
__slots__ = tuple()
|
||||
|
||||
def __init__(self, children, session_id=None, persistent=False):
|
||||
descr = None
|
||||
for child in children:
|
||||
if not isinstance(child, _CommonConfig):
|
||||
raise TypeError(_("metaconfig's children "
|
||||
"should be config, not {0}"
|
||||
).format(type(child)))
|
||||
if child.cfgimpl_get_meta() is not None:
|
||||
raise ValueError(_("child has already a metaconfig's"))
|
||||
if descr is None:
|
||||
descr = child.cfgimpl_get_description()
|
||||
elif not descr is child.cfgimpl_get_description():
|
||||
raise ValueError(_('all config in metaconfig must '
|
||||
'have the same optiondescription'))
|
||||
child._impl_meta = weakref.ref(self)
|
||||
|
||||
super(MetaConfig, self).__init__(children, session_id, persistent, descr)
|
||||
|
||||
|
||||
def mandatory_warnings(config):
|
||||
"""convenience function to trace Options that are mandatory and
|
||||
where no value has been set
|
||||
|
||||
:returns: generator of mandatory Option's path
|
||||
|
||||
"""
|
||||
#if value in cache, properties are not calculated
|
||||
config.cfgimpl_reset_cache(only=('values',))
|
||||
for path in config.cfgimpl_get_description().impl_getpaths(
|
||||
include_groups=True):
|
||||
try:
|
||||
config._getattr(path, force_properties=frozenset(('mandatory',)))
|
||||
except PropertiesOptionError as err:
|
||||
if err.proptype == ['mandatory']:
|
||||
yield path
|
||||
config.cfgimpl_reset_cache(only=('values',))
|
||||
#only for retro-compatibility
|
||||
config.cfgimpl_get_values().mandatory_warnings()
|
||||
|
@ -39,9 +39,7 @@ forbidden_names = ('iter_all', 'iter_group', 'find', 'find_first',
|
||||
|
||||
def valid_name(name):
|
||||
"an option's name is a str and does not start with 'impl' or 'cfgimpl'"
|
||||
try:
|
||||
name = str(name)
|
||||
except:
|
||||
if not isinstance(name, str):
|
||||
return False
|
||||
if re.match(name_regexp, name) is None and not name.startswith('_') \
|
||||
and name not in forbidden_names \
|
||||
@ -337,7 +335,7 @@ class Option(BaseOption):
|
||||
self._consistencies = None
|
||||
|
||||
def _launch_consistency(self, func, option, value, context, index,
|
||||
all_cons_opts):
|
||||
all_cons_opts, warnings_only):
|
||||
"""Launch consistency now
|
||||
|
||||
:param func: function name, this name should start with _cons_
|
||||
@ -352,12 +350,11 @@ class Option(BaseOption):
|
||||
:type index: `int`
|
||||
:param all_cons_opts: all options concerne by this consistency
|
||||
:type all_cons_opts: `list` of `tiramisu.option.Option`
|
||||
:param warnings_only: specific raise error for warning
|
||||
:type warnings_only: `boolean`
|
||||
"""
|
||||
if context is not None:
|
||||
descr = context.cfgimpl_get_description()
|
||||
#option is also in all_cons_opts
|
||||
if option not in all_cons_opts:
|
||||
raise ConfigError(_('option not in all_cons_opts'))
|
||||
|
||||
all_cons_vals = []
|
||||
for opt in all_cons_opts:
|
||||
@ -368,7 +365,8 @@ class Option(BaseOption):
|
||||
#if context, calculate value, otherwise get default value
|
||||
if context is not None:
|
||||
opt_value = context._getattr(
|
||||
descr.impl_get_path_by_opt(opt), validate=False)
|
||||
descr.impl_get_path_by_opt(opt), validate=False,
|
||||
force_permissive=True)
|
||||
else:
|
||||
opt_value = opt.impl_getdefault()
|
||||
|
||||
@ -382,7 +380,7 @@ class Option(BaseOption):
|
||||
except IndexError:
|
||||
#so return if no value
|
||||
return
|
||||
getattr(self, func)(all_cons_opts, all_cons_vals)
|
||||
getattr(self, func)(all_cons_opts, all_cons_vals, warnings_only)
|
||||
|
||||
def impl_validate(self, value, context=None, validate=True,
|
||||
force_index=None):
|
||||
@ -412,7 +410,7 @@ class Option(BaseOption):
|
||||
else:
|
||||
validator_params = {'': (val,)}
|
||||
# Raise ValueError if not valid
|
||||
carry_out_calculation(self._name, config=context,
|
||||
carry_out_calculation(self, config=context,
|
||||
callback=self._validator[0],
|
||||
callback_params=validator_params)
|
||||
|
||||
@ -420,23 +418,41 @@ class Option(BaseOption):
|
||||
if _value is None:
|
||||
return
|
||||
# option validation
|
||||
self._validate(_value)
|
||||
try:
|
||||
self._validate(_value)
|
||||
except ValueError as err:
|
||||
raise ValueError(_('invalid value for option {0}: {1}'
|
||||
'').format(self._name, err))
|
||||
error = None
|
||||
warning = None
|
||||
try:
|
||||
# valid with self._validator
|
||||
val_validator(_value)
|
||||
# if not context launch consistency validation
|
||||
if context is not None:
|
||||
descr._valid_consistency(self, _value, context, _index)
|
||||
self._second_level_validation(_value)
|
||||
except ValueError as err:
|
||||
msg = _("invalid value {0} for option {1}: {2}").format(
|
||||
_value, self._name, err)
|
||||
self._second_level_validation(_value, self._warnings_only)
|
||||
except ValueError as error:
|
||||
if self._warnings_only:
|
||||
warnings.warn_explicit(ValueWarning(msg, self),
|
||||
ValueWarning,
|
||||
self.__class__.__name__, 0)
|
||||
else:
|
||||
raise ValueError(msg)
|
||||
warning = error
|
||||
error = None
|
||||
except ValueWarning as warning:
|
||||
pass
|
||||
if error is None and warning is None:
|
||||
try:
|
||||
# if context launch consistency validation
|
||||
if context is not None:
|
||||
descr._valid_consistency(self, _value, context, _index)
|
||||
except ValueError as error:
|
||||
pass
|
||||
except ValueWarning as warning:
|
||||
pass
|
||||
if warning:
|
||||
msg = _("warning on the value of the option {0}: {1}").format(
|
||||
self._name, warning)
|
||||
warnings.warn_explicit(ValueWarning(msg, self),
|
||||
ValueWarning,
|
||||
self.__class__.__name__, 0)
|
||||
elif error:
|
||||
raise ValueError(_("invalid value for option {0}: {1}").format(
|
||||
self._name, error))
|
||||
|
||||
# generic calculation
|
||||
if context is not None:
|
||||
@ -446,17 +462,13 @@ class Option(BaseOption):
|
||||
do_validation(value, force_index)
|
||||
else:
|
||||
if not isinstance(value, list):
|
||||
raise ValueError(_("which must be a list").format(value,
|
||||
self._name))
|
||||
raise ValueError(_("invalid value {0} for option {1} which must be a list").format(value, self._name))
|
||||
for index, val in enumerate(value):
|
||||
do_validation(val, index)
|
||||
|
||||
def impl_getdefault(self, default_multi=False):
|
||||
def impl_getdefault(self):
|
||||
"accessing the default value"
|
||||
if not default_multi or not self.impl_is_multi():
|
||||
return self._default
|
||||
else:
|
||||
return self.getdefault_multi()
|
||||
return self._default
|
||||
|
||||
def impl_getdefault_multi(self):
|
||||
"accessing the default value for a multi"
|
||||
@ -493,7 +505,7 @@ class Option(BaseOption):
|
||||
def impl_is_multi(self):
|
||||
return self._multi
|
||||
|
||||
def impl_add_consistency(self, func, *other_opts):
|
||||
def impl_add_consistency(self, func, *other_opts, **params):
|
||||
"""Add consistency means that value will be validate with other_opts
|
||||
option's values.
|
||||
|
||||
@ -501,16 +513,18 @@ class Option(BaseOption):
|
||||
:type func: `str`
|
||||
:param other_opts: options used to validate value
|
||||
:type other_opts: `list` of `tiramisu.option.Option`
|
||||
:param params: extra params (only warnings_only are allowed)
|
||||
"""
|
||||
if self._consistencies is None:
|
||||
self._consistencies = []
|
||||
warnings_only = params.get('warnings_only', False)
|
||||
for opt in other_opts:
|
||||
if not isinstance(opt, Option):
|
||||
raise ConfigError(_('consistency should be set with an option'))
|
||||
raise ConfigError(_('consistency must be set with an option'))
|
||||
if self is opt:
|
||||
raise ConfigError(_('cannot add consistency with itself'))
|
||||
if self.impl_is_multi() != opt.impl_is_multi():
|
||||
raise ConfigError(_('every options in consistency should be '
|
||||
raise ConfigError(_('every options in consistency must be '
|
||||
'multi or none'))
|
||||
func = '_cons_{0}'.format(func)
|
||||
all_cons_opts = tuple([self] + list(other_opts))
|
||||
@ -519,19 +533,23 @@ class Option(BaseOption):
|
||||
if self.impl_is_multi():
|
||||
for idx, val in enumerate(value):
|
||||
self._launch_consistency(func, self, val, None,
|
||||
idx, all_cons_opts)
|
||||
idx, all_cons_opts, warnings_only)
|
||||
else:
|
||||
self._launch_consistency(func, self, value, None,
|
||||
None, all_cons_opts)
|
||||
self._consistencies.append((func, all_cons_opts))
|
||||
None, all_cons_opts, warnings_only)
|
||||
self._consistencies.append((func, all_cons_opts, params))
|
||||
self.impl_validate(self.impl_getdefault())
|
||||
|
||||
def _cons_not_equal(self, opts, vals):
|
||||
def _cons_not_equal(self, opts, vals, warnings_only):
|
||||
for idx_inf, val_inf in enumerate(vals):
|
||||
for idx_sup, val_sup in enumerate(vals[idx_inf + 1:]):
|
||||
if val_inf == val_sup is not None:
|
||||
raise ValueError(_("same value for {0} and {1}").format(
|
||||
opts[idx_inf]._name, opts[idx_inf + idx_sup + 1]._name))
|
||||
if warnings_only:
|
||||
msg = _("same value for {0} and {1}, should be different")
|
||||
else:
|
||||
msg = _("same value for {0} and {1}, must be different")
|
||||
raise ValueError(msg.format(opts[idx_inf]._name,
|
||||
opts[idx_inf + idx_sup + 1]._name))
|
||||
|
||||
def _impl_convert_callbacks(self, descr, load=False):
|
||||
if not load and self._callback is None:
|
||||
@ -587,38 +605,22 @@ class Option(BaseOption):
|
||||
consistencies = self._state_consistencies
|
||||
else:
|
||||
consistencies = self._consistencies
|
||||
if isinstance(consistencies, list):
|
||||
new_value = []
|
||||
for consistency in consistencies:
|
||||
values = []
|
||||
for obj in consistency[1]:
|
||||
if load:
|
||||
values.append(descr.impl_get_opt_by_path(obj))
|
||||
else:
|
||||
values.append(descr.impl_get_path_by_opt(obj))
|
||||
new_value.append((consistency[0], tuple(values)))
|
||||
|
||||
else:
|
||||
new_value = {}
|
||||
for key, _consistencies in consistencies.items():
|
||||
new_value[key] = []
|
||||
for key_cons, _cons in _consistencies:
|
||||
_list_cons = []
|
||||
for _con in _cons:
|
||||
if load:
|
||||
_list_cons.append(
|
||||
descr.impl_get_opt_by_path(_con))
|
||||
else:
|
||||
_list_cons.append(
|
||||
descr.impl_get_path_by_opt(_con))
|
||||
new_value[key].append((key_cons, tuple(_list_cons)))
|
||||
new_value = []
|
||||
for consistency in consistencies:
|
||||
values = []
|
||||
for obj in consistency[1]:
|
||||
if load:
|
||||
values.append(descr.impl_get_opt_by_path(obj))
|
||||
else:
|
||||
values.append(descr.impl_get_path_by_opt(obj))
|
||||
new_value.append((consistency[0], tuple(values), consistency[2]))
|
||||
if load:
|
||||
del(self._state_consistencies)
|
||||
self._consistencies = new_value
|
||||
else:
|
||||
self._state_consistencies = new_value
|
||||
|
||||
def _second_level_validation(self, value):
|
||||
def _second_level_validation(self, value, warnings_only):
|
||||
pass
|
||||
|
||||
|
||||
@ -663,7 +665,7 @@ class ChoiceOption(Option):
|
||||
return self._open_values
|
||||
|
||||
def _validate(self, value):
|
||||
if not self._open_values and not value in self._values:
|
||||
if not self.impl_is_openvalues() and not value in self.impl_get_values():
|
||||
raise ValueError(_('value {0} is not permitted, '
|
||||
'only {1} is allowed'
|
||||
'').format(value, self._values))
|
||||
@ -676,7 +678,7 @@ class BoolOption(Option):
|
||||
|
||||
def _validate(self, value):
|
||||
if not isinstance(value, bool):
|
||||
raise ValueError(_('value must be a boolean'))
|
||||
raise ValueError(_('invalid boolean'))
|
||||
|
||||
|
||||
class IntOption(Option):
|
||||
@ -686,7 +688,7 @@ class IntOption(Option):
|
||||
|
||||
def _validate(self, value):
|
||||
if not isinstance(value, int):
|
||||
raise ValueError(_('value must be an integer'))
|
||||
raise ValueError(_('invalid integer'))
|
||||
|
||||
|
||||
class FloatOption(Option):
|
||||
@ -696,7 +698,7 @@ class FloatOption(Option):
|
||||
|
||||
def _validate(self, value):
|
||||
if not isinstance(value, float):
|
||||
raise ValueError(_('value must be a float'))
|
||||
raise ValueError(_('invalid float'))
|
||||
|
||||
|
||||
class StrOption(Option):
|
||||
@ -706,12 +708,11 @@ class StrOption(Option):
|
||||
|
||||
def _validate(self, value):
|
||||
if not isinstance(value, str):
|
||||
raise ValueError(_('value must be a string, not '
|
||||
'{0}').format(type(value)))
|
||||
raise ValueError(_('invalid string'))
|
||||
|
||||
|
||||
if sys.version_info[0] >= 3:
|
||||
#UnicodeOption is same has StrOption in python 3+
|
||||
#UnicodeOption is same as StrOption in python 3+
|
||||
class UnicodeOption(StrOption):
|
||||
__slots__ = tuple()
|
||||
pass
|
||||
@ -724,7 +725,7 @@ else:
|
||||
|
||||
def _validate(self, value):
|
||||
if not isinstance(value, unicode):
|
||||
raise ValueError(_('value must be an unicode'))
|
||||
raise ValueError(_('invalid unicode'))
|
||||
|
||||
|
||||
class SymLinkOption(BaseOption):
|
||||
@ -782,17 +783,51 @@ class IPOption(Option):
|
||||
warnings_only=warnings_only)
|
||||
|
||||
def _validate(self, value):
|
||||
# sometimes an ip term starts with a zero
|
||||
# but this does not fit in some case, for example bind does not like it
|
||||
try:
|
||||
for val in value.split('.'):
|
||||
if val.startswith("0") and len(val) > 1:
|
||||
raise ValueError(_('invalid IP'))
|
||||
except AttributeError:
|
||||
#if integer for example
|
||||
raise ValueError(_('invalid IP'))
|
||||
# 'standard' validation
|
||||
try:
|
||||
IP('{0}/32'.format(value))
|
||||
except ValueError:
|
||||
raise ValueError(_('invalid IP {0}').format(self._name))
|
||||
raise ValueError(_('invalid IP'))
|
||||
|
||||
def _second_level_validation(self, value):
|
||||
def _second_level_validation(self, value, warnings_only):
|
||||
ip = IP('{0}/32'.format(value))
|
||||
if not self._allow_reserved and ip.iptype() == 'RESERVED':
|
||||
raise ValueError(_("IP mustn't not be in reserved class"))
|
||||
if warnings_only:
|
||||
msg = _("IP shouldn't be in reserved class")
|
||||
else:
|
||||
msg = _("invalid IP, mustn't be in reserved class")
|
||||
raise ValueError(msg)
|
||||
if self._private_only and not ip.iptype() == 'PRIVATE':
|
||||
raise ValueError(_("IP must be in private class"))
|
||||
if warnings_only:
|
||||
msg = _("IP should be in private class")
|
||||
else:
|
||||
msg = _("invalid IP, must be in private class")
|
||||
raise ValueError(msg)
|
||||
|
||||
def _cons_in_network(self, opts, vals, warnings_only):
|
||||
if len(vals) != 3:
|
||||
raise ConfigError(_('invalid len for vals'))
|
||||
if None in vals:
|
||||
return
|
||||
ip, network, netmask = vals
|
||||
if IP(ip) not in IP('{0}/{1}'.format(network, netmask)):
|
||||
if warnings_only:
|
||||
msg = _('IP {0} ({1}) not in network {2} ({3}) with netmask {4}'
|
||||
' ({5})')
|
||||
else:
|
||||
msg = _('invalid IP {0} ({1}) not in network {2} ({3}) with '
|
||||
'netmask {4} ({5})')
|
||||
raise ValueError(msg.format(ip, opts[0]._name, network,
|
||||
opts[1]._name, netmask, opts[2]._name))
|
||||
|
||||
|
||||
class PortOption(Option):
|
||||
@ -852,17 +887,23 @@ class PortOption(Option):
|
||||
if self._allow_range and ":" in str(value):
|
||||
value = str(value).split(':')
|
||||
if len(value) != 2:
|
||||
raise ValueError('range must have two values only')
|
||||
raise ValueError(_('invalid port, range must have two values '
|
||||
'only'))
|
||||
if not value[0] < value[1]:
|
||||
raise ValueError('first port in range must be'
|
||||
' smaller than the second one')
|
||||
raise ValueError(_('invalid port, first port in range must be'
|
||||
' smaller than the second one'))
|
||||
else:
|
||||
value = [value]
|
||||
|
||||
for val in value:
|
||||
try:
|
||||
int(val)
|
||||
except ValueError:
|
||||
raise ValueError(_('invalid port'))
|
||||
if not self._min_value <= int(val) <= self._max_value:
|
||||
raise ValueError('port must be an between {0} and {1}'
|
||||
''.format(self._min_value, self._max_value))
|
||||
raise ValueError(_('invalid port, must be an between {0} '
|
||||
'and {1}').format(self._min_value,
|
||||
self._max_value))
|
||||
|
||||
|
||||
class NetworkOption(Option):
|
||||
@ -874,12 +915,16 @@ class NetworkOption(Option):
|
||||
try:
|
||||
IP(value)
|
||||
except ValueError:
|
||||
raise ValueError(_('invalid network address {0}').format(self._name))
|
||||
raise ValueError(_('invalid network address'))
|
||||
|
||||
def _second_level_validation(self, value):
|
||||
def _second_level_validation(self, value, warnings_only):
|
||||
ip = IP(value)
|
||||
if ip.iptype() == 'RESERVED':
|
||||
raise ValueError(_("network shall not be in reserved class"))
|
||||
if warnings_only:
|
||||
msg = _("network address shouldn't be in reserved class")
|
||||
else:
|
||||
msg = _("invalid network address, mustn't be in reserved class")
|
||||
raise ValueError(msg)
|
||||
|
||||
|
||||
class NetmaskOption(Option):
|
||||
@ -891,21 +936,22 @@ class NetmaskOption(Option):
|
||||
try:
|
||||
IP('0.0.0.0/{0}'.format(value))
|
||||
except ValueError:
|
||||
raise ValueError(_('invalid netmask address {0}').format(self._name))
|
||||
raise ValueError(_('invalid netmask address'))
|
||||
|
||||
def _cons_network_netmask(self, opts, vals):
|
||||
def _cons_network_netmask(self, opts, vals, warnings_only):
|
||||
#opts must be (netmask, network) options
|
||||
if None in vals:
|
||||
return
|
||||
self.__cons_netmask(opts, vals[0], vals[1], False)
|
||||
self.__cons_netmask(opts, vals[0], vals[1], False, warnings_only)
|
||||
|
||||
def _cons_ip_netmask(self, opts, vals):
|
||||
def _cons_ip_netmask(self, opts, vals, warnings_only):
|
||||
#opts must be (netmask, ip) options
|
||||
if None in vals:
|
||||
return
|
||||
self.__cons_netmask(opts, vals[0], vals[1], True)
|
||||
self.__cons_netmask(opts, vals[0], vals[1], True, warnings_only)
|
||||
|
||||
def __cons_netmask(self, opts, val_netmask, val_ipnetwork, make_net):
|
||||
def __cons_netmask(self, opts, val_netmask, val_ipnetwork, make_net,
|
||||
warnings_only):
|
||||
if len(opts) != 2:
|
||||
raise ConfigError(_('invalid len for opts'))
|
||||
msg = None
|
||||
@ -918,23 +964,18 @@ class NetmaskOption(Option):
|
||||
IP('{0}/{1}'.format(val_ipnetwork, val_netmask),
|
||||
make_net=not make_net)
|
||||
except ValueError:
|
||||
if not make_net:
|
||||
msg = _("invalid network {0} ({1}) "
|
||||
"with netmask {2} ({3}),"
|
||||
" this network is an IP")
|
||||
pass
|
||||
else:
|
||||
if make_net:
|
||||
msg = _("invalid IP {0} ({1}) with netmask {2} ({3}),"
|
||||
msg = _("invalid IP {0} ({1}) with netmask {2},"
|
||||
" this IP is a network")
|
||||
|
||||
except ValueError:
|
||||
if make_net:
|
||||
msg = _("invalid IP {0} ({1}) with netmask {2} ({3})")
|
||||
else:
|
||||
msg = _("invalid network {0} ({1}) with netmask {2} ({3})")
|
||||
if not make_net:
|
||||
msg = _('invalid network {0} ({1}) with netmask {2}')
|
||||
if msg is not None:
|
||||
raise ValueError(msg.format(val_ipnetwork, opts[1]._name,
|
||||
val_netmask, self._name))
|
||||
val_netmask))
|
||||
|
||||
|
||||
class BroadcastOption(Option):
|
||||
@ -945,9 +986,9 @@ class BroadcastOption(Option):
|
||||
try:
|
||||
IP('{0}/32'.format(value))
|
||||
except ValueError:
|
||||
raise ValueError(_('invalid broadcast address {0}').format(self._name))
|
||||
raise ValueError(_('invalid broadcast address'))
|
||||
|
||||
def _cons_broadcast(self, opts, vals):
|
||||
def _cons_broadcast(self, opts, vals, warnings_only):
|
||||
if len(vals) != 3:
|
||||
raise ConfigError(_('invalid len for vals'))
|
||||
if None in vals:
|
||||
@ -967,20 +1008,44 @@ class DomainnameOption(Option):
|
||||
domainname:
|
||||
fqdn: with tld, not supported yet
|
||||
"""
|
||||
__slots__ = ('_type', '_allow_ip')
|
||||
__slots__ = ('_type', '_allow_ip', '_allow_without_dot', '_domain_re')
|
||||
_opt_type = 'domainname'
|
||||
|
||||
def __init__(self, name, doc, default=None, default_multi=None,
|
||||
requires=None, multi=False, callback=None,
|
||||
callback_params=None, validator=None, validator_params=None,
|
||||
properties=None, allow_ip=False, type_='domainname',
|
||||
warnings_only=False):
|
||||
warnings_only=False, allow_without_dot=False):
|
||||
if type_ not in ['netbios', 'hostname', 'domainname']:
|
||||
raise ValueError(_('unknown type_ {0} for hostname').format(type_))
|
||||
self._type = type_
|
||||
if allow_ip not in [True, False]:
|
||||
raise ValueError(_('allow_ip must be a boolean'))
|
||||
if allow_without_dot not in [True, False]:
|
||||
raise ValueError(_('allow_without_dot must be a boolean'))
|
||||
self._allow_ip = allow_ip
|
||||
self._allow_without_dot = allow_without_dot
|
||||
end = ''
|
||||
extrachar = ''
|
||||
extrachar_mandatory = ''
|
||||
if self._type != 'netbios':
|
||||
allow_number = '\d'
|
||||
else:
|
||||
allow_number = ''
|
||||
if self._type == 'netbios':
|
||||
length = 14
|
||||
elif self._type == 'hostname':
|
||||
length = 62
|
||||
elif self._type == 'domainname':
|
||||
length = 62
|
||||
if allow_without_dot is False:
|
||||
extrachar_mandatory = '\.'
|
||||
else:
|
||||
extrachar = '\.'
|
||||
end = '+[a-z]*'
|
||||
self._domain_re = re.compile(r'^(?:[a-z{0}][a-z\d\-{1}]{{,{2}}}{3}){4}$'
|
||||
''.format(allow_number, extrachar, length,
|
||||
extrachar_mandatory, end))
|
||||
super(DomainnameOption, self).__init__(name, doc, default=default,
|
||||
default_multi=default_multi,
|
||||
callback=callback,
|
||||
@ -999,29 +1064,94 @@ class DomainnameOption(Option):
|
||||
return
|
||||
except ValueError:
|
||||
pass
|
||||
if self._type == 'netbios':
|
||||
length = 15
|
||||
extrachar = ''
|
||||
elif self._type == 'hostname':
|
||||
length = 63
|
||||
extrachar = ''
|
||||
elif self._type == 'domainname':
|
||||
length = 255
|
||||
extrachar = '\.'
|
||||
if '.' not in value:
|
||||
raise ValueError(_("invalid value for {0}, must have dot"
|
||||
"").format(self._name))
|
||||
if len(value) > length:
|
||||
raise ValueError(_("invalid domainname's length for"
|
||||
" {0} (max {1})").format(self._name, length))
|
||||
if len(value) == 1:
|
||||
raise ValueError(_("invalid domainname's length for {0} (min 2)"
|
||||
"").format(self._name))
|
||||
regexp = r'^[a-z]([a-z\d{0}-])*[a-z\d]$'.format(extrachar)
|
||||
if re.match(regexp, value) is None:
|
||||
if self._type == 'domainname' and not self._allow_without_dot and \
|
||||
'.' not in value:
|
||||
raise ValueError(_("invalid domainname, must have dot"))
|
||||
if len(value) > 255:
|
||||
raise ValueError(_("invalid domainname's length (max 255)"))
|
||||
if len(value) < 2:
|
||||
raise ValueError(_("invalid domainname's length (min 2)"))
|
||||
if not self._domain_re.search(value):
|
||||
raise ValueError(_('invalid domainname'))
|
||||
|
||||
|
||||
class EmailOption(DomainnameOption):
|
||||
__slots__ = tuple()
|
||||
_opt_type = 'email'
|
||||
username_re = re.compile(r"^[\w!#$%&'*+\-/=?^`{|}~.]+$")
|
||||
|
||||
def _validate(self, value):
|
||||
splitted = value.split('@', 1)
|
||||
try:
|
||||
username, domain = splitted
|
||||
except ValueError:
|
||||
raise ValueError(_('invalid email address, must contains one @'
|
||||
))
|
||||
if not self.username_re.search(username):
|
||||
raise ValueError(_('invalid username in email address'))
|
||||
super(EmailOption, self)._validate(domain)
|
||||
|
||||
|
||||
class URLOption(DomainnameOption):
|
||||
__slots__ = tuple()
|
||||
_opt_type = 'url'
|
||||
proto_re = re.compile(r'(http|https)://')
|
||||
path_re = re.compile(r"^[a-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
|
||||
|
||||
def _validate(self, value):
|
||||
match = self.proto_re.search(value)
|
||||
if not match:
|
||||
raise ValueError(_('invalid url, must start with http:// or '
|
||||
'https://'))
|
||||
value = value[len(match.group(0)):]
|
||||
# get domain/files
|
||||
splitted = value.split('/', 1)
|
||||
try:
|
||||
domain, files = splitted
|
||||
except ValueError:
|
||||
domain = value
|
||||
files = None
|
||||
# if port in domain
|
||||
splitted = domain.split(':', 1)
|
||||
try:
|
||||
domain, port = splitted
|
||||
|
||||
except ValueError:
|
||||
domain = splitted[0]
|
||||
port = 0
|
||||
if not 0 <= int(port) <= 65535:
|
||||
raise ValueError(_('invalid url, port must be an between 0 and '
|
||||
'65536'))
|
||||
# validate domainname
|
||||
super(URLOption, self)._validate(domain)
|
||||
# validate file
|
||||
if files is not None and files != '' and not self.path_re.search(files):
|
||||
raise ValueError(_('invalid url, must ends with filename'))
|
||||
|
||||
|
||||
class UsernameOption(Option):
|
||||
__slots__ = tuple()
|
||||
_opt_type = 'username'
|
||||
#regexp build with 'man 8 adduser' informations
|
||||
username_re = re.compile(r"^[a-z_][a-z0-9_-]{0,30}[$a-z0-9_-]{0,1}$")
|
||||
|
||||
def _validate(self, value):
|
||||
match = self.username_re.search(value)
|
||||
if not match:
|
||||
raise ValueError(_('invalid username'))
|
||||
|
||||
|
||||
class FilenameOption(Option):
|
||||
__slots__ = tuple()
|
||||
_opt_type = 'file'
|
||||
path_re = re.compile(r"^[a-zA-Z0-9\-\._~/+]+$")
|
||||
|
||||
def _validate(self, value):
|
||||
match = self.path_re.search(value)
|
||||
if not match:
|
||||
raise ValueError(_('invalid filename'))
|
||||
|
||||
|
||||
class OptionDescription(BaseOption):
|
||||
"""Config's schema (organisation, group) and container of Options
|
||||
The `OptionsDescription` objects lives in the `tiramisu.config.Config`.
|
||||
@ -1125,11 +1255,12 @@ class OptionDescription(BaseOption):
|
||||
if not force_no_consistencies and \
|
||||
option._consistencies is not None:
|
||||
for consistency in option._consistencies:
|
||||
func, all_cons_opts = consistency
|
||||
func, all_cons_opts, params = consistency
|
||||
for opt in all_cons_opts:
|
||||
_consistencies.setdefault(opt,
|
||||
[]).append((func,
|
||||
all_cons_opts))
|
||||
all_cons_opts,
|
||||
params))
|
||||
else:
|
||||
_currpath.append(attr)
|
||||
option.impl_build_cache(cache_path,
|
||||
@ -1176,7 +1307,6 @@ class OptionDescription(BaseOption):
|
||||
self._group_type = group_type
|
||||
if isinstance(group_type, groups.MasterGroupType):
|
||||
#if master (same name has group) is set
|
||||
identical_master_child_name = False
|
||||
#for collect all slaves
|
||||
slaves = []
|
||||
master = None
|
||||
@ -1193,7 +1323,6 @@ class OptionDescription(BaseOption):
|
||||
": this option is not a multi"
|
||||
"").format(child._name, self._name))
|
||||
if child._name == self._name:
|
||||
identical_master_child_name = True
|
||||
child._multitype = multitypes.master
|
||||
master = child
|
||||
else:
|
||||
@ -1202,14 +1331,18 @@ class OptionDescription(BaseOption):
|
||||
raise ValueError(_('master group with wrong'
|
||||
' master name for {0}'
|
||||
).format(self._name))
|
||||
if master._callback is not None and master._callback[1] is not None:
|
||||
for key, callbacks in master._callback[1].items():
|
||||
for callbk in callbacks:
|
||||
if isinstance(callbk, tuple):
|
||||
if callbk[0] in slaves:
|
||||
raise ValueError(_("callback of master's option shall "
|
||||
"not refered a slave's ones"))
|
||||
master._master_slaves = tuple(slaves)
|
||||
for child in self.impl_getchildren():
|
||||
if child != master:
|
||||
child._master_slaves = master
|
||||
child._multitype = multitypes.slave
|
||||
if not identical_master_child_name:
|
||||
raise ValueError(_("no child has same nom has master group"
|
||||
" for: {0}").format(self._name))
|
||||
else:
|
||||
raise ValueError(_('group_type: {0}'
|
||||
' not allowed').format(group_type))
|
||||
@ -1223,15 +1356,20 @@ class OptionDescription(BaseOption):
|
||||
#consistencies is something like [('_cons_not_equal', (opt1, opt2))]
|
||||
consistencies = self._cache_consistencies.get(option)
|
||||
if consistencies is not None:
|
||||
for func, all_cons_opts in consistencies:
|
||||
for func, all_cons_opts, params in consistencies:
|
||||
warnings_only = params.get('warnings_only', False)
|
||||
#all_cons_opts[0] is the option where func is set
|
||||
ret = all_cons_opts[0]._launch_consistency(func, option,
|
||||
value,
|
||||
context, index,
|
||||
all_cons_opts)
|
||||
if ret is False:
|
||||
return False
|
||||
return True
|
||||
try:
|
||||
all_cons_opts[0]._launch_consistency(func, option,
|
||||
value,
|
||||
context, index,
|
||||
all_cons_opts,
|
||||
warnings_only)
|
||||
except ValueError as err:
|
||||
if warnings_only:
|
||||
raise ValueWarning(err.message, option)
|
||||
else:
|
||||
raise err
|
||||
|
||||
def _impl_getstate(self, descr=None):
|
||||
"""enables us to export into a dict
|
||||
@ -1341,7 +1479,7 @@ def validate_requires_arg(requires, name):
|
||||
'must be an option in option {0}').format(name))
|
||||
if option.impl_is_multi():
|
||||
raise ValueError(_('malformed requirements option {0} '
|
||||
'should not be a multi').format(name))
|
||||
'must not be a multi').format(name))
|
||||
if expected is not None:
|
||||
try:
|
||||
option._validate(expected)
|
||||
@ -1376,17 +1514,17 @@ def validate_requires_arg(requires, name):
|
||||
|
||||
def validate_callback(callback, callback_params, type_):
|
||||
if type(callback) != FunctionType:
|
||||
raise ValueError(_('{0} should be a function').format(type_))
|
||||
raise ValueError(_('{0} must be a function').format(type_))
|
||||
if callback_params is not None:
|
||||
if not isinstance(callback_params, dict):
|
||||
raise ValueError(_('{0}_params should be a dict').format(type_))
|
||||
raise ValueError(_('{0}_params must be a dict').format(type_))
|
||||
for key, callbacks in callback_params.items():
|
||||
if key != '' and len(callbacks) != 1:
|
||||
raise ValueError(_('{0}_params with key {1} should not have '
|
||||
'length different to 1').format(type_,
|
||||
raise ValueError(_("{0}_params with key {1} mustn't have "
|
||||
"length different to 1").format(type_,
|
||||
key))
|
||||
if not isinstance(callbacks, tuple):
|
||||
raise ValueError(_('{0}_params should be tuple for key "{1}"'
|
||||
raise ValueError(_('{0}_params must be tuple for key "{1}"'
|
||||
).format(type_, key))
|
||||
for callbk in callbacks:
|
||||
if isinstance(callbk, tuple):
|
||||
@ -1395,11 +1533,11 @@ def validate_callback(callback, callback_params, type_):
|
||||
raise ValueError(_('validator not support tuple'))
|
||||
if not isinstance(option, Option) and not \
|
||||
isinstance(option, SymLinkOption):
|
||||
raise ValueError(_('{0}_params should have an option '
|
||||
raise ValueError(_('{0}_params must have an option '
|
||||
'not a {0} for first argument'
|
||||
).format(type_, type(option)))
|
||||
if force_permissive not in [True, False]:
|
||||
raise ValueError(_('{0}_params should have a boolean'
|
||||
raise ValueError(_('{0}_params must have a boolean'
|
||||
' not a {0} for second argument'
|
||||
).format(type_, type(
|
||||
force_permissive)))
|
||||
|
@ -19,7 +19,7 @@ from time import time
|
||||
from copy import copy
|
||||
import weakref
|
||||
from tiramisu.error import (RequirementError, PropertiesOptionError,
|
||||
ConstError)
|
||||
ConstError, ConfigError)
|
||||
from tiramisu.i18n import _
|
||||
|
||||
|
||||
@ -237,6 +237,14 @@ multitypes = MultiTypeModule()
|
||||
populate_multitypes()
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
class Undefined():
|
||||
pass
|
||||
|
||||
|
||||
undefined = Undefined()
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
class Property(object):
|
||||
"a property is responsible of the option's value access rules"
|
||||
@ -249,6 +257,11 @@ class Property(object):
|
||||
self._properties = prop
|
||||
|
||||
def append(self, propname):
|
||||
"""Appends a property named propname
|
||||
|
||||
:param propname: a predefined or user defined property name
|
||||
:type propname: string
|
||||
"""
|
||||
if self._opt is not None and self._opt._calc_properties is not None \
|
||||
and propname in self._opt._calc_properties:
|
||||
raise ValueError(_('cannot append {0} property for option {1}: '
|
||||
@ -258,12 +271,29 @@ class Property(object):
|
||||
self._setting._setproperties(self._properties, self._opt, self._path)
|
||||
|
||||
def remove(self, propname):
|
||||
"""Removes a property named propname
|
||||
|
||||
:param propname: a predefined or user defined property name
|
||||
:type propname: string
|
||||
"""
|
||||
if propname in self._properties:
|
||||
self._properties.remove(propname)
|
||||
self._setting._setproperties(self._properties, self._opt,
|
||||
self._path)
|
||||
|
||||
def extend(self, propnames):
|
||||
"""Extends properties to the existing properties
|
||||
|
||||
:param propnames: an iterable made of property names
|
||||
:type propnames: iterable of string
|
||||
"""
|
||||
for propname in propnames:
|
||||
self.append(propname)
|
||||
|
||||
def reset(self):
|
||||
"""resets the properties (does not **clear** the properties,
|
||||
default properties are still present)
|
||||
"""
|
||||
self._setting.reset(_path=self._path)
|
||||
|
||||
def __contains__(self, propname):
|
||||
@ -275,7 +305,7 @@ class Property(object):
|
||||
|
||||
#____________________________________________________________
|
||||
class Settings(object):
|
||||
"``Config()``'s configuration options"
|
||||
"``config.Config()``'s configuration options settings"
|
||||
__slots__ = ('context', '_owner', '_p_', '__weakref__')
|
||||
|
||||
def __init__(self, context, storage):
|
||||
@ -293,6 +323,17 @@ class Settings(object):
|
||||
self.context = weakref.ref(context)
|
||||
self._p_ = storage
|
||||
|
||||
def _getcontext(self):
|
||||
"""context could be None, we need to test it
|
||||
context is None only if all reference to `Config` object is deleted
|
||||
(for example we delete a `Config` and we manipulate a reference to
|
||||
old `SubConfig`, `Values`, `Multi` or `Settings`)
|
||||
"""
|
||||
context = self.context()
|
||||
if context is None:
|
||||
raise ConfigError(_('the context does not exist anymore'))
|
||||
return context
|
||||
|
||||
#____________________________________________________________
|
||||
# properties methods
|
||||
def __contains__(self, propname):
|
||||
@ -317,16 +358,16 @@ class Settings(object):
|
||||
raise ValueError(_('opt and all_properties must not be set '
|
||||
'together in reset'))
|
||||
if all_properties:
|
||||
self._p_.reset_all_propertives()
|
||||
self._p_.reset_all_properties()
|
||||
else:
|
||||
if opt is not None and _path is None:
|
||||
_path = self._get_path_by_opt(opt)
|
||||
self._p_.reset_properties(_path)
|
||||
self.context().cfgimpl_reset_cache()
|
||||
self._getcontext().cfgimpl_reset_cache()
|
||||
|
||||
def _getproperties(self, opt=None, path=None, is_apply_req=True):
|
||||
if opt is None:
|
||||
props = self._p_.getproperties(path, default_properties)
|
||||
props = copy(self._p_.getproperties(path, default_properties))
|
||||
else:
|
||||
if path is None:
|
||||
raise ValueError(_('if opt is not None, path should not be'
|
||||
@ -337,8 +378,8 @@ class Settings(object):
|
||||
ntime = int(time())
|
||||
is_cached, props = self._p_.getcache(path, ntime)
|
||||
if is_cached:
|
||||
return props
|
||||
props = self._p_.getproperties(path, opt._properties)
|
||||
return copy(props)
|
||||
props = copy(self._p_.getproperties(path, opt._properties))
|
||||
if is_apply_req:
|
||||
props |= self.apply_requires(opt, path)
|
||||
if 'cache' in self:
|
||||
@ -346,7 +387,7 @@ class Settings(object):
|
||||
if ntime is None:
|
||||
ntime = int(time())
|
||||
ntime = ntime + expires_time
|
||||
self._p_.setcache(path, props, ntime)
|
||||
self._p_.setcache(path, copy(props), ntime)
|
||||
return props
|
||||
|
||||
def append(self, propname):
|
||||
@ -362,6 +403,10 @@ class Settings(object):
|
||||
props.remove(propname)
|
||||
self._setproperties(props, None, None)
|
||||
|
||||
def extend(self, propnames):
|
||||
for propname in propnames:
|
||||
self.append(propname)
|
||||
|
||||
def _setproperties(self, properties, opt, path):
|
||||
"""save properties for specified opt
|
||||
(never save properties if same has option properties)
|
||||
@ -375,7 +420,7 @@ class Settings(object):
|
||||
self._p_.reset_properties(path)
|
||||
else:
|
||||
self._p_.setproperties(path, properties)
|
||||
self.context().cfgimpl_reset_cache()
|
||||
self._getcontext().cfgimpl_reset_cache()
|
||||
|
||||
#____________________________________________________________
|
||||
def validate_properties(self, opt_or_descr, is_descr, is_write, path,
|
||||
@ -400,11 +445,13 @@ class Settings(object):
|
||||
(typically with the `frozen` property)
|
||||
"""
|
||||
# opt properties
|
||||
properties = copy(self._getproperties(opt_or_descr, path))
|
||||
properties = self._getproperties(opt_or_descr, path)
|
||||
self_properties = self._getproperties()
|
||||
# remove opt permissive
|
||||
# permissive affect option's permission with or without permissive
|
||||
# global property
|
||||
properties -= self._p_.getpermissive(path)
|
||||
# remove global permissive if need
|
||||
self_properties = copy(self._getproperties())
|
||||
if force_permissive is True or 'permissive' in self_properties:
|
||||
properties -= self._p_.getpermissive()
|
||||
if force_permissives is not None:
|
||||
@ -421,7 +468,7 @@ class Settings(object):
|
||||
properties -= frozenset(('mandatory', 'frozen'))
|
||||
else:
|
||||
if 'mandatory' in properties and \
|
||||
not self.context().cfgimpl_get_values()._isempty(
|
||||
not self._getcontext().cfgimpl_get_values()._isempty(
|
||||
opt_or_descr, value):
|
||||
properties.remove('mandatory')
|
||||
if is_write and 'everything_frozen' in self_properties:
|
||||
@ -544,6 +591,7 @@ class Settings(object):
|
||||
|
||||
# filters the callbacks
|
||||
calc_properties = set()
|
||||
context = self._getcontext()
|
||||
for requires in opt._requires:
|
||||
for require in requires:
|
||||
option, expected, action, inverse, \
|
||||
@ -555,8 +603,7 @@ class Settings(object):
|
||||
" '{0}' with requirement on: "
|
||||
"'{1}'").format(path, reqpath))
|
||||
try:
|
||||
value = self.context()._getattr(reqpath,
|
||||
force_permissive=True)
|
||||
value = context._getattr(reqpath, force_permissive=True)
|
||||
except PropertiesOptionError as err:
|
||||
if not transitive:
|
||||
continue
|
||||
@ -585,7 +632,7 @@ class Settings(object):
|
||||
:param opt: `Option`'s object
|
||||
:returns: path
|
||||
"""
|
||||
return self.context().cfgimpl_get_description().impl_get_path_by_opt(opt)
|
||||
return self._getcontext().cfgimpl_get_description().impl_get_path_by_opt(opt)
|
||||
|
||||
def get_modified_properties(self):
|
||||
return self._p_.get_modified_properties()
|
||||
|
@ -29,7 +29,7 @@ class Settings(Cache):
|
||||
self._permissives = {}
|
||||
super(Settings, self).__init__(storage)
|
||||
|
||||
# propertives
|
||||
# properties
|
||||
def setproperties(self, path, properties):
|
||||
self._properties[path] = properties
|
||||
|
||||
@ -39,7 +39,7 @@ class Settings(Cache):
|
||||
def hasproperties(self, path):
|
||||
return path in self._properties
|
||||
|
||||
def reset_all_propertives(self):
|
||||
def reset_all_properties(self):
|
||||
self._properties.clear()
|
||||
|
||||
def reset_properties(self, path):
|
||||
|
@ -31,7 +31,7 @@ class Settings(Sqlite3DB):
|
||||
self._storage.execute(settings_table, commit=False)
|
||||
self._storage.execute(permissives_table)
|
||||
|
||||
# propertives
|
||||
# properties
|
||||
def setproperties(self, path, properties):
|
||||
path = self._sqlite_encode_path(path)
|
||||
self._storage.execute("DELETE FROM property WHERE path = ?", (path,),
|
||||
@ -54,7 +54,7 @@ class Settings(Sqlite3DB):
|
||||
return self._storage.select("SELECT properties FROM property WHERE "
|
||||
"path = ?", (path,)) is not None
|
||||
|
||||
def reset_all_propertives(self):
|
||||
def reset_all_properties(self):
|
||||
self._storage.execute("DELETE FROM property")
|
||||
|
||||
def reset_properties(self, path):
|
||||
|
@ -19,8 +19,8 @@ from time import time
|
||||
from copy import copy
|
||||
import sys
|
||||
import weakref
|
||||
from tiramisu.error import ConfigError, SlaveError
|
||||
from tiramisu.setting import owners, multitypes, expires_time
|
||||
from tiramisu.error import ConfigError, SlaveError, PropertiesOptionError
|
||||
from tiramisu.setting import owners, multitypes, expires_time, undefined
|
||||
from tiramisu.autolib import carry_out_calculation
|
||||
from tiramisu.i18n import _
|
||||
from tiramisu.option import SymLinkOption
|
||||
@ -44,15 +44,28 @@ class Values(object):
|
||||
# the storage type is dictionary or sqlite3
|
||||
self._p_ = storage
|
||||
|
||||
def _getcontext(self):
|
||||
"""context could be None, we need to test it
|
||||
context is None only if all reference to `Config` object is deleted
|
||||
(for example we delete a `Config` and we manipulate a reference to
|
||||
old `SubConfig`, `Values`, `Multi` or `Settings`)
|
||||
"""
|
||||
context = self.context()
|
||||
if context is None:
|
||||
raise ConfigError(_('the context does not exist anymore'))
|
||||
return context
|
||||
|
||||
def _getdefault(self, opt):
|
||||
"""
|
||||
actually retrieves the default value
|
||||
|
||||
:param opt: the `option.Option()` object
|
||||
"""
|
||||
meta = self.context().cfgimpl_get_meta()
|
||||
meta = self._getcontext().cfgimpl_get_meta()
|
||||
if meta is not None:
|
||||
value = meta.cfgimpl_get_values()[opt]
|
||||
if isinstance(value, Multi):
|
||||
value = list(value)
|
||||
else:
|
||||
value = opt.impl_getdefault()
|
||||
if opt.impl_is_multi():
|
||||
@ -60,7 +73,7 @@ class Values(object):
|
||||
else:
|
||||
return value
|
||||
|
||||
def _getvalue(self, opt, path, validate=True):
|
||||
def _getvalue(self, opt, path):
|
||||
"""actually retrieves the value
|
||||
|
||||
:param opt: the `option.Option()` object
|
||||
@ -69,14 +82,9 @@ class Values(object):
|
||||
if not self._p_.hasvalue(path):
|
||||
# if there is no value
|
||||
value = self._getdefault(opt)
|
||||
if opt.impl_is_multi():
|
||||
value = Multi(value, self.context, opt, path, validate)
|
||||
else:
|
||||
# if there is a value
|
||||
value = self._p_.getvalue(path)
|
||||
if opt.impl_is_multi() and not isinstance(value, Multi):
|
||||
# load value so don't need to validate if is not a Multi
|
||||
value = Multi(value, self.context, opt, path, validate=False)
|
||||
return value
|
||||
|
||||
def get_modified_values(self):
|
||||
@ -103,11 +111,11 @@ class Values(object):
|
||||
if path is None:
|
||||
path = self._get_opt_path(opt)
|
||||
if self._p_.hasvalue(path):
|
||||
setting = self.context().cfgimpl_get_settings()
|
||||
context = self._getcontext()
|
||||
setting = context.cfgimpl_get_settings()
|
||||
opt.impl_validate(opt.impl_getdefault(),
|
||||
self.context(),
|
||||
'validator' in setting)
|
||||
self.context().cfgimpl_reset_cache()
|
||||
context, 'validator' in setting)
|
||||
context.cfgimpl_reset_cache()
|
||||
if (opt.impl_is_multi() and
|
||||
opt.impl_get_multitype() == multitypes.master):
|
||||
for slave in opt.impl_get_master_slaves():
|
||||
@ -135,7 +143,7 @@ class Values(object):
|
||||
callback, callback_params = opt._callback
|
||||
if callback_params is None:
|
||||
callback_params = {}
|
||||
return carry_out_calculation(opt._name, config=self.context(),
|
||||
return carry_out_calculation(opt, config=self._getcontext(),
|
||||
callback=callback,
|
||||
callback_params=callback_params,
|
||||
index=index, max_len=max_len)
|
||||
@ -149,7 +157,7 @@ class Values(object):
|
||||
if path is None:
|
||||
path = self._get_opt_path(opt)
|
||||
ntime = None
|
||||
setting = self.context().cfgimpl_get_settings()
|
||||
setting = self._getcontext().cfgimpl_get_settings()
|
||||
if 'cache' in setting and self._p_.hascache(path):
|
||||
if 'expire' in setting:
|
||||
ntime = int(time())
|
||||
@ -174,7 +182,8 @@ class Values(object):
|
||||
def _getitem(self, opt, path, validate, force_permissive, force_properties,
|
||||
validate_properties):
|
||||
# options with callbacks
|
||||
setting = self.context().cfgimpl_get_settings()
|
||||
context = self._getcontext()
|
||||
setting = context.cfgimpl_get_settings()
|
||||
is_frozen = 'frozen' in setting[opt]
|
||||
# For calculating properties, we need value (ie for mandatory value).
|
||||
# If value is calculating with a PropertiesOptionError's option
|
||||
@ -184,7 +193,7 @@ class Values(object):
|
||||
# ConfigError if properties did not raise.
|
||||
config_error = None
|
||||
force_permissives = None
|
||||
# if value is callback and is not set
|
||||
# if value has callback and is not set
|
||||
# or frozen with force_default_on_freeze
|
||||
if opt.impl_has_callback() and (
|
||||
self._is_default_owner(path) or
|
||||
@ -194,7 +203,7 @@ class Values(object):
|
||||
if (opt.impl_is_multi() and
|
||||
opt.impl_get_multitype() == multitypes.slave):
|
||||
masterp = self._get_opt_path(opt.impl_get_master_slaves())
|
||||
mastervalue = getattr(self.context(), masterp)
|
||||
mastervalue = context._getattr(masterp, validate=validate)
|
||||
lenmaster = len(mastervalue)
|
||||
if lenmaster == 0:
|
||||
value = []
|
||||
@ -226,9 +235,12 @@ class Values(object):
|
||||
if opt.impl_is_multi():
|
||||
value = Multi(value, self.context, opt, path, validate)
|
||||
else:
|
||||
value = self._getvalue(opt, path, validate)
|
||||
value = self._getvalue(opt, path)
|
||||
if opt.impl_is_multi():
|
||||
# load value so don't need to validate if is not a Multi
|
||||
value = Multi(value, self.context, opt, path, validate=validate)
|
||||
if config_error is None and validate:
|
||||
opt.impl_validate(value, self.context(), 'validator' in setting)
|
||||
opt.impl_validate(value, context, 'validator' in setting)
|
||||
if config_error is None and self._is_default_owner(path) and \
|
||||
'force_store_value' in setting[opt]:
|
||||
self.setitem(opt, value, path, is_write=False)
|
||||
@ -249,24 +261,45 @@ class Values(object):
|
||||
# is_write is, for example, used with "force_store_value"
|
||||
# user didn't change value, so not write
|
||||
# valid opt
|
||||
opt.impl_validate(value, self.context(),
|
||||
'validator' in self.context().cfgimpl_get_settings())
|
||||
if opt.impl_is_multi() and not isinstance(value, Multi):
|
||||
context = self._getcontext()
|
||||
opt.impl_validate(value, context,
|
||||
'validator' in context.cfgimpl_get_settings())
|
||||
if opt.impl_is_multi():
|
||||
value = Multi(value, self.context, opt, path, setitem=True)
|
||||
# Save old value
|
||||
if opt.impl_get_multitype() == multitypes.master and \
|
||||
self._p_.hasvalue(path):
|
||||
old_value = self._p_.getvalue(path)
|
||||
old_owner = self._p_.getowner(path, None)
|
||||
else:
|
||||
old_value = undefined
|
||||
old_owner = undefined
|
||||
self._setvalue(opt, path, value, force_permissive=force_permissive,
|
||||
is_write=is_write)
|
||||
if opt.impl_is_multi() and opt.impl_get_multitype() == multitypes.master:
|
||||
try:
|
||||
value._valid_master()
|
||||
except Exception, err:
|
||||
if old_value is not undefined:
|
||||
self._p_.setvalue(path, old_value, old_owner)
|
||||
else:
|
||||
self._p_.resetvalue(path)
|
||||
raise err
|
||||
|
||||
def _setvalue(self, opt, path, value, force_permissive=False,
|
||||
force_properties=None,
|
||||
is_write=True, validate_properties=True):
|
||||
self.context().cfgimpl_reset_cache()
|
||||
context = self._getcontext()
|
||||
context.cfgimpl_reset_cache()
|
||||
if validate_properties:
|
||||
setting = self.context().cfgimpl_get_settings()
|
||||
setting = context.cfgimpl_get_settings()
|
||||
setting.validate_properties(opt, False, is_write,
|
||||
value=value, path=path,
|
||||
force_permissive=force_permissive,
|
||||
force_properties=force_properties)
|
||||
owner = self.context().cfgimpl_get_settings().getowner()
|
||||
owner = context.cfgimpl_get_settings().getowner()
|
||||
if isinstance(value, Multi):
|
||||
value = list(value)
|
||||
self._p_.setvalue(path, value, owner)
|
||||
|
||||
def getowner(self, opt):
|
||||
@ -283,7 +316,7 @@ class Values(object):
|
||||
|
||||
def _getowner(self, path):
|
||||
owner = self._p_.getowner(path, owners.default)
|
||||
meta = self.context().cfgimpl_get_meta()
|
||||
meta = self._getcontext().cfgimpl_get_meta()
|
||||
if owner is owners.default and meta is not None:
|
||||
owner = meta.cfgimpl_get_values()._getowner(path)
|
||||
return owner
|
||||
@ -335,7 +368,7 @@ class Values(object):
|
||||
:param opt: the `option.Option` object
|
||||
:returns: a string with points like "gc.dummy.my_option"
|
||||
"""
|
||||
return self.context().cfgimpl_get_description().impl_get_path_by_opt(opt)
|
||||
return self._getcontext().cfgimpl_get_description().impl_get_path_by_opt(opt)
|
||||
|
||||
# information
|
||||
def set_information(self, key, value):
|
||||
@ -360,6 +393,42 @@ class Values(object):
|
||||
raise ValueError(_("information's item"
|
||||
" not found: {0}").format(key))
|
||||
|
||||
def mandatory_warnings(self):
|
||||
"""convenience function to trace Options that are mandatory and
|
||||
where no value has been set
|
||||
|
||||
:returns: generator of mandatory Option's path
|
||||
|
||||
"""
|
||||
#if value in cache, properties are not calculated
|
||||
self.reset_cache(False)
|
||||
context = self.context()
|
||||
for path in context.cfgimpl_get_description().impl_getpaths(
|
||||
include_groups=True):
|
||||
try:
|
||||
context._getattr(path,
|
||||
force_properties=frozenset(('mandatory',)))
|
||||
except PropertiesOptionError as err:
|
||||
if err.proptype == ['mandatory']:
|
||||
yield path
|
||||
self.reset_cache(False)
|
||||
|
||||
def force_cache(self):
|
||||
"""parse all option to force data in cache
|
||||
"""
|
||||
context = self.context()
|
||||
if not 'cache' in context.cfgimpl_get_settings():
|
||||
raise ConfigError(_('can force cache only if cache '
|
||||
'is actived in config'))
|
||||
#remove all cached properties and value to update "expired" time
|
||||
context.cfgimpl_reset_cache()
|
||||
for path in context.cfgimpl_get_description().impl_getpaths(
|
||||
include_groups=True):
|
||||
try:
|
||||
context._getattr(path)
|
||||
except PropertiesOptionError:
|
||||
pass
|
||||
|
||||
def __getstate__(self):
|
||||
return {'_p_': self._p_}
|
||||
|
||||
@ -387,6 +456,8 @@ class Multi(list):
|
||||
:param opt: the option object that have this Multi value
|
||||
:param setitem: only if set a value
|
||||
"""
|
||||
if isinstance(value, Multi):
|
||||
raise ValueError(_('{0} is already a Multi ').format(opt._name))
|
||||
self.opt = opt
|
||||
self.path = path
|
||||
if not isinstance(context, weakref.ReferenceType):
|
||||
@ -396,21 +467,32 @@ class Multi(list):
|
||||
value = [value]
|
||||
if validate and self.opt.impl_get_multitype() == multitypes.slave:
|
||||
value = self._valid_slave(value, setitem)
|
||||
elif validate and self.opt.impl_get_multitype() == multitypes.master:
|
||||
self._valid_master(value)
|
||||
elif not setitem and validate and \
|
||||
self.opt.impl_get_multitype() == multitypes.master:
|
||||
self._valid_master()
|
||||
super(Multi, self).__init__(value)
|
||||
|
||||
def _getcontext(self):
|
||||
"""context could be None, we need to test it
|
||||
context is None only if all reference to `Config` object is deleted
|
||||
(for example we delete a `Config` and we manipulate a reference to
|
||||
old `SubConfig`, `Values`, `Multi` or `Settings`)
|
||||
"""
|
||||
context = self.context()
|
||||
if context is None:
|
||||
raise ConfigError(_('the context does not exist anymore'))
|
||||
return context
|
||||
|
||||
def _valid_slave(self, value, setitem):
|
||||
#if slave, had values until master's one
|
||||
values = self.context().cfgimpl_get_values()
|
||||
masterp = self.context().cfgimpl_get_description().impl_get_path_by_opt(
|
||||
context = self._getcontext()
|
||||
values = context.cfgimpl_get_values()
|
||||
masterp = context.cfgimpl_get_description().impl_get_path_by_opt(
|
||||
self.opt.impl_get_master_slaves())
|
||||
mastervalue = getattr(self.context(), masterp)
|
||||
mastervalue = context._getattr(masterp, validate=False)
|
||||
masterlen = len(mastervalue)
|
||||
valuelen = len(value)
|
||||
is_default_owner = not values._is_default_owner(self.path) or setitem
|
||||
if valuelen > masterlen or (valuelen < masterlen and
|
||||
is_default_owner):
|
||||
if valuelen > masterlen or (valuelen < masterlen and setitem):
|
||||
raise SlaveError(_("invalid len for the slave: {0}"
|
||||
" which has {1} as master").format(
|
||||
self.opt._name, masterp))
|
||||
@ -427,59 +509,43 @@ class Multi(list):
|
||||
#else: same len so do nothing
|
||||
return value
|
||||
|
||||
def _valid_master(self, value):
|
||||
masterlen = len(value)
|
||||
values = self.context().cfgimpl_get_values()
|
||||
def _valid_master(self):
|
||||
#masterlen = len(value)
|
||||
values = self._getcontext().cfgimpl_get_values()
|
||||
for slave in self.opt._master_slaves:
|
||||
path = values._get_opt_path(slave)
|
||||
if not values._is_default_owner(path):
|
||||
value_slave = values._getvalue(slave, path)
|
||||
if len(value_slave) > masterlen:
|
||||
raise SlaveError(_("invalid len for the master: {0}"
|
||||
" which has {1} as slave with"
|
||||
" greater len").format(
|
||||
self.opt._name, slave._name))
|
||||
elif len(value_slave) < masterlen:
|
||||
for num in range(0, masterlen - len(value_slave)):
|
||||
if slave.impl_has_callback():
|
||||
# if callback add a value, but this value will not
|
||||
# change anymore automaticly (because this value
|
||||
# has owner)
|
||||
index = value_slave.__len__()
|
||||
value_slave.append(
|
||||
values._getcallback_value(slave, index=index),
|
||||
force=True)
|
||||
else:
|
||||
value_slave.append(slave.impl_getdefault_multi(),
|
||||
force=True)
|
||||
Multi(values._getvalue(slave, path), self.context, slave, path)
|
||||
|
||||
def __setitem__(self, index, value):
|
||||
self._validate(value, index)
|
||||
#assume not checking mandatory property
|
||||
super(Multi, self).__setitem__(index, value)
|
||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
|
||||
def append(self, value, force=False):
|
||||
def append(self, value=undefined, force=False):
|
||||
"""the list value can be updated (appened)
|
||||
only if the option is a master
|
||||
"""
|
||||
context = self._getcontext()
|
||||
if not force:
|
||||
if self.opt.impl_get_multitype() == multitypes.slave:
|
||||
raise SlaveError(_("cannot append a value on a multi option {0}"
|
||||
" which is a slave").format(self.opt._name))
|
||||
elif self.opt.impl_get_multitype() == multitypes.master:
|
||||
values = self.context().cfgimpl_get_values()
|
||||
if value is None and self.opt.impl_has_callback():
|
||||
values = context.cfgimpl_get_values()
|
||||
if value is undefined and self.opt.impl_has_callback():
|
||||
value = values._getcallback_value(self.opt)
|
||||
#Force None il return a list
|
||||
if isinstance(value, list):
|
||||
value = None
|
||||
index = self.__len__()
|
||||
if value is undefined:
|
||||
value = self.opt.impl_getdefault_multi()
|
||||
self._validate(value, index)
|
||||
super(Multi, self).append(value)
|
||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path,
|
||||
self,
|
||||
validate_properties=not force)
|
||||
context.cfgimpl_get_values()._setvalue(self.opt, self.path,
|
||||
self,
|
||||
validate_properties=not force)
|
||||
if not force and self.opt.impl_get_multitype() == multitypes.master:
|
||||
for slave in self.opt.impl_get_master_slaves():
|
||||
path = values._get_opt_path(slave)
|
||||
@ -488,16 +554,15 @@ class Multi(list):
|
||||
dvalue = values._getcallback_value(slave, index=index)
|
||||
else:
|
||||
dvalue = slave.impl_getdefault_multi()
|
||||
old_value = values.getitem(slave, path,
|
||||
old_value = values.getitem(slave, path, validate=False,
|
||||
validate_properties=False)
|
||||
if len(old_value) < self.__len__():
|
||||
values.getitem(slave, path,
|
||||
validate_properties=False).append(
|
||||
dvalue, force=True)
|
||||
else:
|
||||
values.getitem(slave, path,
|
||||
validate_properties=False)[
|
||||
index] = dvalue
|
||||
if len(old_value) + 1 != self.__len__():
|
||||
raise SlaveError(_("invalid len for the slave: {0}"
|
||||
" which has {1} as master").format(
|
||||
self.opt._name, self.__len__()))
|
||||
values.getitem(slave, path, validate=False,
|
||||
validate_properties=False).append(
|
||||
dvalue, force=True)
|
||||
|
||||
def sort(self, cmp=None, key=None, reverse=False):
|
||||
if self.opt.impl_get_multitype() in [multitypes.slave,
|
||||
@ -510,7 +575,7 @@ class Multi(list):
|
||||
super(Multi, self).sort(key=key, reverse=reverse)
|
||||
else:
|
||||
super(Multi, self).sort(cmp=cmp, key=key, reverse=reverse)
|
||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
|
||||
def reverse(self):
|
||||
if self.opt.impl_get_multitype() in [multitypes.slave,
|
||||
@ -518,7 +583,7 @@ class Multi(list):
|
||||
raise SlaveError(_("cannot reverse multi option {0} if master or "
|
||||
"slave").format(self.opt._name))
|
||||
super(Multi, self).reverse()
|
||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
|
||||
def insert(self, index, obj):
|
||||
if self.opt.impl_get_multitype() in [multitypes.slave,
|
||||
@ -526,7 +591,7 @@ class Multi(list):
|
||||
raise SlaveError(_("cannot insert multi option {0} if master or "
|
||||
"slave").format(self.opt._name))
|
||||
super(Multi, self).insert(index, obj)
|
||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
|
||||
def extend(self, iterable):
|
||||
if self.opt.impl_get_multitype() in [multitypes.slave,
|
||||
@ -534,12 +599,12 @@ class Multi(list):
|
||||
raise SlaveError(_("cannot extend multi option {0} if master or "
|
||||
"slave").format(self.opt._name))
|
||||
super(Multi, self).extend(iterable)
|
||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
self._getcontext().cfgimpl_get_values()._setvalue(self.opt, self.path, self)
|
||||
|
||||
def _validate(self, value, force_index):
|
||||
if value is not None:
|
||||
try:
|
||||
self.opt.impl_validate(value, context=self.context(),
|
||||
self.opt.impl_validate(value, context=self._getcontext(),
|
||||
force_index=force_index)
|
||||
except ValueError as err:
|
||||
raise ValueError(_("invalid value {0} "
|
||||
@ -557,19 +622,20 @@ class Multi(list):
|
||||
:type force: boolean
|
||||
:returns: item at index
|
||||
"""
|
||||
context = self._getcontext()
|
||||
if not force:
|
||||
if self.opt.impl_get_multitype() == multitypes.slave:
|
||||
raise SlaveError(_("cannot pop a value on a multi option {0}"
|
||||
" which is a slave").format(self.opt._name))
|
||||
elif self.opt.impl_get_multitype() == multitypes.master:
|
||||
if self.opt.impl_get_multitype() == multitypes.master:
|
||||
for slave in self.opt.impl_get_master_slaves():
|
||||
values = self.context().cfgimpl_get_values()
|
||||
values = context.cfgimpl_get_values()
|
||||
if not values.is_default_owner(slave):
|
||||
#get multi without valid properties
|
||||
values.getitem(slave,
|
||||
values.getitem(slave, validate=False,
|
||||
validate_properties=False
|
||||
).pop(index, force=True)
|
||||
#set value without valid properties
|
||||
ret = super(Multi, self).pop(index)
|
||||
self.context().cfgimpl_get_values()._setvalue(self.opt, self.path, self, validate_properties=not force)
|
||||
context.cfgimpl_get_values()._setvalue(self.opt, self.path, self, validate_properties=not force)
|
||||
return ret
|
||||
|
@ -1,63 +1,61 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Project-Id-Version: Tiramisu\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"POT-Creation-Date: 2013-09-28 19:06+CEST\n"
|
||||
"POT-Creation-Date: 2014-03-12 21:49+CET\n"
|
||||
"PO-Revision-Date: \n"
|
||||
"Last-Translator: Emmanuel Garette <egarette@cadoles.com>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
"Language-Team: Tiramisu's team <egarette@cadoles.com>\n"
|
||||
"Language: fr\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"X-Generator: Poedit 1.5.4\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
"X-Poedit-SourceCharset: UTF-8\n"
|
||||
|
||||
#: tiramisu/autolib.py:144
|
||||
#: tiramisu/autolib.py:162
|
||||
msgid ""
|
||||
"unable to carry out a calculation, option {0} has properties: {1} for: {2}"
|
||||
msgstr ""
|
||||
"impossible d'effectuer le calcul, l'option {0} a les propriétés : {1} pour : "
|
||||
"{2}"
|
||||
|
||||
#: tiramisu/autolib.py:153
|
||||
msgid ""
|
||||
"unable to carry out a calculation, option value with multi types must have "
|
||||
"same length for: {0}"
|
||||
msgstr ""
|
||||
"impossible d'effectuer le calcul, la valeur d'une option avec le type multi "
|
||||
"doit avoir la même longueur pour : {0}"
|
||||
|
||||
#: tiramisu/config.py:51
|
||||
#: tiramisu/config.py:52
|
||||
msgid "descr must be an optiondescription, not {0}"
|
||||
msgstr "descr doit être une optiondescription pas un {0}"
|
||||
|
||||
#: tiramisu/config.py:126
|
||||
#: tiramisu/config.py:127
|
||||
msgid "unknown group_type: {0}"
|
||||
msgstr "group_type inconnu: {0}"
|
||||
|
||||
#: tiramisu/config.py:162
|
||||
msgid ""
|
||||
"no option description found for this config (may be metaconfig without meta)"
|
||||
msgstr ""
|
||||
"pas d'option description trouvé pour cette config (peut être une metaconfig "
|
||||
"sans meta)"
|
||||
#: tiramisu/config.py:164 tiramisu/setting.py:339 tiramisu/value.py:57
|
||||
#: tiramisu/value.py:485
|
||||
msgid "the context does not exist anymore"
|
||||
msgstr "le context n'existe plus"
|
||||
|
||||
#: tiramisu/config.py:188
|
||||
#: tiramisu/config.py:169
|
||||
msgid "no option description found for this config (may be GroupConfig)"
|
||||
msgstr ""
|
||||
"pas d'option description trouvé pour cette config (peut être un GroupConfig)"
|
||||
|
||||
#: tiramisu/config.py:195
|
||||
msgid "can't assign to an OptionDescription"
|
||||
msgstr "ne peut pas attribuer une valeur à une OptionDescription"
|
||||
|
||||
#: tiramisu/config.py:319
|
||||
#: tiramisu/config.py:325
|
||||
msgid "unknown type_ type {0}for _find"
|
||||
msgstr "type_ type {0} pour _find inconnu"
|
||||
|
||||
#: tiramisu/config.py:358
|
||||
#: tiramisu/config.py:364
|
||||
msgid "no option found in config with these criteria"
|
||||
msgstr "aucune option trouvée dans la config avec ces critères"
|
||||
|
||||
#: tiramisu/config.py:408
|
||||
#: tiramisu/config.py:414
|
||||
msgid "make_dict can't filtering with value without option"
|
||||
msgstr "make_dict ne peut filtrer sur une valeur mais sans option"
|
||||
|
||||
#: tiramisu/config.py:429
|
||||
#: tiramisu/config.py:435
|
||||
msgid "unexpected path {0}, should start with {1}"
|
||||
msgstr "chemin imprévu {0}, devrait commencer par {1}"
|
||||
|
||||
@ -65,41 +63,66 @@ msgstr "chemin imprévu {0}, devrait commencer par {1}"
|
||||
msgid "opt in getowner must be an option not {0}"
|
||||
msgstr "opt dans getowner doit être une option pas {0}"
|
||||
|
||||
#: tiramisu/option.py:68
|
||||
#: tiramisu/config.py:532
|
||||
msgid "cannot serialize Config with MetaConfig"
|
||||
msgstr "impossible de sérialiser une Config avec une MetaConfig"
|
||||
|
||||
#: tiramisu/config.py:546
|
||||
msgid "this storage is not serialisable, could be a none persistent storage"
|
||||
msgstr "ce storage n'est sérialisable, devrait être une storage non persistant"
|
||||
|
||||
#: tiramisu/config.py:609
|
||||
msgid "metaconfig's children must be a list"
|
||||
msgstr "enfants d'une metaconfig doit être une liste"
|
||||
|
||||
#: tiramisu/config.py:703
|
||||
msgid "metaconfig's children should be config, not {0}"
|
||||
msgstr "enfants d'une metaconfig doit être une config, pas {0}"
|
||||
|
||||
#: tiramisu/config.py:707
|
||||
msgid "child has already a metaconfig's"
|
||||
msgstr "enfant a déjà une metaconfig"
|
||||
|
||||
#: tiramisu/config.py:711
|
||||
msgid "all config in metaconfig must have the same optiondescription"
|
||||
msgstr ""
|
||||
"toutes les configs d'une metaconfig doivent avoir la même optiondescription"
|
||||
|
||||
#: tiramisu/option.py:67
|
||||
msgid "invalid name: {0} for option"
|
||||
msgstr "nom invalide : {0} pour l'option"
|
||||
|
||||
#: tiramisu/option.py:77
|
||||
#: tiramisu/option.py:76
|
||||
msgid "invalid properties type {0} for {1}, must be a tuple"
|
||||
msgstr "type des properties invalide {0} pour {1}, doit être un tuple"
|
||||
|
||||
#: tiramisu/option.py:115
|
||||
#: tiramisu/option.py:114
|
||||
msgid "'{0}' ({1}) object attribute '{2}' is read-only"
|
||||
msgstr "l'attribut {2} de l'objet '{0}' ({1}) est en lecture seule"
|
||||
|
||||
#: tiramisu/option.py:142 tiramisu/value.py:360
|
||||
#: tiramisu/option.py:141 tiramisu/value.py:395
|
||||
msgid "information's item not found: {0}"
|
||||
msgstr "aucune config spécifié alors que c'est nécessaire"
|
||||
msgstr "aucune config spécifiée alors que c'est nécessaire"
|
||||
|
||||
#: tiramisu/option.py:204
|
||||
#: tiramisu/option.py:203
|
||||
msgid "cannot serialize Option, only in OptionDescription"
|
||||
msgstr "ne peut serialiser une Option, seulement via une OptionDescription"
|
||||
|
||||
#: tiramisu/option.py:307
|
||||
#: tiramisu/option.py:306
|
||||
msgid "a default_multi is set whereas multi is False in option: {0}"
|
||||
msgstr ""
|
||||
"une default_multi est renseignée alors que multi est False dans l'option : "
|
||||
"{0}"
|
||||
|
||||
#: tiramisu/option.py:313
|
||||
#: tiramisu/option.py:312
|
||||
msgid "invalid default_multi value {0} for option {1}: {2}"
|
||||
msgstr "la valeur default_multi est invalide {0} pour l'option {1} : {2}"
|
||||
|
||||
#: tiramisu/option.py:318
|
||||
#: tiramisu/option.py:317
|
||||
msgid "default value not allowed if option: {0} is calculated"
|
||||
msgstr "la valeur par défaut n'est pas possible si l'option {0} est calculée"
|
||||
|
||||
#: tiramisu/option.py:321
|
||||
#: tiramisu/option.py:320
|
||||
msgid ""
|
||||
"params defined for a callback function but no callback defined yet for "
|
||||
"option {0}"
|
||||
@ -107,221 +130,289 @@ msgstr ""
|
||||
"params définis pour une fonction callback mais par de callback encore "
|
||||
"définis pour l'option {0}"
|
||||
|
||||
#: tiramisu/option.py:360
|
||||
msgid "option not in all_cons_opts"
|
||||
msgstr "option non présentante dans all_cons_opts"
|
||||
#: tiramisu/option.py:425 tiramisu/option.py:450
|
||||
msgid "invalid value for option {0}: {1}"
|
||||
msgstr "valeur invalide pour l'option {0} : {1}"
|
||||
|
||||
#: tiramisu/option.py:432 tiramisu/value.py:545
|
||||
msgid "invalid value {0} for option {1}: {2}"
|
||||
msgstr "valeur invalide {0} pour l'option {1} : {2}"
|
||||
#: tiramisu/option.py:444
|
||||
msgid "warning on the value of the option {0}: {1}"
|
||||
msgstr "avertissement sur la valeur de l'option {0} : {1}"
|
||||
|
||||
#: tiramisu/option.py:449
|
||||
msgid "which must be a list"
|
||||
msgstr "lequel doit être une liste"
|
||||
#: tiramisu/option.py:461
|
||||
msgid "invalid value {0} for option {1} which must be a list"
|
||||
msgstr "valeur invalide pour l'option {0} : {1} laquelle doit être une liste"
|
||||
|
||||
#: tiramisu/option.py:509
|
||||
msgid "consistency should be set with an option"
|
||||
#: tiramisu/option.py:519
|
||||
msgid "consistency must be set with an option"
|
||||
msgstr "consistency doit être configuré avec une option"
|
||||
|
||||
#: tiramisu/option.py:511
|
||||
#: tiramisu/option.py:521
|
||||
msgid "cannot add consistency with itself"
|
||||
msgstr "ne peut ajouter une consistency avec lui même"
|
||||
|
||||
#: tiramisu/option.py:513
|
||||
msgid "every options in consistency should be multi or none"
|
||||
#: tiramisu/option.py:523
|
||||
msgid "every options in consistency must be multi or none"
|
||||
msgstr ""
|
||||
"toutes les options d'une consistency devrait être multi ou ne pas l'être"
|
||||
"toutes les options d'une consistency doivent être multi ou ne pas l'être"
|
||||
|
||||
#: tiramisu/option.py:533
|
||||
msgid "same value for {0} and {1}"
|
||||
msgstr "même valeur pour {0} et {1}"
|
||||
#: tiramisu/option.py:544
|
||||
msgid "same value for {0} and {1}, should be different"
|
||||
msgstr "même valeur pour {0} et {1}, devrait être différent"
|
||||
|
||||
#: tiramisu/option.py:642
|
||||
#: tiramisu/option.py:546
|
||||
msgid "same value for {0} and {1}, must be different"
|
||||
msgstr "même valeur pour {0} et {1}, doit être différent"
|
||||
|
||||
#: tiramisu/option.py:640
|
||||
msgid "values must be a tuple for {0}"
|
||||
msgstr "values doit être un tuple pour {0}"
|
||||
|
||||
#: tiramisu/option.py:645
|
||||
#: tiramisu/option.py:643
|
||||
msgid "open_values must be a boolean for {0}"
|
||||
msgstr "open_values doit être un booléen pour {0}"
|
||||
|
||||
#: tiramisu/option.py:667
|
||||
#: tiramisu/option.py:665
|
||||
msgid "value {0} is not permitted, only {1} is allowed"
|
||||
msgstr "valeur {0} n'est pas permis, seules {1} sont autorisées"
|
||||
|
||||
#: tiramisu/option.py:679
|
||||
msgid "value must be a boolean"
|
||||
msgstr "valeur doit être un booléen"
|
||||
#: tiramisu/option.py:677
|
||||
msgid "invalid boolean"
|
||||
msgstr "booléen invalide"
|
||||
|
||||
#: tiramisu/option.py:689
|
||||
msgid "value must be an integer"
|
||||
msgstr "valeur doit être un nombre entier"
|
||||
#: tiramisu/option.py:687
|
||||
msgid "invalid integer"
|
||||
msgstr "nombre invalide"
|
||||
|
||||
#: tiramisu/option.py:699
|
||||
msgid "value must be a float"
|
||||
msgstr "valeur doit être un nombre flottant"
|
||||
#: tiramisu/option.py:697
|
||||
msgid "invalid float"
|
||||
msgstr "invalide nombre flottan"
|
||||
|
||||
#: tiramisu/option.py:709
|
||||
msgid "value must be a string, not {0}"
|
||||
msgstr "valeur doit être une chaîne, pas {0}"
|
||||
#: tiramisu/option.py:707
|
||||
msgid "invalid string"
|
||||
msgstr "invalide caractère"
|
||||
|
||||
#: tiramisu/option.py:727
|
||||
msgid "value must be an unicode"
|
||||
msgstr "valeur doit être une valeur unicode"
|
||||
#: tiramisu/option.py:724
|
||||
msgid "invalid unicode"
|
||||
msgstr "invalide unicode"
|
||||
|
||||
#: tiramisu/option.py:739
|
||||
#: tiramisu/option.py:736
|
||||
msgid "malformed symlinkoption must be an option for symlink {0}"
|
||||
msgstr "symlinkoption mal formé, doit être une option pour symlink {0}"
|
||||
|
||||
#: tiramisu/option.py:788
|
||||
msgid "invalid IP {0}"
|
||||
msgstr "adresse IP invalide {0}"
|
||||
#: tiramisu/option.py:787 tiramisu/option.py:790 tiramisu/option.py:795
|
||||
msgid "invalid IP"
|
||||
msgstr "adresse IP invalide"
|
||||
|
||||
#: tiramisu/option.py:793
|
||||
msgid "IP mustn't not be in reserved class"
|
||||
msgstr "IP ne doit pas être d'une classe reservée"
|
||||
#: tiramisu/option.py:801
|
||||
msgid "IP shouldn't be in reserved class"
|
||||
msgstr "l'adresse IP ne devrait pas être d'une classe réservée"
|
||||
|
||||
#: tiramisu/option.py:795
|
||||
msgid "IP must be in private class"
|
||||
msgstr "IP doit être dans la classe privée"
|
||||
#: tiramisu/option.py:803
|
||||
msgid "invalid IP, mustn't be in reserved class"
|
||||
msgstr "adresse IP invalide, ne doit pas être dans une classe réservée"
|
||||
|
||||
#: tiramisu/option.py:833
|
||||
msgid "inconsistency in allowed range"
|
||||
msgstr "inconsistence dans la plage autorisée"
|
||||
#: tiramisu/option.py:807
|
||||
msgid "IP should be in private class"
|
||||
msgstr "l'adresse IP devrait être dans une classe privée"
|
||||
|
||||
#: tiramisu/option.py:838
|
||||
msgid "max value is empty"
|
||||
msgstr "la valeur maximum est vide"
|
||||
#: tiramisu/option.py:809
|
||||
msgid "invalid IP, must be in private class"
|
||||
msgstr "adresse IP invalide, doit être dans la classe privée"
|
||||
|
||||
#: tiramisu/option.py:877
|
||||
msgid "invalid network address {0}"
|
||||
msgstr "adresse réseau invalide {0}"
|
||||
|
||||
#: tiramisu/option.py:882
|
||||
msgid "network shall not be in reserved class"
|
||||
msgstr "le réseau ne doit pas être dans la classe reservée"
|
||||
|
||||
#: tiramisu/option.py:894
|
||||
msgid "invalid netmask address {0}"
|
||||
msgstr "masque de sous-réseau invalide {0}"
|
||||
|
||||
#: tiramisu/option.py:910
|
||||
msgid "invalid len for opts"
|
||||
msgstr "longueur invalide pour opts"
|
||||
|
||||
#: tiramisu/option.py:922
|
||||
msgid "invalid network {0} ({1}) with netmask {2} ({3}), this network is an IP"
|
||||
msgstr "réseau invalide {0} ({1}) avec masque {2} ({3}), ce réseau est une IP"
|
||||
|
||||
#: tiramisu/option.py:927
|
||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3}), this IP is a network"
|
||||
msgstr "IP invalide {0} ({1}) avec masque {2} ({3}), cette IP est un réseau"
|
||||
|
||||
#: tiramisu/option.py:932
|
||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3})"
|
||||
msgstr "IP invalide {0} ({1}) avec masque {2} ({3})"
|
||||
|
||||
#: tiramisu/option.py:934
|
||||
msgid "invalid network {0} ({1}) with netmask {2} ({3})"
|
||||
msgstr "réseau invalide {0} ({1}) avec masque {2} ({3})"
|
||||
|
||||
#: tiramisu/option.py:948
|
||||
msgid "invalid broadcast address {0}"
|
||||
msgstr "adresse de broadcast invalide {0}"
|
||||
|
||||
#: tiramisu/option.py:952
|
||||
#: tiramisu/option.py:814 tiramisu/option.py:989
|
||||
msgid "invalid len for vals"
|
||||
msgstr "longueur invalide pour vals"
|
||||
|
||||
#: tiramisu/option.py:957
|
||||
#: tiramisu/option.py:820
|
||||
msgid "IP {0} ({1}) not in network {2} ({3}) with netmask {4} ({5})"
|
||||
msgstr "IP {0} ({1}) pas dans le réseau {2} ({3}) avec le masque {4} ({5})"
|
||||
|
||||
#: tiramisu/option.py:823
|
||||
msgid "invalid IP {0} ({1}) not in network {2} ({3}) with netmask {4} ({5})"
|
||||
msgstr ""
|
||||
"IP invalide {0} ({1}) pas dans le réseau {2} ({3}) avec le masque {4} ({5})"
|
||||
|
||||
#: tiramisu/option.py:864
|
||||
msgid "inconsistency in allowed range"
|
||||
msgstr "inconsistence dans la plage autorisée"
|
||||
|
||||
#: tiramisu/option.py:869
|
||||
msgid "max value is empty"
|
||||
msgstr "la valeur maximum est vide"
|
||||
|
||||
#: tiramisu/option.py:886
|
||||
msgid "invalid port, range must have two values only"
|
||||
msgstr "port invalide, une plage doit avoir deux valeurs seulement"
|
||||
|
||||
#: tiramisu/option.py:889
|
||||
msgid "invalid port, first port in range must be smaller than the second one"
|
||||
msgstr ""
|
||||
"port invalide, le premier port d'une plage doit être plus petit que le second"
|
||||
|
||||
#: tiramisu/option.py:898
|
||||
msgid "invalid port"
|
||||
msgstr "port invalide"
|
||||
|
||||
#: tiramisu/option.py:900
|
||||
msgid "invalid port, must be an between {0} and {1}"
|
||||
msgstr "port invalide, port doit être entre {0} et {1}"
|
||||
|
||||
#: tiramisu/option.py:914
|
||||
msgid "invalid network address"
|
||||
msgstr "adresse réseau invalide"
|
||||
|
||||
#: tiramisu/option.py:920
|
||||
msgid "network address shouldn't be in reserved class"
|
||||
msgstr "l'adresse réseau ne devait pas être dans la classe réservée"
|
||||
|
||||
#: tiramisu/option.py:922
|
||||
msgid "invalid network address, mustn't be in reserved class"
|
||||
msgstr "adresse réseau invalide, ne doit pas être dans la classe réservée"
|
||||
|
||||
#: tiramisu/option.py:935
|
||||
msgid "invalid netmask address"
|
||||
msgstr "masque de sous-réseau invalide"
|
||||
|
||||
#: tiramisu/option.py:952
|
||||
msgid "invalid len for opts"
|
||||
msgstr "longueur invalide pour opts"
|
||||
|
||||
#: tiramisu/option.py:966
|
||||
msgid "invalid IP {0} ({1}) with netmask {2}, this IP is a network"
|
||||
msgstr "IP invalide {0} ({1}) avec masque {2}, cette IP est un réseau"
|
||||
|
||||
#: tiramisu/option.py:971
|
||||
msgid "invalid network {0} ({1}) with netmask {2}"
|
||||
msgstr "réseau invalide {0} ({1}) avec masque {2}"
|
||||
|
||||
#: tiramisu/option.py:985
|
||||
msgid "invalid broadcast address"
|
||||
msgstr "adresse de broadcast invalide"
|
||||
|
||||
#: tiramisu/option.py:994
|
||||
msgid ""
|
||||
"invalid broadcast {0} ({1}) with network {2} ({3}) and netmask {4} ({5})"
|
||||
msgstr ""
|
||||
"Broadcast invalide {0} ({1}) avec le réseau {2} ({3}) et le masque {4} ({5})"
|
||||
|
||||
#: tiramisu/option.py:979
|
||||
#: tiramisu/option.py:1016
|
||||
msgid "unknown type_ {0} for hostname"
|
||||
msgstr "type_ inconnu {0} pour le nom d'hôte"
|
||||
|
||||
#: tiramisu/option.py:982
|
||||
#: tiramisu/option.py:1019
|
||||
msgid "allow_ip must be a boolean"
|
||||
msgstr "allow_ip doit être un booléen"
|
||||
|
||||
#: tiramisu/option.py:1012
|
||||
msgid "invalid value for {0}, must have dot"
|
||||
msgstr "valeur invalide pour {0}, doit avoir un point"
|
||||
#: tiramisu/option.py:1021
|
||||
msgid "allow_without_dot must be a boolean"
|
||||
msgstr "allow_without_dot doit être un booléen"
|
||||
|
||||
#: tiramisu/option.py:1015
|
||||
msgid "invalid domainname's length for {0} (max {1})"
|
||||
msgstr "longueur du nom de domaine invalide pour {0} (maximum {1})"
|
||||
#: tiramisu/option.py:1065
|
||||
msgid "invalid domainname, must have dot"
|
||||
msgstr "nom de domaine invalide, doit avoir un point"
|
||||
|
||||
#: tiramisu/option.py:1018
|
||||
msgid "invalid domainname's length for {0} (min 2)"
|
||||
msgstr "longueur du nom de domaine invalide pour {0} (minimum 2)"
|
||||
#: tiramisu/option.py:1067
|
||||
msgid "invalid domainname's length (max 255)"
|
||||
msgstr "longueur du nom de domaine invalide (maximum {1})"
|
||||
|
||||
#: tiramisu/option.py:1022
|
||||
#: tiramisu/option.py:1069
|
||||
msgid "invalid domainname's length (min 2)"
|
||||
msgstr "longueur du nom de domaine invalide (minimum 2)"
|
||||
|
||||
#: tiramisu/option.py:1071
|
||||
msgid "invalid domainname"
|
||||
msgstr "nom de domaine invalide"
|
||||
|
||||
#: tiramisu/option.py:1049
|
||||
#: tiramisu/option.py:1084
|
||||
msgid "invalid email address, must contains one @"
|
||||
msgstr "adresse email invalide, doit contenir un @"
|
||||
|
||||
#: tiramisu/option.py:1087
|
||||
msgid "invalid username in email address"
|
||||
msgstr "nom d'utilisateur invalide dans une adresse email"
|
||||
|
||||
#: tiramisu/option.py:1100
|
||||
msgid "invalid url, must start with http:// or https://"
|
||||
msgstr "URL invalide, doit démarrer avec http:// ou https://"
|
||||
|
||||
#: tiramisu/option.py:1119
|
||||
msgid "invalid url, port must be an between 0 and 65536"
|
||||
msgstr "URL invalide, port doit être entre 0 et 65536"
|
||||
|
||||
#: tiramisu/option.py:1125
|
||||
msgid "invalid url, must ends with filename"
|
||||
msgstr "URL invalide, doit finir avec un nom de fichier"
|
||||
|
||||
#: tiramisu/option.py:1137
|
||||
msgid "invalid username"
|
||||
msgstr "utilisateur invalide"
|
||||
|
||||
#: tiramisu/option.py:1148
|
||||
msgid "invalid filename"
|
||||
msgstr "nom de fichier invalide"
|
||||
|
||||
#: tiramisu/option.py:1175
|
||||
msgid "duplicate option name: {0}"
|
||||
msgstr "nom de l'option dupliqué : {0}"
|
||||
|
||||
#: tiramisu/option.py:1067
|
||||
#: tiramisu/option.py:1193
|
||||
msgid "unknown Option {0} in OptionDescription {1}"
|
||||
msgstr "Option {0} inconnue pour l'OptionDescription {1}"
|
||||
|
||||
#: tiramisu/option.py:1118
|
||||
#: tiramisu/option.py:1244
|
||||
msgid "duplicate option: {0}"
|
||||
msgstr "option dupliquée : {0}"
|
||||
|
||||
#: tiramisu/option.py:1148
|
||||
#: tiramisu/option.py:1275
|
||||
msgid "consistency with option {0} which is not in Config"
|
||||
msgstr "consistency avec l'option {0} qui n'est pas dans une Config"
|
||||
|
||||
#: tiramisu/option.py:1156
|
||||
#: tiramisu/option.py:1283
|
||||
msgid "no option for path {0}"
|
||||
msgstr "pas d'option pour le chemin {0}"
|
||||
|
||||
#: tiramisu/option.py:1162
|
||||
#: tiramisu/option.py:1289
|
||||
msgid "no option {0} found"
|
||||
msgstr "pas d'option {0} trouvée"
|
||||
|
||||
#: tiramisu/option.py:1172
|
||||
#: tiramisu/option.py:1299
|
||||
msgid "cannot change group_type if already set (old {0}, new {1})"
|
||||
msgstr "ne peut changer group_type si déjà spécifié (ancien {0}, nouveau {1})"
|
||||
|
||||
#: tiramisu/option.py:1185
|
||||
#: tiramisu/option.py:1311
|
||||
msgid "master group {0} shall not have a subgroup"
|
||||
msgstr "groupe maître {0} ne doit pas avoir de sous-groupe"
|
||||
|
||||
#: tiramisu/option.py:1188
|
||||
#: tiramisu/option.py:1314
|
||||
msgid "master group {0} shall not have a symlinkoption"
|
||||
msgstr "groupe maître {0} ne doit pas avoir de symlinkoption"
|
||||
|
||||
#: tiramisu/option.py:1191
|
||||
#: tiramisu/option.py:1317
|
||||
msgid "not allowed option {0} in group {1}: this option is not a multi"
|
||||
msgstr ""
|
||||
"option non autorisée {0} dans le groupe {1} : cette option n'est pas une "
|
||||
"multi"
|
||||
|
||||
#: tiramisu/option.py:1202
|
||||
#: tiramisu/option.py:1327
|
||||
msgid "master group with wrong master name for {0}"
|
||||
msgstr "le groupe maître avec un nom de maître érroné pour {0}"
|
||||
|
||||
#: tiramisu/option.py:1211
|
||||
msgid "no child has same nom has master group for: {0}"
|
||||
msgstr "pas d'enfant avec le nom du groupe maître pour {0} "
|
||||
#: tiramisu/option.py:1335
|
||||
msgid "callback of master's option shall not refered a slave's ones"
|
||||
msgstr ""
|
||||
"callback d'une variable maitre ne devrait pas référencer des variables "
|
||||
"esclaves"
|
||||
|
||||
#: tiramisu/option.py:1214
|
||||
#: tiramisu/option.py:1343
|
||||
msgid "group_type: {0} not allowed"
|
||||
msgstr "group_type : {0} non autorisé"
|
||||
|
||||
#: tiramisu/option.py:1306
|
||||
#: tiramisu/option.py:1443
|
||||
msgid "malformed requirements type for option: {0}, must be a dict"
|
||||
msgstr ""
|
||||
"type requirements malformé pour l'option : {0}, doit être un dictionnaire"
|
||||
|
||||
#: tiramisu/option.py:1323
|
||||
#: tiramisu/option.py:1460
|
||||
msgid ""
|
||||
"malformed requirements for option: {0} require must have option, expected "
|
||||
"and action keys"
|
||||
@ -329,110 +420,110 @@ msgstr ""
|
||||
"requirements malformé pour l'option : {0} l'exigence doit avoir les clefs "
|
||||
"option, expected et action"
|
||||
|
||||
#: tiramisu/option.py:1328
|
||||
#: tiramisu/option.py:1465
|
||||
msgid "malformed requirements for option: {0} inverse must be boolean"
|
||||
msgstr ""
|
||||
"requirements mal formés pour l'option : {0} inverse doit être un booléen"
|
||||
|
||||
#: tiramisu/option.py:1332
|
||||
#: tiramisu/option.py:1469
|
||||
msgid "malformed requirements for option: {0} transitive must be boolean"
|
||||
msgstr ""
|
||||
"requirements mal formés pour l'option : {0} transitive doit être booléen"
|
||||
|
||||
#: tiramisu/option.py:1336
|
||||
#: tiramisu/option.py:1473
|
||||
msgid "malformed requirements for option: {0} same_action must be boolean"
|
||||
msgstr ""
|
||||
"requirements mal formés pour l'option : {0} same_action doit être un booléen"
|
||||
|
||||
#: tiramisu/option.py:1340
|
||||
#: tiramisu/option.py:1477
|
||||
msgid "malformed requirements must be an option in option {0}"
|
||||
msgstr "requirements mal formés doit être une option dans l'option {0}"
|
||||
|
||||
#: tiramisu/option.py:1343
|
||||
msgid "malformed requirements option {0} should not be a multi"
|
||||
#: tiramisu/option.py:1480
|
||||
msgid "malformed requirements option {0} must not be a multi"
|
||||
msgstr "requirements mal formés l'option {0} ne doit pas être une multi"
|
||||
|
||||
#: tiramisu/option.py:1349
|
||||
#: tiramisu/option.py:1486
|
||||
msgid ""
|
||||
"malformed requirements second argument must be valid for option {0}: {1}"
|
||||
msgstr ""
|
||||
"requirements mal formés deuxième argument doit être valide pour l'option "
|
||||
"{0} : {1}"
|
||||
|
||||
#: tiramisu/option.py:1354
|
||||
#: tiramisu/option.py:1491
|
||||
msgid "inconsistency in action types for option: {0} action: {1}"
|
||||
msgstr "incohérence dans les types action pour l'option : {0} action {1}"
|
||||
|
||||
#: tiramisu/option.py:1379
|
||||
msgid "{0} should be a function"
|
||||
#: tiramisu/option.py:1516
|
||||
msgid "{0} must be a function"
|
||||
msgstr "{0} doit être une fonction"
|
||||
|
||||
#: tiramisu/option.py:1382
|
||||
msgid "{0}_params should be a dict"
|
||||
msgstr "{0}_params devrait être un dict"
|
||||
#: tiramisu/option.py:1519
|
||||
msgid "{0}_params must be a dict"
|
||||
msgstr "{0}_params doit être un dict"
|
||||
|
||||
#: tiramisu/option.py:1385
|
||||
msgid "{0}_params with key {1} should not have length different to 1"
|
||||
#: tiramisu/option.py:1522
|
||||
msgid "{0}_params with key {1} mustn't have length different to 1"
|
||||
msgstr ""
|
||||
"{0}_params avec la clef {1} devrait ne pas avoir une longueur différent de 1"
|
||||
"{0}_params avec la clef {1} ne doit pas avoir une longueur différent de 1"
|
||||
|
||||
#: tiramisu/option.py:1389
|
||||
msgid "{0}_params should be tuple for key \"{1}\""
|
||||
msgstr "{0}_params devrait être un tuple pour la clef \"{1}\""
|
||||
#: tiramisu/option.py:1526
|
||||
msgid "{0}_params must be tuple for key \"{1}\""
|
||||
msgstr "{0}_params doit être un tuple pour la clef \"{1}\""
|
||||
|
||||
#: tiramisu/option.py:1395
|
||||
#: tiramisu/option.py:1532
|
||||
msgid "validator not support tuple"
|
||||
msgstr "validator n'accepte pas de tuple"
|
||||
|
||||
#: tiramisu/option.py:1398
|
||||
msgid "{0}_params should have an option not a {0} for first argument"
|
||||
msgstr "{0}_params devrait avoir une option pas un {0} pour premier argument"
|
||||
#: tiramisu/option.py:1535
|
||||
msgid "{0}_params must have an option not a {0} for first argument"
|
||||
msgstr "{0}_params doit avoir une option pas un {0} pour premier argument"
|
||||
|
||||
#: tiramisu/option.py:1402
|
||||
msgid "{0}_params should have a boolean not a {0} for second argument"
|
||||
msgstr "{0}_params devrait avoir un boolean pas un {0} pour second argument"
|
||||
#: tiramisu/option.py:1539
|
||||
msgid "{0}_params must have a boolean not a {0} for second argument"
|
||||
msgstr "{0}_params doit avoir un booléen pas un {0} pour second argument"
|
||||
|
||||
#: tiramisu/setting.py:111
|
||||
#: tiramisu/setting.py:116
|
||||
msgid "can't rebind {0}"
|
||||
msgstr "ne peut redéfinir ({0})"
|
||||
|
||||
#: tiramisu/setting.py:116
|
||||
#: tiramisu/setting.py:121
|
||||
msgid "can't unbind {0}"
|
||||
msgstr "ne peut supprimer ({0})"
|
||||
|
||||
#: tiramisu/setting.py:254
|
||||
#: tiramisu/setting.py:272
|
||||
msgid "cannot append {0} property for option {1}: this property is calculated"
|
||||
msgstr ""
|
||||
"ne peut ajouter la propriété {0} dans l'option {1}: cette propriété est "
|
||||
"calculée"
|
||||
|
||||
#: tiramisu/setting.py:317
|
||||
#: tiramisu/setting.py:363
|
||||
msgid "opt and all_properties must not be set together in reset"
|
||||
msgstr "opt et all_properties ne doit pas être renseigné ensemble dans reset"
|
||||
|
||||
#: tiramisu/setting.py:332
|
||||
#: tiramisu/setting.py:378
|
||||
msgid "if opt is not None, path should not be None in _getproperties"
|
||||
msgstr ""
|
||||
"si opt n'est pas None, path devrait ne pas être à None dans _getproperties"
|
||||
|
||||
#: tiramisu/setting.py:435
|
||||
#: tiramisu/setting.py:487
|
||||
msgid "cannot change the value for option {0} this option is frozen"
|
||||
msgstr ""
|
||||
"ne peut modifier la valeur de l'option {0} cette option n'est pas modifiable"
|
||||
|
||||
#: tiramisu/setting.py:441
|
||||
#: tiramisu/setting.py:493
|
||||
msgid "trying to access to an option named: {0} with properties {1}"
|
||||
msgstr "tentative d'accès à une option nommée : {0} avec les propriétés {1}"
|
||||
|
||||
#: tiramisu/setting.py:459
|
||||
#: tiramisu/setting.py:511
|
||||
msgid "permissive must be a tuple"
|
||||
msgstr "permissive doit être un tuple"
|
||||
|
||||
#: tiramisu/setting.py:466 tiramisu/value.py:299
|
||||
#: tiramisu/setting.py:518 tiramisu/value.py:334
|
||||
msgid "invalid generic owner {0}"
|
||||
msgstr "invalide owner générique {0}"
|
||||
|
||||
#: tiramisu/setting.py:553
|
||||
#: tiramisu/setting.py:606
|
||||
msgid ""
|
||||
"malformed requirements imbrication detected for option: '{0}' with "
|
||||
"requirement on: '{1}'"
|
||||
@ -440,75 +531,119 @@ msgstr ""
|
||||
"imbrication de requirements mal formés detectée pour l'option : '{0}' avec "
|
||||
"requirement sur : '{1}'"
|
||||
|
||||
#: tiramisu/setting.py:565
|
||||
#: tiramisu/setting.py:617
|
||||
msgid "option '{0}' has requirement's property error: {1} {2}"
|
||||
msgstr "l'option '{0}' a une erreur de propriété pour le requirement : {1} {2}"
|
||||
|
||||
#: tiramisu/storage/__init__.py:47
|
||||
#: tiramisu/storage/__init__.py:52
|
||||
msgid "storage_type is already set, cannot rebind it"
|
||||
msgstr "storage_type est déjà défini, impossible de le redéfinir"
|
||||
|
||||
#: tiramisu/storage/__init__.py:81
|
||||
#: tiramisu/storage/__init__.py:86
|
||||
msgid "option {0} not already exists in storage {1}"
|
||||
msgstr "option {0} n'existe pas dans l'espace de stockage {1}"
|
||||
|
||||
#: tiramisu/storage/dictionary/storage.py:37
|
||||
#: tiramisu/storage/dictionary/storage.py:39
|
||||
msgid "dictionary storage cannot delete session"
|
||||
msgstr ""
|
||||
"impossible de supprimer une session dans un espace de stockage dictionary"
|
||||
|
||||
#: tiramisu/storage/dictionary/storage.py:48
|
||||
#: tiramisu/storage/dictionary/storage.py:50
|
||||
msgid "session already used"
|
||||
msgstr "session déjà utilisée"
|
||||
|
||||
#: tiramisu/storage/dictionary/storage.py:50
|
||||
#: tiramisu/storage/dictionary/storage.py:52
|
||||
msgid "a dictionary cannot be persistent"
|
||||
msgstr "un espace de stockage dictionary ne peut être persistant"
|
||||
|
||||
#: tiramisu/value.py:306
|
||||
#: tiramisu/value.py:341
|
||||
msgid "no value for {0} cannot change owner to {1}"
|
||||
msgstr "pas de valeur pour {0} ne peut changer d'utilisateur pour {1}"
|
||||
|
||||
#: tiramisu/value.py:414
|
||||
#: tiramisu/value.py:423
|
||||
msgid "can force cache only if cache is actived in config"
|
||||
msgstr ""
|
||||
"peut force la mise en cache seulement si le cache est activé dans la config"
|
||||
|
||||
#: tiramisu/value.py:462
|
||||
msgid "{0} is already a Multi "
|
||||
msgstr "{0} est déjà une Multi"
|
||||
|
||||
#: tiramisu/value.py:498 tiramisu/value.py:562
|
||||
msgid "invalid len for the slave: {0} which has {1} as master"
|
||||
msgstr "longueur invalide pour une esclave : {0} qui a {1} comme maître"
|
||||
|
||||
#: tiramisu/value.py:438
|
||||
msgid "invalid len for the master: {0} which has {1} as slave with greater len"
|
||||
msgstr ""
|
||||
"longueur invalide pour un maître : {0} qui a {1} une esclave avec une plus "
|
||||
"grande longueur"
|
||||
|
||||
#: tiramisu/value.py:468
|
||||
#: tiramisu/value.py:534
|
||||
msgid "cannot append a value on a multi option {0} which is a slave"
|
||||
msgstr "ne peut ajouter une valeur sur l'option multi {0} qui est une esclave"
|
||||
|
||||
#: tiramisu/value.py:505
|
||||
#: tiramisu/value.py:572
|
||||
msgid "cannot sort multi option {0} if master or slave"
|
||||
msgstr "ne peut trier une option multi {0} pour une maître ou une esclave"
|
||||
|
||||
#: tiramisu/value.py:509
|
||||
#: tiramisu/value.py:576
|
||||
msgid "cmp is not permitted in python v3 or greater"
|
||||
msgstr "cmp n'est pas permis en python v3 ou supérieure"
|
||||
|
||||
#: tiramisu/value.py:518
|
||||
#: tiramisu/value.py:585
|
||||
msgid "cannot reverse multi option {0} if master or slave"
|
||||
msgstr "ne peut inverser une option multi {0} pour une maître ou une esclave"
|
||||
|
||||
#: tiramisu/value.py:526
|
||||
#: tiramisu/value.py:593
|
||||
msgid "cannot insert multi option {0} if master or slave"
|
||||
msgstr "ne peut insérer une option multi {0} pour une maître ou une esclave"
|
||||
|
||||
#: tiramisu/value.py:534
|
||||
#: tiramisu/value.py:601
|
||||
msgid "cannot extend multi option {0} if master or slave"
|
||||
msgstr "ne peut étendre une option multi {0} pour une maître ou une esclave"
|
||||
|
||||
#: tiramisu/value.py:562
|
||||
#: tiramisu/value.py:612
|
||||
msgid "invalid value {0} for option {1}: {2}"
|
||||
msgstr "valeur invalide {0} pour l'option {1} : {2}"
|
||||
|
||||
#: tiramisu/value.py:630
|
||||
msgid "cannot pop a value on a multi option {0} which is a slave"
|
||||
msgstr "ne peut supprimer une valeur dans l'option multi {0} qui est esclave"
|
||||
|
||||
#~ msgid "invalid value {0} for option {1} which must be a list"
|
||||
#~ msgstr "valeur invalide {0} pour l'option {1} qui doit être une liste"
|
||||
#~ msgid "option not in all_cons_opts"
|
||||
#~ msgstr "option non présentante dans all_cons_opts"
|
||||
|
||||
#~ msgid "invalid network {0} ({1}) with netmask {2}, this network is an IP"
|
||||
#~ msgstr "réseau invalide {0} ({1}) avec masque {2}, ce réseau est une IP"
|
||||
|
||||
#~ msgid "invalid IP {0} ({1}) with netmask {2}"
|
||||
#~ msgstr "IP invalide {0} ({1}) avec masque {2}"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "invalid len for the master: {0} which has {1} as slave with greater len"
|
||||
#~ msgstr ""
|
||||
#~ "longueur invalide pour un maître : {0} qui a {1} une esclave avec une "
|
||||
#~ "plus grande longueur"
|
||||
|
||||
#~ msgid ""
|
||||
#~ "unable to carry out a calculation, option value with multi types must "
|
||||
#~ "have same length for: {0}"
|
||||
#~ msgstr ""
|
||||
#~ "impossible d'effectuer le calcul, la valeur d'une option avec le type "
|
||||
#~ "multi doit avoir la même longueur pour : {0}"
|
||||
|
||||
#~ msgid "no child has same nom has master group for: {0}"
|
||||
#~ msgstr "pas d'enfant avec le nom du groupe maître pour {0} "
|
||||
|
||||
#~ msgid "value must be a boolean"
|
||||
#~ msgstr "valeur doit être un booléen"
|
||||
|
||||
#~ msgid "value must be an integer"
|
||||
#~ msgstr "valeur doit être un nombre entier"
|
||||
|
||||
#~ msgid "value must be a float"
|
||||
#~ msgstr "valeur doit être un nombre flottant"
|
||||
|
||||
#~ msgid "value must be a string, not {0}"
|
||||
#~ msgstr "valeur doit être une chaîne, pas {0}"
|
||||
|
||||
#~ msgid "value must be an unicode"
|
||||
#~ msgstr "valeur doit être une valeur unicode"
|
||||
|
||||
#~ msgid "invalid value {0} for option {1} must be different as {2} option"
|
||||
#~ msgstr ""
|
||||
@ -532,17 +667,6 @@ msgstr "ne peut supprimer une valeur dans l'option multi {0} qui est esclave"
|
||||
#~ msgid "invalid name: {0} for optiondescription"
|
||||
#~ msgstr "nom invalide : {0} pour l'optiondescription"
|
||||
|
||||
#~ msgid "metaconfig's children must be config, not {0}"
|
||||
#~ msgstr "enfants d'une metaconfig doit être une config, pas {0}"
|
||||
|
||||
#~ msgid "all config in metaconfig must have same optiondescription"
|
||||
#~ msgstr ""
|
||||
#~ "toutes les configs d'une metaconfig doivent avoir la même "
|
||||
#~ "optiondescription"
|
||||
|
||||
#~ msgid "child has already a metaconfig's"
|
||||
#~ msgstr "enfant a déjà une metaconfig"
|
||||
|
||||
#~ msgid "not allowed group_type : {0}"
|
||||
#~ msgstr "group_type non autorisé : {0}"
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: PACKAGE VERSION\n"
|
||||
"POT-Creation-Date: 2013-09-28 19:06+CEST\n"
|
||||
"POT-Creation-Date: 2014-03-12 21:49+CET\n"
|
||||
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
|
||||
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
|
||||
"Language-Team: LANGUAGE <LL@li.org>\n"
|
||||
@ -15,43 +15,44 @@ msgstr ""
|
||||
"Generated-By: pygettext.py 1.5\n"
|
||||
|
||||
|
||||
#: tiramisu/autolib.py:144
|
||||
#: tiramisu/autolib.py:162
|
||||
msgid "unable to carry out a calculation, option {0} has properties: {1} for: {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/autolib.py:153
|
||||
msgid "unable to carry out a calculation, option value with multi types must have same length for: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:51
|
||||
#: tiramisu/config.py:52
|
||||
msgid "descr must be an optiondescription, not {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:126
|
||||
#: tiramisu/config.py:127
|
||||
msgid "unknown group_type: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:162
|
||||
msgid "no option description found for this config (may be metaconfig without meta)"
|
||||
#: tiramisu/config.py:164 tiramisu/setting.py:339 tiramisu/value.py:57
|
||||
#: tiramisu/value.py:485
|
||||
msgid "the context does not exist anymore"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:188
|
||||
#: tiramisu/config.py:169
|
||||
msgid "no option description found for this config (may be GroupConfig)"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:195
|
||||
msgid "can't assign to an OptionDescription"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:319
|
||||
#: tiramisu/config.py:325
|
||||
msgid "unknown type_ type {0}for _find"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:358
|
||||
#: tiramisu/config.py:364
|
||||
msgid "no option found in config with these criteria"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:408
|
||||
#: tiramisu/config.py:414
|
||||
msgid "make_dict can't filtering with value without option"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:429
|
||||
#: tiramisu/config.py:435
|
||||
msgid "unexpected path {0}, should start with {1}"
|
||||
msgstr ""
|
||||
|
||||
@ -59,411 +60,507 @@ msgstr ""
|
||||
msgid "opt in getowner must be an option not {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:68
|
||||
#: tiramisu/config.py:532
|
||||
msgid "cannot serialize Config with MetaConfig"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:546
|
||||
msgid "this storage is not serialisable, could be a none persistent storage"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:609
|
||||
msgid "metaconfig's children must be a list"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:703
|
||||
msgid "metaconfig's children should be config, not {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:707
|
||||
msgid "child has already a metaconfig's"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/config.py:711
|
||||
msgid "all config in metaconfig must have the same optiondescription"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:67
|
||||
msgid "invalid name: {0} for option"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:77
|
||||
#: tiramisu/option.py:76
|
||||
msgid "invalid properties type {0} for {1}, must be a tuple"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:115
|
||||
#: tiramisu/option.py:114
|
||||
msgid "'{0}' ({1}) object attribute '{2}' is read-only"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:142 tiramisu/value.py:360
|
||||
#: tiramisu/option.py:141 tiramisu/value.py:395
|
||||
msgid "information's item not found: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:204
|
||||
#: tiramisu/option.py:203
|
||||
msgid "cannot serialize Option, only in OptionDescription"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:307
|
||||
#: tiramisu/option.py:306
|
||||
msgid "a default_multi is set whereas multi is False in option: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:313
|
||||
#: tiramisu/option.py:312
|
||||
msgid "invalid default_multi value {0} for option {1}: {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:318
|
||||
#: tiramisu/option.py:317
|
||||
msgid "default value not allowed if option: {0} is calculated"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:321
|
||||
#: tiramisu/option.py:320
|
||||
msgid "params defined for a callback function but no callback defined yet for option {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:360
|
||||
msgid "option not in all_cons_opts"
|
||||
#: tiramisu/option.py:425 tiramisu/option.py:450
|
||||
msgid "invalid value for option {0}: {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:432 tiramisu/value.py:545
|
||||
msgid "invalid value {0} for option {1}: {2}"
|
||||
#: tiramisu/option.py:444
|
||||
msgid "warning on the value of the option {0}: {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:449
|
||||
msgid "which must be a list"
|
||||
#: tiramisu/option.py:461
|
||||
msgid "invalid value {0} for option {1} which must be a list"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:509
|
||||
msgid "consistency should be set with an option"
|
||||
#: tiramisu/option.py:519
|
||||
msgid "consistency must be set with an option"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:511
|
||||
#: tiramisu/option.py:521
|
||||
msgid "cannot add consistency with itself"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:513
|
||||
msgid "every options in consistency should be multi or none"
|
||||
#: tiramisu/option.py:523
|
||||
msgid "every options in consistency must be multi or none"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:533
|
||||
msgid "same value for {0} and {1}"
|
||||
#: tiramisu/option.py:544
|
||||
msgid "same value for {0} and {1}, should be different"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:642
|
||||
#: tiramisu/option.py:546
|
||||
msgid "same value for {0} and {1}, must be different"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:640
|
||||
msgid "values must be a tuple for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:645
|
||||
#: tiramisu/option.py:643
|
||||
msgid "open_values must be a boolean for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:667
|
||||
#: tiramisu/option.py:665
|
||||
msgid "value {0} is not permitted, only {1} is allowed"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:679
|
||||
msgid "value must be a boolean"
|
||||
#: tiramisu/option.py:677
|
||||
msgid "invalid boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:689
|
||||
msgid "value must be an integer"
|
||||
#: tiramisu/option.py:687
|
||||
msgid "invalid integer"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:699
|
||||
msgid "value must be a float"
|
||||
#: tiramisu/option.py:697
|
||||
msgid "invalid float"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:709
|
||||
msgid "value must be a string, not {0}"
|
||||
#: tiramisu/option.py:707
|
||||
msgid "invalid string"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:727
|
||||
msgid "value must be an unicode"
|
||||
#: tiramisu/option.py:724
|
||||
msgid "invalid unicode"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:739
|
||||
#: tiramisu/option.py:736
|
||||
msgid "malformed symlinkoption must be an option for symlink {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:788
|
||||
msgid "invalid IP {0}"
|
||||
#: tiramisu/option.py:787 tiramisu/option.py:790 tiramisu/option.py:795
|
||||
msgid "invalid IP"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:793
|
||||
msgid "IP mustn't not be in reserved class"
|
||||
#: tiramisu/option.py:801
|
||||
msgid "IP shouldn't be in reserved class"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:795
|
||||
msgid "IP must be in private class"
|
||||
#: tiramisu/option.py:803
|
||||
msgid "invalid IP, mustn't be in reserved class"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:833
|
||||
msgid "inconsistency in allowed range"
|
||||
#: tiramisu/option.py:807
|
||||
msgid "IP should be in private class"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:838
|
||||
msgid "max value is empty"
|
||||
#: tiramisu/option.py:809
|
||||
msgid "invalid IP, must be in private class"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:877
|
||||
msgid "invalid network address {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:882
|
||||
msgid "network shall not be in reserved class"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:894
|
||||
msgid "invalid netmask address {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:910
|
||||
msgid "invalid len for opts"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:922
|
||||
msgid "invalid network {0} ({1}) with netmask {2} ({3}), this network is an IP"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:927
|
||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3}), this IP is a network"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:932
|
||||
msgid "invalid IP {0} ({1}) with netmask {2} ({3})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:934
|
||||
msgid "invalid network {0} ({1}) with netmask {2} ({3})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:948
|
||||
msgid "invalid broadcast address {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:952
|
||||
#: tiramisu/option.py:814 tiramisu/option.py:989
|
||||
msgid "invalid len for vals"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:957
|
||||
#: tiramisu/option.py:820
|
||||
msgid "IP {0} ({1}) not in network {2} ({3}) with netmask {4} ({5})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:823
|
||||
msgid "invalid IP {0} ({1}) not in network {2} ({3}) with netmask {4} ({5})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:864
|
||||
msgid "inconsistency in allowed range"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:869
|
||||
msgid "max value is empty"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:886
|
||||
msgid "invalid port, range must have two values only"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:889
|
||||
msgid "invalid port, first port in range must be smaller than the second one"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:898
|
||||
msgid "invalid port"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:900
|
||||
msgid "invalid port, must be an between {0} and {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:914
|
||||
msgid "invalid network address"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:920
|
||||
msgid "network address shouldn't be in reserved class"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:922
|
||||
msgid "invalid network address, mustn't be in reserved class"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:935
|
||||
msgid "invalid netmask address"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:952
|
||||
msgid "invalid len for opts"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:966
|
||||
msgid "invalid IP {0} ({1}) with netmask {2}, this IP is a network"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:971
|
||||
msgid "invalid network {0} ({1}) with netmask {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:985
|
||||
msgid "invalid broadcast address"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:994
|
||||
msgid "invalid broadcast {0} ({1}) with network {2} ({3}) and netmask {4} ({5})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:979
|
||||
#: tiramisu/option.py:1016
|
||||
msgid "unknown type_ {0} for hostname"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:982
|
||||
#: tiramisu/option.py:1019
|
||||
msgid "allow_ip must be a boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1012
|
||||
msgid "invalid value for {0}, must have dot"
|
||||
#: tiramisu/option.py:1021
|
||||
msgid "allow_without_dot must be a boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1015
|
||||
msgid "invalid domainname's length for {0} (max {1})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1018
|
||||
msgid "invalid domainname's length for {0} (min 2)"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1022
|
||||
msgid "invalid domainname"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1049
|
||||
msgid "duplicate option name: {0}"
|
||||
#: tiramisu/option.py:1065
|
||||
msgid "invalid domainname, must have dot"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1067
|
||||
msgid "unknown Option {0} in OptionDescription {1}"
|
||||
msgid "invalid domainname's length (max 255)"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1118
|
||||
msgid "duplicate option: {0}"
|
||||
#: tiramisu/option.py:1069
|
||||
msgid "invalid domainname's length (min 2)"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1071
|
||||
msgid "invalid domainname"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1084
|
||||
msgid "invalid email address, must contains one @"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1087
|
||||
msgid "invalid username in email address"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1100
|
||||
msgid "invalid url, must start with http:// or https://"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1119
|
||||
msgid "invalid url, port must be an between 0 and 65536"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1125
|
||||
msgid "invalid url, must ends with filename"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1137
|
||||
msgid "invalid username"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1148
|
||||
msgid "invalid filename"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1175
|
||||
msgid "duplicate option name: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1193
|
||||
msgid "unknown Option {0} in OptionDescription {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1244
|
||||
msgid "duplicate option: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1275
|
||||
msgid "consistency with option {0} which is not in Config"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1156
|
||||
#: tiramisu/option.py:1283
|
||||
msgid "no option for path {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1162
|
||||
#: tiramisu/option.py:1289
|
||||
msgid "no option {0} found"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1172
|
||||
#: tiramisu/option.py:1299
|
||||
msgid "cannot change group_type if already set (old {0}, new {1})"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1185
|
||||
#: tiramisu/option.py:1311
|
||||
msgid "master group {0} shall not have a subgroup"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1188
|
||||
#: tiramisu/option.py:1314
|
||||
msgid "master group {0} shall not have a symlinkoption"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1191
|
||||
#: tiramisu/option.py:1317
|
||||
msgid "not allowed option {0} in group {1}: this option is not a multi"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1202
|
||||
#: tiramisu/option.py:1327
|
||||
msgid "master group with wrong master name for {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1211
|
||||
msgid "no child has same nom has master group for: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1214
|
||||
msgid "group_type: {0} not allowed"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1306
|
||||
msgid "malformed requirements type for option: {0}, must be a dict"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1323
|
||||
msgid "malformed requirements for option: {0} require must have option, expected and action keys"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1328
|
||||
msgid "malformed requirements for option: {0} inverse must be boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1332
|
||||
msgid "malformed requirements for option: {0} transitive must be boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1336
|
||||
msgid "malformed requirements for option: {0} same_action must be boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1340
|
||||
msgid "malformed requirements must be an option in option {0}"
|
||||
#: tiramisu/option.py:1335
|
||||
msgid "callback of master's option shall not refered a slave's ones"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1343
|
||||
msgid "malformed requirements option {0} should not be a multi"
|
||||
msgid "group_type: {0} not allowed"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1349
|
||||
#: tiramisu/option.py:1443
|
||||
msgid "malformed requirements type for option: {0}, must be a dict"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1460
|
||||
msgid "malformed requirements for option: {0} require must have option, expected and action keys"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1465
|
||||
msgid "malformed requirements for option: {0} inverse must be boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1469
|
||||
msgid "malformed requirements for option: {0} transitive must be boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1473
|
||||
msgid "malformed requirements for option: {0} same_action must be boolean"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1477
|
||||
msgid "malformed requirements must be an option in option {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1480
|
||||
msgid "malformed requirements option {0} must not be a multi"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1486
|
||||
msgid "malformed requirements second argument must be valid for option {0}: {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1354
|
||||
#: tiramisu/option.py:1491
|
||||
msgid "inconsistency in action types for option: {0} action: {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1379
|
||||
msgid "{0} should be a function"
|
||||
#: tiramisu/option.py:1516
|
||||
msgid "{0} must be a function"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1382
|
||||
msgid "{0}_params should be a dict"
|
||||
#: tiramisu/option.py:1519
|
||||
msgid "{0}_params must be a dict"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1385
|
||||
msgid "{0}_params with key {1} should not have length different to 1"
|
||||
#: tiramisu/option.py:1522
|
||||
msgid "{0}_params with key {1} mustn't have length different to 1"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1389
|
||||
msgid "{0}_params should be tuple for key \"{1}\""
|
||||
#: tiramisu/option.py:1526
|
||||
msgid "{0}_params must be tuple for key \"{1}\""
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1395
|
||||
#: tiramisu/option.py:1532
|
||||
msgid "validator not support tuple"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1398
|
||||
msgid "{0}_params should have an option not a {0} for first argument"
|
||||
#: tiramisu/option.py:1535
|
||||
msgid "{0}_params must have an option not a {0} for first argument"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/option.py:1402
|
||||
msgid "{0}_params should have a boolean not a {0} for second argument"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:111
|
||||
msgid "can't rebind {0}"
|
||||
#: tiramisu/option.py:1539
|
||||
msgid "{0}_params must have a boolean not a {0} for second argument"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:116
|
||||
msgid "can't rebind {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:121
|
||||
msgid "can't unbind {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:254
|
||||
#: tiramisu/setting.py:272
|
||||
msgid "cannot append {0} property for option {1}: this property is calculated"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:317
|
||||
#: tiramisu/setting.py:363
|
||||
msgid "opt and all_properties must not be set together in reset"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:332
|
||||
#: tiramisu/setting.py:378
|
||||
msgid "if opt is not None, path should not be None in _getproperties"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:435
|
||||
#: tiramisu/setting.py:487
|
||||
msgid "cannot change the value for option {0} this option is frozen"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:441
|
||||
#: tiramisu/setting.py:493
|
||||
msgid "trying to access to an option named: {0} with properties {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:459
|
||||
#: tiramisu/setting.py:511
|
||||
msgid "permissive must be a tuple"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:466 tiramisu/value.py:299
|
||||
#: tiramisu/setting.py:518 tiramisu/value.py:334
|
||||
msgid "invalid generic owner {0}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:553
|
||||
#: tiramisu/setting.py:606
|
||||
msgid "malformed requirements imbrication detected for option: '{0}' with requirement on: '{1}'"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/setting.py:565
|
||||
#: tiramisu/setting.py:617
|
||||
msgid "option '{0}' has requirement's property error: {1} {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/storage/__init__.py:47
|
||||
#: tiramisu/storage/__init__.py:52
|
||||
msgid "storage_type is already set, cannot rebind it"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/storage/__init__.py:81
|
||||
#: tiramisu/storage/__init__.py:86
|
||||
msgid "option {0} not already exists in storage {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/storage/dictionary/storage.py:37
|
||||
#: tiramisu/storage/dictionary/storage.py:39
|
||||
msgid "dictionary storage cannot delete session"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/storage/dictionary/storage.py:48
|
||||
#: tiramisu/storage/dictionary/storage.py:50
|
||||
msgid "session already used"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/storage/dictionary/storage.py:50
|
||||
#: tiramisu/storage/dictionary/storage.py:52
|
||||
msgid "a dictionary cannot be persistent"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:306
|
||||
#: tiramisu/value.py:341
|
||||
msgid "no value for {0} cannot change owner to {1}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:414
|
||||
#: tiramisu/value.py:423
|
||||
msgid "can force cache only if cache is actived in config"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:462
|
||||
msgid "{0} is already a Multi "
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:498 tiramisu/value.py:562
|
||||
msgid "invalid len for the slave: {0} which has {1} as master"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:438
|
||||
msgid "invalid len for the master: {0} which has {1} as slave with greater len"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:468
|
||||
#: tiramisu/value.py:534
|
||||
msgid "cannot append a value on a multi option {0} which is a slave"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:505
|
||||
#: tiramisu/value.py:572
|
||||
msgid "cannot sort multi option {0} if master or slave"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:509
|
||||
#: tiramisu/value.py:576
|
||||
msgid "cmp is not permitted in python v3 or greater"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:518
|
||||
#: tiramisu/value.py:585
|
||||
msgid "cannot reverse multi option {0} if master or slave"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:526
|
||||
#: tiramisu/value.py:593
|
||||
msgid "cannot insert multi option {0} if master or slave"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:534
|
||||
#: tiramisu/value.py:601
|
||||
msgid "cannot extend multi option {0} if master or slave"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:562
|
||||
#: tiramisu/value.py:612
|
||||
msgid "invalid value {0} for option {1}: {2}"
|
||||
msgstr ""
|
||||
|
||||
#: tiramisu/value.py:630
|
||||
msgid "cannot pop a value on a multi option {0} which is a slave"
|
||||
msgstr ""
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user