consistency is now simple validation
This commit is contained in:
parent
e62268c46a
commit
5c3a133928
37 changed files with 1163 additions and 6135 deletions
|
@ -5,11 +5,9 @@ from .autopath import do_autopath
|
||||||
do_autopath()
|
do_autopath()
|
||||||
from .config import config_type, get_config, value_list, global_owner
|
from .config import config_type, get_config, value_list, global_owner
|
||||||
|
|
||||||
from tiramisu.setting import owners
|
from tiramisu import ChoiceOption, StrOption, OptionDescription, Config, owners, Calculation, \
|
||||||
from tiramisu import ChoiceOption, StrOption, OptionDescription, Config
|
undefined, Params, ParamValue, ParamOption, list_sessions
|
||||||
from tiramisu.error import ConfigError
|
from tiramisu.error import ConfigError
|
||||||
from tiramisu import undefined, Params, ParamValue, ParamOption
|
|
||||||
from tiramisu.storage import list_sessions
|
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
@ -58,7 +56,7 @@ def test_choiceoption(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_choiceoption_function(config_type):
|
def test_choiceoption_function(config_type):
|
||||||
choice = ChoiceOption('choice', '', values=return_list)
|
choice = ChoiceOption('choice', '', values=Calculation(return_list))
|
||||||
odesc = OptionDescription('od', '', [choice])
|
odesc = OptionDescription('od', '', [choice])
|
||||||
cfg = Config(odesc)
|
cfg = Config(odesc)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
|
@ -79,7 +77,7 @@ def test_choiceoption_function(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_choiceoption_function_error():
|
def test_choiceoption_function_error():
|
||||||
choice = ChoiceOption('choice', '', values=return_error)
|
choice = ChoiceOption('choice', '', values=Calculation(return_error))
|
||||||
odesc = OptionDescription('od', '', [choice])
|
odesc = OptionDescription('od', '', [choice])
|
||||||
cfg = Config(odesc)
|
cfg = Config(odesc)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
|
@ -87,7 +85,7 @@ def test_choiceoption_function_error():
|
||||||
|
|
||||||
|
|
||||||
def test_choiceoption_function_error_args():
|
def test_choiceoption_function_error_args():
|
||||||
choice = ChoiceOption('choice', '', values=return_error, values_params=Params((ParamValue('val1'),)))
|
choice = ChoiceOption('choice', '', values=Calculation(return_error, Params(ParamValue('val1'))))
|
||||||
odesc = OptionDescription('od', '', [choice])
|
odesc = OptionDescription('od', '', [choice])
|
||||||
cfg = Config(odesc)
|
cfg = Config(odesc)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
|
@ -95,7 +93,7 @@ def test_choiceoption_function_error_args():
|
||||||
|
|
||||||
|
|
||||||
def test_choiceoption_function_error_kwargs():
|
def test_choiceoption_function_error_kwargs():
|
||||||
choice = ChoiceOption('choice', '', values=return_error, values_params=Params(kwargs={'kwargs': ParamValue('val1')}))
|
choice = ChoiceOption('choice', '', values=Calculation(return_error, Params(kwargs={'kwargs': ParamValue('val1')})))
|
||||||
odesc = OptionDescription('od', '', [choice])
|
odesc = OptionDescription('od', '', [choice])
|
||||||
cfg = Config(odesc)
|
cfg = Config(odesc)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
|
@ -103,7 +101,7 @@ def test_choiceoption_function_error_kwargs():
|
||||||
|
|
||||||
|
|
||||||
def test_choiceoption_calc_function(config_type):
|
def test_choiceoption_calc_function(config_type):
|
||||||
choice = ChoiceOption('choice', "", values=return_calc_list, values_params=Params((ParamValue('val1'),)))
|
choice = ChoiceOption('choice', "", values=Calculation(return_calc_list, Params(ParamValue('val1'))))
|
||||||
odesc = OptionDescription('od', '', [choice])
|
odesc = OptionDescription('od', '', [choice])
|
||||||
cfg = Config(odesc)
|
cfg = Config(odesc)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
|
@ -125,8 +123,7 @@ def test_choiceoption_calc_opt_function(config_type):
|
||||||
str_ = StrOption('str', '', 'val1')
|
str_ = StrOption('str', '', 'val1')
|
||||||
choice = ChoiceOption('choice',
|
choice = ChoiceOption('choice',
|
||||||
"",
|
"",
|
||||||
values=return_calc_list,
|
values=Calculation(return_calc_list, Params(ParamOption(str_))))
|
||||||
values_params=Params((ParamOption(str_),)))
|
|
||||||
odesc = OptionDescription('od', '', [str_, choice])
|
odesc = OptionDescription('od', '', [str_, choice])
|
||||||
cfg = Config(odesc)
|
cfg = Config(odesc)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
|
@ -148,8 +145,7 @@ def test_choiceoption_calc_opt_function_propertyerror():
|
||||||
str_ = StrOption('str', '', 'val1', properties=('disabled',))
|
str_ = StrOption('str', '', 'val1', properties=('disabled',))
|
||||||
choice = ChoiceOption('choice',
|
choice = ChoiceOption('choice',
|
||||||
"",
|
"",
|
||||||
values=return_calc_list,
|
values=Calculation(return_calc_list, Params(ParamOption(str_))))
|
||||||
values_params=Params((ParamOption(str_),)))
|
|
||||||
odesc = OptionDescription('od', '', [str_, choice])
|
odesc = OptionDescription('od', '', [str_, choice])
|
||||||
cfg = Config(odesc)
|
cfg = Config(odesc)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
|
@ -164,14 +160,12 @@ def test_choiceoption_calc_opt_multi_function():
|
||||||
choice = ChoiceOption('choice',
|
choice = ChoiceOption('choice',
|
||||||
"",
|
"",
|
||||||
default_multi='val2',
|
default_multi='val2',
|
||||||
values=return_val,
|
values=Calculation(return_val, Params(ParamOption(str_))),
|
||||||
values_params=Params((ParamOption(str_),)),
|
|
||||||
multi=True)
|
multi=True)
|
||||||
ch2 = ChoiceOption('ch2',
|
ch2 = ChoiceOption('ch2',
|
||||||
"",
|
"",
|
||||||
default=['val2'],
|
default=['val2'],
|
||||||
values=return_val,
|
values=Calculation(return_val, Params(ParamOption(str_))),
|
||||||
values_params=Params((ParamOption(str_),)),
|
|
||||||
multi=True)
|
multi=True)
|
||||||
odesc = OptionDescription('od', '', [str_, choice, ch2])
|
odesc = OptionDescription('od', '', [str_, choice, ch2])
|
||||||
cfg = Config(odesc)
|
cfg = Config(odesc)
|
||||||
|
@ -203,14 +197,12 @@ def test_choiceoption_calc_opt_multi_function_kwargs(config_type):
|
||||||
choice = ChoiceOption('choice',
|
choice = ChoiceOption('choice',
|
||||||
"",
|
"",
|
||||||
default_multi='val2',
|
default_multi='val2',
|
||||||
values=return_val,
|
values=Calculation(return_val, Params(kwargs={'val': ParamOption(str_)})),
|
||||||
values_params=Params(kwargs={'val': ParamOption(str_)}),
|
|
||||||
multi=True)
|
multi=True)
|
||||||
ch2 = ChoiceOption('ch2',
|
ch2 = ChoiceOption('ch2',
|
||||||
"",
|
"",
|
||||||
default=['val2'],
|
default=['val2'],
|
||||||
values=return_val,
|
values=Calculation(return_val, Params(kwargs={'val': ParamOption(str_)})),
|
||||||
values_params=Params(kwargs={'val': ParamOption(str_)}),
|
|
||||||
multi=True)
|
multi=True)
|
||||||
odesc = OptionDescription('od', '', [str_, choice, ch2])
|
odesc = OptionDescription('od', '', [str_, choice, ch2])
|
||||||
cfg = Config(odesc)
|
cfg = Config(odesc)
|
||||||
|
@ -237,21 +229,12 @@ def test_choiceoption_calc_opt_multi_function_kwargs(config_type):
|
||||||
raises(ValueError, "cfg.option('ch2').value.get()")
|
raises(ValueError, "cfg.option('ch2').value.get()")
|
||||||
|
|
||||||
|
|
||||||
def test_choiceoption_calc_invalid():
|
|
||||||
str_ = StrOption('str', '', ['val1'], multi=True)
|
|
||||||
str_
|
|
||||||
raises(ValueError,
|
|
||||||
"choice = ChoiceOption('choice', '', default_multi='val2', values=[1, 2, 3], \
|
|
||||||
values_params=Params((ParamOption(str_),)), multi=True)")
|
|
||||||
|
|
||||||
|
|
||||||
def test_choiceoption_calc_not_list():
|
def test_choiceoption_calc_not_list():
|
||||||
str_ = StrOption('str', '', 'val1')
|
str_ = StrOption('str', '', 'val1')
|
||||||
choice = ChoiceOption('choice',
|
choice = ChoiceOption('choice',
|
||||||
"",
|
"",
|
||||||
default_multi='val2',
|
default_multi='val2',
|
||||||
values=return_val,
|
values=Calculation(return_val, Params(ParamOption(str_))),
|
||||||
values_params=Params((ParamOption(str_),)),
|
|
||||||
multi=True)
|
multi=True)
|
||||||
odesc = OptionDescription('od', '', [str_, choice])
|
odesc = OptionDescription('od', '', [str_, choice])
|
||||||
cfg = Config(odesc)
|
cfg = Config(odesc)
|
||||||
|
|
|
@ -139,77 +139,11 @@ def test_deref_optiondescription_config():
|
||||||
assert w() is None
|
assert w() is None
|
||||||
|
|
||||||
|
|
||||||
#def test_deref_groupconfig():
|
|
||||||
# if not IS_DEREFABLE:
|
|
||||||
# return
|
|
||||||
# i1 = IntOption('i1', '')
|
|
||||||
# od1 = OptionDescription('od1', '', [i1])
|
|
||||||
# od2 = OptionDescription('od2', '', [od1])
|
|
||||||
# conf1 = Config(od2, 'conf1')
|
|
||||||
# conf2 = Config(od2, 'conf2')
|
|
||||||
# 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():
|
|
||||||
# if not IS_DEREFABLE:
|
|
||||||
# return
|
|
||||||
# i1 = IntOption('i1', '')
|
|
||||||
# od1 = OptionDescription('od1', '', [i1])
|
|
||||||
# od2 = OptionDescription('od2', '', [od1])
|
|
||||||
# conf1 = Config(od2, 'conf1')
|
|
||||||
# conf2 = Config(od2, 'conf2')
|
|
||||||
# meta = MetaConfig([conf1, conf2])
|
|
||||||
# w = weakref.ref(conf1)
|
|
||||||
# del(conf1)
|
|
||||||
# assert w() is not None
|
|
||||||
# del(meta)
|
|
||||||
# assert w() is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_deref_consistency():
|
|
||||||
if not IS_DEREFABLE:
|
|
||||||
return
|
|
||||||
a = IPOption('a', '')
|
|
||||||
b = NetmaskOption('b', '')
|
|
||||||
od = OptionDescription('od', '', [a, b])
|
|
||||||
b.impl_add_consistency('ip_netmask', a)
|
|
||||||
cfg = Config(od)
|
|
||||||
w = weakref.ref(a)
|
|
||||||
x = weakref.ref(b)
|
|
||||||
y = weakref.ref(od)
|
|
||||||
z = weakref.ref(cfg)
|
|
||||||
assert w() is not None
|
|
||||||
assert x() is not None
|
|
||||||
assert y() is not None
|
|
||||||
assert z() is not None
|
|
||||||
del(a)
|
|
||||||
del(b)
|
|
||||||
assert w() is not None
|
|
||||||
assert x() is not None
|
|
||||||
assert y() is not None
|
|
||||||
assert z() is not None
|
|
||||||
del(od)
|
|
||||||
assert w() is not None
|
|
||||||
assert x() is not None
|
|
||||||
assert y() is not None
|
|
||||||
assert z() is not None
|
|
||||||
del(cfg)
|
|
||||||
assert y() is None
|
|
||||||
assert z() is None
|
|
||||||
#assert w() is None
|
|
||||||
#assert x() is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_deref_validator():
|
def test_deref_validator():
|
||||||
if not IS_DEREFABLE:
|
if not IS_DEREFABLE:
|
||||||
return
|
return
|
||||||
a = StrOption('a', '', default='yes')
|
a = StrOption('a', '', default='yes')
|
||||||
b = StrOption('b', '', validator=funcname, validator_params=Params((ParamOption(a),)), default='val')
|
b = StrOption('b', '', validators=[Calculation(funcname, Params(ParamOption(a)))], default='val')
|
||||||
od = OptionDescription('root', '', [a, b])
|
od = OptionDescription('root', '', [a, b])
|
||||||
cfg = Config(od)
|
cfg = Config(od)
|
||||||
w = weakref.ref(a)
|
w = weakref.ref(a)
|
||||||
|
@ -234,8 +168,6 @@ def test_deref_validator():
|
||||||
del(cfg)
|
del(cfg)
|
||||||
assert y() is None
|
assert y() is None
|
||||||
assert z() is None
|
assert z() is None
|
||||||
#assert w() is None
|
|
||||||
#assert x() is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_deref_callback():
|
def test_deref_callback():
|
||||||
|
@ -267,8 +199,6 @@ def test_deref_callback():
|
||||||
del(cfg)
|
del(cfg)
|
||||||
assert y() is None
|
assert y() is None
|
||||||
assert z() is None
|
assert z() is None
|
||||||
#assert w() is None
|
|
||||||
#assert x() is None
|
|
||||||
|
|
||||||
|
|
||||||
def test_deref_symlink():
|
def test_deref_symlink():
|
||||||
|
@ -298,8 +228,6 @@ def test_deref_symlink():
|
||||||
assert w() is not None
|
assert w() is not None
|
||||||
assert x() is not None
|
assert x() is not None
|
||||||
del(cfg)
|
del(cfg)
|
||||||
#assert w() is None
|
|
||||||
#assert x() is None
|
|
||||||
assert y() is None
|
assert y() is None
|
||||||
assert z() is None
|
assert z() is None
|
||||||
|
|
||||||
|
@ -333,7 +261,5 @@ def test_deref_dyn():
|
||||||
assert w() is not None
|
assert w() is not None
|
||||||
assert x() is not None
|
assert x() is not None
|
||||||
del(cfg)
|
del(cfg)
|
||||||
#assert w() is None
|
|
||||||
#assert x() is None
|
|
||||||
assert y() is None
|
assert y() is None
|
||||||
assert z() is None
|
assert z() is None
|
||||||
|
|
|
@ -9,7 +9,7 @@ from tiramisu import BoolOption, StrOption, ChoiceOption, IPOption, \
|
||||||
UnicodeOption, PortOption, BroadcastOption, DomainnameOption, \
|
UnicodeOption, PortOption, BroadcastOption, DomainnameOption, \
|
||||||
EmailOption, URLOption, UsernameOption, FilenameOption, SymLinkOption, \
|
EmailOption, URLOption, UsernameOption, FilenameOption, SymLinkOption, \
|
||||||
OptionDescription, DynOptionDescription, SynDynOption, submulti, Leadership, \
|
OptionDescription, DynOptionDescription, SynDynOption, submulti, Leadership, \
|
||||||
Config, Params, ParamOption, ParamValue, Calculation, calc_value
|
Config, Params, ParamOption, ParamValue, ParamSuffix, ParamSelfOption, Calculation, calc_value
|
||||||
from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError
|
from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError
|
||||||
from tiramisu.storage import list_sessions
|
from tiramisu.storage import list_sessions
|
||||||
|
|
||||||
|
@ -28,7 +28,7 @@ def return_dynval(value='val', suffix=None):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
||||||
def return_list2(suffix=None):
|
def return_list2(suffix):
|
||||||
return [str(suffix), 'val2']
|
return [str(suffix), 'val2']
|
||||||
|
|
||||||
|
|
||||||
|
@ -249,7 +249,7 @@ def test_callback_dyndescription():
|
||||||
|
|
||||||
|
|
||||||
def test_callback_list_dyndescription():
|
def test_callback_list_dyndescription():
|
||||||
st = StrOption('st', '', Calculation(return_list2), multi=True)
|
st = StrOption('st', '', Calculation(return_list2, Params(ParamSuffix())), multi=True)
|
||||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||||
od = OptionDescription('od', '', [dod])
|
od = OptionDescription('od', '', [dod])
|
||||||
od2 = OptionDescription('od', '', [od])
|
od2 = OptionDescription('od', '', [od])
|
||||||
|
@ -675,7 +675,7 @@ def test_requires_dyndescription2():
|
||||||
|
|
||||||
def test_validator_dyndescription():
|
def test_validator_dyndescription():
|
||||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||||
st = StrOption('st', '', validator=return_true, validator_params=Params((ParamValue('yes'),)), default='val')
|
st = StrOption('st', '', validators=[Calculation(return_true, Params((ParamSelfOption(), ParamValue('yes'))))], default='val')
|
||||||
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
|
||||||
od = OptionDescription('od', '', [dod, val1])
|
od = OptionDescription('od', '', [dod, val1])
|
||||||
od2 = OptionDescription('od', '', [od])
|
od2 = OptionDescription('od', '', [od])
|
||||||
|
@ -735,108 +735,13 @@ def test_information_dyndescription_context():
|
||||||
assert api.information.get('testcfgod') == 'val3'
|
assert api.information.get('testcfgod') == 'val3'
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_dyndescription():
|
|
||||||
st1 = StrOption('st', '')
|
|
||||||
st2 = StrOption('st2', '')
|
|
||||||
dod = DynOptionDescription('dod', '', [st1, st2], suffixes=Calculation(return_list))
|
|
||||||
od1 = OptionDescription('od', '', [dod])
|
|
||||||
st1.impl_add_consistency('not_equal', st2)
|
|
||||||
od2 = OptionDescription('od', '', [od1])
|
|
||||||
api = Config(od2)
|
|
||||||
api.option('od.dodval1.stval1').value.set('yes')
|
|
||||||
raises(ValueError, "api.option('od.dodval1.st2val1').value.set('yes')")
|
|
||||||
api.option('od.dodval2.stval2').value.set('yes')
|
|
||||||
raises(ValueError, "api.option('od.dodval2.st2val2').value.set('yes')")
|
|
||||||
raises(ValueError, "api.option('od.dodval1.st2val1').value.set('yes')")
|
|
||||||
api.option('od.dodval2.stval2').value.reset()
|
|
||||||
raises(ValueError, "api.option('od.dodval1.st2val1').value.set('yes')")
|
|
||||||
api.option('od.dodval2.st2val2').value.set('yes')
|
|
||||||
raises(ValueError, "api.option('od.dodval2.stval2').value.set('yes')")
|
|
||||||
#
|
|
||||||
api.option('od.dodval1.stval1').value.reset()
|
|
||||||
api.option('od.dodval2.st2val2').value.reset()
|
|
||||||
api.option('od.dodval1.st2val1').value.set('yes')
|
|
||||||
raises(ValueError, "api.option('od.dodval1.stval1').value.set('yes')")
|
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_dyndescription_default():
|
|
||||||
st = StrOption('st', '', 'yes')
|
|
||||||
st2 = StrOption('st2', '')
|
|
||||||
dod = DynOptionDescription('dod', '', [st, st2], suffixes=Calculation(return_list))
|
|
||||||
od = OptionDescription('od', '', [dod])
|
|
||||||
st.impl_add_consistency('not_equal', st2)
|
|
||||||
od2 = OptionDescription('od', '', [od])
|
|
||||||
api = Config(od2)
|
|
||||||
raises(ValueError, "api.option('od.dodval1.st2val1').value.set('yes')")
|
|
||||||
raises(ValueError, "api.option('od.dodval2.st2val2').value.set('yes')")
|
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_dyndescription_default_multi2():
|
|
||||||
st = StrOption('st', '', ['yes'], multi=True)
|
|
||||||
st2 = StrOption('st2', '', ['yes'], multi=True)
|
|
||||||
dod = DynOptionDescription('dod', '', [st, st2], suffixes=Calculation(return_list))
|
|
||||||
dod
|
|
||||||
# FIXME raises(ValueError, "st.impl_add_consistency('not_equal', st2)")
|
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_only_one_dyndescription():
|
|
||||||
st = StrOption('st', '')
|
|
||||||
st
|
|
||||||
st2 = StrOption('st2', '')
|
|
||||||
dod = DynOptionDescription('dod', '', [st2], suffixes=Calculation(return_list))
|
|
||||||
raises(ConfigError, "st.impl_add_consistency('not_equal', st2)")
|
|
||||||
raises(ConfigError, "st2.impl_add_consistency('not_equal', st)")
|
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_became_dyndescription():
|
|
||||||
st = StrOption('st', '')
|
|
||||||
st2 = StrOption('st2', '')
|
|
||||||
st2.impl_add_consistency('not_equal', st)
|
|
||||||
od = DynOptionDescription('dod', '', [st2], suffixes=Calculation(return_list))
|
|
||||||
od2 = OptionDescription('od', '', [od, st])
|
|
||||||
od2
|
|
||||||
raises(ConfigError, "c = Config(od2)")
|
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_became_dyndescription2():
|
|
||||||
st = StrOption('st', '')
|
|
||||||
st2 = StrOption('st2', '')
|
|
||||||
st.impl_add_consistency('not_equal', st2)
|
|
||||||
od = DynOptionDescription('dod', '', [st2], suffixes=Calculation(return_list))
|
|
||||||
od2 = OptionDescription('od', '', [od, st])
|
|
||||||
od2
|
|
||||||
raises(ConfigError, "c = Config(od2)")
|
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_external_dyndescription():
|
|
||||||
st = StrOption('st', '')
|
|
||||||
st1 = StrOption('st1', '')
|
|
||||||
st2 = StrOption('st2', '')
|
|
||||||
dod = DynOptionDescription('dod', '', [st1, st2], suffixes=Calculation(return_list))
|
|
||||||
od = OptionDescription('od', '', [dod, st])
|
|
||||||
od
|
|
||||||
raises(ConfigError, "st.impl_add_consistency('not_equal', st2)")
|
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_notsame_dyndescription():
|
|
||||||
st1 = StrOption('st1', '')
|
|
||||||
st2 = StrOption('st2', '')
|
|
||||||
dod = DynOptionDescription('dod', '', [st1, st2], suffixes=Calculation(return_list))
|
|
||||||
tst1 = StrOption('tst1', '')
|
|
||||||
tst2 = StrOption('tst2', '')
|
|
||||||
tdod = DynOptionDescription('tdod', '', [tst1, tst2], suffixes=Calculation(return_list))
|
|
||||||
od = OptionDescription('od', '', [dod, tdod])
|
|
||||||
od
|
|
||||||
raises(ConfigError, "st1.impl_add_consistency('not_equal', tst1)")
|
|
||||||
|
|
||||||
|
|
||||||
def test_all_dyndescription():
|
def test_all_dyndescription():
|
||||||
st = StrOption('st', '')
|
st = StrOption('st', '')
|
||||||
ip = IPOption('ip', '')
|
ip = IPOption('ip', '')
|
||||||
network = NetworkOption('network', '')
|
network = NetworkOption('network', '')
|
||||||
netmask = NetmaskOption('netmask', '')
|
netmask = NetmaskOption('netmask', '')
|
||||||
ch = ChoiceOption('ch', '', ('val1', 'val2', 'val3'))
|
ch = ChoiceOption('ch', '', ('val1', 'val2', 'val3'))
|
||||||
ch1 = ChoiceOption('ch1', '', return_list)
|
ch1 = ChoiceOption('ch1', '', Calculation(return_list))
|
||||||
boo = BoolOption('boo', '')
|
boo = BoolOption('boo', '')
|
||||||
intr = IntOption('intr', '')
|
intr = IntOption('intr', '')
|
||||||
floa = FloatOption('floa', '')
|
floa = FloatOption('floa', '')
|
||||||
|
@ -925,34 +830,6 @@ def test_all_dyndescription():
|
||||||
assert api.option('dodval2.filenameval2').value.get() is None
|
assert api.option('dodval2.filenameval2').value.get() is None
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_ip_netmask_dyndescription():
|
|
||||||
ipa = IPOption('a', '')
|
|
||||||
netb = NetmaskOption('b', '')
|
|
||||||
dod = DynOptionDescription('dod', '', [ipa, netb], suffixes=Calculation(return_list))
|
|
||||||
netb.impl_add_consistency('ip_netmask', ipa)
|
|
||||||
od1 = OptionDescription('od', '', [dod])
|
|
||||||
cfg = Config(od1)
|
|
||||||
cfg.option('dodval1.aval1').value.set('192.168.1.1')
|
|
||||||
cfg.option('dodval1.bval1').value.set('255.255.255.0')
|
|
||||||
cfg.option('dodval2.aval2').value.set('192.168.1.2')
|
|
||||||
cfg.option('dodval2.bval2').value.set('255.255.255.128')
|
|
||||||
cfg.option('dodval2.bval2').value.set('255.255.255.0')
|
|
||||||
raises(ValueError, "cfg.option('dodval2.bval2').value.set('255.255.255.255')")
|
|
||||||
|
|
||||||
|
|
||||||
def test_consistency_ip_in_network_dyndescription():
|
|
||||||
neta = NetworkOption('a', '')
|
|
||||||
netb = NetmaskOption('b', '')
|
|
||||||
ipc = IPOption('c', '')
|
|
||||||
dod = DynOptionDescription('dod', '', [neta, netb, ipc], suffixes=Calculation(return_list))
|
|
||||||
ipc.impl_add_consistency('in_network', neta, netb)
|
|
||||||
od1 = OptionDescription('od', '', [dod])
|
|
||||||
cfg = Config(od1)
|
|
||||||
cfg.option('dodval1.aval1').value.set('192.168.1.0')
|
|
||||||
cfg.option('dodval1.bval1').value.set('255.255.255.0')
|
|
||||||
cfg.option('dodval1.cval1').value.set('192.168.1.1')
|
|
||||||
|
|
||||||
|
|
||||||
def test_leadership_dyndescription():
|
def test_leadership_dyndescription():
|
||||||
st1 = StrOption('st1', "", multi=True)
|
st1 = StrOption('st1', "", multi=True)
|
||||||
st2 = StrOption('st2', "", multi=True)
|
st2 = StrOption('st2', "", multi=True)
|
||||||
|
|
|
@ -178,15 +178,6 @@ def test_force_store_value():
|
||||||
compare(conf.value.exportation(), (('wantref', 'wantref2', 'wantref3'), (None, None, None), (False, False, (False,)), ('forced', 'forced', 'forced')))
|
compare(conf.value.exportation(), (('wantref', 'wantref2', 'wantref3'), (None, None, None), (False, False, (False,)), ('forced', 'forced', 'forced')))
|
||||||
|
|
||||||
|
|
||||||
def test_force_store_value_no_requirement():
|
|
||||||
booloption = BoolOption('bool', 'Test boolean option', default=True)
|
|
||||||
try:
|
|
||||||
BoolOption('wantref', 'Test requires', default=False,
|
|
||||||
requires=({'option': booloption, 'expected': True, 'action': 'force_store_value'},))
|
|
||||||
except ValueError:
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
def test_force_store_value_leadership_follower():
|
def test_force_store_value_leadership_follower():
|
||||||
b = IntOption('int', 'Test int option', multi=True)
|
b = IntOption('int', 'Test int option', multi=True)
|
||||||
c = StrOption('str', 'Test string option', multi=True, properties=('force_store_value',))
|
c = StrOption('str', 'Test string option', multi=True, properties=('force_store_value',))
|
||||||
|
|
|
@ -330,9 +330,9 @@ def test_groups_with_leader_default_value_2(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_groups_with_leader_hidden_in_config():
|
def test_groups_with_leader_hidden_in_config():
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, properties=('hidden',))
|
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('hidden',))
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('hidden',))
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0], properties=('hidden',))
|
||||||
od = OptionDescription('root', '', [interface1])
|
od = OptionDescription('root', '', [interface1])
|
||||||
cfg = Config(od)
|
cfg = Config(od)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
|
@ -412,22 +412,6 @@ def test_groups_with_leader_reset_out_of_range(config_type):
|
||||||
cfg.send()
|
cfg.send()
|
||||||
|
|
||||||
|
|
||||||
def test_groups_with_leader_hidden_in_config3():
|
|
||||||
#if leader is hidden, follower are hidden too
|
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, properties=('hidden',))
|
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
|
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
|
||||||
od = OptionDescription('root', '', [interface1])
|
|
||||||
cfg = Config(od)
|
|
||||||
cfg.property.read_write()
|
|
||||||
cfg.permissive.set(frozenset(['hidden']))
|
|
||||||
assert cfg.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.get() == []
|
|
||||||
cfg.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1'])
|
|
||||||
assert cfg.forcepermissive.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
|
|
||||||
raises(PropertiesOptionError, "cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()")
|
|
||||||
raises(PropertiesOptionError, "cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()")
|
|
||||||
|
|
||||||
|
|
||||||
def test_allowed_groups():
|
def test_allowed_groups():
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
|
||||||
|
@ -449,7 +433,8 @@ def test_values_with_leader_disabled_leader(config_type):
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145'])
|
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145'])
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set("192.168.230.145")
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set("192.168.230.145")
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.reset()
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.reset()
|
||||||
cfg_ori.option('ip_admin_eth0.ip_admin_eth0').property.add('disabled')
|
raises(LeadershipError, "cfg_ori.option('ip_admin_eth0.ip_admin_eth0').property.add('disabled')")
|
||||||
|
cfg_ori.option('ip_admin_eth0').property.add('disabled')
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
if config_type != 'tiramisu-api':
|
if config_type != 'tiramisu-api':
|
||||||
# FIXME
|
# FIXME
|
||||||
|
@ -847,49 +832,7 @@ def test_follower_not_multi():
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau")
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau")
|
||||||
raises(ValueError, "Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])")
|
raises(ValueError, "Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])")
|
||||||
|
#
|
||||||
|
|
||||||
def test_follower_not_same():
|
|
||||||
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
|
||||||
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
|
|
||||||
interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
|
|
||||||
ip_admin_eth1 = IPOption('ip_admin_eth1', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
|
||||||
netmask_admin_eth1 = NetmaskOption('netmask_admin_eth1', "masque du sous-réseau", multi=True)
|
|
||||||
netmask_admin_eth1.impl_add_consistency('ip_netmask', ip_admin_eth0)
|
|
||||||
interface1 = Leadership('interface1', '', [ip_admin_eth1, netmask_admin_eth1])
|
|
||||||
od1 = OptionDescription('od', '', [interface0, interface1])
|
|
||||||
maconfig = OptionDescription('toto', '', [od1])
|
|
||||||
raises(ConfigError, "Config(maconfig)")
|
|
||||||
|
|
||||||
|
|
||||||
def test_follower_not_same_not_equal():
|
|
||||||
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
|
||||||
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
|
|
||||||
interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
|
|
||||||
ip_admin_eth1 = IPOption('ip_admin_eth1', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
|
||||||
netmask_admin_eth1 = NetmaskOption('netmask_admin_eth1', "masque du sous-réseau", multi=True)
|
|
||||||
netmask_admin_eth1.impl_add_consistency('not_equal', netmask_admin_eth0)
|
|
||||||
interface1 = Leadership('interface1', '', [ip_admin_eth1, netmask_admin_eth1])
|
|
||||||
od1 = OptionDescription('od', '', [interface0, interface1])
|
|
||||||
maconfig = OptionDescription('toto', '', [od1])
|
|
||||||
cfg = Config(maconfig)
|
|
||||||
cfg.property.read_write()
|
|
||||||
|
|
||||||
|
|
||||||
def test_follower_consistency():
|
|
||||||
network_admin_eth1 = NetworkOption('network_admin_eth1', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
|
||||||
netmask_admin_eth1 = NetmaskOption('netmask_admin_eth1', "masque du sous-réseau", multi=True)
|
|
||||||
netmask_admin_eth1.impl_add_consistency('network_netmask', network_admin_eth1)
|
|
||||||
interface1 = Leadership('interface1', '', [network_admin_eth1, netmask_admin_eth1])
|
|
||||||
od1 = OptionDescription('od', '', [interface1])
|
|
||||||
maconfig = OptionDescription('toto', '', [od1])
|
|
||||||
cfg = Config(maconfig)
|
|
||||||
cfg.property.read_write()
|
|
||||||
cfg.option('od.interface1.network_admin_eth1').value.set(['192.168.1.128', '192.168.2.0', '192.168.3.128'])
|
|
||||||
cfg.option('od.interface1.netmask_admin_eth1', 0).value.set('255.255.255.128')
|
|
||||||
cfg.option('od.interface1.netmask_admin_eth1', 1).value.set('255.255.255.0')
|
|
||||||
cfg.option('od.interface1.netmask_admin_eth1', 2).value.set('255.255.255.128')
|
|
||||||
cfg.option('od.interface1.network_admin_eth1').value.pop(0)
|
|
||||||
|
|
||||||
|
|
||||||
def test_follower_force_store_value():
|
def test_follower_force_store_value():
|
||||||
|
|
|
@ -5,7 +5,8 @@ do_autopath()
|
||||||
from tiramisu.setting import groups, owners
|
from tiramisu.setting import groups, owners
|
||||||
from tiramisu import IntOption, StrOption, NetworkOption, NetmaskOption, BoolOption, ChoiceOption, \
|
from tiramisu import IntOption, StrOption, NetworkOption, NetmaskOption, BoolOption, ChoiceOption, \
|
||||||
IPOption, OptionDescription, Leadership, Config, GroupConfig, MetaConfig, \
|
IPOption, OptionDescription, Leadership, Config, GroupConfig, MetaConfig, \
|
||||||
Calculation, Params, ParamOption, ParamValue, calc_value
|
Calculation, Params, ParamOption, ParamValue, calc_value, ParamSelfOption, \
|
||||||
|
valid_network_netmask, valid_not_equal
|
||||||
from tiramisu.error import ConfigError, ConflictError, PropertiesOptionError, LeadershipError, APIError
|
from tiramisu.error import ConfigError, ConflictError, PropertiesOptionError, LeadershipError, APIError
|
||||||
from tiramisu.storage import list_sessions
|
from tiramisu.storage import list_sessions
|
||||||
from .config import config_type, get_config
|
from .config import config_type, get_config
|
||||||
|
@ -719,9 +720,8 @@ def test_meta_force_default_and_dont_change():
|
||||||
|
|
||||||
def test_meta_properties_meta():
|
def test_meta_properties_meta():
|
||||||
ip_admin_eth0 = NetworkOption('ip_admin_eth0', "ip", multi=True, default=['192.168.1.1'])
|
ip_admin_eth0 = NetworkOption('ip_admin_eth0', "ip", multi=True, default=['192.168.1.1'])
|
||||||
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "mask", multi=True, properties=('disabled',))
|
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "mask", multi=True, validators=[Calculation(valid_network_netmask, Params((ParamOption(ip_admin_eth0), ParamSelfOption())))])
|
||||||
netmask_admin_eth0.impl_add_consistency('network_netmask', ip_admin_eth0)
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0], properties=('disabled',))
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
|
||||||
od = OptionDescription('root', '', [interface1])
|
od = OptionDescription('root', '', [interface1])
|
||||||
conf1 = Config(od, session_id='conf1')
|
conf1 = Config(od, session_id='conf1')
|
||||||
conf2 = Config(od, session_id='conf2')
|
conf2 = Config(od, session_id='conf2')
|
||||||
|
@ -734,8 +734,7 @@ def test_meta_properties_meta():
|
||||||
|
|
||||||
def test_meta_exception_meta():
|
def test_meta_exception_meta():
|
||||||
ip_admin_eth0 = NetworkOption('ip_admin_eth0', "ip", multi=True, default=['192.168.1.1'])
|
ip_admin_eth0 = NetworkOption('ip_admin_eth0', "ip", multi=True, default=['192.168.1.1'])
|
||||||
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "mask", Calculation(raise_exception), multi=True)
|
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "mask", Calculation(raise_exception), multi=True, validators=[Calculation(valid_network_netmask, Params((ParamOption(ip_admin_eth0), ParamSelfOption())))])
|
||||||
netmask_admin_eth0.impl_add_consistency('network_netmask', ip_admin_eth0)
|
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
od = OptionDescription('root', '', [interface1])
|
od = OptionDescription('root', '', [interface1])
|
||||||
conf1 = Config(od, session_id='conf1')
|
conf1 = Config(od, session_id='conf1')
|
||||||
|
@ -753,8 +752,7 @@ def test_meta_properties_requires1():
|
||||||
kwargs={'condition': ParamOption(opt1, todict=True),
|
kwargs={'condition': ParamOption(opt1, todict=True),
|
||||||
'expected': ParamValue(False)}))
|
'expected': ParamValue(False)}))
|
||||||
od2 = OptionDescription('od2', "", [opt2], properties=(disabled_property,))
|
od2 = OptionDescription('od2', "", [opt2], properties=(disabled_property,))
|
||||||
opt3 = BoolOption('opt3', '')
|
opt3 = BoolOption('opt3', '', validators=[Calculation(valid_not_equal, Params((ParamOption(opt2), ParamSelfOption())))])
|
||||||
opt2.impl_add_consistency('not_equal', opt3)
|
|
||||||
od = OptionDescription('root', '', [opt1, od2, opt3])
|
od = OptionDescription('root', '', [opt1, od2, opt3])
|
||||||
conf1 = Config(od, session_id='conf1')
|
conf1 = Config(od, session_id='conf1')
|
||||||
conf1.property.read_write()
|
conf1.property.read_write()
|
||||||
|
@ -775,8 +773,7 @@ def test_meta_properties_requires_mandatory():
|
||||||
'expected': ParamValue('yes'),
|
'expected': ParamValue('yes'),
|
||||||
'default': ParamValue(None)}))
|
'default': ParamValue(None)}))
|
||||||
ip_eth0 = IPOption('ip_eth0', "ip", Calculation(return_condition, Params(kwargs={'val': ParamOption(ip_address), 'condition': ParamOption(eth0_method), 'expected': ParamValue('dhcp')})), properties=(mandatory_property,))
|
ip_eth0 = IPOption('ip_eth0', "ip", Calculation(return_condition, Params(kwargs={'val': ParamOption(ip_address), 'condition': ParamOption(eth0_method), 'expected': ParamValue('dhcp')})), properties=(mandatory_property,))
|
||||||
ip_gw = IPOption('ip_gw', 'gw')
|
ip_gw = IPOption('ip_gw', 'gw', validators=[Calculation(valid_not_equal, Params((ParamOption(ip_eth0), ParamSelfOption())))])
|
||||||
ip_gw.impl_add_consistency('not_equal', ip_eth0)
|
|
||||||
od = OptionDescription('root', '', [ip_gw, probes, eth0_method, ip_address, ip_eth0])
|
od = OptionDescription('root', '', [ip_gw, probes, eth0_method, ip_address, ip_eth0])
|
||||||
conf1 = Config(od, session_id='conf1')
|
conf1 = Config(od, session_id='conf1')
|
||||||
conf1.property.read_write()
|
conf1.property.read_write()
|
||||||
|
|
|
@ -6,7 +6,8 @@ from py.test import raises
|
||||||
from tiramisu.setting import groups, owners
|
from tiramisu.setting import groups, owners
|
||||||
from tiramisu import IntOption, StrOption, NetworkOption, NetmaskOption, \
|
from tiramisu import IntOption, StrOption, NetworkOption, NetmaskOption, \
|
||||||
OptionDescription, Leadership, Config, GroupConfig, MixConfig, \
|
OptionDescription, Leadership, Config, GroupConfig, MixConfig, \
|
||||||
MetaConfig, Params, ParamOption, ParamValue, Calculation
|
MetaConfig, Params, ParamOption, ParamValue, ParamSelfOption, Calculation, \
|
||||||
|
valid_network_netmask
|
||||||
from tiramisu.error import ConfigError, ConflictError, PropertiesOptionError, LeadershipError, APIError
|
from tiramisu.error import ConfigError, ConflictError, PropertiesOptionError, LeadershipError, APIError
|
||||||
from tiramisu.storage import list_sessions
|
from tiramisu.storage import list_sessions
|
||||||
|
|
||||||
|
@ -589,9 +590,8 @@ def test_mix_force_default_and_dont_change():
|
||||||
|
|
||||||
def test_mix_properties_mix():
|
def test_mix_properties_mix():
|
||||||
ip_admin_eth0 = NetworkOption('ip_admin_eth0', "ip", multi=True, default=['192.168.1.1'])
|
ip_admin_eth0 = NetworkOption('ip_admin_eth0', "ip", multi=True, default=['192.168.1.1'])
|
||||||
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "mask", multi=True, properties=('disabled',))
|
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "mask", multi=True, validators=[Calculation(valid_network_netmask, Params((ParamOption(ip_admin_eth0), ParamSelfOption())))])
|
||||||
netmask_admin_eth0.impl_add_consistency('network_netmask', ip_admin_eth0)
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0], properties=('disabled',))
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
|
||||||
od = OptionDescription('root', '', [interface1])
|
od = OptionDescription('root', '', [interface1])
|
||||||
conf1 = Config(od, session_id='conf1')
|
conf1 = Config(od, session_id='conf1')
|
||||||
conf2 = Config(od, session_id='conf2')
|
conf2 = Config(od, session_id='conf2')
|
||||||
|
@ -604,8 +604,7 @@ def test_mix_properties_mix():
|
||||||
|
|
||||||
def test_mix_exception_mix():
|
def test_mix_exception_mix():
|
||||||
ip_admin_eth0 = NetworkOption('ip_admin_eth0', "ip", multi=True, default=['192.168.1.1'])
|
ip_admin_eth0 = NetworkOption('ip_admin_eth0', "ip", multi=True, default=['192.168.1.1'])
|
||||||
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "mask", Calculation(raise_exception), multi=True)
|
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "mask", Calculation(raise_exception), multi=True, validators=[Calculation(valid_network_netmask, Params((ParamOption(ip_admin_eth0), ParamSelfOption())))])
|
||||||
netmask_admin_eth0.impl_add_consistency('network_netmask', ip_admin_eth0)
|
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
od = OptionDescription('root', '', [interface1])
|
od = OptionDescription('root', '', [interface1])
|
||||||
conf1 = Config(od, session_id='conf1')
|
conf1 = Config(od, session_id='conf1')
|
||||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -6,7 +6,7 @@ from .config import config_type, get_config
|
||||||
from py.test import raises
|
from py.test import raises
|
||||||
|
|
||||||
from tiramisu.setting import owners
|
from tiramisu.setting import owners
|
||||||
from tiramisu.error import PropertiesOptionError, ConfigError
|
from tiramisu.error import PropertiesOptionError, ConfigError, LeadershipError
|
||||||
from tiramisu import IntOption, FloatOption, StrOption, ChoiceOption, \
|
from tiramisu import IntOption, FloatOption, StrOption, ChoiceOption, \
|
||||||
BoolOption, OptionDescription, Leadership, Config, undefined
|
BoolOption, OptionDescription, Leadership, Config, undefined
|
||||||
from tiramisu.storage import list_sessions
|
from tiramisu.storage import list_sessions
|
||||||
|
@ -163,7 +163,7 @@ def test_force_default_on_freeze_leader_frozen():
|
||||||
descr = Leadership("dummy1", "", [dummy1, dummy2])
|
descr = Leadership("dummy1", "", [dummy1, dummy2])
|
||||||
descr = OptionDescription("root", "", [descr])
|
descr = OptionDescription("root", "", [descr])
|
||||||
cfg = Config(descr)
|
cfg = Config(descr)
|
||||||
raises(ConfigError, "cfg.option('dummy1.dummy1').property.pop('frozen')")
|
raises(LeadershipError, "cfg.option('dummy1.dummy1').property.pop('frozen')")
|
||||||
|
|
||||||
|
|
||||||
def test_force_metaconfig_on_freeze_leader_frozen():
|
def test_force_metaconfig_on_freeze_leader_frozen():
|
||||||
|
@ -172,7 +172,7 @@ def test_force_metaconfig_on_freeze_leader_frozen():
|
||||||
descr = Leadership("dummy1", "", [dummy1, dummy2])
|
descr = Leadership("dummy1", "", [dummy1, dummy2])
|
||||||
descr = OptionDescription("root", "", [descr])
|
descr = OptionDescription("root", "", [descr])
|
||||||
cfg = Config(descr)
|
cfg = Config(descr)
|
||||||
raises(ConfigError, "cfg.option('dummy1.dummy1').property.pop('frozen')")
|
raises(LeadershipError, "cfg.option('dummy1.dummy1').property.pop('frozen')")
|
||||||
|
|
||||||
|
|
||||||
def test_force_default_on_freeze_follower(config_type):
|
def test_force_default_on_freeze_follower(config_type):
|
||||||
|
|
|
@ -10,9 +10,11 @@ from tiramisu.error import display_list, ConfigError
|
||||||
from tiramisu.setting import owners, groups
|
from tiramisu.setting import owners, groups
|
||||||
from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \
|
from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \
|
||||||
StrOption, OptionDescription, Leadership, Config, undefined, \
|
StrOption, OptionDescription, Leadership, Config, undefined, \
|
||||||
Calculation, Params, ParamOption, ParamValue, ParamIndex, calc_value, calc_value_property_help
|
Calculation, Params, ParamOption, ParamValue, ParamIndex, \
|
||||||
|
calc_value, calc_value_property_help
|
||||||
from tiramisu.error import PropertiesOptionError
|
from tiramisu.error import PropertiesOptionError
|
||||||
from tiramisu.storage import list_sessions
|
from tiramisu.storage import list_sessions
|
||||||
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
def teardown_function(function):
|
def teardown_function(function):
|
||||||
|
|
|
@ -5,9 +5,13 @@ from .config import config_type, get_config
|
||||||
import warnings
|
import warnings
|
||||||
from py.test import raises
|
from py.test import raises
|
||||||
|
|
||||||
from tiramisu import BoolOption, StrOption, OptionDescription, Leadership, Config, Params, ParamValue, ParamOption, ParamContext
|
from tiramisu import BoolOption, StrOption, IPOption, NetmaskOption, NetworkOption, BroadcastOption, \
|
||||||
|
IntOption, \
|
||||||
|
OptionDescription, Leadership, Config, Params, ParamValue, ParamOption, ParamContext, \
|
||||||
|
ParamSelfOption, ParamIndex, Calculation, valid_ip_netmask, valid_network_netmask, \
|
||||||
|
valid_in_network, valid_broadcast, valid_not_equal, undefined
|
||||||
from tiramisu.setting import groups
|
from tiramisu.setting import groups
|
||||||
from tiramisu.error import ValueWarning, ConfigError
|
from tiramisu.error import ValueWarning, ConfigError, PropertiesOptionError
|
||||||
from tiramisu.i18n import _
|
from tiramisu.i18n import _
|
||||||
from tiramisu.storage import list_sessions
|
from tiramisu.storage import list_sessions
|
||||||
|
|
||||||
|
@ -82,15 +86,6 @@ def value_values_auto2(value, values, auto=False):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def value_values_index2(value, values, index, auto=False):
|
|
||||||
if auto != False:
|
|
||||||
raise ValueError('auto should be False')
|
|
||||||
if not (value == 'val1' and values == ['val1'] and index == 'val' or
|
|
||||||
value == 'val1' and values == ['val1', None] and index == 'val' or
|
|
||||||
value == 'val2' and values == ['val1', 'val2'] and index == 'val'):
|
|
||||||
raise ValueError('error')
|
|
||||||
|
|
||||||
|
|
||||||
def value_empty(value, empty, values):
|
def value_empty(value, empty, values):
|
||||||
if not value == 'val' or empty is not False and not values == ['val']:
|
if not value == 'val' or empty is not False and not values == ['val']:
|
||||||
raise ValueError('error')
|
raise ValueError('error')
|
||||||
|
@ -103,9 +98,9 @@ def valid_from_config(value, config):
|
||||||
|
|
||||||
|
|
||||||
def test_validator(config_type):
|
def test_validator(config_type):
|
||||||
opt1 = StrOption('opt1', '', validator=return_true, default='val')
|
opt1 = StrOption('opt1', '', validators=[Calculation(return_true, Params(ParamSelfOption()))], default='val')
|
||||||
raises(ValueError, "StrOption('opt2', '', validator=return_false, default='val')")
|
raises(ValueError, "StrOption('opt2', '', validators=[Calculation(return_false, Params(ParamSelfOption()))], default='val')")
|
||||||
opt2 = StrOption('opt2', '', validator=return_false)
|
opt2 = StrOption('opt2', '', validators=[Calculation(return_false, Params(ParamSelfOption()))])
|
||||||
root = OptionDescription('root', '', [opt1, opt2])
|
root = OptionDescription('root', '', [opt1, opt2])
|
||||||
cfg_ori = Config(root)
|
cfg_ori = Config(root)
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
@ -138,9 +133,9 @@ def test_validator(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params(config_type):
|
def test_validator_params(config_type):
|
||||||
opt1 = StrOption('opt1', '', validator=return_true, validator_params=Params(ParamValue('yes')), default='val')
|
opt1 = StrOption('opt1', '', validators=[Calculation(return_true, Params((ParamSelfOption(), ParamValue('yes'))))], default='val')
|
||||||
raises(ValueError, "StrOption('opt2', '', validator=return_false, validator_params=Params(ParamValue('yes')), default='val')")
|
raises(ValueError, "StrOption('opt2', '', validators=[Calculation(return_false, Params((ParamSelfOption(), ParamValue('yes'))))], default='val')")
|
||||||
opt2 = StrOption('opt2', '', validator=return_false, validator_params=Params(ParamValue('yes')))
|
opt2 = StrOption('opt2', '', validators=[Calculation(return_false, Params((ParamSelfOption(), ParamValue('yes'))))])
|
||||||
root = OptionDescription('root', '', [opt1, opt2])
|
root = OptionDescription('root', '', [opt1, opt2])
|
||||||
cfg_ori = Config(root)
|
cfg_ori = Config(root)
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
@ -157,7 +152,7 @@ def test_validator_params(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params_value_values(config_type):
|
def test_validator_params_value_values(config_type):
|
||||||
opt1 = StrOption('opt1', '', validator=value_values, default=['val'], multi=True)
|
opt1 = StrOption('opt1', '', validators=[Calculation(value_values, Params((ParamSelfOption(whole=False), ParamSelfOption())))], default=['val'], multi=True)
|
||||||
root = OptionDescription('root', '', [opt1])
|
root = OptionDescription('root', '', [opt1])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
|
@ -166,7 +161,7 @@ def test_validator_params_value_values(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params_value_values_index(config_type):
|
def test_validator_params_value_values_index(config_type):
|
||||||
opt1 = StrOption('opt1', '', validator=value_values_index, default=['val'], multi=True)
|
opt1 = StrOption('opt1', '', validators=[Calculation(value_values_index, Params((ParamSelfOption(whole=False), ParamSelfOption(), ParamIndex())))], default=['val'], multi=True)
|
||||||
root = OptionDescription('root', '', [opt1])
|
root = OptionDescription('root', '', [opt1])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
|
@ -175,7 +170,7 @@ def test_validator_params_value_values_index(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params_value_values_leader(config_type):
|
def test_validator_params_value_values_leader(config_type):
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, validator=value_values)
|
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, validators=[Calculation(value_values, Params((ParamSelfOption(whole=False), ParamSelfOption())))])
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True)
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True)
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
root = OptionDescription('root', '', [interface1])
|
root = OptionDescription('root', '', [interface1])
|
||||||
|
@ -186,7 +181,7 @@ def test_validator_params_value_values_leader(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params_value_values_index_leader(config_type):
|
def test_validator_params_value_values_index_leader(config_type):
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, validator=value_values_index)
|
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, validators=[Calculation(value_values_index, Params((ParamSelfOption(whole=False), ParamSelfOption(), ParamIndex())))])
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True)
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True)
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
root = OptionDescription('root', '', [interface1])
|
root = OptionDescription('root', '', [interface1])
|
||||||
|
@ -198,7 +193,7 @@ def test_validator_params_value_values_index_leader(config_type):
|
||||||
|
|
||||||
def test_validator_params_value_values_follower(config_type):
|
def test_validator_params_value_values_follower(config_type):
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True)
|
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True)
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=value_values)
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validators=[Calculation(value_values, Params((ParamSelfOption(), ParamSelfOption(whole=True))))])
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
root = OptionDescription('root', '', [interface1])
|
root = OptionDescription('root', '', [interface1])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
|
@ -212,7 +207,7 @@ def test_validator_params_value_values_follower(config_type):
|
||||||
|
|
||||||
def test_validator_params_value_values_index_follower(config_type):
|
def test_validator_params_value_values_index_follower(config_type):
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True)
|
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True)
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validator=value_values_index)
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=True, validators=[Calculation(value_values_index, Params((ParamSelfOption(), ParamSelfOption(whole=True), ParamIndex())))])
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
root = OptionDescription('root', '', [interface1])
|
root = OptionDescription('root', '', [interface1])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
|
@ -224,18 +219,13 @@ def test_validator_params_value_values_index_follower(config_type):
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val2')
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val2')
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params_value_values_notmulti():
|
|
||||||
raises(ConfigError, "opt1 = StrOption('opt1', '', validator=value_values, default='val')")
|
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params_value_values_kwargs_empty(config_type):
|
def test_validator_params_value_values_kwargs_empty(config_type):
|
||||||
v = BoolOption('v', '', default=False)
|
v = BoolOption('v', '', default=False)
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, default=["ip"])
|
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True, default=["ip"])
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
|
||||||
"masque du sous-reseau",
|
"masque du sous-reseau",
|
||||||
multi=True,
|
multi=True,
|
||||||
validator=value_empty,
|
validators=[Calculation(value_empty, Params((ParamSelfOption(), ParamOption(v))))])
|
||||||
validator_params=Params(ParamOption(v)))
|
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
root = OptionDescription('root', '', [v, interface1])
|
root = OptionDescription('root', '', [v, interface1])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
|
@ -252,8 +242,7 @@ def test_validator_params_value_values_kwargs(config_type):
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
|
||||||
"masque du sous-reseau",
|
"masque du sous-reseau",
|
||||||
multi=True,
|
multi=True,
|
||||||
validator=value_values_auto,
|
validators=[Calculation(value_values_auto, Params((ParamSelfOption(), ParamSelfOption(whole=True)), kwargs={'auto': ParamOption(v)}))])
|
||||||
validator_params=Params(kwargs={'auto': ParamOption(v)}))
|
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
root = OptionDescription('root', '', [v, interface1])
|
root = OptionDescription('root', '', [v, interface1])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
|
@ -269,43 +258,7 @@ def test_validator_params_value_values_kwargs_values(config_type):
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
|
||||||
"masque du sous-reseau",
|
"masque du sous-reseau",
|
||||||
multi=True,
|
multi=True,
|
||||||
validator=value_values_auto2,
|
validators=[Calculation(value_values_auto2, Params(ParamSelfOption(), kwargs={'values': ParamOption(ip_admin_eth0)}))])
|
||||||
validator_params=Params(kwargs={'values': ParamOption(ip_admin_eth0)}))
|
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
|
||||||
root = OptionDescription('root', '', [interface1])
|
|
||||||
cfg = Config(root)
|
|
||||||
cfg = get_config(cfg, config_type)
|
|
||||||
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == []
|
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val'])
|
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('val1')
|
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val', 'val'])
|
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val2')
|
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params_value_values_kwargs2(config_type):
|
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True)
|
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
|
|
||||||
"masque du sous-reseau",
|
|
||||||
multi=True,
|
|
||||||
validator=value_values_index2,
|
|
||||||
validator_params=Params(ParamValue(['val1']), {'index': ParamOption(ip_admin_eth0)}))
|
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
|
||||||
root = OptionDescription('root', '', [interface1])
|
|
||||||
cfg = Config(root)
|
|
||||||
cfg = get_config(cfg, config_type)
|
|
||||||
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == []
|
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val'])
|
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('val1')
|
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val', 'val'])
|
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params_value_values_kwargs_index(config_type):
|
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True)
|
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
|
|
||||||
"masque du sous-reseau",
|
|
||||||
multi=True,
|
|
||||||
validator=value_values_index2,
|
|
||||||
validator_params=Params(kwargs={'index': ParamOption(ip_admin_eth0)}))
|
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
root = OptionDescription('root', '', [interface1])
|
root = OptionDescription('root', '', [interface1])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
|
@ -318,7 +271,7 @@ def test_validator_params_value_values_kwargs_index(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params_context():
|
def test_validator_params_context():
|
||||||
opt1 = StrOption('opt1', '', validator=is_context, validator_params=Params(ParamContext()), default='val')
|
opt1 = StrOption('opt1', '', validators=[Calculation(is_context, Params((ParamSelfOption(), ParamContext())))], default='val')
|
||||||
root = OptionDescription('root', '', [opt1])
|
root = OptionDescription('root', '', [opt1])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
# cfg = get_config(cfg, config_type) # ParamContext not supported
|
# cfg = get_config(cfg, config_type) # ParamContext not supported
|
||||||
|
@ -329,7 +282,7 @@ def test_validator_params_context():
|
||||||
|
|
||||||
def test_validator_params_context_value():
|
def test_validator_params_context_value():
|
||||||
opt1 = StrOption('opt1', '', 'yes')
|
opt1 = StrOption('opt1', '', 'yes')
|
||||||
opt2 = StrOption('opt2', '', validator=valid_from_config, validator_params=Params(ParamContext()), default='val')
|
opt2 = StrOption('opt2', '', validators=[Calculation(valid_from_config, Params((ParamSelfOption(), ParamContext())))], default='val')
|
||||||
root = OptionDescription('root', '', [opt1, opt2])
|
root = OptionDescription('root', '', [opt1, opt2])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
# cfg = get_config(cfg_ori, config_type) # ParamContext not supported
|
# cfg = get_config(cfg_ori, config_type) # ParamContext not supported
|
||||||
|
@ -347,8 +300,8 @@ def test_validator_params_context_value():
|
||||||
|
|
||||||
|
|
||||||
def test_validator_params_key(config_type):
|
def test_validator_params_key(config_type):
|
||||||
opt1 = StrOption('opt1', '', validator=return_true, validator_params=Params(kwargs={'param': ParamValue('yes')}), default='val')
|
opt1 = StrOption('opt1', '', validators=[Calculation(return_true, Params(ParamSelfOption(), kwargs={'param': ParamValue('yes')}))], default='val')
|
||||||
raises(ConfigError, "StrOption('opt2', '', validator=return_true, validator_params=Params(kwargs={'param_unknown': ParamValue('yes')}), default='val')")
|
raises(ConfigError, "StrOption('opt2', '', validators=[Calculation(return_true, Params(ParamSelfOption(), kwargs={'param_unknown': ParamValue('yes')}))], default='val')")
|
||||||
root = OptionDescription('root', '', [opt1])
|
root = OptionDescription('root', '', [opt1])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
|
@ -357,7 +310,7 @@ def test_validator_params_key(config_type):
|
||||||
|
|
||||||
def test_validator_params_option(config_type):
|
def test_validator_params_option(config_type):
|
||||||
opt0 = StrOption('opt0', '', default='yes')
|
opt0 = StrOption('opt0', '', default='yes')
|
||||||
opt1 = StrOption('opt1', '', validator=return_true, validator_params=Params(ParamOption(opt0)), default='val')
|
opt1 = StrOption('opt1', '', validators=[Calculation(return_true, Params((ParamSelfOption(), ParamOption(opt0))))], default='val')
|
||||||
r = OptionDescription('root', '', [opt0, opt1])
|
r = OptionDescription('root', '', [opt0, opt1])
|
||||||
cfg_ori = Config(r)
|
cfg_ori = Config(r)
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
@ -375,7 +328,7 @@ def test_validator_params_option(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_validator_multi(config_type):
|
def test_validator_multi(config_type):
|
||||||
opt1 = StrOption('opt1', '', validator=return_if_val, multi=True)
|
opt1 = StrOption('opt1', '', validators=[Calculation(return_if_val, Params(ParamSelfOption(whole=False)))], multi=True)
|
||||||
root = OptionDescription('root', '', [opt1])
|
root = OptionDescription('root', '', [opt1])
|
||||||
cfg_ori = Config(root)
|
cfg_ori = Config(root)
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
@ -394,9 +347,9 @@ def test_validator_multi(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_validator_warning(config_type):
|
def test_validator_warning(config_type):
|
||||||
opt1 = StrOption('opt1', '', validator=return_true, default='val', warnings_only=True)
|
opt1 = StrOption('opt1', '', validators=[Calculation(return_true, Params(ParamSelfOption()), warnings_only=True)], default='val')
|
||||||
opt2 = StrOption('opt2', '', validator=return_false, warnings_only=True)
|
opt2 = StrOption('opt2', '', validators=[Calculation(return_false, Params(ParamSelfOption()), warnings_only=True)])
|
||||||
opt3 = StrOption('opt3', '', validator=return_if_val, multi=True, warnings_only=True)
|
opt3 = StrOption('opt3', '', validators=[Calculation(return_if_val, Params(ParamSelfOption(whole=False)), warnings_only=True)], multi=True)
|
||||||
root = OptionDescription('root', '', [opt1, opt2, opt3])
|
root = OptionDescription('root', '', [opt1, opt2, opt3])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
|
@ -440,9 +393,9 @@ def test_validator_warning(config_type):
|
||||||
|
|
||||||
|
|
||||||
def test_validator_warning_disabled(config_type):
|
def test_validator_warning_disabled(config_type):
|
||||||
opt1 = StrOption('opt1', '', validator=return_true, default='val', warnings_only=True)
|
opt1 = StrOption('opt1', '', validators=[Calculation(return_true, Params(ParamSelfOption()), warnings_only=True)], default='val')
|
||||||
opt2 = StrOption('opt2', '', validator=return_false, warnings_only=True)
|
opt2 = StrOption('opt2', '', validators=[Calculation(return_false, Params(ParamSelfOption()), warnings_only=True)])
|
||||||
opt3 = StrOption('opt3', '', validator=return_if_val, multi=True, warnings_only=True)
|
opt3 = StrOption('opt3', '', validators=[Calculation(return_if_val, Params(ParamSelfOption(whole=False)), warnings_only=True)], multi=True)
|
||||||
root = OptionDescription('root', '', [opt1, opt2, opt3])
|
root = OptionDescription('root', '', [opt1, opt2, opt3])
|
||||||
cfg_ori = Config(root)
|
cfg_ori = Config(root)
|
||||||
cfg_ori.property.pop('warnings')
|
cfg_ori.property.pop('warnings')
|
||||||
|
@ -485,8 +438,8 @@ def test_validator_warning_disabled(config_type):
|
||||||
def test_validator_warning_leadership(config_type):
|
def test_validator_warning_leadership(config_type):
|
||||||
display_name_ip = "ip reseau autorise"
|
display_name_ip = "ip reseau autorise"
|
||||||
display_name_netmask = "masque du sous-reseau"
|
display_name_netmask = "masque du sous-reseau"
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', display_name_ip, multi=True, validator=return_false, warnings_only=True)
|
ip_admin_eth0 = StrOption('ip_admin_eth0', display_name_ip, multi=True, validators=[Calculation(return_false, Params(ParamSelfOption(whole=False)), warnings_only=True)])
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', display_name_netmask, multi=True, validator=return_if_val, warnings_only=True)
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', display_name_netmask, multi=True, validators=[Calculation(return_if_val, Params(ParamSelfOption()), warnings_only=True)])
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
assert interface1.impl_get_group_type() == groups.leadership
|
assert interface1.impl_get_group_type() == groups.leadership
|
||||||
root = OptionDescription('root', '', [interface1])
|
root = OptionDescription('root', '', [interface1])
|
||||||
|
@ -543,8 +496,7 @@ def test_validator_follower_param(config_type):
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
|
||||||
"masque du sous-reseau",
|
"masque du sous-reseau",
|
||||||
multi=True,
|
multi=True,
|
||||||
validator=return_true,
|
validators=[Calculation(return_true, Params(ParamSelfOption(), kwargs={'param': ParamOption(ip_admin_eth0)}))])
|
||||||
validator_params=Params(kwargs={'param': ParamOption(ip_admin_eth0)}))
|
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
root = OptionDescription('root', '', [interface1])
|
root = OptionDescription('root', '', [interface1])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
|
@ -560,9 +512,8 @@ def test_validator_dependencies():
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise")
|
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise")
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0',
|
||||||
"masque du sous-reseau",
|
"masque du sous-reseau",
|
||||||
validator=return_true,
|
validators=[Calculation(return_true, Params(ParamSelfOption(whole=False), kwargs={'param': ParamOption(ip_admin_eth0)}))])
|
||||||
validator_params=Params(kwargs={'param': ParamOption(ip_admin_eth0)}))
|
opt2 = StrOption('opt2', '', validators=[Calculation(return_false, Params(ParamSelfOption(whole=False)))])
|
||||||
opt2 = StrOption('opt2', '', validator=return_false)
|
|
||||||
root = OptionDescription('root', '', [ip_admin_eth0, netmask_admin_eth0, opt2])
|
root = OptionDescription('root', '', [ip_admin_eth0, netmask_admin_eth0, opt2])
|
||||||
cfg = Config(root)
|
cfg = Config(root)
|
||||||
assert cfg.option('ip_admin_eth0').option.has_dependency() is False
|
assert cfg.option('ip_admin_eth0').option.has_dependency() is False
|
||||||
|
@ -572,3 +523,611 @@ def test_validator_dependencies():
|
||||||
assert cfg.option('ip_admin_eth0').option.has_dependency(False) is True
|
assert cfg.option('ip_admin_eth0').option.has_dependency(False) is True
|
||||||
assert cfg.option('netmask_admin_eth0').option.has_dependency(False) is False
|
assert cfg.option('netmask_admin_eth0').option.has_dependency(False) is False
|
||||||
assert cfg.option('opt2').option.has_dependency(False) is False
|
assert cfg.option('opt2').option.has_dependency(False) is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_ip_netmask(config_type):
|
||||||
|
a = IPOption('a', '')
|
||||||
|
b = NetmaskOption('b', '', validators=[Calculation(valid_ip_netmask, Params((ParamOption(a, todict=True), ParamSelfOption())))])
|
||||||
|
od = OptionDescription('od', '', [a, b])
|
||||||
|
cfg_ori = Config(od)
|
||||||
|
cfg = cfg_ori
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
cfg.option('a').value.set('192.168.1.1')
|
||||||
|
cfg.option('b').value.set('255.255.255.0')
|
||||||
|
cfg.option('a').value.set('192.168.1.2')
|
||||||
|
cfg.option('b').value.set('255.255.255.128')
|
||||||
|
cfg.option('b').value.set('255.255.255.0')
|
||||||
|
cfg.option('a').value.set('192.168.1.0')
|
||||||
|
raises(ValueError, "cfg.option('b').value.get()")
|
||||||
|
cfg.option('a').value.set('192.168.1.255')
|
||||||
|
raises(ValueError, "cfg.option('b').value.get()")
|
||||||
|
cfg.option('a').value.reset()
|
||||||
|
cfg.option('b').value.reset()
|
||||||
|
cfg.option('a').value.set('192.168.1.255')
|
||||||
|
raises(ValueError, "cfg.option('b').value.set('255.255.255.0')")
|
||||||
|
#
|
||||||
|
if config_type == 'tiramisu-api':
|
||||||
|
cfg.send()
|
||||||
|
cfg_ori.property.add('demoting_error_warning')
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('b').value.set('255.255.255.0')
|
||||||
|
assert len(w) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_network_netmask(config_type):
|
||||||
|
a = NetworkOption('a', '')
|
||||||
|
b = NetmaskOption('b', '', validators=[Calculation(valid_network_netmask, Params((ParamOption(a, todict=True), ParamSelfOption())))])
|
||||||
|
od = OptionDescription('od', '', [a, b])
|
||||||
|
cfg_ori = Config(od)
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
cfg.option('a').value.set('192.168.1.1')
|
||||||
|
cfg.option('b').value.set('255.255.255.255')
|
||||||
|
cfg.option('b').value.reset()
|
||||||
|
cfg.option('a').value.set('192.168.1.0')
|
||||||
|
cfg.option('b').value.set('255.255.255.0')
|
||||||
|
cfg.option('a').value.set('192.168.1.1')
|
||||||
|
raises(ValueError, "cfg.option('b').value.get()")
|
||||||
|
#
|
||||||
|
if config_type == 'tiramisu-api':
|
||||||
|
cfg.send()
|
||||||
|
cfg_ori.property.add('demoting_error_warning')
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('a').value.set('192.168.1.1')
|
||||||
|
assert len(w) == 0
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('b').value.get()
|
||||||
|
assert len(w) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_ip_in_network(config_type):
|
||||||
|
a = NetworkOption('a', '')
|
||||||
|
b = NetmaskOption('b', '')
|
||||||
|
c = IPOption('c', '', validators=[Calculation(valid_in_network, Params((ParamSelfOption(), ParamOption(a, todict=True), ParamOption(b, todict=True))))])
|
||||||
|
d = IPOption('d', '', validators=[Calculation(valid_in_network, Params((ParamSelfOption(), ParamOption(a, todict=True), ParamOption(b, todict=True))), warnings_only=True)])
|
||||||
|
od = OptionDescription('od', '', [a, b, c, d])
|
||||||
|
warnings.simplefilter("always", ValueWarning)
|
||||||
|
cfg = Config(od)
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
cfg.option('a').value.set('192.168.1.0')
|
||||||
|
cfg.option('b').value.set('255.255.255.0')
|
||||||
|
cfg.option('c').value.set('192.168.1.1')
|
||||||
|
raises(ValueError, "cfg.option('c').value.set('192.168.2.1')")
|
||||||
|
raises(ValueError, "cfg.option('c').value.set('192.168.1.0')")
|
||||||
|
raises(ValueError, "cfg.option('c').value.set('192.168.1.255')")
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('d').value.set('192.168.2.1')
|
||||||
|
assert len(w) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_ip_in_network_cidr(config_type):
|
||||||
|
a = NetworkOption('a', '', cidr=True)
|
||||||
|
c = IPOption('c', '', validators=[Calculation(valid_in_network, Params((ParamSelfOption(), ParamOption(a, todict=True))))])
|
||||||
|
d = IPOption('d', '', validators=[Calculation(valid_in_network, Params((ParamSelfOption(), ParamOption(a, todict=True))), warnings_only=True)])
|
||||||
|
od = OptionDescription('od', '', [a, c, d])
|
||||||
|
warnings.simplefilter("always", ValueWarning)
|
||||||
|
cfg = Config(od)
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
cfg.option('a').value.set('192.168.1.0/24')
|
||||||
|
cfg.option('c').value.set('192.168.1.1')
|
||||||
|
raises(ValueError, "cfg.option('c').value.set('192.168.2.1')")
|
||||||
|
raises(ValueError, "cfg.option('c').value.set('192.168.1.0')")
|
||||||
|
raises(ValueError, "cfg.option('c').value.set('192.168.1.255')")
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('d').value.set('192.168.2.1')
|
||||||
|
assert len(w) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_ip_netmask_multi(config_type):
|
||||||
|
a = IPOption('a', '', multi=True)
|
||||||
|
b = NetmaskOption('b', '', multi=True, validators=[Calculation(valid_ip_netmask, Params((ParamOption(a, todict=True), ParamSelfOption())))])
|
||||||
|
od = Leadership('a', '', [a, b])
|
||||||
|
od2 = OptionDescription('od2', '', [od])
|
||||||
|
cfg_ori = Config(od2)
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.1'])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.0')
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.2'])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.128')
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.0')
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0'])
|
||||||
|
raises(ValueError, "cfg.option('a.b', 0).value.get()")
|
||||||
|
#
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.2'])
|
||||||
|
if config_type == 'tiramisu-api':
|
||||||
|
cfg.send()
|
||||||
|
cfg_ori.property.add('demoting_error_warning')
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0'])
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('a.b', 0).value.get()
|
||||||
|
assert len(w) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_network_netmask_multi(config_type):
|
||||||
|
a = NetworkOption('a', '', multi=True)
|
||||||
|
b = NetmaskOption('b', '', multi=True, validators=[Calculation(valid_network_netmask, Params((ParamOption(a), ParamSelfOption())))])
|
||||||
|
od = Leadership('a', '', [a, b])
|
||||||
|
od2 = OptionDescription('od', '', [od])
|
||||||
|
cfg = Config(od2)
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.1'])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.255')
|
||||||
|
cfg.option('a.b', 0).value.reset()
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0'])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.0')
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.1'])
|
||||||
|
raises(ValueError, "cfg.option('a.b', 0).value.get()")
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_network_netmask_multi_follower_default_multi(config_type):
|
||||||
|
a = NetworkOption('a', '', default_multi=u'192.168.1.0', multi=True, properties=('mandatory',))
|
||||||
|
b = NetmaskOption('b', '', default_multi=u'255.255.255.0', multi=True, properties=('mandatory',), validators=[Calculation(valid_network_netmask, Params((ParamOption(a), ParamSelfOption())))])
|
||||||
|
od = Leadership('a', '', [a, b])
|
||||||
|
od2 = OptionDescription('od2', '', [od])
|
||||||
|
cfg = Config(od2)
|
||||||
|
cfg.property.read_write()
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
cfg.option('a.a').value.set([undefined])
|
||||||
|
assert cfg.option('a.a').value.get() == ['192.168.1.0']
|
||||||
|
assert cfg.option('a.b', 0).value.get() == '255.255.255.0'
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_network_netmask_multi_follower_default(config_type):
|
||||||
|
a = NetworkOption('a', '', multi=True, properties=('mandatory',))
|
||||||
|
b = NetmaskOption('b', '', default_multi=u'255.255.255.0', multi=True, properties=('mandatory',), validators=[Calculation(valid_network_netmask, Params((ParamOption(a), ParamSelfOption())))])
|
||||||
|
od = Leadership('a', '', [a, b])
|
||||||
|
od2 = OptionDescription('od2', '', [od])
|
||||||
|
cfg_ori = Config(od2)
|
||||||
|
cfg_ori.property.read_write()
|
||||||
|
cfg_ori.property.pop('cache')
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
assert cfg.option('a.a').value.get() == []
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0'])
|
||||||
|
if config_type == 'tiramisu-api':
|
||||||
|
cfg.send()
|
||||||
|
cfg_ori.property.read_only()
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
assert cfg.option('a.a').value.get() == [u'192.168.1.0']
|
||||||
|
assert cfg.option('a.b', 0).value.get() == u'255.255.255.0'
|
||||||
|
if config_type == 'tiramisu-api':
|
||||||
|
cfg.send()
|
||||||
|
cfg_ori.property.read_write()
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
cfg.option('a.a').value.set([u'192.168.1.0', u'192.168.1.1'])
|
||||||
|
raises(ValueError, "cfg.option('a.b', 0).value.set([u'192.168.1.0'])")
|
||||||
|
raises(ValueError, "cfg.option('a.b', 1).value.set([u'192.168.1.1'])")
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0', undefined])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.0')
|
||||||
|
cfg.option('a.b', 1).value.set('255.255.255.255')
|
||||||
|
cfg.option('a.a').value.set([u'192.168.1.0', u'192.168.1.1'])
|
||||||
|
|
||||||
|
|
||||||
|
def return_netmask(*args, **kwargs):
|
||||||
|
return u'255.255.255.0'
|
||||||
|
|
||||||
|
|
||||||
|
def return_netmask2(leader):
|
||||||
|
if leader is not None:
|
||||||
|
if leader.endswith('2.1'):
|
||||||
|
return u'255.255.255.0'
|
||||||
|
if not leader.endswith('.0'):
|
||||||
|
return u'255.255.255.255'
|
||||||
|
return u'255.255.255.0'
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_network_netmask_multi_follower_callback(config_type):
|
||||||
|
a = NetworkOption('a', '', multi=True, properties=('mandatory',))
|
||||||
|
b = NetmaskOption('b', '', Calculation(return_netmask, Params(kwargs={'index': ParamIndex()})), multi=True, properties=('mandatory',), validators=[Calculation(valid_network_netmask, Params((ParamOption(a), ParamSelfOption())))])
|
||||||
|
od = Leadership('a', '', [a, b])
|
||||||
|
od2 = OptionDescription('od2', '', [od])
|
||||||
|
cfg_ori = Config(od2)
|
||||||
|
cfg_ori.property.read_write()
|
||||||
|
cfg_ori.property.pop('cache')
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
assert cfg.option('a.a').value.get() == []
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0'])
|
||||||
|
if config_type == 'tiramisu-api':
|
||||||
|
cfg.send()
|
||||||
|
cfg_ori.property.read_only()
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
assert cfg.option('a.a').value.get() == [u'192.168.1.0']
|
||||||
|
assert cfg.option('a.b', 0).value.get() == '255.255.255.0'
|
||||||
|
if config_type == 'tiramisu-api':
|
||||||
|
cfg.send()
|
||||||
|
cfg_ori.property.read_write()
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
cfg.option('a.a').value.set([u'192.168.1.0', u'192.168.1.1'])
|
||||||
|
cfg.option('a.b', 0).value.get()
|
||||||
|
raises(ValueError, "cfg.option('a.b', 1).value.get()")
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0', undefined])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.0')
|
||||||
|
cfg.option('a.b', 1).value.set('255.255.255.255')
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0', '192.168.1.1'])
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_network_netmask_multi_follower_callback_value(config_type):
|
||||||
|
a = NetworkOption('a', '', multi=True, properties=('mandatory',))
|
||||||
|
b = NetmaskOption('b', '', Calculation(return_netmask2, Params(ParamOption(a))), multi=True, properties=('mandatory',), validators=[Calculation(valid_network_netmask, Params((ParamOption(a), ParamSelfOption())))])
|
||||||
|
od = Leadership('a', '', [a, b])
|
||||||
|
od2 = OptionDescription('od2', '', [od])
|
||||||
|
cfg = Config(od2)
|
||||||
|
cfg.property.read_write()
|
||||||
|
cfg.property.pop('cache')
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
assert cfg.option('a.a').value.get() == []
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0'])
|
||||||
|
assert cfg.option('a.a').value.get() == ['192.168.1.0']
|
||||||
|
assert cfg.option('a.b', 0).value.get() == '255.255.255.0'
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0', '192.168.2.1'])
|
||||||
|
assert cfg.option('a.b', 0).value.get() == '255.255.255.0'
|
||||||
|
raises(ValueError, "cfg.option('a.b', 1).value.get()")
|
||||||
|
cfg.option('a.a').value.pop(1)
|
||||||
|
#
|
||||||
|
assert cfg.option('a.a').value.get() == [u'192.168.1.0']
|
||||||
|
assert cfg.option('a.b', 0).value.get() == '255.255.255.0'
|
||||||
|
cfg.option('a.a').value.set(['192.168.2.1'])
|
||||||
|
raises(ValueError, "cfg.option('a.b', 0).value.get()")
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0'])
|
||||||
|
#
|
||||||
|
assert cfg.option('a.a').value.get() == [u'192.168.1.0']
|
||||||
|
assert cfg.option('a.b', 0).value.get() == '255.255.255.0'
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0', '192.168.1.1'])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.0')
|
||||||
|
cfg.option('a.b', 1).value.set('255.255.255.255')
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_ip_netmask_multi_leader(config_type):
|
||||||
|
a = IPOption('a', '', multi=True)
|
||||||
|
b = NetmaskOption('b', '', multi=True, validators=[Calculation(valid_ip_netmask, Params((ParamOption(a), ParamSelfOption())))])
|
||||||
|
od = Leadership('a', '', [a, b])
|
||||||
|
od2 = OptionDescription('od2', '', [od])
|
||||||
|
cfg = Config(od2)
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.1'])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.0')
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.2'])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.128')
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.0')
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0'])
|
||||||
|
raises(ValueError, "cfg.option('a.b', 0).value.get()")
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.128'])
|
||||||
|
raises(ValueError, "cfg.option('a.b', 0).value.set('255.255.255.128')")
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.2', '192.168.1.3'])
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_network_netmask_multi_leader(config_type):
|
||||||
|
a = NetworkOption('a', '', multi=True)
|
||||||
|
b = NetmaskOption('b', '', multi=True, validators=[Calculation(valid_network_netmask, Params((ParamOption(a), ParamSelfOption())))])
|
||||||
|
od = Leadership('a', '', [a, b])
|
||||||
|
od2 = OptionDescription('od2', '', [od])
|
||||||
|
cfg = Config(od2)
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.1'])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.255')
|
||||||
|
cfg.option('a.b', 0).value.reset()
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0'])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.0')
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.1'])
|
||||||
|
raises(ValueError, "cfg.option('a.b', 0).value.get()")
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_broadcast(config_type):
|
||||||
|
a = NetworkOption('a', '', multi=True)
|
||||||
|
b = NetmaskOption('b', '', multi=True, validators=[Calculation(valid_network_netmask, Params((ParamOption(a), ParamSelfOption())))])
|
||||||
|
c = BroadcastOption('c', '', multi=True, validators=[Calculation(valid_broadcast, Params((ParamOption(a), ParamOption(b), ParamSelfOption())))])
|
||||||
|
od = Leadership('a', '', [a, b, c])
|
||||||
|
od2 = OptionDescription('od2', '', [od])
|
||||||
|
cfg = Config(od2)
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
#first, test network_netmask
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.128'])
|
||||||
|
raises(ValueError, "cfg.option('a.a').value.set(['255.255.255.0'])")
|
||||||
|
#
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0'])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.0')
|
||||||
|
cfg.option('a.c', 0).value.set('192.168.1.255')
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.1'])
|
||||||
|
raises(ValueError, "cfg.option('a.b', 0).value.get()")
|
||||||
|
raises(ValueError, "cfg.option('a.c', 0).value.get()")
|
||||||
|
#
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0', '192.168.2.128'])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.0')
|
||||||
|
cfg.option('a.b', 1).value.set('255.255.255.128')
|
||||||
|
cfg.option('a.c', 0).value.set('192.168.1.255')
|
||||||
|
cfg.option('a.c', 1).value.set('192.168.2.255')
|
||||||
|
raises(ValueError, "cfg.option('a.c', 1).value.set('192.168.2.128')")
|
||||||
|
cfg.option('a.c', 1).value.set('192.168.2.255')
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_broadcast_warnings(config_type):
|
||||||
|
warnings.simplefilter("always", ValueWarning)
|
||||||
|
a = NetworkOption('a', '', properties=('mandatory', 'disabled'))
|
||||||
|
b = NetmaskOption('b', '', properties=('mandatory', 'disabled'), validators=[Calculation(valid_network_netmask, Params((ParamOption(a), ParamSelfOption())), warnings_only=True)])
|
||||||
|
od = OptionDescription('a', '', [a, b])
|
||||||
|
cfg_ori = Config(od)
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('a').value.set('192.168.1.4')
|
||||||
|
cfg.option('b').value.set('255.255.255.0')
|
||||||
|
assert len(w) == 1
|
||||||
|
if config_type == 'tiramisu-api':
|
||||||
|
cfg.send()
|
||||||
|
cfg_ori.property.read_write()
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
list(cfg.value.mandatory())
|
||||||
|
assert len(w) == 0
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_broadcast_default_1():
|
||||||
|
a = NetworkOption('a', '', '192.168.1.0')
|
||||||
|
b = NetmaskOption('b', '', '255.255.255.128')
|
||||||
|
c = BroadcastOption('c', '', '192.168.2.127', validators=[Calculation(valid_broadcast, Params((ParamOption(a), ParamOption(b), ParamSelfOption())))])
|
||||||
|
od = OptionDescription('a', '', [a, b, c])
|
||||||
|
cfg = Config(od)
|
||||||
|
raises(ValueError, "cfg.value.dict()")
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_broadcast_default_2():
|
||||||
|
a = NetworkOption('a', '', '192.168.1.0')
|
||||||
|
b = NetmaskOption('b', '', '255.255.255.128')
|
||||||
|
d = BroadcastOption('d', '', '192.168.1.127', validators=[Calculation(valid_broadcast, Params((ParamOption(a), ParamOption(b), ParamSelfOption())))])
|
||||||
|
od = OptionDescription('a', '', [a, b, d])
|
||||||
|
cfg = Config(od)
|
||||||
|
assert cfg.value.dict()
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_not_all(config_type):
|
||||||
|
a = NetworkOption('a', '', multi=True)
|
||||||
|
b = NetmaskOption('b', '', multi=True, validators=[Calculation(valid_network_netmask, Params((ParamOption(a), ParamSelfOption())))])
|
||||||
|
c = BroadcastOption('c', '', multi=True)
|
||||||
|
od = Leadership('a', '', [a, b, c])
|
||||||
|
od = OptionDescription('od2', '', [od])
|
||||||
|
cfg = Config(od)
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
cfg.option('a.a').value.set(['192.168.1.0'])
|
||||||
|
cfg.option('a.b', 0).value.set('255.255.255.0')
|
||||||
|
cfg.option('a.c', 0).value.set('192.168.1.255')
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_network_netmask_mandatory(config_type):
|
||||||
|
a = NetworkOption('a', '', multi=True, properties=('mandatory',), default=[u'0.0.0.0'])
|
||||||
|
b = NetmaskOption('b', '', multi=True, properties=('mandatory',), default_multi=u'0.0.0.0', validators=[Calculation(valid_network_netmask, Params((ParamOption(a), ParamSelfOption())))])
|
||||||
|
od = Leadership('a', '', [a, b])
|
||||||
|
od2 = OptionDescription('od2', '', [od])
|
||||||
|
cfg = Config(od2)
|
||||||
|
cfg.property.read_only()
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
cfg.value.dict()
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_has_dependency():
|
||||||
|
a = IPOption('a', '')
|
||||||
|
b = NetmaskOption('b', '', validators=[Calculation(valid_ip_netmask, Params((ParamOption(a), ParamSelfOption())))])
|
||||||
|
od = OptionDescription('od', '', [a, b])
|
||||||
|
cfg = Config(od)
|
||||||
|
assert cfg.option('a').option.has_dependency() is False
|
||||||
|
assert cfg.option('b').option.has_dependency() is True
|
||||||
|
assert cfg.option('a').option.has_dependency(False) is True
|
||||||
|
assert cfg.option('b').option.has_dependency(False) is False
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_warnings_only_more_option(config_type):
|
||||||
|
a = IntOption('a', '')
|
||||||
|
b = IntOption('b', '')
|
||||||
|
d = IntOption('d', '', validators=[Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a, todict=True), ParamOption(b, todict=True))), warnings_only=True)])
|
||||||
|
od = OptionDescription('od', '', [a, b, d])
|
||||||
|
cfg = Config(od)
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
cfg.option('a').value.set(1)
|
||||||
|
cfg.option('b').value.set(1)
|
||||||
|
warnings.simplefilter("always", ValueWarning)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('d').value.get()
|
||||||
|
assert w == []
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('d').value.set(1)
|
||||||
|
assert w != []
|
||||||
|
assert len(w) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_error_prefix():
|
||||||
|
a = IntOption('a', '')
|
||||||
|
b = IntOption('b', '', validators=[Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a, todict=True))))])
|
||||||
|
od = OptionDescription('od', '', [a, b])
|
||||||
|
cfg = Config(od)
|
||||||
|
cfg.option('a').value.set(1)
|
||||||
|
try:
|
||||||
|
cfg.option('b').value.set(1)
|
||||||
|
except Exception as err:
|
||||||
|
assert str(err) == _('"{0}" is an invalid {1} for "{2}"').format('1', _('integer'), 'b') + ', ' + _('value is identical to {}').format('"a"')
|
||||||
|
try:
|
||||||
|
cfg.option('b').value.set(1)
|
||||||
|
except Exception as err:
|
||||||
|
err.prefix = ''
|
||||||
|
assert str(err) == _('value is identical to {}').format('"a"')
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_warnings_only_option(config_type):
|
||||||
|
a = IntOption('a', '')
|
||||||
|
b = IntOption('b', '', warnings_only=True, validators=[Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a, todict=True))))])
|
||||||
|
od = OptionDescription('od', '', [a, b])
|
||||||
|
cfg_ori = Config(od)
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
cfg.option('a').value.set(1)
|
||||||
|
raises(ValueError, "cfg.option('b').value.set(1)")
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_not_equal(config_type):
|
||||||
|
a = IntOption('a', '')
|
||||||
|
b = IntOption('b', '', validators=[Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a))))])
|
||||||
|
od = OptionDescription('od', '', [a, b])
|
||||||
|
cfg_ori = Config(od)
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
assert cfg.option('a').value.get() is None
|
||||||
|
assert cfg.option('b').value.get() is None
|
||||||
|
cfg.option('a').value.set(1)
|
||||||
|
cfg.option('a').value.reset()
|
||||||
|
cfg.option('a').value.set(1)
|
||||||
|
raises(ValueError, "cfg.option('b').value.set(1)")
|
||||||
|
cfg.option('b').value.set(2)
|
||||||
|
#
|
||||||
|
if config_type == 'tiramisu-api':
|
||||||
|
cfg.send()
|
||||||
|
cfg_ori.property.add('demoting_error_warning')
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
warnings.simplefilter("always", ValueWarning)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('b').value.set(1)
|
||||||
|
assert len(w) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_not_equal_leadership(config_type):
|
||||||
|
a = IntOption('a', '', multi=True)
|
||||||
|
b = IntOption('b', '', multi=True, validators=[Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a))))])
|
||||||
|
od = Leadership('a', '', [a, b])
|
||||||
|
od2 = OptionDescription('b', '', [od])
|
||||||
|
cfg = Config(od2)
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
assert cfg.option('a.a').value.get() == []
|
||||||
|
cfg.option('a.a').value.set([1])
|
||||||
|
cfg.option('a.a').value.reset()
|
||||||
|
cfg.option('a.a').value.set([1])
|
||||||
|
raises(ValueError, "cfg.option('a.b', 0).value.set(1)")
|
||||||
|
cfg.option('a.b', 0).value.set(2)
|
||||||
|
cfg.option('a.a').value.reset()
|
||||||
|
cfg.option('a.a').value.set([1])
|
||||||
|
cfg.value.dict()
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_not_equal_leadership_default():
|
||||||
|
a = IntOption('a', '', multi=True)
|
||||||
|
b = IntOption('b', '', multi=True, default_multi=1, validators=[Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a))))])
|
||||||
|
od = Leadership('a', '', [a, b])
|
||||||
|
od2 = OptionDescription('a', '', [od])
|
||||||
|
cfg = Config(od2)
|
||||||
|
# FIXME cfg = get_config(cfg, config_type)
|
||||||
|
assert cfg.option('a.a').value.get() == []
|
||||||
|
cfg.option('a.a').value.set([1])
|
||||||
|
raises(ValueError, "cfg.option('a.b', 0).value.get()")
|
||||||
|
cfg.option('a.a').value.set([2])
|
||||||
|
cfg.option('a.a').value.reset()
|
||||||
|
cfg.option('a.a').value.set([2])
|
||||||
|
#
|
||||||
|
cfg.property.add('demoting_error_warning')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('a.b', 0).value.set(2)
|
||||||
|
assert len(w) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_default_diff():
|
||||||
|
a = IntOption('a', '', 3)
|
||||||
|
b = IntOption('b', '', 1, validators=[Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a, todict=True))))])
|
||||||
|
od = OptionDescription('od', '', [a, b])
|
||||||
|
cfg = Config(od)
|
||||||
|
# FIXME cfg = get_config(cfg, config_type)
|
||||||
|
cfg.option('b').value.set(2)
|
||||||
|
cfg.option('a').value.set(1)
|
||||||
|
owner = cfg.owner.get()
|
||||||
|
assert cfg.option('b').owner.get() == owner
|
||||||
|
raises(ValueError, "cfg.option('b').value.reset()")
|
||||||
|
assert cfg.option('b').owner.get() == owner
|
||||||
|
#
|
||||||
|
cfg.property.add('demoting_error_warning')
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('b').value.reset()
|
||||||
|
assert len(w) == 1
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_permissive(config_type):
|
||||||
|
a = IntOption('a', '', 1, properties=('hidden',))
|
||||||
|
b = IntOption('b', '', 2, validators=[Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a, todict=True))))])
|
||||||
|
od = OptionDescription('od', '', [a, b])
|
||||||
|
cfg = Config(od)
|
||||||
|
cfg.property.read_write()
|
||||||
|
cfg.permissive.set(frozenset(['hidden']))
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
raises(ValueError, "cfg.option('b').value.set(1)")
|
||||||
|
cfg.option('b').value.set(2)
|
||||||
|
|
||||||
|
|
||||||
|
def test_validator_disabled(config_type):
|
||||||
|
a = IntOption('a', '', 1, properties=('disabled',))
|
||||||
|
b = IntOption('b', '', 2, validators=[Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a, todict=True, raisepropertyerror=True))))])
|
||||||
|
od = OptionDescription('od', '', [a, b])
|
||||||
|
cfg = Config(od)
|
||||||
|
cfg.property.read_write()
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
raises(PropertiesOptionError, "cfg.option('b').value.set(1)")
|
||||||
|
|
||||||
|
|
||||||
|
def test_consistency_disabled_transitive(config_type):
|
||||||
|
a = IntOption('a', '', 1, properties=('disabled',))
|
||||||
|
b = IntOption('b', '', 2, validators=[Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a, todict=True, notraisepropertyerror=True))))])
|
||||||
|
od = OptionDescription('od', '', [a, b])
|
||||||
|
cfg = Config(od)
|
||||||
|
cfg.property.read_write()
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
cfg.option('b').value.set(1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_consistency_double_warnings(config_type):
|
||||||
|
a = IntOption('a', '', 1)
|
||||||
|
b = IntOption('b', '', 1)
|
||||||
|
c = IntOption('c', '', validators=[Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a, todict=True))), warnings_only=True), Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(b, todict=True))), warnings_only=True)])
|
||||||
|
od = OptionDescription('od', '', [a, b, c])
|
||||||
|
warnings.simplefilter("always", ValueWarning)
|
||||||
|
od2 = OptionDescription('od2', '', [od])
|
||||||
|
cfg_ori = Config(od2)
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('od.c').value.set(1)
|
||||||
|
assert w != []
|
||||||
|
if config_type == 'tiramisu-api':
|
||||||
|
# in this case warnings is for '"a" and "b"'
|
||||||
|
assert len(w) == 1
|
||||||
|
else:
|
||||||
|
# in this cas one warnings is for "a" and the second for "b"
|
||||||
|
assert len(w) == 2
|
||||||
|
cfg.option('od.a').value.set(2)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('od.c').value.get()
|
||||||
|
assert len(w) == 1
|
||||||
|
#
|
||||||
|
if config_type == 'tiramisu-api':
|
||||||
|
cfg.send()
|
||||||
|
cfg_ori.property.pop('warnings')
|
||||||
|
cfg = get_config(cfg_ori, config_type)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
cfg.option('od.c').value.set(1)
|
||||||
|
assert w == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_consistency_warnings_error(config_type):
|
||||||
|
a = IntOption('a', '', 1)
|
||||||
|
b = IntOption('b', '', 1)
|
||||||
|
c = IntOption('c', '', validators=[
|
||||||
|
Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a, todict=True))), warnings_only=True),
|
||||||
|
Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(b, todict=True))))
|
||||||
|
])
|
||||||
|
od = OptionDescription('od', '', [a, b, c])
|
||||||
|
warnings.simplefilter("always", ValueWarning)
|
||||||
|
cfg = Config(od)
|
||||||
|
cfg = get_config(cfg, config_type)
|
||||||
|
with warnings.catch_warnings(record=True) as w:
|
||||||
|
raises(ValueError, "cfg.option('c').value.set(1)")
|
||||||
|
assert w == []
|
||||||
|
|
||||||
|
|
||||||
|
def test_consistency_not_equal_has_dependency():
|
||||||
|
a = IntOption('a', '')
|
||||||
|
b = IntOption('b', '', )
|
||||||
|
b = IntOption('b', '', validators=[Calculation(valid_not_equal, Params((ParamSelfOption(), ParamOption(a, todict=True))))])
|
||||||
|
od = OptionDescription('od', '', [a, b])
|
||||||
|
cfg = Config(od)
|
||||||
|
assert cfg.option('a').option.has_dependency() is False
|
||||||
|
assert cfg.option('b').option.has_dependency() is True
|
||||||
|
assert cfg.option('a').option.has_dependency(False) is True
|
||||||
|
assert cfg.option('b').option.has_dependency(False) is False
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -88,21 +88,21 @@ def test_slots_option_readonly():
|
||||||
p = URLOption('p', '')
|
p = URLOption('p', '')
|
||||||
q = FilenameOption('q', '')
|
q = FilenameOption('q', '')
|
||||||
m = OptionDescription('m', '', [a, b, c, d, e, g, h, i, j, k, l, o, p, q])
|
m = OptionDescription('m', '', [a, b, c, d, e, g, h, i, j, k, l, o, p, q])
|
||||||
a._requires = (((a,),),)
|
a._name = 'a'
|
||||||
b._requires = (((a,),),)
|
b._name = 'b'
|
||||||
c._requires = (((a,),),)
|
c._name = 'c'
|
||||||
d._requires = (((a,),),)
|
d._name = 'd'
|
||||||
e._requires = (((a,),),)
|
e._name = 'e'
|
||||||
g._requires = (((a,),),)
|
g._name = 'g'
|
||||||
h._requires = (((a,),),)
|
h._name = 'h'
|
||||||
i._requires = (((a,),),)
|
i._name = 'i'
|
||||||
j._requires = (((a,),),)
|
j._name = 'j'
|
||||||
k._requires = (((a,),),)
|
k._name = 'k'
|
||||||
l._requires = (((a,),),)
|
l._name = 'l'
|
||||||
m._requires = (((a,),),)
|
m._name = 'm'
|
||||||
o._requires = (((a,),),)
|
o._name = 'o'
|
||||||
p._requires = (((a,),),)
|
p._name = 'p'
|
||||||
q._requires = (((a,),),)
|
q._name = 'q'
|
||||||
Config(m)
|
Config(m)
|
||||||
raises(AttributeError, "a._requires = 'a'")
|
raises(AttributeError, "a._requires = 'a'")
|
||||||
raises(AttributeError, "b._requires = 'b'")
|
raises(AttributeError, "b._requires = 'b'")
|
||||||
|
|
|
@ -14,8 +14,11 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
"""Configuration management library written in python
|
"""Configuration management library written in python
|
||||||
"""
|
"""
|
||||||
from .function import tiramisu_copy, calc_value, calc_value_property_help
|
from .function import calc_value, calc_value_property_help, valid_ip_netmask, \
|
||||||
from .autolib import Calculation, Params, ParamOption, ParamSelfOption, ParamValue, ParamIndex, ParamContext
|
valid_network_netmask, valid_in_network, valid_broadcast, \
|
||||||
|
valid_not_equal
|
||||||
|
from .autolib import Calculation, Params, ParamOption, ParamSelfOption, ParamValue, \
|
||||||
|
ParamIndex, ParamContext, ParamSuffix
|
||||||
from .option import *
|
from .option import *
|
||||||
from .error import APIError
|
from .error import APIError
|
||||||
from .api import Config, MetaConfig, GroupConfig, MixConfig
|
from .api import Config, MetaConfig, GroupConfig, MixConfig
|
||||||
|
@ -32,6 +35,7 @@ allfuncs = ['Calculation',
|
||||||
'ParamValue',
|
'ParamValue',
|
||||||
'ParamIndex',
|
'ParamIndex',
|
||||||
'ParamContext',
|
'ParamContext',
|
||||||
|
'ParamSuffix',
|
||||||
'MetaConfig',
|
'MetaConfig',
|
||||||
'MixConfig',
|
'MixConfig',
|
||||||
'GroupConfig',
|
'GroupConfig',
|
||||||
|
@ -44,9 +48,13 @@ allfuncs = ['Calculation',
|
||||||
'Storage',
|
'Storage',
|
||||||
'list_sessions',
|
'list_sessions',
|
||||||
'delete_session',
|
'delete_session',
|
||||||
'tiramisu_copy',
|
|
||||||
'calc_value',
|
'calc_value',
|
||||||
'calc_value_property_help']
|
'calc_value_property_help',
|
||||||
|
'valid_ip_netmask',
|
||||||
|
'valid_network_netmask',
|
||||||
|
'valid_in_network',
|
||||||
|
'valid_broadcast',
|
||||||
|
]
|
||||||
allfuncs.extend(all_options)
|
allfuncs.extend(all_options)
|
||||||
del(all_options)
|
del(all_options)
|
||||||
__all__ = tuple(allfuncs)
|
__all__ = tuple(allfuncs)
|
||||||
|
|
|
@ -196,11 +196,6 @@ class _TiramisuOptionOptionDescription(CommonTiramisuOption):
|
||||||
option = self._option_bag.option
|
option = self._option_bag.option
|
||||||
return option.impl_has_dependency(self_is_dep)
|
return option.impl_has_dependency(self_is_dep)
|
||||||
|
|
||||||
def requires(self):
|
|
||||||
"""Get requires for an option"""
|
|
||||||
option = self._option_bag.option
|
|
||||||
return option.impl_getrequires()
|
|
||||||
|
|
||||||
def isoptiondescription(self):
|
def isoptiondescription(self):
|
||||||
"""Test if option is an optiondescription"""
|
"""Test if option is an optiondescription"""
|
||||||
option = self._option_bag.option
|
option = self._option_bag.option
|
||||||
|
@ -274,11 +269,6 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
|
||||||
ret = value
|
ret = value
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def consistencies(self):
|
|
||||||
"""Get consistencies for an option (not for optiondescription)"""
|
|
||||||
option = self._option_bag.option
|
|
||||||
return option.get_consistencies()
|
|
||||||
|
|
||||||
def callbacks(self):
|
def callbacks(self):
|
||||||
"""Get callbacks for an option (not for optiondescription)"""
|
"""Get callbacks for an option (not for optiondescription)"""
|
||||||
option = self._option_bag.option
|
option = self._option_bag.option
|
||||||
|
|
|
@ -84,10 +84,14 @@ class ParamOption(Param):
|
||||||
|
|
||||||
|
|
||||||
class ParamSelfOption(Param):
|
class ParamSelfOption(Param):
|
||||||
__slots__ = ('todict',)
|
__slots__ = ('todict', 'whole')
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
todict: bool=False) -> None:
|
todict: bool=False,
|
||||||
|
whole: bool=undefined) -> None:
|
||||||
|
"""whole: send all value for a multi, not only indexed value"""
|
||||||
self.todict = todict
|
self.todict = todict
|
||||||
|
if whole is not undefined:
|
||||||
|
self.whole = whole
|
||||||
|
|
||||||
|
|
||||||
class ParamValue(Param):
|
class ParamValue(Param):
|
||||||
|
@ -104,15 +108,21 @@ class ParamIndex(Param):
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
|
||||||
|
|
||||||
|
class ParamSuffix(Param):
|
||||||
|
__slots__ = tuple()
|
||||||
|
|
||||||
|
|
||||||
class Calculation:
|
class Calculation:
|
||||||
__slots__ = ('function',
|
__slots__ = ('function',
|
||||||
'params',
|
'params',
|
||||||
'help_function',
|
'help_function',
|
||||||
'has_index')
|
'has_index',
|
||||||
|
'warnings_only')
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
function: Callable,
|
function: Callable,
|
||||||
params: Params=Params(),
|
params: Params=Params(),
|
||||||
help_function: Optional[Callable]=None):
|
help_function: Optional[Callable]=None,
|
||||||
|
warnings_only: bool=False):
|
||||||
assert isinstance(function, Callable), _('first argument ({0}) must be a function').format(function)
|
assert isinstance(function, Callable), _('first argument ({0}) must be a function').format(function)
|
||||||
if help_function:
|
if help_function:
|
||||||
assert isinstance(help_function, Callable), _('help_function ({0}) must be a function').format(help_function)
|
assert isinstance(help_function, Callable), _('help_function ({0}) must be a function').format(help_function)
|
||||||
|
@ -127,19 +137,22 @@ class Calculation:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
self.has_index = False
|
self.has_index = False
|
||||||
|
if warnings_only is True:
|
||||||
|
self.warnings_only = warnings_only
|
||||||
|
|
||||||
def execute(self,
|
def execute(self,
|
||||||
option_bag: OptionBag,
|
option_bag: OptionBag,
|
||||||
leadership_must_have_index: bool=False) -> Any:
|
leadership_must_have_index: bool=False,
|
||||||
if leadership_must_have_index and not self.has_index:
|
orig_value: Any=undefined,
|
||||||
leadership_must_have_index = False
|
allow_raises=False) -> Any:
|
||||||
return carry_out_calculation(option_bag.option,
|
return carry_out_calculation(option_bag.option,
|
||||||
callback=self.function,
|
callback=self.function,
|
||||||
callback_params=self.params,
|
callback_params=self.params,
|
||||||
index=option_bag.index,
|
index=option_bag.index,
|
||||||
config_bag=option_bag.config_bag,
|
config_bag=option_bag.config_bag,
|
||||||
fromconsistency=option_bag.fromconsistency,
|
leadership_must_have_index=leadership_must_have_index,
|
||||||
leadership_must_have_index=leadership_must_have_index)
|
orig_value=orig_value,
|
||||||
|
allow_raises=allow_raises)
|
||||||
|
|
||||||
def help(self,
|
def help(self,
|
||||||
option_bag: OptionBag,
|
option_bag: OptionBag,
|
||||||
|
@ -147,14 +160,11 @@ class Calculation:
|
||||||
if not self.help_function:
|
if not self.help_function:
|
||||||
return self.execute(option_bag,
|
return self.execute(option_bag,
|
||||||
leadership_must_have_index=leadership_must_have_index)
|
leadership_must_have_index=leadership_must_have_index)
|
||||||
if leadership_must_have_index and not self.has_index:
|
|
||||||
leadership_must_have_index = False
|
|
||||||
return carry_out_calculation(option_bag.option,
|
return carry_out_calculation(option_bag.option,
|
||||||
callback=self.help_function,
|
callback=self.help_function,
|
||||||
callback_params=self.params,
|
callback_params=self.params,
|
||||||
index=option_bag.index,
|
index=option_bag.index,
|
||||||
config_bag=option_bag.config_bag,
|
config_bag=option_bag.config_bag,
|
||||||
fromconsistency=option_bag.fromconsistency,
|
|
||||||
leadership_must_have_index=leadership_must_have_index)
|
leadership_must_have_index=leadership_must_have_index)
|
||||||
|
|
||||||
|
|
||||||
|
@ -167,49 +177,58 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||||
index: Optional[int],
|
index: Optional[int],
|
||||||
orig_value,
|
orig_value,
|
||||||
config_bag: ConfigBag,
|
config_bag: ConfigBag,
|
||||||
fromconsistency: List,
|
|
||||||
leadership_must_have_index: bool) -> Any:
|
leadership_must_have_index: bool) -> Any:
|
||||||
"""replace Param by true value"""
|
"""replace Param by true value"""
|
||||||
if isinstance(callbk, ParamValue):
|
def calc_index(callbk, index, same_leadership):
|
||||||
return callbk.value
|
if index is not None:
|
||||||
if isinstance(callbk, ParamIndex):
|
if hasattr(callbk, 'whole'):
|
||||||
return index
|
whole = callbk.whole
|
||||||
if config_bag is undefined:
|
else:
|
||||||
return undefined
|
# if value is same_leadership, follower are isolate by default
|
||||||
if isinstance(callbk, ParamContext):
|
# otherwise option is a whole option
|
||||||
# Not an option, set full context
|
whole = not same_leadership
|
||||||
return config_bag.context.duplicate(force_values=get_default_values_storages(),
|
if not whole:
|
||||||
force_settings=get_default_settings_storages())
|
return index
|
||||||
if isinstance(callbk, ParamSelfOption):
|
return None
|
||||||
opt = option
|
|
||||||
else:
|
def calc_self(callbk, option, index, value, config_bag):
|
||||||
# it's ParamOption
|
# index must be apply only if follower
|
||||||
opt = callbk.option
|
is_follower = option.impl_is_follower()
|
||||||
if opt.issubdyn():
|
apply_index = calc_index(callbk, index, is_follower)
|
||||||
opt = opt.to_dynoption(option.rootpath,
|
if value is undefined or (apply_index is None and is_follower):
|
||||||
option.impl_getsuffix())
|
if config_bag is undefined:
|
||||||
path = opt.impl_getpath()
|
return undefined
|
||||||
is_follower = opt.impl_is_follower()
|
path = option.impl_getpath()
|
||||||
if leadership_must_have_index and opt.impl_get_leadership() and index is None:
|
option_bag = get_option_bag(config_bag, option, path, apply_index)
|
||||||
raise Break()
|
option_bag.config_bag.unrestraint()
|
||||||
if index is not None and opt.impl_get_leadership() and \
|
option_bag.config_bag.remove_validation()
|
||||||
opt.impl_get_leadership().in_same_group(option):
|
# if we are in properties calculation, cannot calculated properties
|
||||||
if opt == option:
|
option_bag.properties = config_bag.context.cfgimpl_get_settings().getproperties(option_bag,
|
||||||
index_ = None
|
apply_requires=False)
|
||||||
with_index = False
|
new_value = get_value(callbk, option_bag, path)
|
||||||
elif is_follower:
|
if apply_index is None and is_follower:
|
||||||
index_ = index
|
new_value[index] = value
|
||||||
with_index = False
|
value = new_value
|
||||||
else:
|
elif apply_index is not None and not is_follower:
|
||||||
index_ = None
|
value = value[apply_index]
|
||||||
with_index = True
|
return value
|
||||||
else:
|
|
||||||
index_ = None
|
def get_value(callbk, option_bag, path):
|
||||||
with_index = False
|
try:
|
||||||
if opt == option and orig_value is not undefined and \
|
# get value
|
||||||
(not is_follower or index is None):
|
value = config_bag.context.getattr(path,
|
||||||
value = orig_value
|
option_bag)
|
||||||
else:
|
except PropertiesOptionError as err:
|
||||||
|
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
|
||||||
|
if callbk.notraisepropertyerror or callbk.raisepropertyerror:
|
||||||
|
raise err
|
||||||
|
raise ConfigError(_('unable to carry out a calculation for "{}"'
|
||||||
|
', {}').format(option.impl_get_display_name(), err), err)
|
||||||
|
except ValueError as err:
|
||||||
|
raise ValueError(_('the option "{0}" is used in a calculation but is invalid ({1})').format(option_bag.option.impl_get_display_name(), err))
|
||||||
|
return value
|
||||||
|
|
||||||
|
def get_option_bag(config_bag, opt, path, index_):
|
||||||
# don't validate if option is option that we tried to validate
|
# don't validate if option is option that we tried to validate
|
||||||
config_bag = config_bag.copy()
|
config_bag = config_bag.copy()
|
||||||
config_bag.properties = config_bag.true_properties - {'warnings'}
|
config_bag.properties = config_bag.true_properties - {'warnings'}
|
||||||
|
@ -220,29 +239,64 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
||||||
path,
|
path,
|
||||||
index_,
|
index_,
|
||||||
config_bag)
|
config_bag)
|
||||||
if fromconsistency:
|
return option_bag
|
||||||
option_bag.fromconsistency = fromconsistency.copy()
|
|
||||||
if opt == option:
|
if isinstance(callbk, ParamValue):
|
||||||
option_bag.config_bag.unrestraint()
|
return callbk.value
|
||||||
option_bag.config_bag.remove_validation()
|
|
||||||
# if we are in properties calculation, cannot calculated properties
|
if isinstance(callbk, ParamIndex):
|
||||||
option_bag.properties = config_bag.context.cfgimpl_get_settings().getproperties(option_bag,
|
return index
|
||||||
apply_requires=False)
|
|
||||||
try:
|
if isinstance(callbk, ParamSuffix):
|
||||||
# get value
|
if not option.issubdyn():
|
||||||
value = config_bag.context.getattr(path,
|
raise ConfigError('option "{}" is not in a dynoptiondescription'.format(option.impl_get_display_name()))
|
||||||
option_bag)
|
return option.impl_getsuffix()
|
||||||
if with_index:
|
|
||||||
value = value[index]
|
if isinstance(callbk, ParamContext):
|
||||||
except PropertiesOptionError as err:
|
if config_bag is undefined:
|
||||||
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
|
return undefined
|
||||||
if callbk.notraisepropertyerror or callbk.raisepropertyerror:
|
# Not an option, set full context
|
||||||
raise err
|
return config_bag.context.duplicate(force_values=get_default_values_storages(),
|
||||||
raise ConfigError(_('unable to carry out a calculation for "{}"'
|
force_settings=get_default_settings_storages())
|
||||||
', {}').format(option.impl_get_display_name(), err), err)
|
if isinstance(callbk, ParamSelfOption):
|
||||||
|
if leadership_must_have_index and option.impl_get_leadership() and index is None:
|
||||||
|
raise Break()
|
||||||
|
value = calc_self(callbk, option, index, orig_value, config_bag)
|
||||||
|
if not callbk.todict:
|
||||||
|
return value
|
||||||
|
return {'name': option.impl_get_display_name(),
|
||||||
|
'value': value}
|
||||||
|
|
||||||
|
# it's ParamOption
|
||||||
|
callbk_option = callbk.option
|
||||||
|
if callbk_option.issubdyn():
|
||||||
|
callbk_option = callbk_option.to_dynoption(option.rootpath,
|
||||||
|
option.impl_getsuffix())
|
||||||
|
if leadership_must_have_index and callbk_option.impl_get_leadership() and index is None:
|
||||||
|
raise Break()
|
||||||
|
if config_bag is undefined:
|
||||||
|
return undefined
|
||||||
|
if index is not None and callbk_option.impl_get_leadership() and \
|
||||||
|
callbk_option.impl_get_leadership().in_same_group(option):
|
||||||
|
if not callbk_option.impl_is_follower():
|
||||||
|
# leader
|
||||||
|
index_ = None
|
||||||
|
with_index = True
|
||||||
|
else:
|
||||||
|
# follower
|
||||||
|
index_ = index
|
||||||
|
with_index = False
|
||||||
|
else:
|
||||||
|
index_ = None
|
||||||
|
with_index = False
|
||||||
|
path = callbk_option.impl_getpath()
|
||||||
|
option_bag = get_option_bag(config_bag, callbk_option, path, index_)
|
||||||
|
value = get_value(callbk, option_bag, path)
|
||||||
|
if with_index:
|
||||||
|
value = value[index]
|
||||||
if not callbk.todict:
|
if not callbk.todict:
|
||||||
return value
|
return value
|
||||||
return {'name': opt.impl_get_display_name(),
|
return {'name': callbk_option.impl_get_display_name(),
|
||||||
'value': value}
|
'value': value}
|
||||||
|
|
||||||
|
|
||||||
|
@ -251,10 +305,9 @@ def carry_out_calculation(option,
|
||||||
callback_params: Optional[Params],
|
callback_params: Optional[Params],
|
||||||
index: Optional[int],
|
index: Optional[int],
|
||||||
config_bag: Optional[ConfigBag],
|
config_bag: Optional[ConfigBag],
|
||||||
fromconsistency: List,
|
|
||||||
orig_value=undefined,
|
orig_value=undefined,
|
||||||
leadership_must_have_index: bool=False,
|
leadership_must_have_index: bool=False,
|
||||||
is_validator: int=False):
|
allow_raises: int=False):
|
||||||
"""a function that carries out a calculation for an option's value
|
"""a function that carries out a calculation for an option's value
|
||||||
|
|
||||||
:param option: the option
|
:param option: the option
|
||||||
|
@ -265,109 +318,16 @@ def carry_out_calculation(option,
|
||||||
:type callback_params: dict
|
:type callback_params: dict
|
||||||
:param index: if an option is multi, only calculates the nth value
|
:param index: if an option is multi, only calculates the nth value
|
||||||
:type index: int
|
:type index: int
|
||||||
:param is_validator: to know if carry_out_calculation is used to validate a value
|
:param allow_raises: to know if carry_out_calculation is used to validate a value
|
||||||
|
|
||||||
The callback_params is a dict. Key is used to build args (if key is '')
|
The callback_params is a dict. Key is used to build args (if key is '')
|
||||||
and kwargs (otherwise). Values are tuple of:
|
and kwargs (otherwise). Values are tuple of:
|
||||||
- values
|
- values
|
||||||
- tuple with option and boolean's force_permissive (True when don't raise
|
- tuple with option and boolean's force_permissive (True when don't raise
|
||||||
if PropertiesOptionError)
|
if PropertiesOptionError)
|
||||||
Values could have multiple values only when key is ''.
|
Values could have multiple values only when key is ''."""
|
||||||
|
|
||||||
* if no callback_params:
|
|
||||||
=> calculate(<function func at 0x2092320>, [], {})
|
|
||||||
|
|
||||||
* if callback_params={'': ('yes',)}
|
|
||||||
=> calculate(<function func at 0x2092320>, ['yes'], {})
|
|
||||||
|
|
||||||
* if callback_params={'value': ('yes',)}
|
|
||||||
=> calculate(<function func at 0x165b320>, [], {'value': 'yes'})
|
|
||||||
|
|
||||||
* if callback_params={'': ('yes', 'no')}
|
|
||||||
=> calculate('yes', 'no')
|
|
||||||
|
|
||||||
* 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(<function func at 0x1cea320>, [11], {})
|
|
||||||
|
|
||||||
- a multi option and not leadership
|
|
||||||
opt1 == [1, 2, 3]
|
|
||||||
=> calculate(<function func at 0x223c320>, [[1, 2, 3]], {})
|
|
||||||
|
|
||||||
- option is leader or follower 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 leader or follower 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(<function func at 0x17ff320>, [], {'value': 11})
|
|
||||||
|
|
||||||
- a multi option:
|
|
||||||
opt1 == [1, 2, 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 == 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(<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]
|
|
||||||
=> 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))}
|
|
||||||
=> raises ValueError()
|
|
||||||
|
|
||||||
If index is not undefined, return a value, otherwise return:
|
|
||||||
|
|
||||||
* a list if one parameters have multi option
|
|
||||||
* a value otherwise
|
|
||||||
|
|
||||||
If calculate return list, this list is extend to return value.
|
|
||||||
"""
|
|
||||||
args = []
|
args = []
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
# if callback_params has a callback, launch several time calculate()
|
|
||||||
if option.issubdyn():
|
|
||||||
#FIXME why here? should be a ParamSuffix !
|
|
||||||
kwargs['suffix'] = option.impl_getsuffix()
|
|
||||||
if callback_params:
|
if callback_params:
|
||||||
for callbk in callback_params.args:
|
for callbk in callback_params.args:
|
||||||
try:
|
try:
|
||||||
|
@ -376,7 +336,6 @@ def carry_out_calculation(option,
|
||||||
index,
|
index,
|
||||||
orig_value,
|
orig_value,
|
||||||
config_bag,
|
config_bag,
|
||||||
fromconsistency,
|
|
||||||
leadership_must_have_index)
|
leadership_must_have_index)
|
||||||
if value is undefined:
|
if value is undefined:
|
||||||
return undefined
|
return undefined
|
||||||
|
@ -395,7 +354,6 @@ def carry_out_calculation(option,
|
||||||
index,
|
index,
|
||||||
orig_value,
|
orig_value,
|
||||||
config_bag,
|
config_bag,
|
||||||
fromconsistency,
|
|
||||||
leadership_must_have_index)
|
leadership_must_have_index)
|
||||||
if value is undefined:
|
if value is undefined:
|
||||||
return undefined
|
return undefined
|
||||||
|
@ -409,7 +367,7 @@ def carry_out_calculation(option,
|
||||||
continue
|
continue
|
||||||
ret = calculate(option,
|
ret = calculate(option,
|
||||||
callback,
|
callback,
|
||||||
is_validator,
|
allow_raises,
|
||||||
args,
|
args,
|
||||||
kwargs)
|
kwargs)
|
||||||
if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \
|
if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \
|
||||||
|
@ -434,7 +392,7 @@ def carry_out_calculation(option,
|
||||||
|
|
||||||
def calculate(option,
|
def calculate(option,
|
||||||
callback: Callable,
|
callback: Callable,
|
||||||
is_validator: bool,
|
allow_raises: bool,
|
||||||
args,
|
args,
|
||||||
kwargs):
|
kwargs):
|
||||||
"""wrapper that launches the 'callback'
|
"""wrapper that launches the 'callback'
|
||||||
|
@ -447,7 +405,7 @@ def calculate(option,
|
||||||
try:
|
try:
|
||||||
return callback(*args, **kwargs)
|
return callback(*args, **kwargs)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
if is_validator:
|
if allow_raises:
|
||||||
raise err
|
raise err
|
||||||
error = err
|
error = err
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
|
|
|
@ -48,8 +48,7 @@ class SubConfig(object):
|
||||||
descr,
|
descr,
|
||||||
context,
|
context,
|
||||||
config_bag,
|
config_bag,
|
||||||
subpath=None,
|
subpath=None):
|
||||||
fromconsistency=None):
|
|
||||||
""" Configuration option management class
|
""" Configuration option management class
|
||||||
|
|
||||||
:param descr: describes the configuration schema
|
:param descr: describes the configuration schema
|
||||||
|
@ -82,8 +81,6 @@ class SubConfig(object):
|
||||||
full_leaderpath,
|
full_leaderpath,
|
||||||
None,
|
None,
|
||||||
cconfig_bag)
|
cconfig_bag)
|
||||||
if fromconsistency:
|
|
||||||
moption_bag.fromconsistency = fromconsistency
|
|
||||||
value = self.getattr(leaderpath,
|
value = self.getattr(leaderpath,
|
||||||
moption_bag)
|
moption_bag)
|
||||||
self._impl_length = len(value)
|
self._impl_length = len(value)
|
||||||
|
@ -179,8 +176,7 @@ class SubConfig(object):
|
||||||
|
|
||||||
def cfgimpl_get_home_by_path(self,
|
def cfgimpl_get_home_by_path(self,
|
||||||
path,
|
path,
|
||||||
config_bag,
|
config_bag):
|
||||||
fromconsistency=None):
|
|
||||||
""":returns: tuple (config, name)"""
|
""":returns: tuple (config, name)"""
|
||||||
path = path.split('.')
|
path = path.split('.')
|
||||||
for step in path[:-1]:
|
for step in path[:-1]:
|
||||||
|
@ -193,8 +189,6 @@ class SubConfig(object):
|
||||||
subpath,
|
subpath,
|
||||||
None,
|
None,
|
||||||
config_bag)
|
config_bag)
|
||||||
if fromconsistency is not None:
|
|
||||||
option_bag.fromconsistency = fromconsistency
|
|
||||||
self = self.get_subconfig(option_bag)
|
self = self.get_subconfig(option_bag)
|
||||||
assert isinstance(self, SubConfig), _('unknown option {}').format(path[-1])
|
assert isinstance(self, SubConfig), _('unknown option {}').format(path[-1])
|
||||||
return self, path[-1]
|
return self, path[-1]
|
||||||
|
@ -253,17 +247,11 @@ class SubConfig(object):
|
||||||
|
|
||||||
def get_subconfig(self,
|
def get_subconfig(self,
|
||||||
option_bag):
|
option_bag):
|
||||||
if option_bag.fromconsistency:
|
|
||||||
fromconsistency = option_bag.fromconsistency.copy()
|
|
||||||
else:
|
|
||||||
fromconsistency = None
|
|
||||||
|
|
||||||
self.cfgimpl_get_settings().validate_properties(option_bag)
|
self.cfgimpl_get_settings().validate_properties(option_bag)
|
||||||
return SubConfig(option_bag.option,
|
return SubConfig(option_bag.option,
|
||||||
self._impl_context,
|
self._impl_context,
|
||||||
option_bag.config_bag,
|
option_bag.config_bag,
|
||||||
option_bag.path,
|
option_bag.path)
|
||||||
fromconsistency)
|
|
||||||
|
|
||||||
def getattr(self,
|
def getattr(self,
|
||||||
name,
|
name,
|
||||||
|
@ -276,13 +264,8 @@ class SubConfig(object):
|
||||||
"""
|
"""
|
||||||
config_bag = option_bag.config_bag
|
config_bag = option_bag.config_bag
|
||||||
if '.' in name:
|
if '.' in name:
|
||||||
if option_bag.fromconsistency:
|
|
||||||
fromconsistency = option_bag.fromconsistency.copy()
|
|
||||||
else:
|
|
||||||
fromconsistency = None
|
|
||||||
self, name = self.cfgimpl_get_home_by_path(name,
|
self, name = self.cfgimpl_get_home_by_path(name,
|
||||||
config_bag,
|
config_bag)
|
||||||
fromconsistency)
|
|
||||||
|
|
||||||
option = option_bag.option
|
option = option_bag.option
|
||||||
if option.impl_is_symlinkoption():
|
if option.impl_is_symlinkoption():
|
||||||
|
@ -309,8 +292,7 @@ class SubConfig(object):
|
||||||
length,
|
length,
|
||||||
option_bag.index))
|
option_bag.index))
|
||||||
if option.impl_is_follower() and option_bag.index is None:
|
if option.impl_is_follower() and option_bag.index is None:
|
||||||
needs_re_verify_follower_properties = option_bag.option.impl_getrequires() or \
|
needs_re_verify_follower_properties = self.cfgimpl_get_settings().has_properties_index(option_bag)
|
||||||
self.cfgimpl_get_settings().has_properties_index(option_bag)
|
|
||||||
value = []
|
value = []
|
||||||
for idx in range(length):
|
for idx in range(length):
|
||||||
soption_bag = OptionBag()
|
soption_bag = OptionBag()
|
||||||
|
@ -318,7 +300,6 @@ class SubConfig(object):
|
||||||
option_bag.path,
|
option_bag.path,
|
||||||
idx,
|
idx,
|
||||||
config_bag)
|
config_bag)
|
||||||
soption_bag.fromconsistency = option_bag.fromconsistency.copy()
|
|
||||||
try:
|
try:
|
||||||
value.append(self.getattr(name,
|
value.append(self.getattr(name,
|
||||||
soption_bag,
|
soption_bag,
|
||||||
|
@ -860,7 +841,6 @@ class KernelGroupConfig(_CommonConfig):
|
||||||
err.proptype,
|
err.proptype,
|
||||||
err._settings,
|
err._settings,
|
||||||
err._opt_type,
|
err._opt_type,
|
||||||
err._requires,
|
|
||||||
err._name,
|
err._name,
|
||||||
err._orig_opt))
|
err._orig_opt))
|
||||||
except (ValueError, LeadershipError, AttributeError) as err:
|
except (ValueError, LeadershipError, AttributeError) as err:
|
||||||
|
@ -1069,7 +1049,6 @@ class KernelMixConfig(KernelGroupConfig):
|
||||||
err.proptype,
|
err.proptype,
|
||||||
err._settings,
|
err._settings,
|
||||||
err._opt_type,
|
err._opt_type,
|
||||||
err._requires,
|
|
||||||
err._name,
|
err._name,
|
||||||
err._orig_opt))
|
err._orig_opt))
|
||||||
except (ValueError, LeadershipError, AttributeError) as err:
|
except (ValueError, LeadershipError, AttributeError) as err:
|
||||||
|
|
|
@ -58,12 +58,10 @@ class PropertiesOptionError(AttributeError):
|
||||||
proptype,
|
proptype,
|
||||||
settings,
|
settings,
|
||||||
opt_type=None,
|
opt_type=None,
|
||||||
requires=None,
|
|
||||||
name=None,
|
name=None,
|
||||||
orig_opt=None):
|
orig_opt=None):
|
||||||
if opt_type:
|
if opt_type:
|
||||||
self._opt_type = opt_type
|
self._opt_type = opt_type
|
||||||
self._requires = requires
|
|
||||||
self._name = name
|
self._name = name
|
||||||
self._orig_opt = orig_opt
|
self._orig_opt = orig_opt
|
||||||
else:
|
else:
|
||||||
|
@ -71,7 +69,6 @@ class PropertiesOptionError(AttributeError):
|
||||||
self._opt_type = 'optiondescription'
|
self._opt_type = 'optiondescription'
|
||||||
else:
|
else:
|
||||||
self._opt_type = 'option'
|
self._opt_type = 'option'
|
||||||
self._requires = option_bag.option.impl_getrequires()
|
|
||||||
self._name = option_bag.option.impl_get_display_name()
|
self._name = option_bag.option.impl_get_display_name()
|
||||||
self._orig_opt = None
|
self._orig_opt = None
|
||||||
self._option_bag = option_bag
|
self._option_bag = option_bag
|
||||||
|
@ -84,30 +81,21 @@ class PropertiesOptionError(AttributeError):
|
||||||
self._orig_opt = opt
|
self._orig_opt = opt
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
#this part is a bit slow, so only execute when display
|
# this part is a bit slow, so only execute when display
|
||||||
if self.msg is not None:
|
if self.msg is not None:
|
||||||
return self.msg
|
return self.msg
|
||||||
if self._settings is None:
|
if self._settings is None:
|
||||||
return 'error'
|
return 'error'
|
||||||
req = self._settings.apply_requires(self._option_bag,
|
properties = list(self._settings.calc_raises_properties(self._option_bag,
|
||||||
True)
|
apply_requires=False))
|
||||||
if req != {}:
|
for property_ in self._settings.get_calculated_properties(self._option_bag):
|
||||||
only_one = len(req) == 1
|
properties.append(property_.help(self._option_bag))
|
||||||
msg = []
|
|
||||||
for action, msg_ in req.items():
|
|
||||||
msg.append('"{0}" ({1})'.format(action, display_list(msg_, add_quote=False)))
|
|
||||||
msg = display_list(msg, add_quote=False)
|
|
||||||
else:
|
|
||||||
properties = list(self._settings.calc_raises_properties(self._option_bag,
|
|
||||||
apply_requires=False))
|
|
||||||
for property_ in self._settings.get_calculated_properties(self._option_bag):
|
|
||||||
properties.append(property_.help(self._option_bag))
|
|
||||||
|
|
||||||
if not properties:
|
if not properties:
|
||||||
# if proptype == ['mandatory']
|
# if proptype == ['mandatory']
|
||||||
properties = self.proptype
|
properties = self.proptype
|
||||||
only_one = len(properties) == 1
|
only_one = len(properties) == 1
|
||||||
msg = display_list(properties, add_quote=True)
|
msg = display_list(properties, add_quote=True)
|
||||||
if only_one:
|
if only_one:
|
||||||
prop_msg = _('property')
|
prop_msg = _('property')
|
||||||
else:
|
else:
|
||||||
|
@ -125,7 +113,7 @@ class PropertiesOptionError(AttributeError):
|
||||||
self._name,
|
self._name,
|
||||||
prop_msg,
|
prop_msg,
|
||||||
msg))
|
msg))
|
||||||
del self._requires, self._opt_type, self._name
|
del self._opt_type, self._name
|
||||||
del self._settings, self._orig_opt
|
del self._settings, self._orig_opt
|
||||||
return self.msg
|
return self.msg
|
||||||
|
|
||||||
|
@ -150,13 +138,6 @@ class ConflictError(Exception):
|
||||||
|
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
# miscellaneous exceptions
|
# miscellaneous exceptions
|
||||||
class RequirementError(Exception):
|
|
||||||
"""a recursive loop occurs in the requirements tree
|
|
||||||
requires
|
|
||||||
"""
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class LeadershipError(Exception):
|
class LeadershipError(Exception):
|
||||||
"problem with a leadership's value length"
|
"problem with a leadership's value length"
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -14,13 +14,144 @@
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
from typing import Any, List, Optional
|
from typing import Any, List, Optional
|
||||||
from operator import add, mul, sub, truediv
|
from operator import add, mul, sub, truediv
|
||||||
|
from ipaddress import ip_address, ip_interface, ip_network
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
from .setting import undefined
|
from .setting import undefined
|
||||||
from .error import display_list
|
from .error import display_list
|
||||||
|
|
||||||
|
|
||||||
def tiramisu_copy(val): # pragma: no cover
|
def valid_network_netmask(network: str,
|
||||||
return val
|
netmask: str):
|
||||||
|
"""FIXME
|
||||||
|
"""
|
||||||
|
if isinstance(network, dict):
|
||||||
|
network_value = network['value']
|
||||||
|
network_display_name = '({})'.format(network['name'])
|
||||||
|
else:
|
||||||
|
network_value = network
|
||||||
|
network_display_name = ''
|
||||||
|
if None in [network_value, netmask]:
|
||||||
|
return
|
||||||
|
try:
|
||||||
|
ip_network('{0}/{1}'.format(network_value, netmask))
|
||||||
|
except ValueError:
|
||||||
|
raise ValueError(_('network "{0}" {1}does not match with this netmask').format(network_value,
|
||||||
|
network_display_name))
|
||||||
|
|
||||||
|
def valid_ip_netmask(ip: str,
|
||||||
|
netmask: str):
|
||||||
|
if isinstance(ip, dict):
|
||||||
|
ip_value = ip['value']
|
||||||
|
ip_display_name = '({})'.format(ip['name'])
|
||||||
|
else:
|
||||||
|
ip_value = ip
|
||||||
|
ip_display_name = ''
|
||||||
|
if None in [ip_value, netmask]:
|
||||||
|
return
|
||||||
|
ip_netmask = ip_interface('{0}/{1}'.format(ip_value, netmask))
|
||||||
|
if ip_netmask.ip == ip_netmask.network.network_address:
|
||||||
|
raise ValueError(_('IP \"{0}\" {1}with this netmask is in fact a network address').format(ip_value, ip_display_name))
|
||||||
|
elif ip_netmask.ip == ip_netmask.network.broadcast_address:
|
||||||
|
raise ValueError(_('IP \"{0}\" {1}with this netmask is in fact a broacast address').format(ip_value, ip_display_name))
|
||||||
|
|
||||||
|
|
||||||
|
# FIXME CIDR ?
|
||||||
|
def valid_broadcast(network: 'NetworkOption',
|
||||||
|
netmask: 'NetmaskOption',
|
||||||
|
broadcast: 'BroadcastOption'):
|
||||||
|
if isinstance(network, dict):
|
||||||
|
network_value = network['value']
|
||||||
|
network_display_name = ' ({})'.format(network['name'])
|
||||||
|
else:
|
||||||
|
network_value = network
|
||||||
|
network_display_name = ''
|
||||||
|
if isinstance(netmask, dict):
|
||||||
|
netmask_value = netmask['value']
|
||||||
|
netmask_display_name = ' ({})'.format(netmask['name'])
|
||||||
|
else:
|
||||||
|
netmask_value = netmask
|
||||||
|
netmask_display_name = ''
|
||||||
|
if ip_network('{0}/{1}'.format(network, netmask)).broadcast_address != ip_address(broadcast):
|
||||||
|
raise ValueError(_('broadcast invalid with network {0}{1} and netmask {2}{3}'
|
||||||
|
'').format(network_value,
|
||||||
|
network_display_name,
|
||||||
|
netmask_value,
|
||||||
|
netmask_display_name))
|
||||||
|
|
||||||
|
|
||||||
|
def valid_in_network(ip,
|
||||||
|
network,
|
||||||
|
netmask=None):
|
||||||
|
if isinstance(network, dict):
|
||||||
|
network_value = network['value']
|
||||||
|
network_display_name = ' ({})'.format(network['name'])
|
||||||
|
else:
|
||||||
|
network_value = network
|
||||||
|
network_display_name = ''
|
||||||
|
if netmask is None:
|
||||||
|
network_obj = ip_network('{0}'.format(network_value))
|
||||||
|
else:
|
||||||
|
if isinstance(netmask, dict):
|
||||||
|
netmask_value = netmask['value']
|
||||||
|
netmask_display_name = ' ({})'.format(netmask['name'])
|
||||||
|
else:
|
||||||
|
netmask_value = netmask
|
||||||
|
netmask_display_name = ''
|
||||||
|
network_obj = ip_network('{0}/{1}'.format(network_value,
|
||||||
|
netmask_value))
|
||||||
|
if ip_interface(ip) not in network_obj:
|
||||||
|
if netmask is None:
|
||||||
|
msg = _('this IP is not in network {0}{1}').format(network_value,
|
||||||
|
network_display_name)
|
||||||
|
else:
|
||||||
|
msg = _('this IP is not in network {0}{1} with netmask {2}{3}').format(network_value,
|
||||||
|
network_display_name,
|
||||||
|
netmask_value,
|
||||||
|
netmask_display_name)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
# test if ip is not network/broadcast IP
|
||||||
|
ip_netmask = ip_interface('{0}/{1}'.format(ip, network_obj.netmask))
|
||||||
|
if ip_netmask.ip == ip_netmask.network.network_address:
|
||||||
|
if netmask is None:
|
||||||
|
msg = _('this IP with the network {0}{1} is in fact a network address').format(network_value,
|
||||||
|
network_display_name)
|
||||||
|
else:
|
||||||
|
msg = _('this IP with the netmask {0}{1} is in fact a network address').format(netmask_value,
|
||||||
|
netmask_display_name)
|
||||||
|
raise ValueError(msg)
|
||||||
|
elif ip_netmask.ip == ip_netmask.network.broadcast_address:
|
||||||
|
if netmask is None:
|
||||||
|
msg = _('this IP with the network {0}{1} is in fact a broadcast address').format(network_value,
|
||||||
|
network_display_name)
|
||||||
|
else:
|
||||||
|
msg = _('this IP with the netmask {0}{1} is in fact a broadcast address').format(netmask_value,
|
||||||
|
netmask_display_name)
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
|
def valid_not_equal(*values):
|
||||||
|
equal = set()
|
||||||
|
for idx, val in enumerate(values[1:]):
|
||||||
|
if isinstance(val, dict):
|
||||||
|
if 'propertyerror' in val:
|
||||||
|
continue
|
||||||
|
tval = val['value']
|
||||||
|
else:
|
||||||
|
tval = val
|
||||||
|
if values[0] == tval is not None:
|
||||||
|
if isinstance(val, dict):
|
||||||
|
if equal is True:
|
||||||
|
equal = set()
|
||||||
|
equal.add(val['name'])
|
||||||
|
elif not equal:
|
||||||
|
equal = True
|
||||||
|
if equal:
|
||||||
|
if equal is not True:
|
||||||
|
msg = _('value is identical to {}').format(display_list(list(equal), add_quote=True))
|
||||||
|
else:
|
||||||
|
msg = _('value is identical')
|
||||||
|
raise ValueError(msg)
|
||||||
|
|
||||||
|
|
||||||
class CalcValue:
|
class CalcValue:
|
||||||
|
|
|
@ -51,14 +51,8 @@ class Base:
|
||||||
__slots__ = ('_name',
|
__slots__ = ('_name',
|
||||||
'_path',
|
'_path',
|
||||||
'_informations',
|
'_informations',
|
||||||
#calcul
|
|
||||||
'_subdyn',
|
'_subdyn',
|
||||||
'_requires',
|
|
||||||
'_properties',
|
'_properties',
|
||||||
'_calc_properties',
|
|
||||||
#
|
|
||||||
'_consistencies',
|
|
||||||
#other
|
|
||||||
'_has_dependency',
|
'_has_dependency',
|
||||||
'_dependencies',
|
'_dependencies',
|
||||||
'_has_calc_context',
|
'_has_calc_context',
|
||||||
|
@ -68,19 +62,10 @@ class Base:
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
name: str,
|
name: str,
|
||||||
doc: str,
|
doc: str,
|
||||||
requires=None,
|
|
||||||
properties=None,
|
properties=None,
|
||||||
is_multi: bool=False) -> None:
|
is_multi: bool=False) -> None:
|
||||||
if not valid_name(name):
|
if not valid_name(name):
|
||||||
raise ValueError(_('"{0}" is an invalid name for an option').format(name))
|
raise ValueError(_('"{0}" is an invalid name for an option').format(name))
|
||||||
if requires is not None:
|
|
||||||
calc_properties, requires = validate_requires_arg(self,
|
|
||||||
is_multi,
|
|
||||||
requires,
|
|
||||||
name)
|
|
||||||
else:
|
|
||||||
calc_properties = frozenset()
|
|
||||||
requires = undefined
|
|
||||||
if properties is None:
|
if properties is None:
|
||||||
properties = frozenset()
|
properties = frozenset()
|
||||||
elif isinstance(properties, tuple):
|
elif isinstance(properties, tuple):
|
||||||
|
@ -92,153 +77,18 @@ class Base:
|
||||||
assert isinstance(properties, frozenset), _('invalid properties type {0} for {1},'
|
assert isinstance(properties, frozenset), _('invalid properties type {0} for {1},'
|
||||||
' must be a frozenset').format(type(properties),
|
' must be a frozenset').format(type(properties),
|
||||||
name)
|
name)
|
||||||
self.validate_properties(name,
|
|
||||||
calc_properties,
|
|
||||||
properties)
|
|
||||||
_setattr = object.__setattr__
|
|
||||||
_setattr(self, '_name', name)
|
|
||||||
_setattr(self, '_informations', {'doc': doc})
|
|
||||||
if calc_properties is not undefined:
|
|
||||||
_setattr(self, '_calc_properties', calc_properties)
|
|
||||||
if requires is not undefined:
|
|
||||||
_setattr(self, '_requires', requires)
|
|
||||||
if properties:
|
|
||||||
_setattr(self, '_properties', properties)
|
|
||||||
|
|
||||||
def validate_properties(self,
|
|
||||||
name: str,
|
|
||||||
calc_properties: FrozenSet[str],
|
|
||||||
properties: FrozenSet[str]) -> None:
|
|
||||||
set_forbidden_properties = calc_properties & properties
|
|
||||||
if set_forbidden_properties != frozenset():
|
|
||||||
raise ValueError(_('conflict: properties already set in requirement {0} for {1}'
|
|
||||||
'').format(display_list(set_forbidden_properties, add_quote=True),
|
|
||||||
name))
|
|
||||||
assert isinstance(properties, frozenset), _('invalid properties type {0} for {1},'
|
|
||||||
' must be a frozenset').format(type(properties),
|
|
||||||
name)
|
|
||||||
for prop in properties:
|
for prop in properties:
|
||||||
if not isinstance(prop, str):
|
if not isinstance(prop, str):
|
||||||
if not isinstance(prop, Calculation):
|
if not isinstance(prop, Calculation):
|
||||||
raise ValueError(_('invalid property type {0} for {1}, must be a string or a Calculation').format(type(prop), name))
|
raise ValueError(_('invalid property type {0} for {1}, must be a string or a Calculation').format(type(prop), name))
|
||||||
params = prop.params
|
for param in chain(prop.params.args, prop.params.kwargs.values()):
|
||||||
for param in chain(params.args, params.kwargs.values()):
|
|
||||||
if isinstance(param, ParamOption):
|
if isinstance(param, ParamOption):
|
||||||
param.option._add_dependency(self)
|
param.option._add_dependency(self)
|
||||||
|
_setattr = object.__setattr__
|
||||||
def _get_function_args(self,
|
_setattr(self, '_name', name)
|
||||||
function: Callable) -> Tuple[Set[str], Set[str], bool, bool]:
|
_setattr(self, '_informations', {'doc': doc})
|
||||||
args = set()
|
if properties:
|
||||||
kwargs = set()
|
_setattr(self, '_properties', properties)
|
||||||
positional = False
|
|
||||||
keyword = False
|
|
||||||
for param in signature(function).parameters.values():
|
|
||||||
if param.kind == param.VAR_POSITIONAL:
|
|
||||||
positional = True
|
|
||||||
elif param.kind == param.VAR_KEYWORD:
|
|
||||||
keyword = True
|
|
||||||
elif param.default is param.empty:
|
|
||||||
args.add(param.name)
|
|
||||||
else:
|
|
||||||
kwargs.add(param.name)
|
|
||||||
return args, kwargs, positional, keyword
|
|
||||||
|
|
||||||
def _get_parameters_args(self,
|
|
||||||
calculator_params: Optional[Params],
|
|
||||||
add_value: bool) -> Tuple[Set[str], Set[str]]:
|
|
||||||
args = set()
|
|
||||||
kwargs = set()
|
|
||||||
# add value as first argument
|
|
||||||
if add_value:
|
|
||||||
args.add('value')
|
|
||||||
if self.impl_is_dynoptiondescription():
|
|
||||||
kwargs.add('suffix')
|
|
||||||
if calculator_params:
|
|
||||||
for idx in range(len(calculator_params.args)):
|
|
||||||
# construct an appropriate name
|
|
||||||
args.add('param{}'.format(idx))
|
|
||||||
for param in calculator_params.kwargs:
|
|
||||||
kwargs.add(param)
|
|
||||||
return args, kwargs
|
|
||||||
|
|
||||||
def _build_calculator_params(self,
|
|
||||||
calculator: Callable,
|
|
||||||
calculator_params: Optional[Params],
|
|
||||||
type_: str,
|
|
||||||
add_value: bool=False) -> Union[None, Params]:
|
|
||||||
"""
|
|
||||||
:add_value: add value as first argument for validator
|
|
||||||
"""
|
|
||||||
assert isinstance(calculator, Callable), _('{0} must be a function').format(type_)
|
|
||||||
if calculator_params is not None:
|
|
||||||
assert isinstance(calculator_params, Params), _('{0}_params must be a params'
|
|
||||||
'').format(type_)
|
|
||||||
for param in chain(calculator_params.args, calculator_params.kwargs.values()):
|
|
||||||
if isinstance(param, ParamContext):
|
|
||||||
self._has_calc_context = True
|
|
||||||
elif isinstance(param, ParamOption):
|
|
||||||
param.option._add_dependency(self)
|
|
||||||
if type_ == 'validator':
|
|
||||||
self._has_dependency = True
|
|
||||||
is_multi = self.impl_is_optiondescription() or self.impl_is_multi()
|
|
||||||
func_args, func_kwargs, func_positional, func_keyword = self._get_function_args(calculator)
|
|
||||||
calculator_args, calculator_kwargs = self._get_parameters_args(calculator_params, add_value)
|
|
||||||
# remove knowned kwargs
|
|
||||||
common_kwargs = func_kwargs & calculator_kwargs
|
|
||||||
func_kwargs -= common_kwargs
|
|
||||||
calculator_kwargs -= common_kwargs
|
|
||||||
# remove knowned calculator's kwargs in func's args
|
|
||||||
common = func_args & calculator_kwargs
|
|
||||||
func_args -= common
|
|
||||||
calculator_kwargs -= common
|
|
||||||
# remove unknown calculator's args in func's args
|
|
||||||
for idx in range(min(len(calculator_args), len(func_args))):
|
|
||||||
func_args.pop()
|
|
||||||
calculator_args.pop()
|
|
||||||
# remove unknown calculator's args in func's kwargs
|
|
||||||
if is_multi:
|
|
||||||
func_kwargs_left = func_kwargs - {'index', 'self'}
|
|
||||||
else:
|
|
||||||
func_kwargs_left = func_kwargs
|
|
||||||
func_kwargs_pop = set()
|
|
||||||
for idx in range(min(len(calculator_args), len(func_kwargs_left))):
|
|
||||||
func_kwargs_pop.add(func_kwargs_left.pop())
|
|
||||||
calculator_args.pop()
|
|
||||||
func_kwargs -= func_kwargs_pop
|
|
||||||
# func_positional or keyword is True, so assume all args or kwargs are satisfy
|
|
||||||
if func_positional:
|
|
||||||
calculator_args = set()
|
|
||||||
if func_keyword:
|
|
||||||
calculator_kwargs = set()
|
|
||||||
if calculator_args or calculator_kwargs:
|
|
||||||
# there is more args/kwargs than expected!
|
|
||||||
raise ConfigError(_('cannot find those arguments "{}" in function "{}" for "{}"'
|
|
||||||
'').format(display_list(list(calculator_args | calculator_kwargs)),
|
|
||||||
calculator.__name__,
|
|
||||||
self.impl_get_display_name()))
|
|
||||||
has_index = False
|
|
||||||
if is_multi and func_args and not self.impl_is_dynoptiondescription():
|
|
||||||
if calculator_params is None:
|
|
||||||
calculator_params = Params()
|
|
||||||
params = list(calculator_params.args)
|
|
||||||
if add_value:
|
|
||||||
# only for validator
|
|
||||||
params.append(ParamOption(self))
|
|
||||||
func_args.pop()
|
|
||||||
if func_args:
|
|
||||||
has_index = True
|
|
||||||
params.append(ParamIndex())
|
|
||||||
func_args.pop()
|
|
||||||
calculator_params.args = tuple(params)
|
|
||||||
if func_args:
|
|
||||||
raise ConfigError(_('missing those arguments "{}" in function "{}" for "{}"'
|
|
||||||
'').format(display_list(list(func_args)),
|
|
||||||
calculator.__name__,
|
|
||||||
self.impl_get_display_name()))
|
|
||||||
if not self.impl_is_dynoptiondescription() and is_multi and \
|
|
||||||
not has_index and 'index' in func_kwargs:
|
|
||||||
calculator_params.kwargs['index'] = ParamIndex()
|
|
||||||
return calculator_params
|
|
||||||
|
|
||||||
def impl_has_dependency(self,
|
def impl_has_dependency(self,
|
||||||
self_is_dep: bool=True) -> bool:
|
self_is_dep: bool=True) -> bool:
|
||||||
|
@ -323,9 +173,6 @@ class Base:
|
||||||
def getsubdyn(self):
|
def getsubdyn(self):
|
||||||
return self._subdyn()
|
return self._subdyn()
|
||||||
|
|
||||||
def impl_getrequires(self):
|
|
||||||
return getattr(self, '_requires', STATIC_TUPLE)
|
|
||||||
|
|
||||||
def impl_get_callback(self):
|
def impl_get_callback(self):
|
||||||
call = getattr(self, '_val_call', (None, None))[1]
|
call = getattr(self, '_val_call', (None, None))[1]
|
||||||
if call is None:
|
if call is None:
|
||||||
|
@ -373,7 +220,6 @@ class Base:
|
||||||
raise AttributeError(_("'{0}' ({1}) object attribute '{2}' is"
|
raise AttributeError(_("'{0}' ({1}) object attribute '{2}' is"
|
||||||
" read-only").format(self.__class__.__name__,
|
" read-only").format(self.__class__.__name__,
|
||||||
self,
|
self,
|
||||||
#self.impl_getname(),
|
|
||||||
key))
|
key))
|
||||||
self._informations[key] = value
|
self._informations[key] = value
|
||||||
|
|
||||||
|
@ -445,181 +291,3 @@ class BaseOption(Base):
|
||||||
|
|
||||||
def impl_is_symlinkoption(self) -> bool:
|
def impl_is_symlinkoption(self) -> bool:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
def validate_requires_arg(new_option: BaseOption,
|
|
||||||
multi: bool,
|
|
||||||
requires: List[dict],
|
|
||||||
name: str) -> Tuple[FrozenSet, Tuple]:
|
|
||||||
"""check malformed requirements
|
|
||||||
and tranform dict to internal tuple
|
|
||||||
|
|
||||||
:param requires: have a look at the
|
|
||||||
:meth:`tiramisu.setting.Settings.apply_requires` method to
|
|
||||||
know more about
|
|
||||||
the description of the requires dictionary
|
|
||||||
"""
|
|
||||||
def get_option(require):
|
|
||||||
if 'option' in require:
|
|
||||||
option = require['option']
|
|
||||||
if option == 'self':
|
|
||||||
option = new_option
|
|
||||||
if __debug__:
|
|
||||||
if not isinstance(option, BaseOption):
|
|
||||||
raise ValueError(_('malformed requirements '
|
|
||||||
'must be an option in option {0}').format(name))
|
|
||||||
if not multi and option.impl_is_multi():
|
|
||||||
raise ValueError(_('malformed requirements '
|
|
||||||
'multi option must not set '
|
|
||||||
'as requires of non multi option {0}').format(name))
|
|
||||||
option._add_dependency(new_option)
|
|
||||||
else:
|
|
||||||
callback = require['callback']
|
|
||||||
callback_params = new_option._build_calculator_params(callback,
|
|
||||||
require.get('callback_params'),
|
|
||||||
'callback')
|
|
||||||
option = (callback, callback_params)
|
|
||||||
return option
|
|
||||||
|
|
||||||
def _set_expected(action,
|
|
||||||
inverse,
|
|
||||||
transitive,
|
|
||||||
same_action,
|
|
||||||
option,
|
|
||||||
expected,
|
|
||||||
operator):
|
|
||||||
if inverse not in ret_requires[action]:
|
|
||||||
ret_requires[action][inverse] = ([(option, [expected])], action, inverse, transitive, same_action, operator)
|
|
||||||
else:
|
|
||||||
for exp in ret_requires[action][inverse][0]:
|
|
||||||
if exp[0] == option:
|
|
||||||
exp[1].append(expected)
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
ret_requires[action][inverse][0].append((option, [expected]))
|
|
||||||
|
|
||||||
def set_expected(require,
|
|
||||||
ret_requires):
|
|
||||||
expected = require['expected']
|
|
||||||
inverse = get_inverse(require)
|
|
||||||
transitive = get_transitive(require)
|
|
||||||
same_action = get_sameaction(require)
|
|
||||||
operator = get_operator(require)
|
|
||||||
if isinstance(expected, list):
|
|
||||||
for exp in expected:
|
|
||||||
if __debug__ and set(exp.keys()) != {'option', 'value'}:
|
|
||||||
raise ValueError(_('malformed requirements expected must have '
|
|
||||||
'option and value for option {0}').format(name))
|
|
||||||
option = get_option(exp)
|
|
||||||
if __debug__:
|
|
||||||
try:
|
|
||||||
option._validate(exp['value'], undefined)
|
|
||||||
except ValueError as err:
|
|
||||||
raise ValueError(_('malformed requirements expected value '
|
|
||||||
'must be valid for option {0}'
|
|
||||||
': {1}').format(name, err))
|
|
||||||
_set_expected(action,
|
|
||||||
inverse,
|
|
||||||
transitive,
|
|
||||||
same_action,
|
|
||||||
option,
|
|
||||||
exp['value'],
|
|
||||||
operator)
|
|
||||||
else:
|
|
||||||
option = get_option(require)
|
|
||||||
if __debug__ and not isinstance(option, tuple) and expected is not None:
|
|
||||||
try:
|
|
||||||
option._validate(expected, undefined)
|
|
||||||
except ValueError as err:
|
|
||||||
raise ValueError(_('malformed requirements expected value '
|
|
||||||
'must be valid for option {0}'
|
|
||||||
': {1}').format(name, err))
|
|
||||||
_set_expected(action,
|
|
||||||
inverse,
|
|
||||||
transitive,
|
|
||||||
same_action,
|
|
||||||
option,
|
|
||||||
expected,
|
|
||||||
operator)
|
|
||||||
|
|
||||||
def get_action(require):
|
|
||||||
action = require['action']
|
|
||||||
if action == 'force_store_value':
|
|
||||||
raise ValueError(_("malformed requirements for option: {0}"
|
|
||||||
" action cannot be force_store_value"
|
|
||||||
).format(name))
|
|
||||||
return action
|
|
||||||
|
|
||||||
def get_inverse(require):
|
|
||||||
inverse = require.get('inverse', False)
|
|
||||||
if inverse not in [True, False]:
|
|
||||||
raise ValueError(_('malformed requirements for option: {0}'
|
|
||||||
' inverse must be boolean'))
|
|
||||||
return inverse
|
|
||||||
|
|
||||||
def get_transitive(require):
|
|
||||||
transitive = require.get('transitive', True)
|
|
||||||
if transitive not in [True, False]:
|
|
||||||
raise ValueError(_('malformed requirements for option: {0}'
|
|
||||||
' transitive must be boolean'))
|
|
||||||
return transitive
|
|
||||||
|
|
||||||
def get_sameaction(require):
|
|
||||||
same_action = require.get('same_action', True)
|
|
||||||
if same_action not in [True, False]:
|
|
||||||
raise ValueError(_('malformed requirements for option: {0}'
|
|
||||||
' same_action must be boolean'))
|
|
||||||
return same_action
|
|
||||||
|
|
||||||
def get_operator(require):
|
|
||||||
operator = require.get('operator', 'or')
|
|
||||||
if operator not in ['and', 'or']:
|
|
||||||
raise ValueError(_('malformed requirements for option: "{0}"'
|
|
||||||
' operator must be "or" or "and"').format(operator))
|
|
||||||
return operator
|
|
||||||
|
|
||||||
|
|
||||||
ret_requires = {}
|
|
||||||
config_action = set()
|
|
||||||
|
|
||||||
# start parsing all requires given by user (has dict)
|
|
||||||
# transforme it to a tuple
|
|
||||||
for require in requires:
|
|
||||||
if __debug__:
|
|
||||||
if not isinstance(require, dict):
|
|
||||||
raise ValueError(_("malformed requirements type for option:"
|
|
||||||
" {0}, must be a dict").format(name))
|
|
||||||
valid_keys = ('option', 'expected', 'action', 'inverse', 'transitive',
|
|
||||||
'same_action', 'operator', 'callback', 'callback_params')
|
|
||||||
unknown_keys = frozenset(require.keys()) - frozenset(valid_keys)
|
|
||||||
if unknown_keys != frozenset():
|
|
||||||
raise ValueError(_('malformed requirements for option: {0}'
|
|
||||||
' unknown keys {1}, must only '
|
|
||||||
'{2}').format(name,
|
|
||||||
unknown_keys,
|
|
||||||
valid_keys))
|
|
||||||
# {'expected': ..., 'option': ..., 'action': ...}
|
|
||||||
# {'expected': [{'option': ..., 'value': ...}, ...}], 'action': ...}
|
|
||||||
# {'expected': ..., 'callback': ..., 'action': ...}
|
|
||||||
if not 'expected' in require or not 'action' in require or \
|
|
||||||
not (isinstance(require['expected'], list) or \
|
|
||||||
'option' in require or \
|
|
||||||
'callback' in require):
|
|
||||||
raise ValueError(_("malformed requirements for option: {0}"
|
|
||||||
" require must have option, expected and"
|
|
||||||
" action keys").format(name))
|
|
||||||
action = get_action(require)
|
|
||||||
config_action.add(action)
|
|
||||||
if action not in ret_requires:
|
|
||||||
ret_requires[action] = {}
|
|
||||||
set_expected(require, ret_requires)
|
|
||||||
|
|
||||||
# transform dict to tuple
|
|
||||||
ret = []
|
|
||||||
for requires in ret_requires.values():
|
|
||||||
ret_action = []
|
|
||||||
for require in requires.values():
|
|
||||||
ret_action.append((tuple(require[0]), require[1],
|
|
||||||
require[2], require[3], require[4], require[5]))
|
|
||||||
ret.append(tuple(ret_action))
|
|
||||||
return frozenset(config_action), tuple(ret)
|
|
||||||
|
|
|
@ -46,22 +46,3 @@ class BroadcastOption(Option):
|
||||||
ip_address(value)
|
ip_address(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
def _cons_broadcast(self,
|
|
||||||
current_opt,
|
|
||||||
opts,
|
|
||||||
vals,
|
|
||||||
warnings_only,
|
|
||||||
context):
|
|
||||||
if len(vals) != 3:
|
|
||||||
raise ConfigError(_('invalid broadcast consistency, a network and a netmask are needed'))
|
|
||||||
if None in vals:
|
|
||||||
return
|
|
||||||
broadcast, network, netmask = vals
|
|
||||||
if ip_network('{0}/{1}'.format(network, netmask)).broadcast_address != ip_address(broadcast):
|
|
||||||
raise ValueError(_('broadcast "{4}" invalid with network {0}/{1} ("{2}"/"{3}")'
|
|
||||||
'').format(network,
|
|
||||||
netmask,
|
|
||||||
opts[1].impl_get_display_name(),
|
|
||||||
opts[2].impl_get_display_name(),
|
|
||||||
broadcast))
|
|
||||||
|
|
|
@ -23,7 +23,7 @@ from types import FunctionType
|
||||||
from ..setting import undefined
|
from ..setting import undefined
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .option import Option
|
from .option import Option
|
||||||
from ..autolib import carry_out_calculation
|
from ..autolib import carry_out_calculation, Calculation
|
||||||
from ..error import ConfigError, display_list
|
from ..error import ConfigError, display_list
|
||||||
|
|
||||||
|
|
||||||
|
@ -41,83 +41,44 @@ class ChoiceOption(Option):
|
||||||
doc,
|
doc,
|
||||||
values,
|
values,
|
||||||
default=None,
|
default=None,
|
||||||
values_params=None,
|
|
||||||
default_multi=None,
|
default_multi=None,
|
||||||
requires=None,
|
|
||||||
multi=False,
|
multi=False,
|
||||||
callback=None,
|
validators=None,
|
||||||
callback_params=None,
|
|
||||||
validator=None,
|
|
||||||
validator_params=None,
|
|
||||||
properties=None,
|
properties=None,
|
||||||
warnings_only=False):
|
warnings_only=False):
|
||||||
|
|
||||||
"""
|
"""
|
||||||
:param values: is a list of values the option can possibly take
|
:param values: is a list of values the option can possibly take
|
||||||
"""
|
"""
|
||||||
if isinstance(values, FunctionType):
|
if not isinstance(values, (Calculation, tuple)):
|
||||||
values_params = self._build_calculator_params(values,
|
raise TypeError(_('values must be a tuple or a calculation for {0}'
|
||||||
values_params,
|
).format(name))
|
||||||
'values')
|
|
||||||
if values_params:
|
|
||||||
self._choice_values_params = values_params
|
|
||||||
else:
|
|
||||||
if values_params is not None:
|
|
||||||
raise ValueError(_('values is not a function, so values_params must be None'))
|
|
||||||
if not isinstance(values, tuple):
|
|
||||||
raise TypeError(_('values must be a tuple or a function for {0}'
|
|
||||||
).format(name))
|
|
||||||
self._choice_values = values
|
self._choice_values = values
|
||||||
super(ChoiceOption, self).__init__(name,
|
super(ChoiceOption, self).__init__(name,
|
||||||
doc,
|
doc,
|
||||||
default=default,
|
default=default,
|
||||||
default_multi=default_multi,
|
default_multi=default_multi,
|
||||||
callback=callback,
|
|
||||||
callback_params=callback_params,
|
|
||||||
requires=requires,
|
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validators=validators,
|
||||||
validator_params=validator_params,
|
|
||||||
properties=properties,
|
properties=properties,
|
||||||
warnings_only=warnings_only)
|
warnings_only=warnings_only)
|
||||||
|
|
||||||
def get_callback(self):
|
|
||||||
values = self._choice_values
|
|
||||||
if isinstance(values, FunctionType):
|
|
||||||
return (values, getattr(self, '_choice_values_params', {}))
|
|
||||||
else:
|
|
||||||
return (None, None)
|
|
||||||
|
|
||||||
def impl_get_values(self,
|
def impl_get_values(self,
|
||||||
option_bag,
|
option_bag):
|
||||||
current_opt=undefined):
|
if isinstance(self._choice_values, Calculation):
|
||||||
if current_opt is undefined:
|
values = self._choice_values.execute(option_bag)
|
||||||
current_opt = self
|
if values is not undefined and not isinstance(values, list):
|
||||||
values, values_params = self.get_callback()
|
raise ConfigError(_('calculated values for {0} is not a list'
|
||||||
if values is not None:
|
'').format(self.impl_getname()))
|
||||||
if option_bag is undefined:
|
|
||||||
values = undefined
|
|
||||||
else:
|
|
||||||
values = carry_out_calculation(current_opt,
|
|
||||||
callback=values,
|
|
||||||
callback_params=values_params,
|
|
||||||
index=None,
|
|
||||||
config_bag=option_bag.config_bag,
|
|
||||||
fromconsistency=[])
|
|
||||||
if values is not undefined and not isinstance(values, list):
|
|
||||||
raise ConfigError(_('calculated values for {0} is not a list'
|
|
||||||
'').format(self.impl_getname()))
|
|
||||||
else:
|
else:
|
||||||
values = self._choice_values
|
values = self._choice_values
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
|
||||||
def _validate(self,
|
def _validate(self,
|
||||||
value,
|
value,
|
||||||
option_bag,
|
option_bag,
|
||||||
current_opt=undefined):
|
current_opt=undefined):
|
||||||
values = self.impl_get_values(option_bag,
|
values = self.impl_get_values(option_bag)
|
||||||
current_opt=current_opt)
|
|
||||||
if values is not undefined and value not in values:
|
if values is not undefined and value not in values:
|
||||||
if len(values) == 1:
|
if len(values) == 1:
|
||||||
raise ValueError(_('only "{0}" is allowed'
|
raise ValueError(_('only "{0}" is allowed'
|
||||||
|
|
|
@ -42,12 +42,8 @@ class DomainnameOption(IPOption):
|
||||||
doc,
|
doc,
|
||||||
default=None,
|
default=None,
|
||||||
default_multi=None,
|
default_multi=None,
|
||||||
requires=None,
|
|
||||||
multi: bool=False,
|
multi: bool=False,
|
||||||
callback=None,
|
validators=None,
|
||||||
callback_params=None,
|
|
||||||
validator=None,
|
|
||||||
validator_params=None,
|
|
||||||
properties=None,
|
properties=None,
|
||||||
allow_ip: bool=False,
|
allow_ip: bool=False,
|
||||||
cidr: bool=False,
|
cidr: bool=False,
|
||||||
|
@ -94,12 +90,8 @@ class DomainnameOption(IPOption):
|
||||||
doc,
|
doc,
|
||||||
default=default,
|
default=default,
|
||||||
default_multi=default_multi,
|
default_multi=default_multi,
|
||||||
callback=callback,
|
|
||||||
callback_params=callback_params,
|
|
||||||
requires=requires,
|
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validators=validators,
|
||||||
validator_params=validator_params,
|
|
||||||
properties=properties,
|
properties=properties,
|
||||||
warnings_only=warnings_only,
|
warnings_only=warnings_only,
|
||||||
cidr=cidr,
|
cidr=cidr,
|
||||||
|
|
|
@ -41,13 +41,11 @@ class DynOptionDescription(OptionDescription):
|
||||||
doc: str,
|
doc: str,
|
||||||
children: List[BaseOption],
|
children: List[BaseOption],
|
||||||
suffixes: Calculation,
|
suffixes: Calculation,
|
||||||
requires=None,
|
|
||||||
properties=None) -> None:
|
properties=None) -> None:
|
||||||
|
|
||||||
super().__init__(name,
|
super().__init__(name,
|
||||||
doc,
|
doc,
|
||||||
children,
|
children,
|
||||||
requires,
|
|
||||||
properties)
|
properties)
|
||||||
# check children + set relation to this dynoptiondescription
|
# check children + set relation to this dynoptiondescription
|
||||||
for child in children:
|
for child in children:
|
||||||
|
|
|
@ -18,15 +18,14 @@
|
||||||
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
|
||||||
# the whole pypy projet is under MIT licence
|
# the whole pypy projet is under MIT licence
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
from ipaddress import ip_address, ip_interface, ip_network
|
from ipaddress import ip_address, ip_interface
|
||||||
|
|
||||||
from ..error import ConfigError
|
from ..error import ConfigError
|
||||||
from ..setting import undefined, Undefined, OptionBag
|
from ..setting import undefined, Undefined, OptionBag
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .option import Option
|
from .option import Option
|
||||||
from .stroption import StrOption
|
from .stroption import StrOption
|
||||||
from .netmaskoption import NetmaskOption
|
from ..function import valid_ip_netmask
|
||||||
from .networkoption import NetworkOption
|
|
||||||
|
|
||||||
|
|
||||||
class IPOption(StrOption):
|
class IPOption(StrOption):
|
||||||
|
@ -40,12 +39,8 @@ class IPOption(StrOption):
|
||||||
doc,
|
doc,
|
||||||
default=None,
|
default=None,
|
||||||
default_multi=None,
|
default_multi=None,
|
||||||
requires=None,
|
|
||||||
multi=False,
|
multi=False,
|
||||||
callback=None,
|
validators=None,
|
||||||
callback_params=None,
|
|
||||||
validator=None,
|
|
||||||
validator_params=None,
|
|
||||||
properties=None,
|
properties=None,
|
||||||
private_only=False,
|
private_only=False,
|
||||||
allow_reserved=False,
|
allow_reserved=False,
|
||||||
|
@ -63,12 +58,8 @@ class IPOption(StrOption):
|
||||||
doc,
|
doc,
|
||||||
default=default,
|
default=default,
|
||||||
default_multi=default_multi,
|
default_multi=default_multi,
|
||||||
callback=callback,
|
|
||||||
callback_params=callback_params,
|
|
||||||
requires=requires,
|
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validators=validators,
|
||||||
validator_params=validator_params,
|
|
||||||
properties=properties,
|
properties=properties,
|
||||||
warnings_only=warnings_only,
|
warnings_only=warnings_only,
|
||||||
extra=extra)
|
extra=extra)
|
||||||
|
@ -98,9 +89,11 @@ class IPOption(StrOption):
|
||||||
if not cidr:
|
if not cidr:
|
||||||
ip_address(value)
|
ip_address(value)
|
||||||
else:
|
else:
|
||||||
ip_interface(value)
|
ip = ip_interface(value)
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
if cidr:
|
||||||
|
valid_ip_netmask(str(ip.ip), str(ip.netmask))
|
||||||
|
|
||||||
def _second_level_validation(self,
|
def _second_level_validation(self,
|
||||||
value,
|
value,
|
||||||
|
@ -118,68 +111,3 @@ class IPOption(StrOption):
|
||||||
else:
|
else:
|
||||||
msg = _("must be private IP")
|
msg = _("must be private IP")
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
if '/' in value:
|
|
||||||
net = NetmaskOption(self.impl_getname(),
|
|
||||||
self.impl_get_display_name(),
|
|
||||||
str(ip.netmask))
|
|
||||||
net._cons_ip_netmask(self,
|
|
||||||
(net, self),
|
|
||||||
(str(ip.netmask), str(ip.ip)),
|
|
||||||
warnings_only,
|
|
||||||
None,
|
|
||||||
True)
|
|
||||||
|
|
||||||
def _cons_in_network(self,
|
|
||||||
current_opt,
|
|
||||||
opts,
|
|
||||||
vals,
|
|
||||||
warnings_only,
|
|
||||||
context):
|
|
||||||
if len(opts) == 2 and isinstance(opts[0], IPOption) and \
|
|
||||||
opts[0].impl_get_extra('_cidr') == False and \
|
|
||||||
isinstance(opts[1], NetworkOption) and \
|
|
||||||
opts[1].impl_get_extra('_cidr') == True:
|
|
||||||
if None in vals:
|
|
||||||
return
|
|
||||||
ip, network = vals
|
|
||||||
network_obj = ip_network(network)
|
|
||||||
if ip_interface(ip) not in network_obj:
|
|
||||||
msg = _('IP not in network "{0}" ("{1}")')
|
|
||||||
raise ValueError(msg.format(network,
|
|
||||||
opts[1].impl_get_display_name()))
|
|
||||||
# test if ip is not network/broadcast IP
|
|
||||||
netmask = NetmaskOption(self.impl_getname(),
|
|
||||||
self.impl_get_display_name(),
|
|
||||||
str(network_obj.netmask))
|
|
||||||
netmask._cons_ip_netmask(self,
|
|
||||||
(netmask, self),
|
|
||||||
(str(network_obj.netmask), str(ip)),
|
|
||||||
warnings_only,
|
|
||||||
None,
|
|
||||||
True)
|
|
||||||
else:
|
|
||||||
if len(vals) != 3 and context is undefined:
|
|
||||||
raise ConfigError(_('ip_network needs an IP, a network and a netmask'))
|
|
||||||
if len(vals) != 3 or None in vals:
|
|
||||||
return
|
|
||||||
ip, network, netmask = vals
|
|
||||||
if ip_interface(ip) not in ip_network('{0}/{1}'.format(network,
|
|
||||||
netmask)):
|
|
||||||
if current_opt == opts[0]:
|
|
||||||
msg = _('IP not in network "{2}"/"{4}" ("{3}"/"{5}")')
|
|
||||||
elif current_opt == opts[1]:
|
|
||||||
msg = _('the network doest not match with IP "{0}" ("{1}") and network "{4}" ("{5}")')
|
|
||||||
else:
|
|
||||||
msg = _('the netmask does not match with IP "{0}" ("{1}") and broadcast "{2}" ("{3}")')
|
|
||||||
raise ValueError(msg.format(ip,
|
|
||||||
opts[0].impl_get_display_name(),
|
|
||||||
network,
|
|
||||||
opts[1].impl_get_display_name(),
|
|
||||||
netmask,
|
|
||||||
opts[2].impl_get_display_name()))
|
|
||||||
# test if ip is not network/broadcast IP
|
|
||||||
opts[2]._cons_ip_netmask(current_opt,
|
|
||||||
(opts[2], opts[0]),
|
|
||||||
(netmask, ip),
|
|
||||||
warnings_only,
|
|
||||||
context)
|
|
||||||
|
|
|
@ -25,13 +25,13 @@ from typing import List, Iterator, Optional, Any
|
||||||
|
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..setting import groups, undefined, OptionBag, Settings
|
from ..setting import groups, undefined, OptionBag, Settings, ALLOWED_LEADER_PROPERTIES
|
||||||
from ..value import Values
|
from ..value import Values
|
||||||
from .optiondescription import OptionDescription
|
from .optiondescription import OptionDescription
|
||||||
from .syndynoptiondescription import SynDynLeadership
|
from .syndynoptiondescription import SynDynLeadership
|
||||||
from .baseoption import BaseOption
|
from .baseoption import BaseOption
|
||||||
from .option import Option
|
from .option import Option
|
||||||
from ..error import RequirementError
|
from ..error import LeadershipError
|
||||||
from ..autolib import Calculation, ParamOption
|
from ..autolib import Calculation, ParamOption
|
||||||
|
|
||||||
|
|
||||||
|
@ -43,12 +43,10 @@ class Leadership(OptionDescription):
|
||||||
name: str,
|
name: str,
|
||||||
doc: str,
|
doc: str,
|
||||||
children: List[BaseOption],
|
children: List[BaseOption],
|
||||||
requires=None,
|
|
||||||
properties=None) -> None:
|
properties=None) -> None:
|
||||||
super().__init__(name,
|
super().__init__(name,
|
||||||
doc,
|
doc,
|
||||||
children,
|
children,
|
||||||
requires=requires,
|
|
||||||
properties=properties)
|
properties=properties)
|
||||||
self._group_type = groups.leadership
|
self._group_type = groups.leadership
|
||||||
followers = []
|
followers = []
|
||||||
|
@ -93,28 +91,9 @@ class Leadership(OptionDescription):
|
||||||
raise ValueError(_("callback of leader's option shall "
|
raise ValueError(_("callback of leader's option shall "
|
||||||
"not refered to a follower's ones"))
|
"not refered to a follower's ones"))
|
||||||
|
|
||||||
# leader should not have requires, only Leadership should have
|
for prop in leader.impl_getproperties():
|
||||||
# so move requires to Leadership
|
if prop not in ALLOWED_LEADER_PROPERTIES and not isinstance(prop, Calculation):
|
||||||
# if Leadership has requires too, cannot manage this move so raises
|
raise LeadershipError(_('leader cannot have "{}" property').format(prop))
|
||||||
leader_requires = getattr(leader, '_requires', None)
|
|
||||||
if leader_requires:
|
|
||||||
if __debug__ and self.impl_getrequires():
|
|
||||||
raise RequirementError(_('leader {} have requirement, but Leadership {} too'
|
|
||||||
'').format(leader.impl_getname(),
|
|
||||||
self.impl_getname()))
|
|
||||||
leader_calproperties = getattr(leader, '_requires', None)
|
|
||||||
if leader_calproperties:
|
|
||||||
setattr(self, '_requires', leader_requires)
|
|
||||||
delattr(leader, '_requires')
|
|
||||||
if __debug__:
|
|
||||||
for requires_ in getattr(self, '_requires', ()):
|
|
||||||
for require in requires_:
|
|
||||||
for require_opt, values in require[0]:
|
|
||||||
if not isinstance(require_opt, tuple) and require_opt.impl_is_multi() and require_opt.impl_get_leadership():
|
|
||||||
raise ValueError(_('malformed requirements option "{0}" '
|
|
||||||
'must not be in follower for "{1}"').format(
|
|
||||||
require_opt.impl_getname(),
|
|
||||||
self.impl_getname()))
|
|
||||||
|
|
||||||
def is_leader(self,
|
def is_leader(self,
|
||||||
opt: Option) -> bool:
|
opt: Option) -> bool:
|
||||||
|
|
|
@ -49,58 +49,3 @@ class NetmaskOption(StrOption):
|
||||||
ip_network('0.0.0.0/{0}'.format(value))
|
ip_network('0.0.0.0/{0}'.format(value))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
def _cons_network_netmask(self,
|
|
||||||
current_opt: Option,
|
|
||||||
opts: List[Option],
|
|
||||||
vals: List[str],
|
|
||||||
warnings_only: bool,
|
|
||||||
context: 'Config'):
|
|
||||||
if context is undefined and len(vals) != 2:
|
|
||||||
raise ConfigError(_('network_netmask needs a network and a netmask'))
|
|
||||||
if None in vals or len(vals) != 2:
|
|
||||||
return
|
|
||||||
val_netmask, val_network = vals
|
|
||||||
opt_netmask, opt_network = opts
|
|
||||||
try:
|
|
||||||
ip_network('{0}/{1}'.format(val_network, val_netmask))
|
|
||||||
except ValueError:
|
|
||||||
if current_opt == opt_network:
|
|
||||||
raise ValueError(_('the netmask "{0}" ("{1}") does not match').format(val_netmask,
|
|
||||||
opt_netmask.impl_get_display_name()))
|
|
||||||
else:
|
|
||||||
raise ValueError(_('the network "{0}" ("{1}") does not match').format(val_network,
|
|
||||||
opt_network.impl_get_display_name()))
|
|
||||||
|
|
||||||
def _cons_ip_netmask(self,
|
|
||||||
current_opt: Option,
|
|
||||||
opts: List[Option],
|
|
||||||
vals: List[str],
|
|
||||||
warnings_only: bool,
|
|
||||||
context: 'config',
|
|
||||||
_cidr: bool=False):
|
|
||||||
if context is undefined and len(vals) != 2:
|
|
||||||
raise ConfigError(_('ip_netmask needs an IP and a netmask'))
|
|
||||||
if None in vals or len(vals) != 2:
|
|
||||||
return
|
|
||||||
val_netmask, val_ip = vals
|
|
||||||
opt_netmask, opt_ip = opts
|
|
||||||
ip = ip_interface('{0}/{1}'.format(val_ip, val_netmask))
|
|
||||||
if not _cidr and current_opt == opt_ip:
|
|
||||||
if ip.ip == ip.network.network_address:
|
|
||||||
raise ValueError( _('this is a network with netmask "{0}" ("{1}")'
|
|
||||||
'').format(val_netmask,
|
|
||||||
opt_netmask.impl_get_display_name()))
|
|
||||||
elif ip.ip == ip.network.broadcast_address:
|
|
||||||
raise ValueError(_('this is a broadcast with netmask "{0}" ("{1}")'
|
|
||||||
'').format(val_netmask,
|
|
||||||
opt_netmask.impl_get_display_name()))
|
|
||||||
else:
|
|
||||||
if ip.ip == ip.network.network_address:
|
|
||||||
raise ValueError(_('IP "{0}" ("{1}") is the network'
|
|
||||||
'').format(val_ip,
|
|
||||||
opt_ip.impl_get_display_name()))
|
|
||||||
elif ip.ip == ip.network.broadcast_address:
|
|
||||||
raise ValueError(_('IP "{0}" ("{1}") is the broadcast'
|
|
||||||
'').format(val_ip,
|
|
||||||
opt_ip.impl_get_display_name()))
|
|
||||||
|
|
|
@ -36,12 +36,8 @@ class NetworkOption(Option):
|
||||||
doc,
|
doc,
|
||||||
default=None,
|
default=None,
|
||||||
default_multi=None,
|
default_multi=None,
|
||||||
requires=None,
|
|
||||||
multi=False,
|
multi=False,
|
||||||
callback=None,
|
validators=None,
|
||||||
callback_params=None,
|
|
||||||
validator=None,
|
|
||||||
validator_params=None,
|
|
||||||
properties=None,
|
properties=None,
|
||||||
warnings_only=False,
|
warnings_only=False,
|
||||||
cidr=False):
|
cidr=False):
|
||||||
|
@ -50,12 +46,8 @@ class NetworkOption(Option):
|
||||||
doc,
|
doc,
|
||||||
default=default,
|
default=default,
|
||||||
default_multi=default_multi,
|
default_multi=default_multi,
|
||||||
callback=callback,
|
|
||||||
callback_params=callback_params,
|
|
||||||
requires=requires,
|
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validators=validators,
|
||||||
validator_params=validator_params,
|
|
||||||
properties=properties,
|
properties=properties,
|
||||||
warnings_only=warnings_only,
|
warnings_only=warnings_only,
|
||||||
extra=extra)
|
extra=extra)
|
||||||
|
|
|
@ -27,11 +27,11 @@ from itertools import chain
|
||||||
from .baseoption import BaseOption, submulti, STATIC_TUPLE
|
from .baseoption import BaseOption, submulti, STATIC_TUPLE
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..setting import undefined, OptionBag, Undefined
|
from ..setting import undefined, OptionBag, Undefined
|
||||||
from ..autolib import Calculation, carry_out_calculation, Params, ParamValue, ParamContext, ParamOption
|
from ..autolib import Calculation, Params, ParamValue, ParamContext, ParamOption
|
||||||
from ..error import (ConfigError, ValueWarning, ValueErrorWarning, PropertiesOptionError,
|
from ..error import (ConfigError, ValueWarning, ValueErrorWarning, PropertiesOptionError,
|
||||||
ValueOptionError, display_list)
|
ValueOptionError, display_list)
|
||||||
from .syndynoption import SynDynOption
|
from .syndynoption import SynDynOption
|
||||||
ALLOWED_CONST_LIST = ['_cons_not_equal']
|
#ALLOWED_CONST_LIST = ['_cons_not_equal']
|
||||||
|
|
||||||
|
|
||||||
class Option(BaseOption):
|
class Option(BaseOption):
|
||||||
|
@ -43,14 +43,14 @@ class Option(BaseOption):
|
||||||
__slots__ = ('_extra',
|
__slots__ = ('_extra',
|
||||||
'_warnings_only',
|
'_warnings_only',
|
||||||
'_allow_empty_list',
|
'_allow_empty_list',
|
||||||
#multi
|
# multi
|
||||||
'_multi',
|
'_multi',
|
||||||
'_unique',
|
'_unique',
|
||||||
#value
|
# value
|
||||||
'_default',
|
'_default',
|
||||||
'_default_multi',
|
'_default_multi',
|
||||||
#calcul
|
#
|
||||||
'_val_call',
|
'_validators',
|
||||||
#
|
#
|
||||||
'_leadership',
|
'_leadership',
|
||||||
'_choice_values',
|
'_choice_values',
|
||||||
|
@ -62,13 +62,9 @@ class Option(BaseOption):
|
||||||
doc: str,
|
doc: str,
|
||||||
default: Any=undefined,
|
default: Any=undefined,
|
||||||
default_multi: Any=None,
|
default_multi: Any=None,
|
||||||
requires: List[Dict]=None,
|
|
||||||
multi: bool=False,
|
multi: bool=False,
|
||||||
unique: bool=undefined,
|
unique: bool=undefined,
|
||||||
callback: Optional[Callable]=None,
|
validators: Optional[List[Calculation]]=None,
|
||||||
callback_params: Optional[Params]=None,
|
|
||||||
validator: Optional[Callable]=None,
|
|
||||||
validator_params: Optional[Params]=None,
|
|
||||||
properties: Optional[List[str]]=None,
|
properties: Optional[List[str]]=None,
|
||||||
warnings_only: bool=False,
|
warnings_only: bool=False,
|
||||||
extra: Optional[Dict]=None,
|
extra: Optional[Dict]=None,
|
||||||
|
@ -99,19 +95,23 @@ class Option(BaseOption):
|
||||||
default = []
|
default = []
|
||||||
super().__init__(name,
|
super().__init__(name,
|
||||||
doc,
|
doc,
|
||||||
requires=requires,
|
|
||||||
properties=properties,
|
properties=properties,
|
||||||
is_multi=is_multi)
|
is_multi=is_multi)
|
||||||
if validator is not None:
|
if __debug__:
|
||||||
validator_params = self._build_calculator_params(validator,
|
if validators is not None:
|
||||||
validator_params,
|
if not isinstance(validators, list):
|
||||||
'validator',
|
raise ValueError(_('validators must be a list of Calculation for "{}"').format(name))
|
||||||
add_value=True)
|
for validator in validators:
|
||||||
if not validator_params:
|
if not isinstance(validator, Calculation):
|
||||||
val_call = (validator,)
|
raise ValueError(_('validators must be a Calculation for "{}"').format(name))
|
||||||
else:
|
for param in chain(validator.params.args, validator.params.kwargs.values()):
|
||||||
val_call = (validator, validator_params)
|
if isinstance(param, ParamContext):
|
||||||
self._val_call = (val_call, None)
|
self._has_calc_context = True
|
||||||
|
elif isinstance(param, ParamOption):
|
||||||
|
param.option._add_dependency(self)
|
||||||
|
self._has_dependency = True
|
||||||
|
|
||||||
|
self._validators = tuple(validators)
|
||||||
if extra is not None and extra != {}:
|
if extra is not None and extra != {}:
|
||||||
_setattr(self, '_extra', extra)
|
_setattr(self, '_extra', extra)
|
||||||
if unique != undefined and not isinstance(unique, bool):
|
if unique != undefined and not isinstance(unique, bool):
|
||||||
|
@ -126,9 +126,14 @@ class Option(BaseOption):
|
||||||
def test_multi_value(value):
|
def test_multi_value(value):
|
||||||
if isinstance(value, Calculation):
|
if isinstance(value, Calculation):
|
||||||
return
|
return
|
||||||
|
option_bag = OptionBag()
|
||||||
|
option_bag.set_option(self,
|
||||||
|
undefined,
|
||||||
|
None,
|
||||||
|
undefined)
|
||||||
try:
|
try:
|
||||||
self._validate(value,
|
self._validate(value,
|
||||||
undefined)
|
option_bag)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
str_err = str(err)
|
str_err = str(err)
|
||||||
if not str_err:
|
if not str_err:
|
||||||
|
@ -168,9 +173,6 @@ class Option(BaseOption):
|
||||||
default = tuple(default)
|
default = tuple(default)
|
||||||
_setattr(self, '_default', default)
|
_setattr(self, '_default', default)
|
||||||
|
|
||||||
self._impl_set_callback(callback,
|
|
||||||
callback_params)
|
|
||||||
|
|
||||||
def value_dependencies(self,
|
def value_dependencies(self,
|
||||||
value: Any) -> Any:
|
value: Any) -> Any:
|
||||||
if isinstance(value, list):
|
if isinstance(value, list):
|
||||||
|
@ -250,16 +252,6 @@ class Option(BaseOption):
|
||||||
#__________________________________________________________________________
|
#__________________________________________________________________________
|
||||||
# validator
|
# validator
|
||||||
|
|
||||||
def impl_get_validator(self) -> Tuple[Callable, Params]:
|
|
||||||
val = getattr(self, '_val_call', (None,))[0]
|
|
||||||
if val is None:
|
|
||||||
ret_val = (None, None)
|
|
||||||
elif len(val) == 1:
|
|
||||||
ret_val = (val[0], None)
|
|
||||||
else:
|
|
||||||
ret_val = val
|
|
||||||
return ret_val
|
|
||||||
|
|
||||||
def impl_validate(self,
|
def impl_validate(self,
|
||||||
value: Any,
|
value: Any,
|
||||||
option_bag: OptionBag,
|
option_bag: OptionBag,
|
||||||
|
@ -272,13 +264,9 @@ class Option(BaseOption):
|
||||||
|
|
||||||
if check_error and config_bag is not undefined and \
|
if check_error and config_bag is not undefined and \
|
||||||
not 'validator' in config_bag.properties:
|
not 'validator' in config_bag.properties:
|
||||||
# just to check propertieserror
|
|
||||||
self.valid_consistency(option_bag,
|
|
||||||
value,
|
|
||||||
check_error,
|
|
||||||
is_warnings_only)
|
|
||||||
return
|
return
|
||||||
|
|
||||||
|
|
||||||
def _is_not_unique(value):
|
def _is_not_unique(value):
|
||||||
# if set(value) has not same length than value
|
# if set(value) has not same length than value
|
||||||
if check_error and self.impl_is_unique() and \
|
if check_error and self.impl_is_unique() and \
|
||||||
|
@ -291,26 +279,33 @@ class Option(BaseOption):
|
||||||
|
|
||||||
def calculation_validator(val,
|
def calculation_validator(val,
|
||||||
_index):
|
_index):
|
||||||
validator, validator_params = self.impl_get_validator()
|
for validator in getattr(self, '_validators', []):
|
||||||
if validator is not None:
|
calc_is_warnings_only = hasattr(validator, 'warnings_only') and validator.warnings_only
|
||||||
#inject value in calculation
|
if ((check_error and not calc_is_warnings_only) or
|
||||||
if validator_params is None:
|
(not check_error and calc_is_warnings_only)):
|
||||||
args = []
|
try:
|
||||||
kwargs = None
|
kwargs = {'allow_raises': True}
|
||||||
else:
|
if _index is not None and option_bag.index == _index:
|
||||||
args = list(validator_params.args)
|
soption_bag = option_bag
|
||||||
kwargs = validator_params.kwargs
|
else:
|
||||||
args.insert(0, ParamValue(val))
|
soption_bag = option_bag.copy()
|
||||||
validator_params_ = Params(tuple(args), kwargs)
|
soption_bag.index = _index
|
||||||
# Raise ValueError if not valid
|
kwargs['orig_value'] = value
|
||||||
carry_out_calculation(option_bag.ori_option,
|
|
||||||
callback=validator,
|
validator.execute(soption_bag,
|
||||||
callback_params=validator_params_,
|
leadership_must_have_index=True,
|
||||||
index=_index,
|
**kwargs)
|
||||||
config_bag=option_bag.config_bag,
|
except ValueError as err:
|
||||||
fromconsistency=option_bag.fromconsistency,
|
if calc_is_warnings_only:
|
||||||
orig_value=value,
|
warnings.warn_explicit(ValueWarning(val,
|
||||||
is_validator=True)
|
self._display_name,
|
||||||
|
self,
|
||||||
|
'{0}'.format(err),
|
||||||
|
_index),
|
||||||
|
ValueWarning,
|
||||||
|
self.__class__.__name__, 0)
|
||||||
|
else:
|
||||||
|
raise err
|
||||||
|
|
||||||
def do_validation(_value,
|
def do_validation(_value,
|
||||||
_index):
|
_index):
|
||||||
|
@ -328,8 +323,6 @@ class Option(BaseOption):
|
||||||
if ((check_error and not is_warnings_only) or
|
if ((check_error and not is_warnings_only) or
|
||||||
(not check_error and is_warnings_only)):
|
(not check_error and is_warnings_only)):
|
||||||
try:
|
try:
|
||||||
calculation_validator(_value,
|
|
||||||
_index)
|
|
||||||
self._second_level_validation(_value,
|
self._second_level_validation(_value,
|
||||||
is_warnings_only)
|
is_warnings_only)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
|
@ -343,6 +336,8 @@ class Option(BaseOption):
|
||||||
self.__class__.__name__, 0)
|
self.__class__.__name__, 0)
|
||||||
else:
|
else:
|
||||||
raise err
|
raise err
|
||||||
|
calculation_validator(_value,
|
||||||
|
_index)
|
||||||
try:
|
try:
|
||||||
val = value
|
val = value
|
||||||
err_index = force_index
|
err_index = force_index
|
||||||
|
@ -379,12 +374,6 @@ class Option(BaseOption):
|
||||||
for err_index, val in enumerate(value):
|
for err_index, val in enumerate(value):
|
||||||
do_validation(val,
|
do_validation(val,
|
||||||
err_index)
|
err_index)
|
||||||
|
|
||||||
if (not is_warnings_only or not check_error) and not isinstance(value, Calculation):
|
|
||||||
self.valid_consistency(option_bag,
|
|
||||||
value,
|
|
||||||
check_error,
|
|
||||||
is_warnings_only)
|
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
if config_bag is undefined or \
|
if config_bag is undefined or \
|
||||||
'demoting_error_warning' not in config_bag.properties:
|
'demoting_error_warning' not in config_bag.properties:
|
||||||
|
@ -419,11 +408,6 @@ class Option(BaseOption):
|
||||||
warnings_only: bool) -> None:
|
warnings_only: bool) -> None:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
#__________________________________________________________________________
|
|
||||||
# leadership
|
|
||||||
# def impl_is_leadership(self):
|
|
||||||
# return self.impl_get_leadership() is not None
|
|
||||||
|
|
||||||
def impl_is_leader(self):
|
def impl_is_leader(self):
|
||||||
leadership = self.impl_get_leadership()
|
leadership = self.impl_get_leadership()
|
||||||
if leadership is None:
|
if leadership is None:
|
||||||
|
@ -442,327 +426,6 @@ class Option(BaseOption):
|
||||||
return leadership
|
return leadership
|
||||||
return leadership()
|
return leadership()
|
||||||
|
|
||||||
#____________________________________________________________
|
|
||||||
# consistencies
|
|
||||||
|
|
||||||
def impl_add_consistency(self,
|
|
||||||
func: str,
|
|
||||||
*other_opts,
|
|
||||||
**params) -> None:
|
|
||||||
"""Add consistency means that value will be validate with other_opts
|
|
||||||
option's values.
|
|
||||||
|
|
||||||
:param func: function's name
|
|
||||||
:type func: `str`
|
|
||||||
:param other_opts: options used to validate value
|
|
||||||
:type other_opts: `list` of `tiramisu.option.Option`
|
|
||||||
:param params: extra params (warnings_only and transitive are allowed)
|
|
||||||
"""
|
|
||||||
if self.impl_is_readonly():
|
|
||||||
raise AttributeError(_("'{0}' ({1}) cannot add consistency, option is"
|
|
||||||
" read-only").format(
|
|
||||||
self.__class__.__name__,
|
|
||||||
self.impl_getname()))
|
|
||||||
self._valid_consistencies(other_opts,
|
|
||||||
func=func)
|
|
||||||
func = '_cons_{0}'.format(func)
|
|
||||||
if func not in dir(self):
|
|
||||||
raise ConfigError(_('consistency {0} not available for this option').format(func))
|
|
||||||
options = [weakref.ref(self)]
|
|
||||||
for option in other_opts:
|
|
||||||
options.append(weakref.ref(option))
|
|
||||||
all_cons_opts = tuple(options)
|
|
||||||
unknown_params = set(params.keys()) - set(['warnings_only', 'transitive'])
|
|
||||||
if unknown_params != set():
|
|
||||||
raise ValueError(_('unknown parameter {0} in consistency').format(unknown_params))
|
|
||||||
self._add_consistency(func,
|
|
||||||
all_cons_opts,
|
|
||||||
params)
|
|
||||||
#validate default value when add consistency
|
|
||||||
option_bag = OptionBag()
|
|
||||||
option_bag.set_option(self,
|
|
||||||
undefined,
|
|
||||||
None,
|
|
||||||
undefined)
|
|
||||||
default = self.impl_getdefault()
|
|
||||||
if isinstance(default, tuple):
|
|
||||||
default = list(default)
|
|
||||||
self.impl_validate(default,
|
|
||||||
option_bag)
|
|
||||||
self.impl_validate(default,
|
|
||||||
option_bag,
|
|
||||||
check_error=False)
|
|
||||||
if func != '_cons_not_equal':
|
|
||||||
#consistency could generate warnings or errors
|
|
||||||
self._has_dependency = True
|
|
||||||
for wopt in all_cons_opts:
|
|
||||||
opt = wopt()
|
|
||||||
if func in ALLOWED_CONST_LIST:
|
|
||||||
if getattr(opt, '_unique', undefined) == undefined:
|
|
||||||
opt._unique = True
|
|
||||||
if opt != self:
|
|
||||||
self._add_dependency(opt)
|
|
||||||
opt._add_dependency(self)
|
|
||||||
|
|
||||||
def _add_consistency(self,
|
|
||||||
func: str,
|
|
||||||
all_cons_opts: List[BaseOption],
|
|
||||||
params: Dict) -> None:
|
|
||||||
cons = (-1, func, all_cons_opts, params)
|
|
||||||
consistencies = getattr(self, '_consistencies', None)
|
|
||||||
if consistencies is None:
|
|
||||||
self._consistencies = [cons]
|
|
||||||
else:
|
|
||||||
consistencies.append(cons)
|
|
||||||
|
|
||||||
def get_consistencies(self):
|
|
||||||
return getattr(self, '_consistencies', STATIC_TUPLE)
|
|
||||||
|
|
||||||
def has_consistencies(self, context) -> bool:
|
|
||||||
descr = context.cfgimpl_get_description()
|
|
||||||
if getattr(descr, '_cache_consistencies', None) is None:
|
|
||||||
return False
|
|
||||||
return self in descr._cache_consistencies
|
|
||||||
|
|
||||||
def valid_consistency(self,
|
|
||||||
option_bag: OptionBag,
|
|
||||||
value: Any,
|
|
||||||
check_error: bool,
|
|
||||||
option_warnings_only: bool) -> None:
|
|
||||||
if option_bag.config_bag is not undefined:
|
|
||||||
descr = option_bag.config_bag.context.cfgimpl_get_description()
|
|
||||||
# no consistency found at all
|
|
||||||
if getattr(descr, '_cache_consistencies', None) is None:
|
|
||||||
return
|
|
||||||
# get consistencies for this option
|
|
||||||
consistencies = descr._cache_consistencies.get(option_bag.option)
|
|
||||||
else:
|
|
||||||
# is no context, get consistencies in option
|
|
||||||
consistencies = option_bag.option.get_consistencies()
|
|
||||||
if consistencies:
|
|
||||||
if option_bag.config_bag is undefined:
|
|
||||||
coption_bag = option_bag.copy()
|
|
||||||
else:
|
|
||||||
cconfig_bag = option_bag.config_bag.copy()
|
|
||||||
cconfig_bag.remove_warnings()
|
|
||||||
cconfig_bag.set_permissive()
|
|
||||||
coption_bag = option_bag.copy()
|
|
||||||
coption_bag.config_bag = cconfig_bag
|
|
||||||
if not option_bag.fromconsistency:
|
|
||||||
fromconsistency_is_empty = True
|
|
||||||
option_bag.fromconsistency = [cons_id for cons_id, f, a, p in consistencies]
|
|
||||||
else:
|
|
||||||
fromconsistency_is_empty = False
|
|
||||||
for cons_id, func, all_cons_opts, params in consistencies:
|
|
||||||
if not fromconsistency_is_empty and cons_id in option_bag.fromconsistency:
|
|
||||||
continue
|
|
||||||
warnings_only = option_warnings_only or params.get('warnings_only', False)
|
|
||||||
if (warnings_only and not check_error) or (not warnings_only and check_error):
|
|
||||||
transitive = params.get('transitive', True)
|
|
||||||
#all_cons_opts[0] is the option where func is set
|
|
||||||
if option_bag.ori_option.impl_is_dynsymlinkoption():
|
|
||||||
opts = []
|
|
||||||
for opt in all_cons_opts:
|
|
||||||
opts.append(opt().to_dynoption(option_bag.ori_option.rootpath,
|
|
||||||
option_bag.ori_option.suffix))
|
|
||||||
wopt = opts[0]
|
|
||||||
else:
|
|
||||||
opts = all_cons_opts
|
|
||||||
wopt = opts[0]()
|
|
||||||
wopt.launch_consistency(self,
|
|
||||||
func,
|
|
||||||
cons_id,
|
|
||||||
coption_bag,
|
|
||||||
value,
|
|
||||||
opts,
|
|
||||||
warnings_only,
|
|
||||||
transitive)
|
|
||||||
if fromconsistency_is_empty:
|
|
||||||
option_bag.fromconsistency = []
|
|
||||||
|
|
||||||
def _valid_consistencies(self,
|
|
||||||
other_opts: List[BaseOption],
|
|
||||||
init: bool=True,
|
|
||||||
func: Optional[str]=None) -> None:
|
|
||||||
if self.issubdyn():
|
|
||||||
dynod = self.getsubdyn()
|
|
||||||
else:
|
|
||||||
dynod = None
|
|
||||||
if self.impl_is_submulti():
|
|
||||||
raise ConfigError(_('cannot add consistency with submulti option'))
|
|
||||||
is_multi = self.impl_is_multi()
|
|
||||||
for opt in other_opts:
|
|
||||||
if isinstance(opt, weakref.ReferenceType):
|
|
||||||
opt = opt()
|
|
||||||
assert not opt.impl_is_submulti(), _('cannot add consistency with submulti option')
|
|
||||||
assert isinstance(opt, Option), _('consistency must be set with an option, not {}').format(opt)
|
|
||||||
if opt.issubdyn():
|
|
||||||
if dynod is None:
|
|
||||||
raise ConfigError(_('almost one option in consistency is '
|
|
||||||
'in a dynoptiondescription but not all'))
|
|
||||||
subod = opt.getsubdyn()
|
|
||||||
if dynod != subod:
|
|
||||||
raise ConfigError(_('option in consistency must be in same'
|
|
||||||
' dynoptiondescription'))
|
|
||||||
dynod = subod
|
|
||||||
elif dynod is not None:
|
|
||||||
raise ConfigError(_('almost one option in consistency is in a '
|
|
||||||
'dynoptiondescription but not all'))
|
|
||||||
if self is opt:
|
|
||||||
raise ConfigError(_('cannot add consistency with itself'))
|
|
||||||
if is_multi != opt.impl_is_multi():
|
|
||||||
raise ConfigError(_('every options in consistency must be '
|
|
||||||
'multi or none'))
|
|
||||||
# FIXME
|
|
||||||
if init and func != 'not_equal':
|
|
||||||
opt._has_dependency = True
|
|
||||||
|
|
||||||
def launch_consistency(self,
|
|
||||||
current_opt: BaseOption,
|
|
||||||
func: Callable,
|
|
||||||
cons_id: int,
|
|
||||||
option_bag: OptionBag,
|
|
||||||
value: Any,
|
|
||||||
opts: List[BaseOption],
|
|
||||||
warnings_only: bool,
|
|
||||||
transitive: bool) -> None:
|
|
||||||
"""Launch consistency now
|
|
||||||
"""
|
|
||||||
all_cons_vals = []
|
|
||||||
all_cons_opts = []
|
|
||||||
length = None
|
|
||||||
for opt in opts:
|
|
||||||
if isinstance(opt, weakref.ReferenceType):
|
|
||||||
opt = opt()
|
|
||||||
try:
|
|
||||||
opt_value = self.get_consistency_value(option_bag,
|
|
||||||
opt,
|
|
||||||
cons_id,
|
|
||||||
value,
|
|
||||||
func)
|
|
||||||
except PropertiesOptionError as err:
|
|
||||||
if transitive:
|
|
||||||
err.set_orig_opt(option_bag.option)
|
|
||||||
raise err
|
|
||||||
else:
|
|
||||||
if opt.impl_is_multi() and option_bag.index is None and \
|
|
||||||
func not in ALLOWED_CONST_LIST:
|
|
||||||
len_value = len(opt_value)
|
|
||||||
if length is not None and length != len_value:
|
|
||||||
if option_bag.config_bag is undefined:
|
|
||||||
return
|
|
||||||
raise ValueError(_('unexpected length of "{}" in constency "{}", '
|
|
||||||
'should be "{}"').format(len(opt_value),
|
|
||||||
opt.impl_get_display_name(),
|
|
||||||
length)) # pragma: no cover
|
|
||||||
length = len_value
|
|
||||||
if isinstance(opt_value, list) and func in ALLOWED_CONST_LIST:
|
|
||||||
for value_ in opt_value:
|
|
||||||
all_cons_vals.append(value_)
|
|
||||||
all_cons_opts.append(opt)
|
|
||||||
else:
|
|
||||||
all_cons_vals.append(opt_value)
|
|
||||||
all_cons_opts.append(opt)
|
|
||||||
if option_bag.config_bag is not undefined and \
|
|
||||||
not 'validator' in option_bag.config_bag.properties:
|
|
||||||
return
|
|
||||||
all_values = []
|
|
||||||
if length is None:
|
|
||||||
all_values = [all_cons_vals]
|
|
||||||
elif length:
|
|
||||||
all_values = zip(*all_cons_vals)
|
|
||||||
try:
|
|
||||||
context = option_bag.config_bag if option_bag.config_bag is undefined else option_bag.config_bag.context
|
|
||||||
for values in all_values:
|
|
||||||
getattr(self, func)(current_opt,
|
|
||||||
all_cons_opts,
|
|
||||||
values,
|
|
||||||
warnings_only,
|
|
||||||
context)
|
|
||||||
except ValueError as err:
|
|
||||||
if warnings_only:
|
|
||||||
warnings.warn_explicit(ValueWarning(value,
|
|
||||||
self._display_name,
|
|
||||||
current_opt,
|
|
||||||
"{}".format(err),
|
|
||||||
option_bag.index),
|
|
||||||
ValueWarning,
|
|
||||||
self.__class__.__name__, 0)
|
|
||||||
else:
|
|
||||||
raise err
|
|
||||||
|
|
||||||
def get_consistency_value(self,
|
|
||||||
option_bag: OptionBag,
|
|
||||||
current_option: BaseOption,
|
|
||||||
cons_id: int,
|
|
||||||
value: Any,
|
|
||||||
func: str) -> Any:
|
|
||||||
if option_bag.ori_option == current_option:
|
|
||||||
# orig_option is current option
|
|
||||||
# we have already value, so use it
|
|
||||||
return value
|
|
||||||
if option_bag.config_bag is undefined:
|
|
||||||
#if no context get default value
|
|
||||||
return current_option.impl_getdefault()
|
|
||||||
if func in ALLOWED_CONST_LIST:
|
|
||||||
index = None
|
|
||||||
index_ = None
|
|
||||||
elif current_option.impl_is_leader():
|
|
||||||
index = option_bag.index
|
|
||||||
index_ = None
|
|
||||||
else:
|
|
||||||
index = option_bag.index
|
|
||||||
index_ = index
|
|
||||||
#otherwise calculate value
|
|
||||||
path = current_option.impl_getpath()
|
|
||||||
coption_bag = OptionBag()
|
|
||||||
coption_bag.set_option(current_option,
|
|
||||||
path,
|
|
||||||
index_,
|
|
||||||
option_bag.config_bag)
|
|
||||||
fromconsistency = option_bag.fromconsistency.copy()
|
|
||||||
fromconsistency.append(cons_id)
|
|
||||||
coption_bag.fromconsistency = fromconsistency
|
|
||||||
current_value = option_bag.config_bag.context.getattr(path,
|
|
||||||
coption_bag)
|
|
||||||
if index_ is None and index is not None:
|
|
||||||
#if self is a follower and current_option is a leader and func not in ALLOWED_CONST_LIST
|
|
||||||
#return only the value of the leader for isolate follower
|
|
||||||
current_value = current_value[index]
|
|
||||||
return current_value
|
|
||||||
|
|
||||||
def _cons_not_equal(self,
|
|
||||||
current_opt: BaseOption,
|
|
||||||
opts: List[BaseOption],
|
|
||||||
vals: List[Any],
|
|
||||||
warnings_only: bool,
|
|
||||||
context) -> None:
|
|
||||||
equal = []
|
|
||||||
is_current = False
|
|
||||||
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:
|
|
||||||
for opt_ in [opts[idx_inf], opts[idx_inf + idx_sup + 1]]:
|
|
||||||
if opt_ == current_opt:
|
|
||||||
is_current = True
|
|
||||||
elif opt_ not in equal:
|
|
||||||
equal.append(opt_)
|
|
||||||
if equal:
|
|
||||||
if is_current:
|
|
||||||
if warnings_only:
|
|
||||||
msg = _('should be different from the value of {}')
|
|
||||||
else:
|
|
||||||
msg = _('must be different from the value of {}')
|
|
||||||
else:
|
|
||||||
if warnings_only:
|
|
||||||
msg = _('value for {} should be different')
|
|
||||||
else:
|
|
||||||
msg = _('value for {} must be different')
|
|
||||||
equal_name = []
|
|
||||||
for opt in equal:
|
|
||||||
equal_name.append(opt.impl_get_display_name())
|
|
||||||
raise ValueError(msg.format(display_list(list(equal_name), add_quote=True)))
|
|
||||||
|
|
||||||
def to_dynoption(self,
|
def to_dynoption(self,
|
||||||
rootpath: str,
|
rootpath: str,
|
||||||
suffix: str) -> SynDynOption:
|
suffix: str) -> SynDynOption:
|
||||||
|
|
|
@ -25,14 +25,12 @@ from typing import Optional, Iterator, Union, List
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..setting import ConfigBag, OptionBag, groups, undefined, owners, Undefined
|
from ..setting import ConfigBag, OptionBag, groups, undefined, owners, Undefined
|
||||||
from .baseoption import BaseOption
|
from .baseoption import BaseOption
|
||||||
from .option import ALLOWED_CONST_LIST
|
|
||||||
from .syndynoptiondescription import SynDynOptionDescription, SynDynLeadership
|
from .syndynoptiondescription import SynDynOptionDescription, SynDynLeadership
|
||||||
from ..error import ConfigError, ConflictError
|
from ..error import ConfigError, ConflictError
|
||||||
|
|
||||||
|
|
||||||
class CacheOptionDescription(BaseOption):
|
class CacheOptionDescription(BaseOption):
|
||||||
__slots__ = ('_cache_consistencies',
|
__slots__ = ('_cache_force_store_values',)
|
||||||
'_cache_force_store_values')
|
|
||||||
|
|
||||||
def impl_already_build_caches(self) -> bool:
|
def impl_already_build_caches(self) -> bool:
|
||||||
return self.impl_is_readonly()
|
return self.impl_is_readonly()
|
||||||
|
@ -101,60 +99,10 @@ class CacheOptionDescription(BaseOption):
|
||||||
'"force_metaconfig_on_freeze" '
|
'"force_metaconfig_on_freeze" '
|
||||||
'property without "frozen"'
|
'property without "frozen"'
|
||||||
'').format(option.impl_get_display_name()))
|
'').format(option.impl_get_display_name()))
|
||||||
for cons_id, func, all_cons_opts, params in option.get_consistencies():
|
|
||||||
option._valid_consistencies(all_cons_opts[1:], init=False)
|
|
||||||
if func not in ALLOWED_CONST_LIST and is_multi:
|
|
||||||
if __debug__ and not option.impl_get_leadership():
|
|
||||||
raise ConfigError(_('malformed consistency option "{0}" '
|
|
||||||
'must be in same leadership').format(
|
|
||||||
option.impl_getname()))
|
|
||||||
leadership = option.impl_get_leadership()
|
|
||||||
for weak_opt in all_cons_opts:
|
|
||||||
opt = weak_opt()
|
|
||||||
if __debug__ and func not in ALLOWED_CONST_LIST and is_multi:
|
|
||||||
if not opt.impl_get_leadership():
|
|
||||||
raise ConfigError(_('malformed consistency option "{0}" '
|
|
||||||
'must not be a multi for "{1}"').format(
|
|
||||||
option.impl_getname(), opt.impl_getname()))
|
|
||||||
elif leadership != opt.impl_get_leadership():
|
|
||||||
raise ConfigError(_('malformed consistency option "{0}" '
|
|
||||||
'must be in same leadership as "{1}"').format(
|
|
||||||
option.impl_getname(), opt.impl_getname()))
|
|
||||||
_consistencies.setdefault(weak_opt,
|
|
||||||
[]).append((_consistencies_id,
|
|
||||||
func,
|
|
||||||
all_cons_opts,
|
|
||||||
params))
|
|
||||||
_consistencies_id += 1
|
|
||||||
# if context is set to callback, must be reset each time a value change
|
# if context is set to callback, must be reset each time a value change
|
||||||
if hasattr(option, '_has_calc_context'):
|
if hasattr(option, '_has_calc_context'):
|
||||||
self._add_dependency(option)
|
self._add_dependency(option)
|
||||||
|
|
||||||
if __debug__:
|
|
||||||
is_follower = None
|
|
||||||
if is_multi:
|
|
||||||
all_requires = option.impl_getrequires()
|
|
||||||
for requires in all_requires:
|
|
||||||
for require in requires:
|
|
||||||
#if option in require is a multi:
|
|
||||||
# * option in require must be a leader or a follower
|
|
||||||
# * current option must be a follower (and only a follower)
|
|
||||||
# * option in require and current option must be in same leadership
|
|
||||||
for require_opt, values in require[0]:
|
|
||||||
if not isinstance(require_opt, tuple) and require_opt.impl_is_multi():
|
|
||||||
if is_follower is None:
|
|
||||||
is_follower = option.impl_is_follower()
|
|
||||||
if is_follower:
|
|
||||||
leadership = option.impl_get_leadership()
|
|
||||||
if is_follower and require_opt.impl_get_leadership():
|
|
||||||
if leadership != require_opt.impl_get_leadership():
|
|
||||||
raise ValueError(_('malformed requirements option "{0}" '
|
|
||||||
'must be in same leadership for "{1}"').format(
|
|
||||||
require_opt.impl_getname(), option.impl_getname()))
|
|
||||||
else:
|
|
||||||
raise ValueError(_('malformed requirements option "{0}" '
|
|
||||||
'must not be a multi for "{1}"').format(
|
|
||||||
require_opt.impl_getname(), option.impl_getname()))
|
|
||||||
if option.impl_is_readonly():
|
if option.impl_is_readonly():
|
||||||
raise ConflictError(_('duplicate option: {0}').format(option))
|
raise ConflictError(_('duplicate option: {0}').format(option))
|
||||||
if not self.impl_is_readonly() and display_name:
|
if not self.impl_is_readonly() and display_name:
|
||||||
|
@ -162,15 +110,6 @@ class CacheOptionDescription(BaseOption):
|
||||||
option._path = subpath
|
option._path = subpath
|
||||||
option._set_readonly()
|
option._set_readonly()
|
||||||
if init:
|
if init:
|
||||||
if _consistencies != {}:
|
|
||||||
self._cache_consistencies = {}
|
|
||||||
for weak_opt, cons in _consistencies.items():
|
|
||||||
opt = weak_opt()
|
|
||||||
if __debug__ and opt not in cache_option:
|
|
||||||
raise ConfigError(_('consistency with option {0} '
|
|
||||||
'which is not in Config').format(
|
|
||||||
opt.impl_getname()))
|
|
||||||
self._cache_consistencies[opt] = tuple(cons)
|
|
||||||
self._cache_force_store_values = force_store_values
|
self._cache_force_store_values = force_store_values
|
||||||
self._path = self._name
|
self._path = self._name
|
||||||
self._set_readonly()
|
self._set_readonly()
|
||||||
|
@ -275,7 +214,6 @@ class OptionDescription(OptionDescriptionWalk):
|
||||||
name: str,
|
name: str,
|
||||||
doc: str,
|
doc: str,
|
||||||
children: List[BaseOption],
|
children: List[BaseOption],
|
||||||
requires=None,
|
|
||||||
properties=None) -> None:
|
properties=None) -> None:
|
||||||
"""
|
"""
|
||||||
:param children: a list of options (including optiondescriptions)
|
:param children: a list of options (including optiondescriptions)
|
||||||
|
@ -285,7 +223,6 @@ class OptionDescription(OptionDescriptionWalk):
|
||||||
'must be a list').format(name)
|
'must be a list').format(name)
|
||||||
super().__init__(name,
|
super().__init__(name,
|
||||||
doc=doc,
|
doc=doc,
|
||||||
requires=requires,
|
|
||||||
properties=properties)
|
properties=properties)
|
||||||
child_names = []
|
child_names = []
|
||||||
if __debug__:
|
if __debug__:
|
||||||
|
|
|
@ -48,12 +48,8 @@ class PortOption(StrOption):
|
||||||
doc,
|
doc,
|
||||||
default=None,
|
default=None,
|
||||||
default_multi=None,
|
default_multi=None,
|
||||||
requires=None,
|
|
||||||
multi=False,
|
multi=False,
|
||||||
callback=None,
|
validators=None,
|
||||||
callback_params=None,
|
|
||||||
validator=None,
|
|
||||||
validator_params=None,
|
|
||||||
properties=None,
|
properties=None,
|
||||||
allow_range=False,
|
allow_range=False,
|
||||||
allow_zero=False,
|
allow_zero=False,
|
||||||
|
@ -89,12 +85,8 @@ class PortOption(StrOption):
|
||||||
doc,
|
doc,
|
||||||
default=default,
|
default=default,
|
||||||
default_multi=default_multi,
|
default_multi=default_multi,
|
||||||
callback=callback,
|
|
||||||
callback_params=callback_params,
|
|
||||||
requires=requires,
|
|
||||||
multi=multi,
|
multi=multi,
|
||||||
validator=validator,
|
validators=validators,
|
||||||
validator_params=validator_params,
|
|
||||||
properties=properties,
|
properties=properties,
|
||||||
warnings_only=warnings_only,
|
warnings_only=warnings_only,
|
||||||
extra=extra)
|
extra=extra)
|
||||||
|
|
|
@ -58,6 +58,3 @@ class SymLinkOption(BaseOption):
|
||||||
|
|
||||||
def impl_getopt(self) -> BaseOption:
|
def impl_getopt(self) -> BaseOption:
|
||||||
return self._opt
|
return self._opt
|
||||||
|
|
||||||
def get_consistencies(self) -> tuple:
|
|
||||||
return ()
|
|
||||||
|
|
|
@ -64,24 +64,11 @@ class SynDynOption:
|
||||||
def impl_getpath(self) -> str:
|
def impl_getpath(self) -> str:
|
||||||
return self.rootpath + '.' + self.impl_getname()
|
return self.rootpath + '.' + self.impl_getname()
|
||||||
|
|
||||||
def impl_validate(self,
|
|
||||||
value: Any,
|
|
||||||
option_bag: OptionBag,
|
|
||||||
check_error: bool=True) -> None:
|
|
||||||
soption_bag = OptionBag()
|
|
||||||
soption_bag.set_option(self.opt,
|
|
||||||
self.impl_getpath(),
|
|
||||||
option_bag.index,
|
|
||||||
option_bag.config_bag)
|
|
||||||
soption_bag.ori_option = option_bag.option
|
|
||||||
soption_bag.fromconsistency = option_bag.fromconsistency.copy()
|
|
||||||
self.opt.impl_validate(value,
|
|
||||||
soption_bag,
|
|
||||||
check_error=check_error)
|
|
||||||
|
|
||||||
def impl_is_dynsymlinkoption(self) -> bool:
|
def impl_is_dynsymlinkoption(self) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def impl_get_leadership(self):
|
def impl_get_leadership(self):
|
||||||
return self.opt.impl_get_leadership().to_dynoption(self.rootpath,
|
leadership = self.opt.impl_get_leadership()
|
||||||
self.suffix)
|
if leadership:
|
||||||
|
return leadership.to_dynoption(self.rootpath,
|
||||||
|
self.suffix)
|
||||||
|
|
|
@ -15,8 +15,7 @@
|
||||||
# You should have received a copy of the GNU Lesser General Public License
|
# You should have received a copy of the GNU Lesser General Public License
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
from .error import (RequirementError, PropertiesOptionError,
|
from .error import PropertiesOptionError, ConstError, ConfigError, LeadershipError, display_list
|
||||||
ConstError, ConfigError, display_list)
|
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
@ -109,7 +108,12 @@ FORBIDDEN_SET_PROPERTIES = frozenset(['force_store_value'])
|
||||||
FORBIDDEN_SET_PERMISSIVES = frozenset(['force_default_on_freeze',
|
FORBIDDEN_SET_PERMISSIVES = frozenset(['force_default_on_freeze',
|
||||||
'force_metaconfig_on_freeze',
|
'force_metaconfig_on_freeze',
|
||||||
'force_store_value'])
|
'force_store_value'])
|
||||||
|
ALLOWED_LEADER_PROPERTIES = frozenset(['empty',
|
||||||
|
'force_store_value',
|
||||||
|
'mandatory',
|
||||||
|
'force_default_on_freeze',
|
||||||
|
'force_metaconfig_on_freeze',
|
||||||
|
'frozen'])
|
||||||
|
|
||||||
static_set = frozenset()
|
static_set = frozenset()
|
||||||
|
|
||||||
|
@ -123,12 +127,10 @@ class OptionBag:
|
||||||
'properties', # properties of current option
|
'properties', # properties of current option
|
||||||
'properties_setted',
|
'properties_setted',
|
||||||
'apply_requires', # apply requires or not for this option
|
'apply_requires', # apply requires or not for this option
|
||||||
'fromconsistency' # history for consistency
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.option = None
|
self.option = None
|
||||||
self.fromconsistency = []
|
|
||||||
|
|
||||||
def set_option(self,
|
def set_option(self,
|
||||||
option,
|
option,
|
||||||
|
@ -235,9 +237,6 @@ class ConfigBag:
|
||||||
return
|
return
|
||||||
raise KeyError('unknown key {} for ConfigBag'.format(key)) # pragma: no cover
|
raise KeyError('unknown key {} for ConfigBag'.format(key)) # pragma: no cover
|
||||||
|
|
||||||
# def __setattr__(self, key, value):
|
|
||||||
# super().__setattr__(key, value)
|
|
||||||
|
|
||||||
def copy(self):
|
def copy(self):
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
for key in self.__slots__:
|
for key in self.__slots__:
|
||||||
|
@ -447,24 +446,19 @@ class Settings(object):
|
||||||
if isinstance(prop, str):
|
if isinstance(prop, str):
|
||||||
props.add(prop)
|
props.add(prop)
|
||||||
elif apply_requires:
|
elif apply_requires:
|
||||||
new_props = prop.execute(option_bag,
|
new_prop = prop.execute(option_bag,
|
||||||
leadership_must_have_index=True)
|
leadership_must_have_index=True)
|
||||||
if not new_props:
|
if not new_prop:
|
||||||
continue
|
continue
|
||||||
elif not isinstance(new_props, str):
|
elif not isinstance(new_prop, str):
|
||||||
raise ValueError(_('invalid property type {} for {} with {} function').format(type(new_props),
|
raise ValueError(_('invalid property type {} for {} with {} function').format(type(new_prop),
|
||||||
option_bag.option.impl_getname(),
|
option_bag.option.impl_getname(),
|
||||||
prop.function.__name__))
|
prop.function.__name__))
|
||||||
props.add(new_props)
|
if not option.impl_is_optiondescription() and option.impl_is_leader() and new_prop not in ALLOWED_LEADER_PROPERTIES:
|
||||||
# else:
|
raise LeadershipError(_('leader cannot have "{}" property').format(new_prop))
|
||||||
# props.update(new_props)
|
props.add(new_prop)
|
||||||
if apply_requires:
|
|
||||||
props |= self.apply_requires(option_bag,
|
|
||||||
False,
|
|
||||||
search_properties=search_properties)
|
|
||||||
props -= self.getpermissives(option,
|
props -= self.getpermissives(option,
|
||||||
path)
|
path)
|
||||||
#if apply_requires and config_bag.properties == config_bag.true_properties:
|
|
||||||
if apply_requires and not config_bag.is_unrestraint:
|
if apply_requires and not config_bag.is_unrestraint:
|
||||||
cache.setcache(path,
|
cache.setcache(path,
|
||||||
index,
|
index,
|
||||||
|
@ -508,195 +502,6 @@ class Settings(object):
|
||||||
path = opt.impl_getpath()
|
path = opt.impl_getpath()
|
||||||
return self._pp_.getpermissives(path)
|
return self._pp_.getpermissives(path)
|
||||||
|
|
||||||
def apply_requires(self,
|
|
||||||
option_bag,
|
|
||||||
readable,
|
|
||||||
search_properties=None):
|
|
||||||
"""carries out the jit (just in time) requirements between options
|
|
||||||
|
|
||||||
a requirement is a tuple of this form that comes from the option's
|
|
||||||
requirements validation::
|
|
||||||
|
|
||||||
(option, expected, action, inverse, transitive, same_action)
|
|
||||||
|
|
||||||
let's have a look at all the tuple's items:
|
|
||||||
|
|
||||||
- **option** is the target option's
|
|
||||||
|
|
||||||
- **expected** is the target option's value that is going to trigger
|
|
||||||
an action
|
|
||||||
|
|
||||||
- **action** is the (property) action to be accomplished if the target
|
|
||||||
option happens to have the expected value
|
|
||||||
|
|
||||||
- if **inverse** is `True` and if the target option's value does not
|
|
||||||
apply, then the property action must be removed from the option's
|
|
||||||
properties list (wich means that the property is inverted)
|
|
||||||
|
|
||||||
- **transitive**: but what happens if the target option cannot be
|
|
||||||
accessed ? We don't kown the target option's value. Actually if some
|
|
||||||
property in the target option is not present in the permissive, the
|
|
||||||
target option's value cannot be accessed. In this case, the
|
|
||||||
**action** have to be applied to the option. (the **action** property
|
|
||||||
is then added to the option).
|
|
||||||
|
|
||||||
- **same_action**: actually, if **same_action** is `True`, the
|
|
||||||
transitivity is not accomplished. The transitivity is accomplished
|
|
||||||
only if the target option **has the same property** that the demanded
|
|
||||||
action. If the target option's value is not accessible because of
|
|
||||||
another reason, because of a property of another type, then an
|
|
||||||
exception :exc:`~error.RequirementError` is raised.
|
|
||||||
|
|
||||||
And at last, if no target option matches the expected values, the
|
|
||||||
action will not add to the option's properties list.
|
|
||||||
|
|
||||||
:param opt: the option on wich the requirement occurs
|
|
||||||
:type opt: `option.Option()`
|
|
||||||
:param path: the option's path in the config
|
|
||||||
:type path: str
|
|
||||||
"""
|
|
||||||
current_requires = option_bag.option.impl_getrequires()
|
|
||||||
|
|
||||||
# filters the callbacks
|
|
||||||
if readable:
|
|
||||||
calc_properties = {}
|
|
||||||
else:
|
|
||||||
calc_properties = set()
|
|
||||||
|
|
||||||
if not current_requires:
|
|
||||||
return calc_properties
|
|
||||||
|
|
||||||
context = option_bag.config_bag.context
|
|
||||||
all_properties = None
|
|
||||||
for requires in current_requires:
|
|
||||||
for require in requires:
|
|
||||||
exps, action, inverse, transitive, same_action, operator = require
|
|
||||||
#if search_properties and action not in search_properties:
|
|
||||||
# continue
|
|
||||||
breaked = False
|
|
||||||
for option, expected in exps:
|
|
||||||
if not isinstance(option, tuple):
|
|
||||||
if option.issubdyn():
|
|
||||||
option = option.to_dynoption(option_bag.option.rootpath,
|
|
||||||
option_bag.option.impl_getsuffix())
|
|
||||||
reqpath = option.impl_getpath()
|
|
||||||
if __debug__ and reqpath.startswith(option_bag.path + '.'):
|
|
||||||
# FIXME too later!
|
|
||||||
raise RequirementError(_("malformed requirements "
|
|
||||||
"imbrication detected for option:"
|
|
||||||
" '{0}' with requirement on: "
|
|
||||||
"'{1}'").format(option_bag.path, reqpath))
|
|
||||||
idx = None
|
|
||||||
is_indexed = False
|
|
||||||
if option.impl_is_follower():
|
|
||||||
idx = option_bag.index
|
|
||||||
if idx is None:
|
|
||||||
continue
|
|
||||||
elif option.impl_is_leader() and option_bag.index is None:
|
|
||||||
continue
|
|
||||||
elif option.impl_is_multi() and option_bag.index is not None:
|
|
||||||
is_indexed = True
|
|
||||||
config_bag = option_bag.config_bag.copy()
|
|
||||||
soption_bag = OptionBag()
|
|
||||||
soption_bag.set_option(option,
|
|
||||||
reqpath,
|
|
||||||
idx,
|
|
||||||
config_bag)
|
|
||||||
if option_bag.option == option:
|
|
||||||
soption_bag.config_bag.unrestraint()
|
|
||||||
soption_bag.config_bag.remove_validation()
|
|
||||||
soption_bag.apply_requires = False
|
|
||||||
else:
|
|
||||||
soption_bag.config_bag.properties = soption_bag.config_bag.true_properties
|
|
||||||
soption_bag.config_bag.set_permissive()
|
|
||||||
else:
|
|
||||||
if not option_bag.option.impl_is_optiondescription() and option_bag.option.impl_is_follower():
|
|
||||||
idx = option_bag.index
|
|
||||||
if idx is None:
|
|
||||||
continue
|
|
||||||
is_indexed = False
|
|
||||||
try:
|
|
||||||
if not isinstance(option, tuple):
|
|
||||||
value = context.getattr(reqpath,
|
|
||||||
soption_bag)
|
|
||||||
else:
|
|
||||||
value = context.cfgimpl_get_values().carry_out_calculation(option_bag,
|
|
||||||
option[0],
|
|
||||||
option[1])
|
|
||||||
except (PropertiesOptionError, ConfigError) as err:
|
|
||||||
if isinstance(err, ConfigError):
|
|
||||||
if not isinstance(err.ori_err, PropertiesOptionError):
|
|
||||||
raise err
|
|
||||||
err = err.ori_err
|
|
||||||
properties = err.proptype
|
|
||||||
# if not transitive, properties must be verify in current requires
|
|
||||||
# otherwise if same_action, property must be in properties
|
|
||||||
# otherwise add property in returned properties (if operator is 'and')
|
|
||||||
if not transitive:
|
|
||||||
if all_properties is None:
|
|
||||||
all_properties = []
|
|
||||||
for requires_ in current_requires:
|
|
||||||
for require_ in requires_:
|
|
||||||
all_properties.append(require_[1])
|
|
||||||
if not set(properties) - set(all_properties):
|
|
||||||
continue
|
|
||||||
if same_action and action not in properties:
|
|
||||||
if len(properties) == 1:
|
|
||||||
prop_msg = _('property')
|
|
||||||
else:
|
|
||||||
prop_msg = _('properties')
|
|
||||||
err = RequirementError(_('cannot access to option "{0}" because '
|
|
||||||
'required option "{1}" has {2} {3}'
|
|
||||||
'').format(option_bag.option.impl_get_display_name(),
|
|
||||||
option.impl_get_display_name(),
|
|
||||||
prop_msg,
|
|
||||||
display_list(list(properties), add_quote=True)))
|
|
||||||
err.proptype = properties
|
|
||||||
raise err
|
|
||||||
# transitive action, add action
|
|
||||||
if operator != 'and':
|
|
||||||
if readable:
|
|
||||||
for msg in self.apply_requires(err._option_bag,
|
|
||||||
True).values():
|
|
||||||
calc_properties.setdefault(action, []).extend(msg)
|
|
||||||
else:
|
|
||||||
calc_properties.add(action)
|
|
||||||
breaked = True
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if is_indexed:
|
|
||||||
value = value[option_bag.index]
|
|
||||||
if (not inverse and value in expected or
|
|
||||||
inverse and value not in expected):
|
|
||||||
if operator != 'and':
|
|
||||||
if readable:
|
|
||||||
display_value = display_list(expected, 'or', add_quote=True)
|
|
||||||
if isinstance(option, tuple):
|
|
||||||
if not inverse:
|
|
||||||
msg = _('the calculated value is {0}').format(display_value)
|
|
||||||
else:
|
|
||||||
msg = _('the calculated value is not {0}').format(display_value)
|
|
||||||
else:
|
|
||||||
name = option.impl_get_display_name()
|
|
||||||
if not inverse:
|
|
||||||
msg = _('the value of "{0}" is {1}').format(name, display_value)
|
|
||||||
else:
|
|
||||||
msg = _('the value of "{0}" is not {1}').format(name, display_value)
|
|
||||||
calc_properties.setdefault(action, []).append(msg)
|
|
||||||
else:
|
|
||||||
calc_properties.add(action)
|
|
||||||
breaked = True
|
|
||||||
break
|
|
||||||
elif operator == 'and':
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
if operator == 'and':
|
|
||||||
calc_properties.add(action)
|
|
||||||
continue
|
|
||||||
if breaked:
|
|
||||||
break
|
|
||||||
return calc_properties
|
|
||||||
|
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
# set methods
|
# set methods
|
||||||
def set_context_properties(self,
|
def set_context_properties(self,
|
||||||
|
@ -715,23 +520,21 @@ class Settings(object):
|
||||||
(never save properties if same has option properties)
|
(never save properties if same has option properties)
|
||||||
"""
|
"""
|
||||||
opt = option_bag.option
|
opt = option_bag.option
|
||||||
if opt.impl_getrequires() is not None:
|
|
||||||
not_allowed_props = properties & \
|
|
||||||
getattr(opt, '_calc_properties', static_set)
|
|
||||||
if not_allowed_props:
|
|
||||||
raise ValueError(_('cannot set property {} for option "{}" this property is '
|
|
||||||
'calculated').format(display_list(list(not_allowed_props),
|
|
||||||
add_quote=True),
|
|
||||||
opt.impl_get_display_name()))
|
|
||||||
if opt.impl_is_symlinkoption():
|
if opt.impl_is_symlinkoption():
|
||||||
raise TypeError(_("can't assign property to the symlinkoption \"{}\""
|
raise TypeError(_("can't assign property to the symlinkoption \"{}\""
|
||||||
"").format(opt.impl_get_display_name()))
|
"").format(opt.impl_get_display_name()))
|
||||||
if ('force_default_on_freeze' in properties or 'force_metaconfig_on_freeze' in properties) and \
|
if not opt.impl_is_optiondescription() and opt.impl_is_leader():
|
||||||
'frozen' not in properties and \
|
not_allowed_properties = properties - ALLOWED_LEADER_PROPERTIES
|
||||||
opt.impl_is_leader():
|
if not_allowed_properties:
|
||||||
raise ConfigError(_('a leader ({0}) cannot have '
|
if len(not_allowed_properties) == 1:
|
||||||
'"force_default_on_freeze" or "force_metaconfig_on_freeze" property without "frozen"'
|
raise LeadershipError(_('leader cannot have "{}" property').format(list(not_allowed_properties)[0]))
|
||||||
'').format(opt.impl_get_display_name()))
|
else:
|
||||||
|
raise LeadershipError(_('leader cannot have {} properties').format(display_list(list(not_allowed_properties), add_quote=True)))
|
||||||
|
if ('force_default_on_freeze' in properties or 'force_metaconfig_on_freeze' in properties) and \
|
||||||
|
'frozen' not in properties:
|
||||||
|
raise LeadershipError(_('a leader ({0}) cannot have '
|
||||||
|
'"force_default_on_freeze" or "force_metaconfig_on_freeze" property without "frozen"'
|
||||||
|
'').format(opt.impl_get_display_name()))
|
||||||
self._p_.setproperties(path,
|
self._p_.setproperties(path,
|
||||||
properties)
|
properties)
|
||||||
# values too because of follower values could have a PropertiesOptionError has value
|
# values too because of follower values could have a PropertiesOptionError has value
|
||||||
|
|
|
@ -67,7 +67,7 @@ class Callbacks(object):
|
||||||
raise ValueError(_('context is not supported from now for {}').format(path))
|
raise ValueError(_('context is not supported from now for {}').format(path))
|
||||||
if isinstance(callback_param, ParamOption):
|
if isinstance(callback_param, ParamOption):
|
||||||
has_option = True
|
has_option = True
|
||||||
if callback.__name__ != 'tiramisu_copy' or 'expire' in childapi.option.properties():
|
if 'expire' in childapi.option.properties():
|
||||||
self.tiramisu_web.set_remotable(callback_param.option.impl_getpath(), form)
|
self.tiramisu_web.set_remotable(callback_param.option.impl_getpath(), form)
|
||||||
if not has_option and form.get(path, {}).get('remote', False) == False:
|
if not has_option and form.get(path, {}).get('remote', False) == False:
|
||||||
if 'expire' in childapi.option.properties():
|
if 'expire' in childapi.option.properties():
|
||||||
|
@ -79,14 +79,15 @@ class Callbacks(object):
|
||||||
form.setdefault(path, {})['clearable'] = True
|
form.setdefault(path, {})['clearable'] = True
|
||||||
|
|
||||||
def manage_callbacks(self, form):
|
def manage_callbacks(self, form):
|
||||||
for callback, callback_params, path, childapi, schema, force_store_value in self.callbacks:
|
pass
|
||||||
if callback_params is not None:
|
#for callback, callback_params, path, childapi, schema, force_store_value in self.callbacks:
|
||||||
for callback_param in chain(callback_params.args, callback_params.kwargs.values()):
|
# if callback_params is not None:
|
||||||
if isinstance(callback_param, ParamOption) and callback.__name__ == 'tiramisu_copy':
|
# for callback_param in chain(callback_params.args, callback_params.kwargs.values()):
|
||||||
opt_path = callback_param.option.impl_getpath()
|
# if isinstance(callback_param, ParamOption) and callback.__name__ == 'tiramisu_copy':
|
||||||
if form.get(opt_path, {}).get('remote') is not True:
|
# opt_path = callback_param.option.impl_getpath()
|
||||||
form.setdefault(opt_path, {})
|
# if form.get(opt_path, {}).get('remote') is not True:
|
||||||
form[opt_path].setdefault('copy', []).append(path)
|
# form.setdefault(opt_path, {})
|
||||||
|
# form[opt_path].setdefault('copy', []).append(path)
|
||||||
|
|
||||||
def process(self,
|
def process(self,
|
||||||
form):
|
form):
|
||||||
|
|
|
@ -17,7 +17,7 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
import weakref
|
import weakref
|
||||||
from typing import Optional, Any, Callable
|
from typing import Optional, Any, Callable
|
||||||
from .error import ConfigError, PropertiesOptionError, RequirementError
|
from .error import ConfigError, PropertiesOptionError
|
||||||
from .setting import owners, undefined, forbidden_owners, OptionBag, ConfigBag
|
from .setting import owners, undefined, forbidden_owners, OptionBag, ConfigBag
|
||||||
from .autolib import Calculation, carry_out_calculation, Params
|
from .autolib import Calculation, carry_out_calculation, Params
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
|
@ -78,7 +78,7 @@ class Values(object):
|
||||||
# store value in cache
|
# store value in cache
|
||||||
properties = option_bag.config_bag.properties
|
properties = option_bag.config_bag.properties
|
||||||
validator = 'validator' in properties and 'demoting_error_warning' not in properties
|
validator = 'validator' in properties and 'demoting_error_warning' not in properties
|
||||||
if not option_bag.fromconsistency and (not is_cached or validator):
|
if not is_cached or validator:
|
||||||
cache.setcache(option_bag.path,
|
cache.setcache(option_bag.path,
|
||||||
option_bag.index,
|
option_bag.index,
|
||||||
value,
|
value,
|
||||||
|
@ -258,8 +258,7 @@ class Values(object):
|
||||||
callback=callback,
|
callback=callback,
|
||||||
callback_params=callback_params,
|
callback_params=callback_params,
|
||||||
index=option_bag.index,
|
index=option_bag.index,
|
||||||
config_bag=option_bag.config_bag,
|
config_bag=option_bag.config_bag)
|
||||||
fromconsistency=option_bag.fromconsistency)
|
|
||||||
def isempty(self,
|
def isempty(self,
|
||||||
opt,
|
opt,
|
||||||
value,
|
value,
|
||||||
|
@ -289,24 +288,8 @@ class Values(object):
|
||||||
context = option_bag.config_bag.context
|
context = option_bag.config_bag.context
|
||||||
owner = self.get_context_owner()
|
owner = self.get_context_owner()
|
||||||
if 'validator' in option_bag.config_bag.properties:
|
if 'validator' in option_bag.config_bag.properties:
|
||||||
if option_bag.index is not None or option_bag.option.has_consistencies(context):
|
self.setvalue_validation(value,
|
||||||
# set value to a fake config when option has dependency
|
option_bag)
|
||||||
# validation will be complet in this case (consistency, ...)
|
|
||||||
tested_context = context._gen_fake_values()
|
|
||||||
config_bag = option_bag.config_bag.copy()
|
|
||||||
config_bag.unrestraint()
|
|
||||||
config_bag.context = tested_context
|
|
||||||
soption_bag = option_bag.copy()
|
|
||||||
soption_bag.config_bag = config_bag
|
|
||||||
tested_context.cfgimpl_get_values().setvalue(value,
|
|
||||||
soption_bag,
|
|
||||||
True)
|
|
||||||
soption_bag.config_bag.properties = option_bag.config_bag.properties
|
|
||||||
tested_context.getattr(soption_bag.path,
|
|
||||||
soption_bag)
|
|
||||||
else:
|
|
||||||
self.setvalue_validation(value,
|
|
||||||
option_bag)
|
|
||||||
|
|
||||||
self._setvalue(option_bag,
|
self._setvalue(option_bag,
|
||||||
value,
|
value,
|
||||||
|
@ -622,7 +605,7 @@ class Values(object):
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
if err.proptype == ['mandatory']:
|
if err.proptype == ['mandatory']:
|
||||||
yield path
|
yield path
|
||||||
except (RequirementError, ConfigError):
|
except ConfigError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def mandatory_warnings(self,
|
def mandatory_warnings(self,
|
||||||
|
|
Loading…
Reference in a new issue