add Calculation to properties

This commit is contained in:
Emmanuel Garette 2019-09-01 09:41:53 +02:00
parent 7c641961d3
commit bb2ecc94d9
27 changed files with 2358 additions and 574 deletions

View File

@ -5,12 +5,11 @@ from py.test import raises
from .autopath import do_autopath from .autopath import do_autopath
do_autopath() do_autopath()
from tiramisu.option import BoolOption, IPOption, IntOption, StrOption, OptionDescription, Leadership from tiramisu import BoolOption, IPOption, IntOption, StrOption, OptionDescription, Leadership, Config, \
from tiramisu import Config undefined, Calculation, Params, ParamValue, ParamOption, \
list_sessions, default_storage, delete_session, calc_value
from tiramisu.error import ConfigError, PropertiesOptionError from tiramisu.error import ConfigError, PropertiesOptionError
from tiramisu.setting import groups from tiramisu.setting import groups
from tiramisu import undefined, Params, ParamValue, ParamOption, \
list_sessions, default_storage, delete_session
def teardown_function(function): def teardown_function(function):
@ -497,8 +496,12 @@ def test_cache_leader_callback():
def test_cache_requires(): def test_cache_requires():
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '', disabled_property = Calculation(calc_value,
requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a),
'expected': ParamValue(False),
'default': ParamValue(None)}))
b = IPOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b]) od = OptionDescription('service', '', [a, b])
cfg = Config(od) cfg = Config(od)
cfg.property.read_write() cfg.property.read_write()
@ -545,8 +548,12 @@ def test_cache_requires():
def test_cache_global_properties(): def test_cache_global_properties():
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '', disabled_property = Calculation(calc_value,
requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a),
'expected': ParamValue(False),
'default': ParamValue(None)}))
b = IPOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b]) od = OptionDescription('service', '', [a, b])
cfg = Config(od) cfg = Config(od)
cfg.property.read_write() cfg.property.read_write()

View File

@ -131,7 +131,7 @@ def test_base_config_in_a_tree():
def test_not_valid_properties(): def test_not_valid_properties():
raises(TypeError, "stroption = StrOption('str', 'Test string option', default='abc', properties=['mandatory',])") raises(AssertionError, "stroption = StrOption('str', 'Test string option', default='abc', properties='mandatory')")
def test_information_config(): def test_information_config():

View File

@ -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 Config, Params, ParamOption, ParamValue, 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
@ -494,16 +494,24 @@ def test_decrease_dyndescription_context():
def test_dyndescription_root(): def test_dyndescription_root():
boolean = BoolOption('boolean', '', True) boolean = BoolOption('boolean', '', True)
st1 = StrOption('st', '', requires=[{'option': boolean, 'expected': False, disabled_property = Calculation(calc_value,
'action': 'disabled'}]) Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(boolean),
'expected': ParamValue(False),
'default': ParamValue(None)}))
st1 = StrOption('st', '', properties=(disabled_property,))
dod = DynOptionDescription('dod', '', [boolean, st1], callback=return_list) dod = DynOptionDescription('dod', '', [boolean, st1], callback=return_list)
raises(ConfigError, "Config(dod)") raises(ConfigError, "Config(dod)")
def test_requires_dyndescription(): def test_requires_dyndescription():
boolean = BoolOption('boolean', '', True) boolean = BoolOption('boolean', '', True)
st1 = StrOption('st', '', requires=[{'option': boolean, 'expected': False, disabled_property = Calculation(calc_value,
'action': 'disabled'}]) Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(boolean, raisepropertyerror=True),
'expected': ParamValue(False),
'default': ParamValue(None)}))
st1 = StrOption('st', '', properties=(disabled_property,))
dod = DynOptionDescription('dod', '', [st1], callback=return_list) dod = DynOptionDescription('dod', '', [st1], callback=return_list)
od1 = OptionDescription('od', '', [dod]) od1 = OptionDescription('od', '', [dod])
od2 = OptionDescription('od', '', [od1, boolean]) od2 = OptionDescription('od', '', [od1, boolean])
@ -547,11 +555,18 @@ def test_requires_dyndescription():
def test_requires_dyndescription_boolean(): def test_requires_dyndescription_boolean():
boolean1 = BoolOption('boolean1', '', True) boolean1 = BoolOption('boolean1', '', True)
boolean = BoolOption('boolean', '', True, requires=[{'option': boolean1, disabled_property = Calculation(calc_value,
'expected': False, Params(ParamValue('disabled'),
'action': 'disabled'}]) kwargs={'condition': ParamOption(boolean1, raisepropertyerror=True),
st = StrOption('st', '', requires=[{'option': boolean, 'expected': False, 'expected': ParamValue(False),
'action': 'disabled'}]) 'default': ParamValue(None)}))
boolean = BoolOption('boolean', '', True, properties=(disabled_property,))
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(boolean, raisepropertyerror=True),
'expected': ParamValue(False),
'default': ParamValue(None)}))
st = StrOption('st', '', properties=(disabled_property,))
dod = DynOptionDescription('dod', '', [st], callback=return_list) dod = DynOptionDescription('dod', '', [st], callback=return_list)
od = OptionDescription('od', '', [dod]) od = OptionDescription('od', '', [dod])
od2 = OptionDescription('od', '', [od, boolean1, boolean]) od2 = OptionDescription('od', '', [od, boolean1, boolean])
@ -578,8 +593,12 @@ def test_requires_dyndescription_boolean():
def test_requires_dyndescription_in_dyn(): def test_requires_dyndescription_in_dyn():
boolean = BoolOption('boolean', '', True) boolean = BoolOption('boolean', '', True)
st = StrOption('st', '', requires=[{'option': boolean, 'expected': False, disabled_property = Calculation(calc_value,
'action': 'disabled'}]) Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(boolean, raisepropertyerror=True),
'expected': ParamValue(False),
'default': ParamValue(None)}))
st = StrOption('st', '', properties=(disabled_property,))
dod = DynOptionDescription('dod', '', [boolean, st], callback=return_list) dod = DynOptionDescription('dod', '', [boolean, st], callback=return_list)
od = OptionDescription('od', '', [dod]) od = OptionDescription('od', '', [dod])
od2 = OptionDescription('od', '', [od]) od2 = OptionDescription('od', '', [od])
@ -608,9 +627,12 @@ def test_requires_dyndescription_in_dyn():
def test_requires_dyndescription2(): def test_requires_dyndescription2():
boolean = BoolOption('boolean', '', True) boolean = BoolOption('boolean', '', True)
st1 = StrOption('st', '') st1 = StrOption('st', '')
dod = DynOptionDescription('dod', '', [st1], callback=return_list, disabled_property = Calculation(calc_value,
requires=[{'option': boolean, 'expected': False, Params(ParamValue('disabled'),
'action': 'disabled'}]) kwargs={'condition': ParamOption(boolean, raisepropertyerror=True),
'expected': ParamValue(False),
'default': ParamValue(None)}))
dod = DynOptionDescription('dod', '', [st1], callback=return_list, properties=(disabled_property,))
od1 = OptionDescription('od', '', [dod]) od1 = OptionDescription('od', '', [dod])
od2 = OptionDescription('od', '', [od1, boolean]) od2 = OptionDescription('od', '', [od1, boolean])
api = Config(od2) api = Config(od2)

View File

@ -8,7 +8,7 @@ from py.test import raises
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, SymLinkOption, Leadership, Config, \ StrOption, OptionDescription, SymLinkOption, Leadership, Config, \
Params, ParamContext, ParamOption, ParamValue Calculation, Params, ParamContext, ParamOption, ParamValue, calc_value
from tiramisu.error import PropertiesOptionError, ConfigError from tiramisu.error import PropertiesOptionError, ConfigError
from tiramisu.storage import list_sessions from tiramisu.storage import list_sessions
@ -41,14 +41,23 @@ def make_description_freeze():
floatoption = FloatOption('float', 'Test float option', default=2.3) floatoption = FloatOption('float', 'Test float option', default=2.3)
stroption = StrOption('str', 'Test string option', default="abc") stroption = StrOption('str', 'Test string option', default="abc")
boolop = BoolOption('boolop', 'Test boolean option op', default=[True], multi=True) boolop = BoolOption('boolop', 'Test boolean option op', default=[True], multi=True)
wantref_option = BoolOption('wantref', 'Test requires', default=False, properties=('force_store_value',), hidden_property = Calculation(calc_value,
requires=({'option': booloption, 'expected': True, 'action': 'hidden'},)) Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(booloption, raisepropertyerror=True),
'expected': ParamValue(True),
'default': ParamValue(None)}))
wantref_option = BoolOption('wantref', 'Test requires', default=False, properties=('force_store_value', hidden_property))
wantref2_option = BoolOption('wantref2', 'Test requires', default=False, properties=('force_store_value', 'hidden')) wantref2_option = BoolOption('wantref2', 'Test requires', default=False, properties=('force_store_value', 'hidden'))
wantref3_option = BoolOption('wantref3', 'Test requires', default=[False], multi=True, properties=('force_store_value',)) wantref3_option = BoolOption('wantref3', 'Test requires', default=[False], multi=True, properties=('force_store_value',))
st2 = SymLinkOption('st2', wantref3_option) st2 = SymLinkOption('st2', wantref3_option)
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(booloption, raisepropertyerror=True),
'expected': ParamValue(True),
'default': ParamValue(None)}))
wantframework_option = BoolOption('wantframework', 'Test requires', wantframework_option = BoolOption('wantframework', 'Test requires',
default=False, default=False,
requires=({'option': booloption, 'expected': True, 'action': 'hidden'},)) properties=(hidden_property,))
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
descr = OptionDescription('tiramisu', '', [gcgroup, booloption, objspaceoption, descr = OptionDescription('tiramisu', '', [gcgroup, booloption, objspaceoption,

View File

@ -6,7 +6,8 @@ do_autopath()
from py.test import raises from py.test import raises
from tiramisu import Config from tiramisu import Config
from tiramisu import IntOption, StrOption, UnicodeOption, OptionDescription, \ from tiramisu import IntOption, StrOption, UnicodeOption, OptionDescription, \
SymLinkOption, Leadership, undefined, Params, ParamOption SymLinkOption, Leadership, undefined, Calculation, Params, \
ParamOption, ParamValue, calc_value
from tiramisu.error import PropertiesOptionError, ConfigError from tiramisu.error import PropertiesOptionError, ConfigError
from tiramisu.setting import groups from tiramisu.setting import groups
from tiramisu.storage import list_sessions from tiramisu.storage import list_sessions
@ -575,7 +576,12 @@ def test_mandatory_warnings_requires():
properties=('mandatory', )) properties=('mandatory', ))
stroption2 = UnicodeOption('unicode2', 'Test string option', stroption2 = UnicodeOption('unicode2', 'Test string option',
properties=('mandatory', )) properties=('mandatory', ))
stroption3 = StrOption('str3', 'Test string option', multi=True, requires=[{'option': stroption, 'expected': 'yes', 'action': 'mandatory', 'transitive': False}]) mandatory_property = Calculation(calc_value,
Params(ParamValue('mandatory'),
kwargs={'condition': ParamOption(stroption, notraisepropertyerror=True),
'expected': ParamValue('yes'),
'no_condition_is_invalid': ParamValue(True)}))
stroption3 = StrOption('str3', 'Test string option', multi=True, properties=(mandatory_property,))
descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3]) descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3])
cfg = Config(descr) cfg = Config(descr)
cfg.option('str').value.set('') cfg.option('str').value.set('')
@ -593,7 +599,13 @@ def test_mandatory_warnings_requires_leadership():
stroption = StrOption('str', 'Test string option', default="abc", stroption = StrOption('str', 'Test string option', default="abc",
properties=('mandatory', )) properties=('mandatory', ))
stroption1 = StrOption('str1', 'Test string option', multi=True) stroption1 = StrOption('str1', 'Test string option', multi=True)
stroption2 = StrOption('str2', 'Test string option', multi=True, requires=[{'option': stroption, 'expected': 'yes', 'action': 'mandatory', 'transitive': False}]) mandatory_property = Calculation(calc_value,
Params(ParamValue(None),
kwargs={'condition': ParamOption(stroption),
'expected': ParamValue('yes'),
'inverse_condition': ParamValue(True),
'default': ParamValue('mandatory')}))
stroption2 = StrOption('str2', 'Test string option', multi=True, properties=(mandatory_property,))
leadership = Leadership('leader', 'leadership', [stroption1, stroption2]) leadership = Leadership('leader', 'leadership', [stroption1, stroption2])
descr = OptionDescription('tiram', '', [stroption, leadership]) descr = OptionDescription('tiram', '', [stroption, leadership])
cfg = Config(descr) cfg = Config(descr)
@ -607,7 +619,13 @@ def test_mandatory_warnings_requires_leadership():
def test_mandatory_warnings_requires_leadership_follower(): def test_mandatory_warnings_requires_leadership_follower():
stroption = StrOption('str', 'Test string option', multi=True) stroption = StrOption('str', 'Test string option', multi=True)
stroption1 = StrOption('str1', 'Test string option', multi=True) stroption1 = StrOption('str1', 'Test string option', multi=True)
stroption2 = StrOption('str2', 'Test string option', multi=True, requires=[{'option': stroption1, 'expected': 'yes', 'action': 'mandatory', 'transitive': False}]) mandatory_property = Calculation(calc_value,
Params(ParamValue(None),
kwargs={'condition': ParamOption(stroption1),
'expected': ParamValue('yes'),
'inverse_condition': ParamValue(True),
'default': ParamValue('mandatory')}))
stroption2 = StrOption('str2', 'Test string option', multi=True, properties=(mandatory_property,))
leadership = Leadership('leader', 'leadership', [stroption, stroption1, stroption2]) leadership = Leadership('leader', 'leadership', [stroption, stroption1, stroption2])
descr = OptionDescription('tiram', '', [leadership]) descr = OptionDescription('tiram', '', [leadership])
cfg = Config(descr) cfg = Config(descr)

View File

@ -5,7 +5,7 @@ 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, \
Params, ParamOption, ParamValue Calculation, Params, ParamOption, ParamValue, calc_value
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
@ -748,7 +748,11 @@ def test_meta_exception_meta():
def test_meta_properties_requires1(): def test_meta_properties_requires1():
opt1 = BoolOption('opt1', 'opt1', False) opt1 = BoolOption('opt1', 'opt1', False)
opt2 = BoolOption('opt2', "") opt2 = BoolOption('opt2', "")
od2 = OptionDescription('od2', "", [opt2], requires=({'option': opt1, 'expected': False, 'action': 'disabled'},)) disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(opt1, todict=True),
'expected': ParamValue(False)}))
od2 = OptionDescription('od2', "", [opt2], properties=(disabled_property,))
opt3 = BoolOption('opt3', '') opt3 = BoolOption('opt3', '')
opt2.impl_add_consistency('not_equal', opt3) opt2.impl_add_consistency('not_equal', opt3)
od = OptionDescription('root', '', [opt1, od2, opt3]) od = OptionDescription('root', '', [opt1, od2, opt3])
@ -765,7 +769,12 @@ def test_meta_properties_requires_mandatory():
probes = BoolOption('probes', 'probes available', False) probes = BoolOption('probes', 'probes available', False)
eth0_method = ChoiceOption('eth0_method', '', ('static', 'dhcp'), 'static') eth0_method = ChoiceOption('eth0_method', '', ('static', 'dhcp'), 'static')
ip_address = IPOption('ip_address', '') ip_address = IPOption('ip_address', '')
ip_eth0 = IPOption('ip_eth0', "ip", requires=({'option': probes, 'expected': True, 'action': 'mandatory'},), callback=return_condition, callback_params=Params(kwargs={'val': ParamOption(ip_address), 'condition': ParamOption(eth0_method), 'expected': ParamValue('dhcp')})) mandatory_property = Calculation(calc_value,
Params(ParamValue('mandatory'),
kwargs={'condition': ParamOption(probes),
'expected': ParamValue('yes'),
'default': ParamValue(None)}))
ip_eth0 = IPOption('ip_eth0', "ip", properties=(mandatory_property,), callback=return_condition, callback_params=Params(kwargs={'val': ParamOption(ip_address), 'condition': ParamOption(eth0_method), 'expected': ParamValue('dhcp')}))
ip_gw = IPOption('ip_gw', 'gw') ip_gw = IPOption('ip_gw', 'gw')
ip_gw.impl_add_consistency('not_equal', ip_eth0) 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])

View File

@ -3,13 +3,14 @@ do_autopath()
from .config import config_type, get_config from .config import config_type, get_config
from py.test import raises from py.test import raises
import warnings
from tiramisu import Config from tiramisu import Config
from tiramisu.config import KernelConfig from tiramisu.config import KernelConfig
from tiramisu.setting import groups, owners from tiramisu.setting import groups, owners
from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \ from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \
StrOption, OptionDescription, SymLinkOption, IPOption, NetmaskOption, Leadership, \ StrOption, OptionDescription, SymLinkOption, IPOption, NetmaskOption, Leadership, \
undefined, Params, ParamOption, ParamValue, ParamContext, calc_value undefined, Calculation, Params, ParamOption, ParamValue, ParamContext, calc_value
from tiramisu.error import PropertiesOptionError, ConflictError, LeadershipError, ConfigError from tiramisu.error import PropertiesOptionError, ConflictError, LeadershipError, ConfigError
from tiramisu.i18n import _ from tiramisu.i18n import _
from tiramisu.storage import list_sessions from tiramisu.storage import list_sessions
@ -102,11 +103,9 @@ def make_description_duplicates():
floatoption = FloatOption('float', 'Test float option', default=2.3) floatoption = FloatOption('float', 'Test float option', default=2.3)
stroption = StrOption('str', 'Test string option', default="abc") stroption = StrOption('str', 'Test string option', default="abc")
boolop = BoolOption('boolop', 'Test boolean option op', default=True) boolop = BoolOption('boolop', 'Test boolean option op', default=True)
wantref_option = BoolOption('wantref', 'Test requires', default=False, wantref_option = BoolOption('wantref', 'Test requires', default=False)
requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
wantframework_option = BoolOption('wantframework', 'Test requires', wantframework_option = BoolOption('wantframework', 'Test requires',
default=False, default=False)
requires=({'option': boolop, 'expected': True, 'action': 'hidden'},))
# dummy2 (same path) # dummy2 (same path)
gcdummy2 = BoolOption('dummy', 'dummy2', default=True) gcdummy2 = BoolOption('dummy', 'dummy2', default=True)
# dummy3 (same name) # dummy3 (same name)
@ -123,13 +122,18 @@ def test_identical_paths():
"""If in the schema (the option description) there is something that """If in the schema (the option description) there is something that
have the same name, an exection is raised have the same name, an exection is raised
""" """
raises(ConflictError, "make_description_duplicates()") with warnings.catch_warnings(record=True) as w:
raises(ConflictError, "make_description_duplicates()")
def test_hidden_if_in2(config_type): def test_hidden_if_in2(config_type):
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default="abc", hidden_property = Calculation(calc_value,
requires=({'option': intoption, 'expected': 1, 'action': 'hidden'},)) Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(intoption),
'expected': ParamValue(1),
'default': ParamValue(None)}))
stroption = StrOption('str', 'Test string option', default="abc", properties=(hidden_property,))
descr = OptionDescription('constraints', '', [stroption, intoption]) descr = OptionDescription('constraints', '', [stroption, intoption])
cfg_ori = Config(descr) cfg_ori = Config(descr)
cfg_ori.property.read_write() cfg_ori.property.read_write()
@ -154,8 +158,12 @@ def test_hidden_if_in_with_group(config_type):
booloption = BoolOption('bool', 'Test boolean option', default=True) booloption = BoolOption('bool', 'Test boolean option', default=True)
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default="abc") stroption = StrOption('str', 'Test string option', default="abc")
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption], hidden_property = Calculation(calc_value,
requires=({'option': intoption, 'expected': 1, 'action': 'hidden'},)) Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(intoption),
'expected': ParamValue(1),
'default': ParamValue(None)}))
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption], properties=(hidden_property,))
descr = OptionDescription('constraints', '', [gcgroup, booloption, descr = OptionDescription('constraints', '', [gcgroup, booloption,
objspaceoption, stroption, intoption]) objspaceoption, stroption, intoption])
cfg_ori = Config(descr) cfg_ori = Config(descr)
@ -179,8 +187,12 @@ def test_disabled_with_group():
booloption = BoolOption('bool', 'Test boolean option', default=True) booloption = BoolOption('bool', 'Test boolean option', default=True)
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default="abc") stroption = StrOption('str', 'Test string option', default="abc")
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption], disabled_property = Calculation(calc_value,
requires=({'option': intoption, 'expected': 1, 'action': 'disabled'},)) Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(intoption),
'expected': ParamValue(1),
'default': ParamValue(None)}))
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption], properties=(disabled_property,))
descr = OptionDescription('constraints', '', [gcgroup, booloption, descr = OptionDescription('constraints', '', [gcgroup, booloption,
objspaceoption, stroption, intoption]) objspaceoption, stroption, intoption])
cfg = Config(descr) cfg = Config(descr)
@ -201,11 +213,15 @@ def make_description_callback():
floatoption = FloatOption('float', 'Test float option', default=2.3) floatoption = FloatOption('float', 'Test float option', default=2.3)
stroption = StrOption('str', 'Test string option', default="abc") stroption = StrOption('str', 'Test string option', default="abc")
boolop = BoolOption('boolop', 'Test boolean option op', default=True) boolop = BoolOption('boolop', 'Test boolean option op', default=True)
wantref_option = BoolOption('wantref', 'Test requires', default=False, hidden_property = Calculation(calc_value,
requires=({'option': boolop, 'expected': True, 'action': 'hidden'},)) Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(boolop),
'expected': ParamValue(True),
'default': ParamValue(None)}))
wantref_option = BoolOption('wantref', 'Test requires', default=False, properties=(hidden_property,))
wantframework_option = BoolOption('wantframework', 'Test requires', wantframework_option = BoolOption('wantframework', 'Test requires',
default=False, default=False,
requires=({'option': boolop, 'expected': True, 'action': 'hidden'},)) properties=(hidden_property,))
gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption]) gcgroup = OptionDescription('gc', '', [gcoption, gcdummy, floatoption])
descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption, descr = OptionDescription('constraints', '', [gcgroup, booloption, objspaceoption,
wantref_option, stroption, wantref_option, stroption,
@ -268,7 +284,7 @@ def test_params():
def test_param_option(): def test_param_option():
val1 = StrOption('val1', "") val1 = StrOption('val1', "")
raises(ValueError, "ParamOption('str')") raises(ValueError, "ParamOption('str')")
raises(ValueError, "ParamOption(val1, 'str')") raises(AssertionError, "ParamOption(val1, 'str')")
def test_callback_invalid(): def test_callback_invalid():

View File

@ -9,7 +9,8 @@ from tiramisu.i18n import _
from tiramisu.error import display_list, ConfigError 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
from tiramisu.error import PropertiesOptionError from tiramisu.error import PropertiesOptionError
from tiramisu.storage import list_sessions from tiramisu.storage import list_sessions
@ -168,8 +169,11 @@ def test_reset_with_multi(config_type):
def test_property_only_raises(): def test_property_only_raises():
s = StrOption("string", "", default=["string"], default_multi="string", multi=True) s = StrOption("string", "", default=["string"], default_multi="string", multi=True)
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default=["abc"], default_multi="abc", hidden_property = Calculation(calc_value,
requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}], multi=True) Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(intoption),
'expected': ParamValue(1)}))
stroption = StrOption('str', 'Test string option', default=["abc"], default_multi="abc", properties=(hidden_property,), multi=True)
descr = OptionDescription("options", "", [s, intoption, stroption]) descr = OptionDescription("options", "", [s, intoption, stroption])
cfg = Config(descr) cfg = Config(descr)
cfg.property.read_write() cfg.property.read_write()
@ -231,8 +235,11 @@ def test_access_with_multi_default(config_type):
def test_multi_with_requires(): def test_multi_with_requires():
s = StrOption("string", "", default=["string"], default_multi="string", multi=True) s = StrOption("string", "", default=["string"], default_multi="string", multi=True)
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default=["abc"], default_multi="abc", hidden_property = Calculation(calc_value,
requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}], multi=True) Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(intoption),
'expected': ParamValue(1)}))
stroption = StrOption('str', 'Test string option', default=["abc"], default_multi="abc", properties=(hidden_property,), multi=True)
descr = OptionDescription("options", "", [s, intoption, stroption]) descr = OptionDescription("options", "", [s, intoption, stroption])
cfg = Config(descr) cfg = Config(descr)
cfg.property.read_write() cfg.property.read_write()
@ -242,23 +249,32 @@ def test_multi_with_requires():
assert 'hidden' in cfg.forcepermissive.option('str').property.get() assert 'hidden' in cfg.forcepermissive.option('str').property.get()
def test__requires_with_inverted(): def test_requires_with_inverted():
s = StrOption("string", "", default=["string"], multi=True) s = StrOption("string", "", default=["string"], multi=True)
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default=["abc"], default_multi="abc", hide_property = Calculation(calc_value,
requires=[{'option': intoption, 'expected': 1, 'action': 'hide', 'inverse': True}], multi=True) Params(ParamValue('hide'),
kwargs={'condition': ParamOption(intoption),
'expected': ParamValue(1),
'inverse_condition': ParamValue(True)}))
stroption = StrOption('str', 'Test string option', default=["abc"], default_multi="abc", properties=(hide_property,), multi=True)
descr = OptionDescription("options", "", [s, intoption, stroption]) descr = OptionDescription("options", "", [s, intoption, stroption])
cfg = Config(descr) cfg = Config(descr)
assert not 'hidden' in cfg.option('str').property.get() assert not 'hidden' in cfg.option('str').property.get()
assert 'hide' in cfg.option('str').property.get()
cfg.option('int').value.set(1) cfg.option('int').value.set(1)
assert not 'hidden' in cfg.option('str').property.get() assert not 'hidden' in cfg.option('str').property.get()
assert not 'hide' in cfg.option('str').property.get()
def test_multi_with_requires_in_another_group(): def test_multi_with_requires_in_another_group():
s = StrOption("string", "", default=["string"], multi=True) s = StrOption("string", "", default=["string"], multi=True)
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default=["abc"], hidden_property = Calculation(calc_value,
requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}], multi=True) Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(intoption),
'expected': ParamValue(1)}))
stroption = StrOption('str', 'Test string option', default=["abc"], properties=(hidden_property,), multi=True)
descr = OptionDescription("opt", "", [stroption]) descr = OptionDescription("opt", "", [stroption])
descr2 = OptionDescription("opt2", "", [intoption, s, descr]) descr2 = OptionDescription("opt2", "", [intoption, s, descr])
cfg = Config(descr2) cfg = Config(descr2)
@ -272,8 +288,12 @@ def test_multi_with_requires_in_another_group():
def test_multi_with_requires_in_another_group_inverse(): def test_multi_with_requires_in_another_group_inverse():
s = StrOption("string", "", default=["string"], multi=True) s = StrOption("string", "", default=["string"], multi=True)
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default=["abc"], hidden_property = Calculation(calc_value,
requires=[{'option': intoption, 'expected': 0, 'action': 'hidden', 'inverse': True}], multi=True) Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(intoption),
'expected': ParamValue(1)}))
# requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}], multi=True)
stroption = StrOption('str', 'Test string option', default=["abc"], properties=(hidden_property,), multi=True)
descr = OptionDescription("opt", "", [stroption]) descr = OptionDescription("opt", "", [stroption])
descr2 = OptionDescription("opt2", "", [intoption, s, descr]) descr2 = OptionDescription("opt2", "", [intoption, s, descr])
cfg = Config(descr2) cfg = Config(descr2)
@ -287,8 +307,11 @@ def test_multi_with_requires_in_another_group_inverse():
def test_apply_requires_from_config(): def test_apply_requires_from_config():
s = StrOption("string", "", default=["string"], multi=True) s = StrOption("string", "", default=["string"], multi=True)
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default=["abc"], hidden_property = Calculation(calc_value,
requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}], multi=True) Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(intoption),
'expected': ParamValue(1)}))
stroption = StrOption('str', 'Test string option', default=["abc"], properties=(hidden_property,), multi=True)
descr = OptionDescription("opt", "", [stroption]) descr = OptionDescription("opt", "", [stroption])
descr2 = OptionDescription("opt2", "", [intoption, s, descr]) descr2 = OptionDescription("opt2", "", [intoption, s, descr])
cfg = Config(descr2) cfg = Config(descr2)
@ -304,8 +327,11 @@ def test_apply_requires_from_config():
def test_apply_requires_with_disabled(): def test_apply_requires_with_disabled():
s = StrOption("string", "", default=["string"], multi=True) s = StrOption("string", "", default=["string"], multi=True)
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default=["abc"], disabled_property = Calculation(calc_value,
requires=[{'option': intoption, 'expected': 1, 'action': 'disabled'}], multi=True) Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(intoption),
'expected': ParamValue(1)}))
stroption = StrOption('str', 'Test string option', default=["abc"], properties=(disabled_property,), multi=True)
descr = OptionDescription("opt", "", [stroption]) descr = OptionDescription("opt", "", [stroption])
descr2 = OptionDescription("opt2", "", [intoption, s, descr]) descr2 = OptionDescription("opt2", "", [intoption, s, descr])
cfg = Config(descr2) cfg = Config(descr2)
@ -321,8 +347,11 @@ def test_apply_requires_with_disabled():
def test_multi_with_requires_with_disabled_in_another_group(): def test_multi_with_requires_with_disabled_in_another_group():
s = StrOption("string", "", default=["string"], multi=True) s = StrOption("string", "", default=["string"], multi=True)
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default=["abc"], disabled_property = Calculation(calc_value,
requires=[{'option': intoption, 'expected': 1, 'action': 'disabled'}], multi=True) Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(intoption),
'expected': ParamValue(1)}))
stroption = StrOption('str', 'Test string option', default=["abc"], properties=(disabled_property,), multi=True)
descr = OptionDescription("opt", "", [stroption]) descr = OptionDescription("opt", "", [stroption])
descr2 = OptionDescription("opt2", "", [intoption, s, descr]) descr2 = OptionDescription("opt2", "", [intoption, s, descr])
cfg = Config(descr2) cfg = Config(descr2)
@ -331,42 +360,54 @@ def test_multi_with_requires_with_disabled_in_another_group():
cfg.option('int').value.set(1) cfg.option('int').value.set(1)
raises(PropertiesOptionError, "cfg.option('opt.str').value.set(['a', 'b'])") raises(PropertiesOptionError, "cfg.option('opt.str').value.set(['a', 'b'])")
assert 'disabled' in cfg.unrestraint.option('opt.str').property.get() assert 'disabled' in cfg.unrestraint.option('opt.str').property.get()
#
#
def test_multi_with_requires_that_is_multi(): #def test_multi_with_requires_that_is_multi():
b = IntOption('int', 'Test int option', default=[0], multi=True) # b = IntOption('int', 'Test int option', default=[0], multi=True)
c = StrOption('str', 'Test string option', default=['abc'], requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True) # hidden_property = Calculation(calc_value,
descr = OptionDescription("opt", "", [b, c]) # Params(ParamValue('hidden'),
descr # kwargs={'condition': ParamOption(b),
raises(ValueError, "Config(descr)") # 'expected': ParamValue(1)}))
# c = StrOption('str', 'Test string option', default=['abc'], properties=(hidden_property,), multi=True)
# descr = OptionDescription("opt", "", [b, c])
def test_multi_with_requires_that_is_multi_inverse(): # descr
b = IntOption('int', 'Test int option', default=[0], multi=True) # # FIXME: ValueError: requirement mal formés pour l'option "int" ne doit pas être une valeur multiple pour "str"
c = StrOption('str', 'Test string option', default=['abc'], requires=[{'option': b, 'expected': 0, 'action': 'hidden', 'inverse': True}], multi=True) # raises(ValueError, "Config(descr)")
descr = OptionDescription("opt", "", [b, c]) #
descr #
raises(ValueError, "Config(descr)") #def test_multi_with_requires_that_is_multi_inverse():
# b = IntOption('int', 'Test int option', default=[0], multi=True)
# c = StrOption('str', 'Test string option', default=['abc'], requires=[{'option': b, 'expected': 0, 'action': 'hidden', 'inverse': True}], multi=True)
def test_multi_with_requires_that_is_leadership(): # descr = OptionDescription("opt", "", [b, c])
b = IntOption('int', 'Test int option', default=[0], multi=True) # descr
c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True) # Config(descr)
descr = Leadership("int", "", [b, c]) # # FIXME: ValueError: requirement mal formés pour l'option "int" ne doit pas être une valeur multiple pour "str"
od = OptionDescription('root', '', [descr]) # raises(ValueError, "Config(descr)")
Config(od) #
#
#def test_multi_with_requires_that_is_leadership():
def test_multi_with_requires_that_is_leadership_leader(): # b = IntOption('int', 'Test int option', default=[0], multi=True)
b = IntOption('int', 'Test int option', multi=True) # c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True) # descr = Leadership("int", "", [b, c])
raises(ValueError, "Leadership('str', '', [c, b])") # od = OptionDescription('root', '', [descr])
# Config(od)
#
#
#def test_multi_with_requires_that_is_leadership_leader():
# b = IntOption('int', 'Test int option', multi=True)
# c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
# raises(ValueError, "Leadership('str', '', [c, b])")
def test_multi_with_requires_that_is_leadership_follower(): def test_multi_with_requires_that_is_leadership_follower():
b = IntOption('int', 'Test int option', default=[0], multi=True) b = IntOption('int', 'Test int option', default=[0], multi=True)
c = StrOption('str', 'Test string option', multi=True) c = StrOption('str', 'Test string option', multi=True)
d = StrOption('str1', 'Test string option', requires=[{'option': c, 'expected': '1', 'action': 'hidden'}], multi=True) hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(c),
'index': ParamIndex(),
'expected': ParamValue('1')}))
d = StrOption('str1', 'Test string option', properties=(hidden_property,), multi=True)
descr = Leadership("int", "", [b, c, d]) descr = Leadership("int", "", [b, c, d])
descr2 = OptionDescription('od', '', [descr]) descr2 = OptionDescription('od', '', [descr])
cfg = Config(descr2) cfg = Config(descr2)
@ -392,7 +433,13 @@ def test_multi_with_requires_that_is_leadership_follower():
def test_multi_with_requires_that_is_leadership_follower_inverse(): def test_multi_with_requires_that_is_leadership_follower_inverse():
b = IntOption('int', 'Test int option', default=[0], multi=True) b = IntOption('int', 'Test int option', default=[0], multi=True)
c = StrOption('str', 'Test string option', multi=True) c = StrOption('str', 'Test string option', multi=True)
d = StrOption('str1', 'Test string option', requires=[{'option': c, 'expected': None, 'action': 'hidden', 'inverse': True}], multi=True) hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(c),
'index': ParamIndex(),
'inverse_condition': ParamValue(True),
'expected': ParamValue(None)}))
d = StrOption('str1', 'Test string option', properties=(hidden_property,), multi=True)
descr = Leadership("int", "", [b, c, d]) descr = Leadership("int", "", [b, c, d])
descr2 = OptionDescription('od', '', [descr]) descr2 = OptionDescription('od', '', [descr])
cfg = Config(descr2) cfg = Config(descr2)
@ -415,16 +462,22 @@ def test_multi_with_requires_that_is_leadership_follower_inverse():
raises(PropertiesOptionError, "cfg.option('int.str1', 1).value.get()") raises(PropertiesOptionError, "cfg.option('int.str1', 1).value.get()")
def test_multi_with_requires_that_is_not_same_leadership(): #def test_multi_with_requires_that_is_not_same_leadership():
b = IntOption('int', 'Test int option', default=[0], multi=True) # b = IntOption('int', 'Test int option', default=[0], multi=True)
c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True) # hidden_property = Calculation(calc_value,
descr1 = Leadership("int", "", [b, c]) # Params(ParamValue('hidden'),
d = IntOption('int1', 'Test int option', default=[0], multi=True) # kwargs={'condition': ParamOption(b),
e = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True) # 'index': ParamIndex(),
descr2 = Leadership("int1", "", [d, e]) # 'expected': ParamValue(1)}))
descr3 = OptionDescription('val', '', [descr1, descr2]) # c = StrOption('str', 'Test string option', properties=(hidden_property,), multi=True)
descr3 # #c = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
raises(ValueError, "Config(descr3)") # descr1 = Leadership("int", "", [b, c])
# d = IntOption('int1', 'Test int option', default=[0], multi=True)
# e = StrOption('str', 'Test string option', requires=[{'option': b, 'expected': 1, 'action': 'hidden'}], multi=True)
# descr2 = Leadership("int1", "", [d, e])
# descr3 = OptionDescription('val', '', [descr1, descr2])
# descr3
# raises(ValueError, "Config(descr3)")
def test_multi_with_bool(): def test_multi_with_bool():
@ -606,17 +659,45 @@ def test_pprint():
s2 = StrOption("string2", "", default="string") s2 = StrOption("string2", "", default="string")
s3 = StrOption("string3", "", default=["string"], default_multi="string", multi=True, properties=('hidden',)) s3 = StrOption("string3", "", default=["string"], default_multi="string", multi=True, properties=('hidden',))
intoption = IntOption('int', 'Test int option', default=0) intoption = IntOption('int', 'Test int option', default=0)
stroption = StrOption('str', 'Test string option', default="abc", hidden_property = Calculation(calc_value,
requires=[{'option': intoption, 'expected': 2, 'action': 'hidden', 'inverse': True}, Params(ParamValue('hidden'),
{'option': intoption, 'expected': 3, 'action': 'hidden', 'inverse': True}, kwargs={'condition': ParamOption(intoption, todict=True),
{'option': intoption, 'expected': 4, 'action': 'hidden', 'inverse': True}, 'expected_0': ParamValue(2),
{'option': intoption, 'expected': 1, 'action': 'disabled'}, 'expected_1': ParamValue(3),
{'option': s2, 'expected': 'string', 'action': 'disabled'}]) 'expected_2': ParamValue(4),
'inverse_condition': ParamValue(True)}),
calc_value_property_help)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition_0': ParamOption(intoption, todict=True),
'expected_0': ParamValue(1),
'condition_1': ParamOption(s2, todict=True),
'expected_1': ParamValue('string')}),
calc_value_property_help)
stroption = StrOption('str', 'Test string option', default="abc", properties=(hidden_property, disabled_property))
# requires=[{'option': intoption, 'expected': 2, 'action': 'hidden', 'inverse': True},
# {'option': intoption, 'expected': 3, 'action': 'hidden', 'inverse': True},
# {'option': intoption, 'expected': 4, 'action': 'hidden', 'inverse': True},
# {'option': intoption, 'expected': 1, 'action': 'disabled'},
# {'option': s2, 'expected': 'string', 'action': 'disabled'}])
val2 = StrOption('val2', "") val2 = StrOption('val2', "")
descr2 = OptionDescription("options", "", [val2], requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}]) hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(intoption, todict=True),
'expected': ParamValue(1)}),
calc_value_property_help)
descr2 = OptionDescription("options", "", [val2], properties=(hidden_property,))
#descr2 = OptionDescription("options", "", [val2], requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}])
val3 = StrOption('val3', "", requires=[{'option': stroption, 'expected': '2', 'action': 'hidden', 'inverse': True}]) hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(stroption, todict=True),
'expected': ParamValue('2'),
'inverse_condition': ParamValue(True)}),
calc_value_property_help)
val3 = StrOption('val3', "", properties=(hidden_property,))
#val3 = StrOption('val3', "", requires=[{'option': stroption, 'expected': '2', 'action': 'hidden', 'inverse': True}])
descr = OptionDescription("options", "", [s, s2, s3, intoption, stroption, descr2, val3]) descr = OptionDescription("options", "", [s, s2, s3, intoption, stroption, descr2, val3])
cfg = Config(descr) cfg = Config(descr)

View File

@ -7,7 +7,8 @@ from .config import config_type, get_config
from py.test import raises from py.test import raises
from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \ from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \
PasswordOption, StrOption, DateOption, OptionDescription, Config PasswordOption, StrOption, DateOption, OptionDescription, Config, \
Calculation, Params, ParamOption, ParamValue, calc_value
from tiramisu.error import PropertiesOptionError from tiramisu.error import PropertiesOptionError
from tiramisu.storage import list_sessions from tiramisu.storage import list_sessions
@ -26,11 +27,17 @@ def make_description():
floatoption = FloatOption('float', 'Test float option', default=2.3) floatoption = FloatOption('float', 'Test float option', default=2.3)
stroption = StrOption('str', 'Test string option', default="abc") stroption = StrOption('str', 'Test string option', default="abc")
wantref_option = BoolOption('wantref', 'Test requires', default=False, hidden_property = Calculation(calc_value,
requires=({'option': gcoption, 'expected': 'ref', 'action': 'hidden'},)) Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(gcoption),
'expected': ParamValue('ref')}))
wantref_option = BoolOption('wantref', 'Test requires', default=False, properties=(hidden_property,))
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(gcoption),
'expected': ParamValue('framework')}))
wantframework_option = BoolOption('wantframework', 'Test requires', wantframework_option = BoolOption('wantframework', 'Test requires',
default=False, default=False, properties=(hidden_property,))
requires=({'option': gcoption, 'expected': 'framework', 'action': 'hidden'},))
# ____________________________________________________________ # ____________________________________________________________
booloptiontwo = BoolOption('booltwo', 'Test boolean option two', default=False) booloptiontwo = BoolOption('booltwo', 'Test boolean option two', default=False)

View File

@ -9,8 +9,9 @@ from tiramisu.setting import groups
from tiramisu import setting from tiramisu import setting
setting.expires_time = 1 setting.expires_time = 1
from tiramisu import IPOption, OptionDescription, BoolOption, IntOption, StrOption, \ from tiramisu import IPOption, OptionDescription, BoolOption, IntOption, StrOption, \
Leadership, Config, calc_value, Params, ParamOption Leadership, Config, calc_value, Params, ParamOption, Calculation, ParamValue, ParamSelfOption, ParamIndex, \
from tiramisu.error import PropertiesOptionError, RequirementError, ConfigError calc_value_property_help
from tiramisu.error import PropertiesOptionError, RequirementError, ConfigError, display_list
from py.test import raises from py.test import raises
from tiramisu.storage import list_sessions, delete_session from tiramisu.storage import list_sessions, delete_session
@ -54,7 +55,7 @@ def test_properties(config_type):
cfg_ori.unrestraint.option('ip_address_service').property.pop('disabled') cfg_ori.unrestraint.option('ip_address_service').property.pop('disabled')
def test_requires(config_type): def test_requires_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '', b = IPOption('ip_address_service', '',
requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
@ -76,7 +77,33 @@ def test_requires(config_type):
cfg.option('ip_address_service').value.get() cfg.option('ip_address_service').value.get()
def test_requires_callback(config_type): def test_requires(config_type):
a = BoolOption('activate_service', '', True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a, todict=True),
'expected': ParamValue(False)}))
b = IPOption('ip_address_service', '',
properties=(disabled_property,))
od = OptionDescription('service', '', [a, b])
cfg = Config(od)
cfg.property.read_write()
assert not cfg.option('activate_service').option.requires()
assert not cfg.option('ip_address_service').option.requires()
cfg = get_config(cfg, config_type)
cfg.option('ip_address_service').value.get()
cfg.option('activate_service').value.set(False)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('activate_service').value.set(True)
cfg.option('ip_address_service').value.get()
def test_requires_callback_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '', b = IPOption('ip_address_service', '',
requires=[{'callback': calc_value, 'callback_params': Params(ParamOption(a)), 'expected': False, 'action': 'disabled'}]) requires=[{'callback': calc_value, 'callback_params': Params(ParamOption(a)), 'expected': False, 'action': 'disabled'}])
@ -98,7 +125,7 @@ def test_requires_callback(config_type):
cfg.option('ip_address_service').value.get() cfg.option('ip_address_service').value.get()
def test_requires_inverse(config_type): def test_requires_inverse_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '', b = IPOption('ip_address_service', '',
requires=[{'option': a, 'expected': False, 'action': 'disabled', 'inverse': True}]) requires=[{'option': a, 'expected': False, 'action': 'disabled', 'inverse': True}])
@ -122,7 +149,35 @@ def test_requires_inverse(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_self(config_type): def test_requires_inverse(config_type):
a = BoolOption('activate_service', '', True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a, todict=True),
'expected': ParamValue(False),
'inverse_condition': ParamValue(True)}))
b = IPOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('activate_service').value.set(False)
cfg.option('ip_address_service').value.get()
cfg.option('activate_service').value.set(True)
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
def test_requires_self_legacy(config_type):
a = StrOption('ip_address_service', '', a = StrOption('ip_address_service', '',
requires=[{'option': 'self', 'expected': 'b', 'action': 'disabled'}]) requires=[{'option': 'self', 'expected': 'b', 'action': 'disabled'}])
od = OptionDescription('service', '', [a]) od = OptionDescription('service', '', [a])
@ -141,7 +196,29 @@ def test_requires_self(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_with_requires(config_type): def test_requires_self(config_type):
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamSelfOption(),
'expected': ParamValue('b')}))
a = StrOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
assert cfg.option('ip_address_service').value.get() == None
cfg.option('ip_address_service').value.set('a')
assert cfg.option('ip_address_service').value.get() == 'a'
cfg.option('ip_address_service').value.set('b')
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
def test_requires_with_requires_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '', b = IPOption('ip_address_service', '',
requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
@ -162,7 +239,31 @@ def test_requires_with_requires(config_type):
cfg.option('ip_address_service').value.get() cfg.option('ip_address_service').value.get()
def test_requires_invalid(): def test_requires_with_requires(config_type):
a = BoolOption('activate_service', '', True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a),
'expected': ParamValue(False)}))
b = IPOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b])
cfg = Config(od)
cfg.property.read_write()
cfg.option('ip_address_service').property.add('test')
cfg = get_config(cfg, config_type)
cfg.option('ip_address_service').value.get()
cfg.option('activate_service').value.set(False)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('activate_service').value.set(True)
cfg.option('ip_address_service').value.get()
def test_requires_invalid_legacy():
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
a a
raises(ValueError, "IPOption('ip_address_service', '', requires='string')") raises(ValueError, "IPOption('ip_address_service', '', requires='string')")
@ -177,7 +278,7 @@ def test_requires_invalid():
raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': 'string', 'action': 'disabled'}])") raises(ValueError, "IPOption('ip_address_service', '', requires=[{'option': a, 'expected': 'string', 'action': 'disabled'}])")
def test_requires_same_action(config_type): def test_requires_same_action_legacy(config_type):
activate_service = BoolOption('activate_service', '', True) activate_service = BoolOption('activate_service', '', True)
activate_service_web = BoolOption('activate_service_web', '', True, activate_service_web = BoolOption('activate_service_web', '', True,
requires=[{'option': activate_service, 'expected': False, requires=[{'option': activate_service, 'expected': False,
@ -223,7 +324,59 @@ def test_requires_same_action(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_same_action_callback(config_type): def test_requires_same_action(config_type):
activate_service = BoolOption('activate_service', '', True)
new_property = Calculation(calc_value,
Params(ParamValue('new'),
kwargs={'condition': ParamOption(activate_service, todict=True),
'expected': ParamValue(False)}),
calc_value_property_help)
activate_service_web = BoolOption('activate_service_web', '', True, properties=(new_property,))
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(activate_service_web, notraisepropertyerror=True, todict=True),
'expected': ParamValue(False)}),
calc_value_property_help)
ip_address_service_web = IPOption('ip_address_service_web', '', properties=(disabled_property,))
od1 = OptionDescription('service', '', [activate_service, activate_service_web, ip_address_service_web])
cfg = Config(od1)
cfg.property.read_write()
cfg.property.add('new')
cfg = get_config(cfg, config_type)
cfg.option('activate_service').value.get()
cfg.option('activate_service_web').value.get()
cfg.option('ip_address_service_web').value.get()
cfg.option('activate_service').value.set(False)
#
props = []
try:
cfg.option('activate_service_web').value.get()
except PropertiesOptionError as err:
props = err.proptype
if config_type == 'tiramisu':
assert frozenset(props) == frozenset(['new'])
else:
assert frozenset(props) == frozenset(['disabled'])
#
props = []
try:
cfg.option('ip_address_service_web').value.get()
except PropertiesOptionError as err:
props = err.proptype
submsg = '"disabled" (' + _('the value of "{0}" is {1}').format('activate_service', '"False"') + ')'
if config_type == 'tiramisu':
submsg = '"new" (' + _('the value of "{0}" is {1}').format('activate_service', '"False"') + ')'
submsg = '"disabled" (' + str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'activate_service_web', _('property'), submsg)) + ')'
assert str(err) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'ip_address_service_web', _('property'), submsg))
#access to cache
assert str(err) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'ip_address_service_web', _('property'), submsg))
else:
# FIXME
assert str(err) == 'error'
assert frozenset(props) == frozenset(['disabled'])
def test_requires_same_action_callback_legacy(config_type):
activate_service = BoolOption('activate_service', '', True) activate_service = BoolOption('activate_service', '', True)
activate_service_web = BoolOption('activate_service_web', '', True, activate_service_web = BoolOption('activate_service_web', '', True,
requires=[{'callback': calc_value, 'callback_params': Params(ParamOption(activate_service)), 'expected': False, requires=[{'callback': calc_value, 'callback_params': Params(ParamOption(activate_service)), 'expected': False,
@ -269,7 +422,7 @@ def test_requires_same_action_callback(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_multiple_requires(config_type): def test_multiple_requires_legacy(config_type):
a = StrOption('activate_service', '') a = StrOption('activate_service', '')
b = IPOption('ip_address_service', '', b = IPOption('ip_address_service', '',
requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'}, requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'},
@ -299,7 +452,40 @@ def test_multiple_requires(config_type):
cfg.option('ip_address_service').value.get() cfg.option('ip_address_service').value.get()
def test_multiple_requires_cumulative(config_type): def test_multiple_requires(config_type):
a = StrOption('activate_service', '')
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a),
'expected_0': ParamValue('yes'),
'expected_1': ParamValue('ok')}))
b = IPOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
cfg.option('ip_address_service').value.get()
cfg.option('activate_service').value.set('yes')
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('activate_service').value.set('ok')
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('activate_service').value.set('no')
cfg.option('ip_address_service').value.get()
def test_multiple_requires_cumulative_legacy(config_type):
a = StrOption('activate_service', '') a = StrOption('activate_service', '')
b = IPOption('ip_address_service', '', b = IPOption('ip_address_service', '',
requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'}, requires=[{'option': a, 'expected': 'yes', 'action': 'disabled'},
@ -327,7 +513,41 @@ def test_multiple_requires_cumulative(config_type):
cfg.option('ip_address_service').value.get() cfg.option('ip_address_service').value.get()
def test_multiple_requires_cumulative_inverse(config_type): def test_multiple_requires_cumulative(config_type):
a = StrOption('activate_service', '')
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a),
'expected': ParamValue('yes')}))
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(a),
'expected': ParamValue('yes')}))
b = IPOption('ip_address_service', '', properties=(disabled_property, hidden_property))
od = OptionDescription('service', '', [a, b])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
cfg.option('ip_address_service').value.get()
cfg.option('activate_service').value.set('yes')
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
if config_type == 'tiramisu':
assert set(props) == {'hidden', 'disabled'}
else:
assert set(props) == {'disabled'}
cfg.option('activate_service').value.set('ok')
cfg.option('ip_address_service').value.get()
cfg.option('activate_service').value.set('no')
cfg.option('ip_address_service').value.get()
def test_multiple_requires_cumulative_inverse_legacy(config_type):
a = StrOption('activate_service', '') a = StrOption('activate_service', '')
b = IPOption('ip_address_service', '', b = IPOption('ip_address_service', '',
requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True}, requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True},
@ -371,7 +591,59 @@ def test_multiple_requires_cumulative_inverse(config_type):
assert set(props) == {'disabled'} assert set(props) == {'disabled'}
def test_multiple_requires_inverse(config_type): def test_multiple_requires_cumulative_inverse(config_type):
a = StrOption('activate_service', '')
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a),
'expected': ParamValue('yes'),
'inverse_condition': ParamValue(True)}))
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(a),
'expected': ParamValue('yes'),
'inverse_condition': ParamValue(True)}))
b = IPOption('ip_address_service', '', properties=(disabled_property, hidden_property))
od = OptionDescription('service', '', [a, b])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
if config_type == 'tiramisu':
assert set(props) == {'hidden', 'disabled'}
else:
assert set(props) == {'disabled'}
cfg.option('activate_service').value.set('yes')
cfg.option('ip_address_service').value.get()
cfg.option('activate_service').value.set('ok')
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
if config_type == 'tiramisu':
assert set(props) == {'hidden', 'disabled'}
else:
assert set(props) == {'disabled'}
cfg.option('activate_service').value.set('no')
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
if config_type == 'tiramisu':
assert set(props) == {'hidden', 'disabled'}
else:
assert set(props) == {'disabled'}
def test_multiple_requires_inverse_legacy(config_type):
a = StrOption('activate_service', '') a = StrOption('activate_service', '')
b = IPOption('ip_address_service', '', b = IPOption('ip_address_service', '',
requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True}, requires=[{'option': a, 'expected': 'yes', 'action': 'disabled', 'inverse': True},
@ -402,7 +674,42 @@ def test_multiple_requires_inverse(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_transitive(config_type): def test_multiple_requires_inverse(config_type):
a = StrOption('activate_service', '')
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a),
'expected_0': ParamValue('yes'),
'expected_1': ParamValue('ok'),
'inverse_condition': ParamValue(True)}))
b = IPOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('activate_service').value.set('yes')
cfg.option('ip_address_service').value.get()
cfg.option('activate_service').value.set('ok')
cfg.option('ip_address_service').value.get()
cfg.option('activate_service').value.set('no')
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
def test_requires_transitive_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = BoolOption('activate_service_web', '', True, b = BoolOption('activate_service_web', '', True,
requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
@ -433,7 +740,44 @@ def test_requires_transitive(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_transitive_callback(config_type): def test_requires_transitive(config_type):
a = BoolOption('activate_service', '', True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(False)}))
b = BoolOption('activate_service_web', '', True, properties=(disabled_property,))
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(b, raisepropertyerror=True),
'expected': ParamValue(False)}))
d = IPOption('ip_address_service_web', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b, d])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
cfg.option('activate_service').value.get()
cfg.option('activate_service_web').value.get()
cfg.option('ip_address_service_web').value.get()
cfg.option('activate_service').value.set(False)
#
props = []
try:
cfg.option('activate_service_web').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
#
props = []
try:
cfg.option('ip_address_service_web').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
def test_requires_transitive_callback_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = BoolOption('activate_service_web', '', True, b = BoolOption('activate_service_web', '', True,
requires=[{'callback': calc_value, 'callback_params': Params(ParamOption(a)), 'expected': False, 'action': 'disabled'}]) requires=[{'callback': calc_value, 'callback_params': Params(ParamOption(a)), 'expected': False, 'action': 'disabled'}])
@ -464,7 +808,7 @@ def test_requires_transitive_callback(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_transitive_unrestraint(config_type): def test_requires_transitive_unrestraint_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = BoolOption('activate_service_web', '', True, b = BoolOption('activate_service_web', '', True,
requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
@ -486,7 +830,34 @@ def test_requires_transitive_unrestraint(config_type):
assert cfg_ori.unrestraint.option('ip_address_service_web').property.get() == {'disabled'} assert cfg_ori.unrestraint.option('ip_address_service_web').property.get() == {'disabled'}
def test_requires_transitive_owner(config_type): def test_requires_transitive_unrestraint(config_type):
a = BoolOption('activate_service', '', True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(False)}))
b = BoolOption('activate_service_web', '', True, properties=(disabled_property,))
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(b, notraisepropertyerror=True),
'expected': ParamValue(False)}))
d = IPOption('ip_address_service_web', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b, d])
cfg_ori = Config(od)
cfg_ori.property.read_write()
cfg = get_config(cfg_ori, config_type)
cfg.option('activate_service').value.get()
cfg.option('activate_service_web').value.get()
cfg.option('ip_address_service_web').value.get()
cfg.option('activate_service').value.set(False)
#
if config_type == 'tiramisu-api':
cfg.send()
assert cfg_ori.unrestraint.option('activate_service_web').property.get() == {'disabled'}
assert cfg_ori.unrestraint.option('ip_address_service_web').property.get() == {'disabled'}
def test_requires_transitive_owner_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = BoolOption('activate_service_web', '', True, b = BoolOption('activate_service_web', '', True,
requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
@ -511,7 +882,38 @@ def test_requires_transitive_owner(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_transitive_bis(config_type): def test_requires_transitive_owner(config_type):
a = BoolOption('activate_service', '', True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(False)}))
b = BoolOption('activate_service_web', '', True, properties=(disabled_property,))
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(b, notraisepropertyerror=True),
'expected': ParamValue(False)}))
d = IPOption('ip_address_service_web', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b, d])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
cfg.option('activate_service').value.get()
cfg.option('activate_service_web').value.get()
cfg.option('ip_address_service_web').value.get()
#no more default value
cfg.option('ip_address_service_web').value.set('1.1.1.1')
cfg.option('activate_service').value.set(False)
props = []
try:
cfg.option('ip_address_service_web').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
def test_requires_transitive_bis_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
abis = BoolOption('activate_service_bis', '', True) abis = BoolOption('activate_service_bis', '', True)
b = BoolOption('activate_service_web', '', True, b = BoolOption('activate_service_web', '', True,
@ -543,7 +945,46 @@ def test_requires_transitive_bis(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_transitive_hidden_permissive(): def test_requires_transitive_bis(config_type):
a = BoolOption('activate_service', '', True)
abis = BoolOption('activate_service_bis', '', True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(True),
'inverse_condition': ParamValue(True)}))
b = BoolOption('activate_service_web', '', True, properties=(disabled_property,))
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(b, notraisepropertyerror=True),
'expected': ParamValue(True),
'inverse_condition': ParamValue(True)}))
d = IPOption('ip_address_service_web', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, abis, b, d])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
#
cfg.option('activate_service_web').value.get()
cfg.option('ip_address_service_web').value.get()
cfg.option('activate_service').value.set(False)
#
props = []
try:
cfg.option('activate_service_web').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
#
props = []
try:
cfg.option('ip_address_service_web').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
def test_requires_transitive_hidden_permissive_legacy():
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = BoolOption('activate_service_web', '', True, b = BoolOption('activate_service_web', '', True,
requires=[{'option': a, 'expected': False, 'action': 'hidden'}]) requires=[{'option': a, 'expected': False, 'action': 'hidden'}])
@ -561,7 +1002,31 @@ def test_requires_transitive_hidden_permissive():
cfg.option('ip_address_service_web').value.get() cfg.option('ip_address_service_web').value.get()
def test_requires_transitive_hidden_disabled(config_type): def test_requires_transitive_hidden_permissive():
a = BoolOption('activate_service', '', True)
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(False)}))
b = BoolOption('activate_service_web', '', True, properties=(hidden_property,))
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(b, notraisepropertyerror=True),
'expected': ParamValue(False)}))
d = IPOption('ip_address_service_web', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b, d])
cfg = Config(od)
cfg.property.read_write()
# FIXME permissive cfg = get_config(cfg, config_type)
cfg.option('activate_service').value.get()
cfg.option('ip_address_service_web').value.get()
cfg.option('ip_address_service_web').value.get()
cfg.option('activate_service').value.set(False)
#
cfg.option('ip_address_service_web').value.get()
def test_requires_transitive_hidden_disabled_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = BoolOption('activate_service_web', '', True, b = BoolOption('activate_service_web', '', True,
requires=[{'option': a, 'expected': False, 'action': 'hidden'}]) requires=[{'option': a, 'expected': False, 'action': 'hidden'}])
@ -588,7 +1053,40 @@ def test_requires_transitive_hidden_disabled(config_type):
cfg.option('ip_address_service_web').value.get() cfg.option('ip_address_service_web').value.get()
def test_requires_transitive_hidden_disabled_multiple(config_type): def test_requires_transitive_hidden_disabled(config_type):
a = BoolOption('activate_service', '', True)
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(False)}))
b = BoolOption('activate_service_web', '', True, properties=(hidden_property,))
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(b, notraisepropertyerror=True),
'expected': ParamValue(False)}))
d = IPOption('ip_address_service_web', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b, d])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
cfg.option('activate_service').value.get()
cfg.option('activate_service_web').value.get()
cfg.option('ip_address_service_web').value.get()
cfg.option('activate_service').value.set(False)
#
props = []
try:
cfg.option('activate_service_web').value.get()
except PropertiesOptionError as err:
props = err.proptype
if config_type == 'tiramisu-api':
assert frozenset(props) == frozenset(['disabled'])
else:
assert frozenset(props) == frozenset(['hidden'])
cfg.option('ip_address_service_web').value.get()
def test_requires_transitive_hidden_disabled_multiple_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = BoolOption('activate_service_web', '', True, b = BoolOption('activate_service_web', '', True,
requires=[{'option': a, 'expected': False, 'action': 'hidden'}, requires=[{'option': a, 'expected': False, 'action': 'hidden'},
@ -651,7 +1149,79 @@ def test_requires_transitive_hidden_disabled_multiple(config_type):
del req del req
def test_requires_not_transitive(config_type): def test_requires_transitive_hidden_disabled_multiple(config_type):
a = BoolOption('activate_service', '', True)
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(False)}))
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(False)}))
b = BoolOption('activate_service_web', '', True, properties=(hidden_property, disabled_property))
mandatory_property = Calculation(calc_value,
Params(ParamValue('mandatory'),
kwargs={'condition': ParamOption(b),
'expected': ParamValue(False)}))
d = IPOption('ip_address_service_web', '', properties=(mandatory_property,))
od = OptionDescription('service', '', [a, b, d])
cfg_ori = Config(od)
cfg_ori.property.read_write()
cfg = get_config(cfg_ori, config_type)
cfg.option('activate_service').value.get()
cfg.option('activate_service_web').value.get()
cfg.option('ip_address_service_web').value.get()
req = None
if config_type == 'tiramisu-api':
try:
cfg.option('activate_service').value.set(False)
except ConfigError as err:
req = err
error_msg = str(_('unable to transform tiramisu object to dict: {}').format(_('cannot access to option "{0}" because required option "{1}" has {2} {3}').format('ip_address_service_web', 'activate_service_web', _('property'), '"disabled"')))
else:
cfg.option('activate_service').value.set(False)
#
props = []
try:
cfg.option('activate_service_web').value.get()
except PropertiesOptionError as err:
props = err.proptype
if config_type == 'tiramisu-api':
assert set(props) == {'disabled',}
else:
assert set(props) == {'disabled', 'hidden'}
del props
#
try:
cfg.option('ip_address_service_web').value.get()
except ConfigError as err:
req = err
error_msg = str(_('unable to carry out a calculation for "{0}", cannot access to option "{1}" because has {2} {3}').format('ip_address_service_web', 'activate_service_web', _('properties'), display_list(['hidden', 'disabled'], add_quote=True)))
assert req, "ip_address_service_web should raise ConfigError"
assert str(req) == error_msg
del req
#
cfg_ori.permissive.set(frozenset())
if config_type == 'tiramisu-api':
try:
cfg = get_config(cfg_ori, config_type)
except ConfigError as err:
req = err
error_msg = str(_('unable to transform tiramisu object to dict: {}').format(_('cannot access to option "{0}" because required option "{1}" has {2} {3}').format('ip_address_service_web', 'activate_service_web', _('properties'), '"disabled" {} "hidden"'.format(_('and')))))
else:
cfg = get_config(cfg_ori, config_type)
try:
cfg.option('ip_address_service_web').value.get()
except ConfigError as err:
req = err
error_msg = str(_('unable to carry out a calculation for "{0}", cannot access to option "{1}" because has {2} {3}').format('ip_address_service_web', 'activate_service_web', _('properties'), display_list(['hidden', 'disabled'], add_quote=True)))
assert req, "ip_address_service_web should raise RequirementError"
assert str(req) == error_msg
del req
def test_requires_not_transitive_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = BoolOption('activate_service_web', '', True, b = BoolOption('activate_service_web', '', True,
requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
@ -677,7 +1247,39 @@ def test_requires_not_transitive(config_type):
cfg.option('ip_address_service_web').value.get() cfg.option('ip_address_service_web').value.get()
def test_requires_not_transitive_not_same_action(config_type): def test_requires_not_transitive(config_type):
a = BoolOption('activate_service', '', True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(False)}))
b = BoolOption('activate_service_web', '', True, properties=(disabled_property,))
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(b, notraisepropertyerror=True),
'no_condition_is_invalid': ParamValue(True),
'expected': ParamValue(False)}))
d = IPOption('ip_address_service_web', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b, d])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
cfg.option('activate_service').value.get()
cfg.option('activate_service_web').value.get()
cfg.option('ip_address_service_web').value.get()
cfg.option('activate_service').value.set(False)
#
props = []
try:
cfg.option('activate_service_web').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
#
cfg.option('ip_address_service_web').value.get()
def test_requires_not_transitive_not_same_action_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = BoolOption('activate_service_web', '', True, b = BoolOption('activate_service_web', '', True,
requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
@ -706,7 +1308,41 @@ def test_requires_not_transitive_not_same_action(config_type):
raises(RequirementError, "cfg.option('ip_address_service_web').value.get()") raises(RequirementError, "cfg.option('ip_address_service_web').value.get()")
def test_requires_None(config_type): def test_requires_not_transitive_not_same_action(config_type):
a = BoolOption('activate_service', '', True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(False)}))
b = BoolOption('activate_service_web', '', True, properties=(disabled_property,))
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(b),
'expected': ParamValue(False)}))
d = IPOption('ip_address_service_web', '', properties=(hidden_property,))
od = OptionDescription('service', '', [a, b, d])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
cfg.option('activate_service').value.get()
cfg.option('activate_service_web').value.get()
cfg.option('ip_address_service_web').value.get()
if config_type == 'tiramisu-api':
raises(ConfigError, "cfg.option('activate_service').value.set(False)")
else:
cfg.option('activate_service').value.set(False)
#
props = []
try:
cfg.option('activate_service_web').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
#
raises(ConfigError, "cfg.option('ip_address_service_web').value.get()")
def test_requires_none_legacy(config_type):
a = BoolOption('activate_service', '') a = BoolOption('activate_service', '')
b = IPOption('ip_address_service', '', b = IPOption('ip_address_service', '',
requires=[{'option': a, 'expected': None, 'action': 'disabled'}]) requires=[{'option': a, 'expected': None, 'action': 'disabled'}])
@ -724,7 +1360,28 @@ def test_requires_None(config_type):
cfg.option('ip_address_service').value.get() cfg.option('ip_address_service').value.get()
def test_requires_multi_disabled(config_type): def test_requires_none(config_type):
a = BoolOption('activate_service', '')
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(None)}))
b = IPOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('activate_service').value.set(False)
cfg.option('ip_address_service').value.get()
def test_requires_multi_disabled_legacy(config_type):
a = BoolOption('activate_service', '') a = BoolOption('activate_service', '')
b = IntOption('num_service', '') b = IntOption('num_service', '')
c = IPOption('ip_address_service', '', c = IPOption('ip_address_service', '',
@ -765,7 +1422,53 @@ def test_requires_multi_disabled(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_multi_disabled_callback(config_type): def test_requires_multi_disabled(config_type):
a = BoolOption('activate_service', '')
b = IntOption('num_service', '')
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition_0': ParamOption(a, notraisepropertyerror=True),
'condition_1': ParamOption(b, notraisepropertyerror=True),
'expected_0': ParamValue(True),
'expected_1': ParamValue(1),
'condition_operator': ParamValue('OR')}))
c = IPOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b, c])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
cfg.option('ip_address_service').value.get()
cfg.option('activate_service').value.set(True)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('activate_service').value.set(False)
cfg.option('ip_address_service').value.get()
cfg.option('num_service').value.set(1)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('activate_service').value.set(True)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
def test_requires_multi_disabled_callback_legacy(config_type):
a = BoolOption('activate_service', '') a = BoolOption('activate_service', '')
b = IntOption('num_service', '') b = IntOption('num_service', '')
c = IPOption('ip_address_service', '', c = IPOption('ip_address_service', '',
@ -806,7 +1509,7 @@ def test_requires_multi_disabled_callback(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_multi_disabled_new_format(config_type): def test_requires_multi_disabled_new_format_legacy(config_type):
a = BoolOption('activate_service', '') a = BoolOption('activate_service', '')
b = IntOption('num_service', '') b = IntOption('num_service', '')
c = IPOption('ip_address_service', '', c = IPOption('ip_address_service', '',
@ -846,7 +1549,7 @@ def test_requires_multi_disabled_new_format(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_unknown_operator(): def test_requires_unknown_operator_legacy():
a = BoolOption('activate_service', '') a = BoolOption('activate_service', '')
b = IntOption('num_service', '') b = IntOption('num_service', '')
raises(ValueError, """IPOption('ip_address_service', '', raises(ValueError, """IPOption('ip_address_service', '',
@ -854,7 +1557,7 @@ def test_requires_unknown_operator():
'action': 'disabled', 'operator': 'unknown'}])""") 'action': 'disabled', 'operator': 'unknown'}])""")
def test_requires_keys(): def test_requires_keys_legacy():
a = BoolOption('activate_service', '') a = BoolOption('activate_service', '')
b = IntOption('num_service', '') b = IntOption('num_service', '')
raises(ValueError, """IPOption('ip_address_service', '', raises(ValueError, """IPOption('ip_address_service', '',
@ -862,7 +1565,7 @@ def test_requires_keys():
'action': 'disabled', 'operator': 'and'}])""") 'action': 'disabled', 'operator': 'and'}])""")
def test_requires_unvalid(): def test_requires_unvalid_legacy():
a = BoolOption('activate_service', '') a = BoolOption('activate_service', '')
b = IntOption('num_service', '') b = IntOption('num_service', '')
raises(ValueError, """IPOption('ip_address_service', '', raises(ValueError, """IPOption('ip_address_service', '',
@ -870,7 +1573,7 @@ def test_requires_unvalid():
'action': 'disabled', 'operator': 'and'}])""") 'action': 'disabled', 'operator': 'and'}])""")
def test_requires_multi_disabled_new_format_and(config_type): def test_requires_multi_disabled_new_format_and_legacy(config_type):
a = BoolOption('activate_service', '') a = BoolOption('activate_service', '')
b = IntOption('num_service', '') b = IntOption('num_service', '')
c = IPOption('ip_address_service', '', c = IPOption('ip_address_service', '',
@ -910,7 +1613,7 @@ def test_requires_multi_disabled_new_format_and(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_multi_disabled_new_format_and_2(config_type): def test_requires_multi_disabled_new_format_and_2_legacy(config_type):
a = BoolOption('activate_service', '') a = BoolOption('activate_service', '')
b = IntOption('num_service', '') b = IntOption('num_service', '')
c = IPOption('ip_address_service', '', c = IPOption('ip_address_service', '',
@ -955,7 +1658,7 @@ def test_requires_multi_disabled_new_format_and_2(config_type):
assert frozenset(props) == frozenset(['disabled', 'expert']) assert frozenset(props) == frozenset(['disabled', 'expert'])
def test_requires_multi_disabled_inverse(config_type): def test_requires_multi_disabled_inverse_legacy(config_type):
a = BoolOption('activate_service', '') a = BoolOption('activate_service', '')
b = IntOption('num_service', '') b = IntOption('num_service', '')
c = IPOption('ip_address_service', '', c = IPOption('ip_address_service', '',
@ -1003,7 +1706,60 @@ def test_requires_multi_disabled_inverse(config_type):
cfg.option('ip_address_service').value.get() cfg.option('ip_address_service').value.get()
def test_requires_multi_disabled_2(config_type): def test_requires_multi_disabled_inverse(config_type):
a = BoolOption('activate_service', '')
b = IntOption('num_service', '')
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition_0': ParamOption(a, notraisepropertyerror=True),
'condition_1': ParamOption(b, notraisepropertyerror=True),
'expected_0': ParamValue(True),
'expected_1': ParamValue(1),
'condition_operator': ParamValue('OR'),
'inverse_condition_0': ParamValue(True),
'inverse_condition_1': ParamValue(True)}))
c = IPOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b, c])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('activate_service').value.set(True)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('activate_service').value.set(False)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('num_service').value.set(1)
props = []
try:
cfg.option('ip_address_service').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('activate_service').value.set(True)
cfg.option('ip_address_service').value.get()
def test_requires_multi_disabled_2_legacy(config_type):
a = BoolOption('a', '') a = BoolOption('a', '')
b = BoolOption('b', '') b = BoolOption('b', '')
c = BoolOption('c', '') c = BoolOption('c', '')
@ -1051,7 +1807,60 @@ def test_requires_multi_disabled_2(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_multi_disabled_inverse_2(config_type): def test_requires_multi_disabled_2(config_type):
a = BoolOption('a', '')
b = BoolOption('b', '')
c = BoolOption('c', '')
d = BoolOption('d', '')
e = BoolOption('e', '')
f = BoolOption('f', '')
g = BoolOption('g', '')
h = BoolOption('h', '')
i = BoolOption('i', '')
j = BoolOption('j', '')
k = BoolOption('k', '')
l = BoolOption('l', '')
m = BoolOption('m', '')
list_bools = [a, b, c, d, e, f, g, h, i, j, k, l, m]
requires = []
kwargs={'expected': ParamValue(True),
'condition_operator': ParamValue('OR')}
for idx, boo in enumerate(list_bools):
kwargs['condition_{}'.format(idx)] = ParamOption(boo, notraisepropertyerror=True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs=kwargs))
z = IPOption('z', '', properties=(disabled_property,))
y = copy(list_bools)
y.append(z)
od = OptionDescription('service', '', y)
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
cfg.option('z').value.get()
for boo in list_bools:
cfg.option(boo.impl_getname()).value.set(True)
props = []
try:
cfg.option('z').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
for boo in list_bools:
cfg.option(boo.impl_getname()).value.set(False)
if boo == m:
cfg.option('z').value.get()
else:
props = []
try:
cfg.option('z').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
def test_requires_multi_disabled_inverse_2_legacy(config_type):
a = BoolOption('a', '') a = BoolOption('a', '')
b = BoolOption('b', '') b = BoolOption('b', '')
c = BoolOption('c', '') c = BoolOption('c', '')
@ -1105,7 +1914,84 @@ def test_requires_multi_disabled_inverse_2(config_type):
assert frozenset(props) == frozenset(['disabled']) assert frozenset(props) == frozenset(['disabled'])
def test_requires_requirement_append(config_type): def test_requires_multi_disabled_inverse_2(config_type):
a = BoolOption('a', '')
b = BoolOption('b', '')
c = BoolOption('c', '')
d = BoolOption('d', '')
e = BoolOption('e', '')
f = BoolOption('f', '')
g = BoolOption('g', '')
h = BoolOption('h', '')
i = BoolOption('i', '')
j = BoolOption('j', '')
k = BoolOption('k', '')
l = BoolOption('l', '')
m = BoolOption('m', '')
list_bools = [a, b, c, d, e, f, g, h, i, j, k, l, m]
requires = []
kwargs={'expected': ParamValue(True),
'condition_operator': ParamValue('OR')}
for idx, boo in enumerate(list_bools):
kwargs['condition_{}'.format(idx)] = ParamOption(boo, notraisepropertyerror=True)
kwargs['inverse_condition_{}'.format(idx)] = ParamValue(True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs=kwargs))
#for boo in list_bools:
# requires.append({'option': boo, 'expected': True, 'action': 'disabled',
# 'inverse': True})
z = IPOption('z', '', properties=(disabled_property,))
y = copy(list_bools)
y.append(z)
od = OptionDescription('service', '', y)
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
props = []
try:
cfg.option('z').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
for boo in list_bools:
cfg.option(boo.impl_getname()).value.set(True)
if boo != m:
# it's disabled until last option is modified
props = []
try:
cfg.option('z').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('z').value.get()
for boo in list_bools:
cfg.option(boo.impl_getname()).value.set(False)
props = []
try:
cfg.option('z').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
try:
cfg.option('z').value.get()
except PropertiesOptionError as err:
props = err.proptype
for boo in reversed(list_bools):
cfg.option(boo.impl_getname()).value.set(True)
if boo != a:
# it's disabled until last option is modified
props = []
try:
cfg.option('z').value.get()
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.option('z').value.get()
def test_requires_requirement_append_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '', b = IPOption('ip_address_service', '',
requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
@ -1117,7 +2003,7 @@ def test_requires_requirement_append(config_type):
cfg.option('ip_address_service').property.get() cfg.option('ip_address_service').property.get()
if config_type == 'tiramisu-api': if config_type == 'tiramisu-api':
cfg.send() cfg.send()
raises(ValueError, "cfg_ori.option('ip_address_service').property.add('disabled')") #raises(ValueError, "cfg_ori.option('ip_address_service').property.add('disabled')")
cfg = get_config(cfg_ori, config_type) cfg = get_config(cfg_ori, config_type)
cfg.option('activate_service').value.set(False) cfg.option('activate_service').value.set(False)
# disabled is now set, test to remove disabled before store in storage # disabled is now set, test to remove disabled before store in storage
@ -1126,7 +2012,31 @@ def test_requires_requirement_append(config_type):
cfg_ori.unrestraint.option('ip_address_service').property.add("test") cfg_ori.unrestraint.option('ip_address_service').property.add("test")
def test_requires_different_inverse(config_type): def test_requires_requirement_append(config_type):
a = BoolOption('activate_service', '', True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(False)}))
b = IPOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b])
cfg_ori = Config(od)
cfg_ori.property.read_write()
cfg = get_config(cfg_ori, config_type)
cfg.property.get()
cfg.option('ip_address_service').property.get()
if config_type == 'tiramisu-api':
cfg.send()
#raises(ValueError, "cfg_ori.option('ip_address_service').property.add('disabled')")
cfg = get_config(cfg_ori, config_type)
cfg.option('activate_service').value.set(False)
# disabled is now set, test to remove disabled before store in storage
if config_type == 'tiramisu-api':
cfg.send()
cfg_ori.unrestraint.option('ip_address_service').property.add("test")
def test_requires_different_inverse_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '', requires=[ b = IPOption('ip_address_service', '', requires=[
{'option': a, 'expected': True, 'action': 'disabled', 'inverse': True}, {'option': a, 'expected': True, 'action': 'disabled', 'inverse': True},
@ -1140,7 +2050,27 @@ def test_requires_different_inverse(config_type):
raises(PropertiesOptionError, "cfg.option('ip_address_service').value.get()") raises(PropertiesOptionError, "cfg.option('ip_address_service').value.get()")
def test_requires_different_inverse_unicode(config_type): def test_requires_different_inverse(config_type):
a = BoolOption('activate_service', '', True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition_0': ParamOption(a, notraisepropertyerror=True),
'condition_1': ParamOption(a, notraisepropertyerror=True),
'expected_0': ParamValue(True),
'expected_1': ParamValue(True),
'condition_operator': ParamValue('OR'),
'inverse_condition_0': ParamValue(True)}))
b = IPOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, b])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
#raises(PropertiesOptionError, "cfg.option('ip_address_service').value.get()")
cfg.option('activate_service').value.set(False)
raises(PropertiesOptionError, "cfg.option('ip_address_service').value.get()")
def test_requires_different_inverse_unicode_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
d = StrOption('activate_other_service', '', 'val2') d = StrOption('activate_other_service', '', 'val2')
b = IPOption('ip_address_service', '', requires=[ b = IPOption('ip_address_service', '', requires=[
@ -1161,7 +2091,34 @@ def test_requires_different_inverse_unicode(config_type):
raises(PropertiesOptionError, "cfg.option('ip_address_service').value.get()") raises(PropertiesOptionError, "cfg.option('ip_address_service').value.get()")
def test_requires_recursive_path(config_type): def test_requires_different_inverse_unicode(config_type):
a = BoolOption('activate_service', '', True)
d = StrOption('activate_other_service', '', 'val2')
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition_0': ParamOption(a, notraisepropertyerror=True),
'condition_1': ParamOption(d, notraisepropertyerror=True),
'expected_0': ParamValue(True),
'expected_1': ParamValue('val1'),
'condition_operator': ParamValue('OR'),
'inverse_condition_0': ParamValue(True)}))
b = IPOption('ip_address_service', '', properties=(disabled_property,))
od = OptionDescription('service', '', [a, d, b])
cfg = Config(od)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
assert cfg.option('ip_address_service').value.get() == None
cfg.option('activate_service').value.set(False)
raises(PropertiesOptionError, "cfg.option('ip_address_service').value.get()")
cfg.option('activate_service').value.set(True)
assert cfg.option('ip_address_service').value.get() == None
cfg.option('activate_other_service').value.set('val1')
raises(PropertiesOptionError, "cfg.option('ip_address_service').value.get()")
cfg.option('activate_service').value.set(False)
raises(PropertiesOptionError, "cfg.option('ip_address_service').value.get()")
def test_requires_recursive_path_legacy(config_type):
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '', b = IPOption('ip_address_service', '',
requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
@ -1176,28 +2133,38 @@ def test_requires_recursive_path(config_type):
raises(RequirementError, "cfg.option('service.a').value.get()") raises(RequirementError, "cfg.option('service.a').value.get()")
def test_optiondescription_requires(): def test_optiondescription_requires_legacy():
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = BoolOption('ip_address_service', '', multi=True) b = BoolOption('ip_address_service', '', multi=True)
a, b
OptionDescription('service', '', [b], requires=[{'option': a, 'expected': False, 'action': 'disabled'}]) OptionDescription('service', '', [b], requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
def test_optiondescription_requires_multi(): def test_optiondescription_requires():
a = BoolOption('activate_service', '', True)
b = BoolOption('ip_address_service', '', multi=True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(a, notraisepropertyerror=True),
'expected': ParamValue(False)}))
OptionDescription('service', '', [b], properties=(disabled_property,))
def test_optiondescription_requires_multi_legacy():
# FIXME not legacy !!!
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
b = IPOption('ip_address_service', '', multi=True) b = IPOption('ip_address_service', '', multi=True)
a, b a, b
raises(ValueError, "OptionDescription('service', '', [a], requires=[{'option': b, 'expected': False, 'action': 'disabled'}])") raises(ValueError, "OptionDescription('service', '', [a], requires=[{'option': b, 'expected': False, 'action': 'disabled'}])")
def test_properties_conflict(): def test_properties_conflict_legacy():
a = BoolOption('activate_service', '', True) a = BoolOption('activate_service', '', True)
a a
raises(ValueError, "IPOption('ip_address_service', '', properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])") raises(ValueError, "IPOption('ip_address_service', '', properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")
raises(ValueError, "od1 = OptionDescription('service', '', [a], properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])") raises(ValueError, "od1 = OptionDescription('service', '', [a], properties=('disabled',), requires=[{'option': a, 'expected': False, 'action': 'disabled'}])")
def test_leadership_requires(config_type): def test_leadership_requires_legacy(config_type):
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,
requires=[{'option': ip_admin_eth0, 'expected': '192.168.1.1', 'action': 'disabled'}]) requires=[{'option': ip_admin_eth0, 'expected': '192.168.1.1', 'action': 'disabled'}])
@ -1248,7 +2215,63 @@ def test_leadership_requires(config_type):
del ret['ip_admin_eth0.netmask_admin_eth0'] del ret['ip_admin_eth0.netmask_admin_eth0']
def test_leadership_requires_callback(config_type): def test_leadership_requires(config_type):
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(ip_admin_eth0, notraisepropertyerror=True),
'expected': ParamValue('192.168.1.1'),
'no_condition_is_invalid': ParamValue(True),
'index': ParamIndex()}))
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=(disabled_property,))
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
od = OptionDescription('toto', '', [interface1])
cfg = Config(od)
cfg.property.read_write()
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(['192.168.1.2'])
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.2']
#
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.1'])
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
raises(PropertiesOptionError, "cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get()")
#
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.2'])
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() is None
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('255.255.255.255')
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.255.255'
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['192.168.1.2', '192.168.1.2'],
'ip_admin_eth0.netmask_admin_eth0': [None, '255.255.255.255']}
#
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.1'])
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
raises(PropertiesOptionError, "cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get()")
ret = cfg.value.dict()
assert set(ret.keys()) == set(['ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert ret['ip_admin_eth0.ip_admin_eth0'] == ['192.168.1.2', '192.168.1.1']
assert len(ret['ip_admin_eth0.netmask_admin_eth0']) == 2
assert ret['ip_admin_eth0.netmask_admin_eth0'][0] is None
assert isinstance(ret['ip_admin_eth0.netmask_admin_eth0'][1], PropertiesOptionError)
del ret['ip_admin_eth0.netmask_admin_eth0'][1]
del ret['ip_admin_eth0.netmask_admin_eth0'][0]
del ret['ip_admin_eth0.netmask_admin_eth0']
#
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.255')
ret = cfg.value.dict()
assert set(ret.keys()) == set(['ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert ret['ip_admin_eth0.ip_admin_eth0'] == ['192.168.1.2', '192.168.1.1']
assert len(ret['ip_admin_eth0.netmask_admin_eth0']) == 2
assert ret['ip_admin_eth0.netmask_admin_eth0'][0] == '255.255.255.255'
assert isinstance(ret['ip_admin_eth0.netmask_admin_eth0'][1], PropertiesOptionError)
del ret['ip_admin_eth0.netmask_admin_eth0'][1]
del ret['ip_admin_eth0.netmask_admin_eth0'][0]
del ret['ip_admin_eth0.netmask_admin_eth0']
def test_leadership_requires_callback_legacy(config_type):
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,
requires=[{'callback': calc_value, 'callback_params': Params(ParamOption(ip_admin_eth0)), 'expected': '192.168.1.1', 'action': 'disabled'}]) requires=[{'callback': calc_value, 'callback_params': Params(ParamOption(ip_admin_eth0)), 'expected': '192.168.1.1', 'action': 'disabled'}])
@ -1299,7 +2322,8 @@ def test_leadership_requires_callback(config_type):
del ret['ip_admin_eth0.netmask_admin_eth0'] del ret['ip_admin_eth0.netmask_admin_eth0']
def test_leadership_requires_both(): def test_leadership_requires_both_legacy():
# FIXME ne devrait pas pouvoir mettre de propriété calculé sur une master ...
ip_admin = StrOption('ip_admin_eth0', "ip réseau autorisé") ip_admin = StrOption('ip_admin_eth0', "ip réseau autorisé")
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,
requires=[{'option': ip_admin, 'expected': '192.168.1.1', 'action': 'disabled'}]) requires=[{'option': ip_admin, 'expected': '192.168.1.1', 'action': 'disabled'}])
@ -1307,7 +2331,7 @@ def test_leadership_requires_both():
raises(RequirementError, "Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0], requires=[{'option': ip_admin, 'expected': '192.168.1.1', 'action': 'disabled'}])") raises(RequirementError, "Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0], requires=[{'option': ip_admin, 'expected': '192.168.1.1', 'action': 'disabled'}])")
def test_leadership_requires_properties_invalid(): def test_leadership_requires_properties_invalid_legacy():
ip_admin = StrOption('ip_admin', "ip réseau autorisé") ip_admin = StrOption('ip_admin', "ip réseau autorisé")
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,
@ -1315,16 +2339,7 @@ def test_leadership_requires_properties_invalid():
raises(ValueError, "Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0], properties=('disabled',), requires=[{'option': ip_admin, 'expected': '192.168.1.1', 'action': 'disabled'}])") raises(ValueError, "Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0], properties=('disabled',), requires=[{'option': ip_admin, 'expected': '192.168.1.1', 'action': 'disabled'}])")
def test_leadership_requires_properties_invalid_2(): def test_leadership_requires_properties_legacy():
ip_admin = StrOption('ip_admin', "ip réseau autorisé")
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True,
requires=[{'option': ip_admin, 'expected': '192.168.1.1', 'action': 'disabled'}])
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True,
requires=[{'option': ip_admin_eth0, 'expected': '192.168.1.1', 'action': 'disabled'}])
raises(ValueError, "Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0], properties=('disabled',))")
def test_leadership_requires_properties():
ip_admin = StrOption('ip_admin', "ip réseau autorisé") ip_admin = StrOption('ip_admin', "ip réseau autorisé")
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,
@ -1333,7 +2348,7 @@ def test_leadership_requires_properties():
requires=[{'option': ip_admin, 'expected': '192.168.1.1', 'action': 'disabled'}]) requires=[{'option': ip_admin, 'expected': '192.168.1.1', 'action': 'disabled'}])
def test_leadership_requires_leader(config_type): def test_leadership_requires_leader_legacy(config_type):
activate = BoolOption('activate', "Activer l'accès au réseau", True) activate = BoolOption('activate', "Activer l'accès au réseau", True)
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,
requires=[{'option': activate, 'expected': False, 'action': 'disabled'}]) requires=[{'option': activate, 'expected': False, 'action': 'disabled'}])
@ -1362,7 +2377,40 @@ def test_leadership_requires_leader(config_type):
assert cfg.value.dict() == {'activate': False} assert cfg.value.dict() == {'activate': False}
def test_leadership_requires_leader_callback(config_type): def test_leadership_requires_leader(config_type):
activate = BoolOption('activate', "Activer l'accès au réseau", True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(activate, notraisepropertyerror=True),
'expected': ParamValue(False),
'index': ParamIndex()}))
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True, properties=(disabled_property,))
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('toto', '', [activate, interface1])
cfg = Config(od)
cfg.property.read_write()
#
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == []
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2'])
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.2']
#
cfg.option('activate').value.set(False)
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()")
#
cfg.option('activate').value.set(True)
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
#
cfg.option('activate').value.set(False)
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()")
assert cfg.value.dict() == {'activate': False}
def test_leadership_requires_leader_callback_legacy(config_type):
activate = BoolOption('activate', "Activer l'accès au réseau", True) activate = BoolOption('activate', "Activer l'accès au réseau", True)
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,
requires=[{'callback': calc_value, 'callback_params': Params(ParamOption(activate)), 'expected': False, 'action': 'disabled'}]) requires=[{'callback': calc_value, 'callback_params': Params(ParamOption(activate)), 'expected': False, 'action': 'disabled'}])
@ -1391,7 +2439,7 @@ def test_leadership_requires_leader_callback(config_type):
assert cfg.value.dict() == {'activate': False} assert cfg.value.dict() == {'activate': False}
def test_leadership_requires_leadership(config_type): def test_leadership_requires_leadership_legacy(config_type):
activate = BoolOption('activate', "Activer l'accès au réseau", True) activate = BoolOption('activate', "Activer l'accès au réseau", True)
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)
@ -1424,7 +2472,44 @@ def test_leadership_requires_leadership(config_type):
assert cfg.value.dict() == {'activate': False} assert cfg.value.dict() == {'activate': False}
def test_leadership_requires_leadership_callback(config_type): def test_leadership_requires_leadership(config_type):
activate = BoolOption('activate', "Activer l'accès au réseau", 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)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(activate, notraisepropertyerror=True),
'expected': ParamValue(False),
'index': ParamIndex()}))
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0], properties=(disabled_property,))
od = OptionDescription('toto', '', [activate, interface1])
cfg = Config(od)
cfg.property.read_write()
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(['192.168.1.2'])
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.2']
#
cfg.option('activate').value.set(False)
if config_type != 'tiramisu-api':
# FIXME
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()")
#
cfg.option('activate').value.set(True)
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
#
cfg.option('activate').value.set(False)
if config_type != 'tiramisu-api':
# FIXME
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()")
assert cfg.value.dict() == {'activate': False}
def test_leadership_requires_leadership_callback_legacy(config_type):
activate = BoolOption('activate', "Activer l'accès au réseau", True) activate = BoolOption('activate', "Activer l'accès au réseau", True)
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)
@ -1453,7 +2538,7 @@ def test_leadership_requires_leadership_callback(config_type):
assert cfg.value.dict() == {'activate': False} assert cfg.value.dict() == {'activate': False}
def test_leadership_requires_no_leader(config_type): def test_leadership_requires_no_leader_legacy(config_type):
activate = BoolOption('activate', "Activer l'accès au réseau", True) activate = BoolOption('activate', "Activer l'accès au réseau", True)
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,
@ -1483,7 +2568,41 @@ def test_leadership_requires_no_leader(config_type):
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['192.168.1.2', '192.168.1.1'], 'activate': False} assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['192.168.1.2', '192.168.1.1'], 'activate': False}
def test_leadership_requires_no_leader_callback(config_type): def test_leadership_requires_no_leader(config_type):
activate = BoolOption('activate', "Activer l'accès au réseau", True)
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(activate, notraisepropertyerror=True),
'expected': ParamValue(False),
'index': ParamIndex()}))
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=(disabled_property,))
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
od = OptionDescription('toto', '', [activate, interface1])
cfg = Config(od)
cfg.property.read_write()
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(['192.168.1.2'])
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.2']
cfg.option('activate').value.set(False)
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.1'])
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.2', '192.168.1.1']
raises(PropertiesOptionError, "cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()")
raises(PropertiesOptionError, "cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get()")
cfg.option('activate').value.set(True)
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() is None
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('255.255.255.255')
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.255.255'
cfg.option('activate').value.set(False)
raises(PropertiesOptionError, "cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()")
raises(PropertiesOptionError, "cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get()")
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['192.168.1.2', '192.168.1.1'], 'activate': False}
def test_leadership_requires_no_leader_callback_legacy(config_type):
activate = BoolOption('activate', "Activer l'accès au réseau", True) activate = BoolOption('activate', "Activer l'accès au réseau", True)
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,
@ -1518,7 +2637,7 @@ def test_leadership_requires_no_leader_callback(config_type):
del dico['ip_admin_eth0.netmask_admin_eth0'][0] del dico['ip_admin_eth0.netmask_admin_eth0'][0]
def test_leadership_requires_complet(config_type): def test_leadership_requires_complet_legacy(config_type):
optiontoto = StrOption('unicodetoto', "Unicode") optiontoto = StrOption('unicodetoto', "Unicode")
option = StrOption('unicode', "Unicode leader", multi=True) option = StrOption('unicode', "Unicode leader", multi=True)
option1 = StrOption('unicode1', "Unicode follower 1", multi=True) option1 = StrOption('unicode1', "Unicode follower 1", multi=True)
@ -1606,7 +2725,107 @@ def test_leadership_requires_complet(config_type):
del dico['options.unicode.unicode7'] del dico['options.unicode.unicode7']
def test_leadership_requires_complet_callback(config_type): def test_leadership_requires_complet(config_type):
optiontoto = StrOption('unicodetoto', "Unicode")
option = StrOption('unicode', "Unicode leader", multi=True)
option1 = StrOption('unicode1', "Unicode follower 1", multi=True)
option2 = StrOption('unicode2', "Values 'test' must show 'Unicode follower 3'", multi=True)
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(option, notraisepropertyerror=True),
'expected': ParamValue('test'),
'index': ParamIndex(),
'no_condition_is_invalid': ParamValue(True),
'inverse_condition': ParamValue(True)}))
option3 = StrOption('unicode3', "Unicode follower 3", properties=(hidden_property,), multi=True)
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(option2, notraisepropertyerror=True),
'expected': ParamValue('test'),
'no_condition_is_invalid': ParamValue(True),
'index': ParamIndex(),
'inverse_condition': ParamValue(True)}))
option4 = StrOption('unicode4', "Unicode follower 4", properties=(hidden_property,), multi=True)
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(optiontoto, notraisepropertyerror=True),
'expected': ParamValue('test'),
'no_condition_is_invalid': ParamValue(True),
'inverse_condition': ParamValue(True)}))
option5 = StrOption('unicode5', "Unicode follower 5", properties=(hidden_property,), multi=True)
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition_0': ParamOption(optiontoto, notraisepropertyerror=True),
'expected_0': ParamValue('test'),
'condition_1': ParamOption(option2, notraisepropertyerror=True),
'expected_1': ParamValue('test'),
'no_condition_is_invalid': ParamValue(True),
'index': ParamIndex(),
'condition_operator': ParamValue('OR'),
'inverse_condition_0': ParamValue(True),
'inverse_condition_1': ParamValue(True)}))
option6 = StrOption('unicode6', "Unicode follower 6", properties=(hidden_property,), multi=True)
hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'),
kwargs={'condition_0': ParamOption(option2, notraisepropertyerror=True),
'expected_0': ParamValue('test'),
'condition_1': ParamOption(optiontoto, notraisepropertyerror=True),
'expected_1': ParamValue('test'),
'no_condition_is_invalid': ParamValue(True),
'index': ParamIndex(),
'inverse_condition': ParamValue(True)}))
option7 = StrOption('unicode7', "Unicode follower 7", properties=(hidden_property,), multi=True)
descr1 = Leadership("unicode", "Common configuration 1",
[option, option1, option2, option3, option4, option5, option6, option7])
descr = OptionDescription("options", "Common configuration 2", [descr1, optiontoto])
descr = OptionDescription("unicode1_leadership_requires", "Leader followers with Unicode follower 3 hidden when Unicode follower 2 is test", [descr])
cfg = Config(descr)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
cfg.option('options.unicode.unicode').value.set(['test', 'trah'])
cfg.option('options.unicode.unicode2', 0).value.set('test')
dico = cfg.value.dict()
assert dico.keys() == set(['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode2', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicodetoto'])
assert dico['options.unicode.unicode'] == ['test', 'trah']
assert dico['options.unicode.unicode1'] == [None, None]
assert dico['options.unicode.unicode2'] == ['test', None]
assert dico['options.unicode.unicode3'][0] is None
assert isinstance(dico['options.unicode.unicode3'][1], PropertiesOptionError)
assert dico['options.unicode.unicode4'][0] is None
assert isinstance(dico['options.unicode.unicode4'][1], PropertiesOptionError)
assert dico['options.unicodetoto'] is None
del dico['options.unicode.unicode3'][1]
del dico['options.unicode.unicode3']
del dico['options.unicode.unicode4'][1]
del dico['options.unicode.unicode4']
#
cfg.option('options.unicodetoto').value.set('test')
dico = cfg.value.dict()
assert dico.keys() == set(['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode2', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicode.unicode5', 'options.unicode.unicode6', 'options.unicode.unicode7', 'options.unicodetoto'])
assert dico['options.unicode.unicode'] == ['test', 'trah']
assert dico['options.unicode.unicode1'] == [None, None]
assert dico['options.unicode.unicode2'] == ['test', None]
assert dico['options.unicode.unicode3'][0] is None
assert isinstance(dico['options.unicode.unicode3'][1], PropertiesOptionError)
assert dico['options.unicode.unicode4'][0] is None
assert isinstance(dico['options.unicode.unicode4'][1], PropertiesOptionError)
assert dico['options.unicode.unicode5'] == [None, None]
assert dico['options.unicode.unicode6'][0] is None
assert isinstance(dico['options.unicode.unicode6'][1], PropertiesOptionError)
assert dico['options.unicode.unicode7'][0] is None
assert isinstance(dico['options.unicode.unicode7'][1], PropertiesOptionError)
assert dico['options.unicodetoto'] == 'test'
del dico['options.unicode.unicode3'][1]
del dico['options.unicode.unicode3']
del dico['options.unicode.unicode4'][1]
del dico['options.unicode.unicode4']
del dico['options.unicode.unicode6'][1]
del dico['options.unicode.unicode6']
del dico['options.unicode.unicode7'][1]
del dico['options.unicode.unicode7']
def test_leadership_requires_complet_callback_legacy(config_type):
optiontoto = StrOption('unicodetoto', "Unicode leader") optiontoto = StrOption('unicodetoto', "Unicode leader")
option = StrOption('unicode', "Unicode leader", multi=True) option = StrOption('unicode', "Unicode leader", multi=True)
option1 = StrOption('unicode1', "Unicode follower 1", multi=True) option1 = StrOption('unicode1', "Unicode follower 1", multi=True)
@ -1707,7 +2926,7 @@ def test_leadership_requires_complet_callback(config_type):
del dico['options.unicode.unicode7'] del dico['options.unicode.unicode7']
def test_leadership_requires_transitive1(config_type): def test_leadership_requires_transitive1_legacy(config_type):
optiontoto = StrOption('unicodetoto', "Simple unicode") optiontoto = StrOption('unicodetoto', "Simple unicode")
option = StrOption('unicode', "Unicode leader", multi=True) option = StrOption('unicode', "Unicode leader", multi=True)
option1 = StrOption('unicode1', "Unicode follower 1", multi=True) option1 = StrOption('unicode1', "Unicode follower 1", multi=True)
@ -1823,7 +3042,128 @@ def test_leadership_requires_transitive1(config_type):
del (dico['options.unicode.unicode4'][0]) del (dico['options.unicode.unicode4'][0])
def test_leadership_requires_transitive_callback(config_type): def test_leadership_requires_transitive1(config_type):
optiontoto = StrOption('unicodetoto', "Simple unicode")
option = StrOption('unicode', "Unicode leader", multi=True)
option1 = StrOption('unicode1', "Unicode follower 1", multi=True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(optiontoto, raisepropertyerror=True),
'expected': ParamValue('test'),
'index': ParamIndex(),
'inverse_condition': ParamValue(True)}))
option2 = StrOption('unicode2', "Unicode follower 2", properties=(disabled_property,), multi=True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(option2, raisepropertyerror=True),
'expected': ParamValue('test'),
'index': ParamIndex(),
'no_condition_is_invalid': ParamValue(True),
'inverse_condition': ParamValue(True)}))
option3 = StrOption('unicode3', "Unicode follower 3", properties=(disabled_property,), multi=True)
disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(option3, raisepropertyerror=True),
'expected': ParamValue('test'),
'index': ParamIndex(),
'no_condition_is_invalid': ParamValue(True),
'inverse_condition': ParamValue(True)}))
option4 = StrOption('unicode4', "Unicode follower 4", properties=(disabled_property,), multi=True)
descr1 = Leadership("unicode", "Common configuration 1",
[option, option1, option2, option3, option4])
descr = OptionDescription("options", "Common configuration 2", [descr1, optiontoto])
descr = OptionDescription("unicode1", "", [descr])
cfg = Config(descr)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'options.unicode.unicode': [], 'options.unicode.unicode1': [], 'options.unicode.unicode3': [], 'options.unicode.unicode4': [], 'options.unicodetoto': None}
#
cfg.option('options.unicodetoto').value.set('test')
assert cfg.value.dict() == {'options.unicode.unicode': [], 'options.unicode.unicode1': [], 'options.unicode.unicode2': [], 'options.unicode.unicode3': [], 'options.unicode.unicode4': [], 'options.unicodetoto': 'test'}
#
cfg.option('options.unicode.unicode').value.set(['a', 'b', 'c'])
dico = cfg.value.dict()
assert list(dico.keys()) == ['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode2', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicodetoto']
assert dico['options.unicodetoto'] == 'test'
assert dico['options.unicode.unicode'] == ['a', 'b', 'c']
assert dico['options.unicode.unicode1'] == [None, None, None]
assert dico['options.unicode.unicode2'] == [None, None, None]
assert isinstance(dico['options.unicode.unicode3'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode3'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode3'][2], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][2], PropertiesOptionError)
del (dico['options.unicode.unicode3'][2])
del (dico['options.unicode.unicode3'][1])
del (dico['options.unicode.unicode3'][0])
del (dico['options.unicode.unicode4'][2])
del (dico['options.unicode.unicode4'][1])
del (dico['options.unicode.unicode4'][0])
#
cfg.option('options.unicode.unicode2', 1).value.set('test')
cfg.option('options.unicode.unicode3', 1).value.set('test')
dico = cfg.value.dict()
assert list(dico.keys()) == ['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode2', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicodetoto']
assert dico['options.unicodetoto'] == 'test'
assert dico['options.unicode.unicode'] == ['a', 'b', 'c']
assert dico['options.unicode.unicode1'] == [None, None, None]
assert dico['options.unicode.unicode2'] == [None, 'test', None]
assert isinstance(dico['options.unicode.unicode3'][0], PropertiesOptionError)
assert dico['options.unicode.unicode3'][1] == 'test'
assert isinstance(dico['options.unicode.unicode3'][2], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][0], PropertiesOptionError)
assert dico['options.unicode.unicode4'][1] == None
assert isinstance(dico['options.unicode.unicode4'][2], PropertiesOptionError)
del (dico['options.unicode.unicode3'][2])
del (dico['options.unicode.unicode3'][1])
del (dico['options.unicode.unicode3'][0])
del (dico['options.unicode.unicode4'][2])
del (dico['options.unicode.unicode4'][1])
del (dico['options.unicode.unicode4'][0])
#
cfg.option('options.unicode.unicode2', 1).value.set('rah')
dico = cfg.value.dict()
assert list(dico.keys()) == ['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode2', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicodetoto']
assert dico['options.unicodetoto'] == 'test'
assert dico['options.unicode.unicode'] == ['a', 'b', 'c']
assert dico['options.unicode.unicode1'] == [None, None, None]
assert dico['options.unicode.unicode2'] == [None, 'rah', None]
assert isinstance(dico['options.unicode.unicode3'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode3'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode3'][2], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][2], PropertiesOptionError)
del (dico['options.unicode.unicode3'][2])
del (dico['options.unicode.unicode3'][1])
del (dico['options.unicode.unicode3'][0])
del (dico['options.unicode.unicode4'][2])
del (dico['options.unicode.unicode4'][1])
del (dico['options.unicode.unicode4'][0])
#
cfg.option('options.unicode.unicode2', 1).value.set('test')
cfg.option('options.unicodetoto').value.set('rah')
dico = cfg.value.dict()
assert list(dico.keys()) == ['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicodetoto']
assert dico['options.unicodetoto'] == 'rah'
assert dico['options.unicode.unicode'] == ['a', 'b', 'c']
assert dico['options.unicode.unicode1'] == [None, None, None]
assert isinstance(dico['options.unicode.unicode3'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode3'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode3'][2], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][2], PropertiesOptionError)
del (dico['options.unicode.unicode3'][2])
del (dico['options.unicode.unicode3'][1])
del (dico['options.unicode.unicode3'][0])
del (dico['options.unicode.unicode4'][2])
del (dico['options.unicode.unicode4'][1])
del (dico['options.unicode.unicode4'][0])
def test_leadership_requires_transitive_callback_legacy(config_type):
optiontoto = StrOption('unicodetoto', "Unicode leader") optiontoto = StrOption('unicodetoto', "Unicode leader")
option = StrOption('unicode', "Unicode leader", multi=True) option = StrOption('unicode', "Unicode leader", multi=True)
option1 = StrOption('unicode1', "Unicode follower 1", multi=True) option1 = StrOption('unicode1', "Unicode follower 1", multi=True)
@ -1943,3 +3283,8 @@ def test_leadership_requires_transitive_callback(config_type):
del (dico['options.unicode.unicode4'][2]) del (dico['options.unicode.unicode4'][2])
del (dico['options.unicode.unicode4'][1]) del (dico['options.unicode.unicode4'][1])
del (dico['options.unicode.unicode4'][0]) del (dico['options.unicode.unicode4'][0])
# FIXME tester l'ajout d'un Calculation
# FIXME permissive peut etre in calcul !
# FIXME Calculation sur des multis ...

View File

@ -1,9 +1,8 @@
#from autopath import do_autopath #from autopath import do_autopath
#do_autopath() #do_autopath()
# #
from tiramisu.option import BoolOption, UnicodeOption, SymLinkOption, \ from tiramisu import BoolOption, UnicodeOption, SymLinkOption, OptionDescription, DynOptionDescription, \
OptionDescription, DynOptionDescription Calculation, Params, ParamOption, ParamValue, calc_value, Config
from tiramisu import Config
from pickle import dumps from pickle import dumps
from py.test import raises from py.test import raises
import sys import sys
@ -213,7 +212,12 @@ def _diff_conf(cfg1, cfg2):
def test_diff_opt(): def test_diff_opt():
b = BoolOption('b', '') b = BoolOption('b', '')
u = UnicodeOption('u', '', requires=[{'option': b, 'expected': True, 'action': 'disabled', 'inverse': True}]) disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(b),
'expected': ParamValue(True),
'inverse_condition': ParamValue(True)}))
u = UnicodeOption('u', '', properties=(disabled_property,))
s = SymLinkOption('s', u) s = SymLinkOption('s', u)
o = OptionDescription('o', '', [b, u, s]) o = OptionDescription('o', '', [b, u, s])
o1 = OptionDescription('o1', '', [o]) o1 = OptionDescription('o1', '', [o])

View File

@ -5,7 +5,7 @@ do_autopath()
from .config import config_type, get_config from .config import config_type, get_config
from tiramisu import BoolOption, StrOption, SymLinkOption, \ from tiramisu import BoolOption, StrOption, SymLinkOption, \
OptionDescription, Leadership, Config OptionDescription, Leadership, Config, Calculation, calc_value, Params, ParamOption, ParamValue
from tiramisu.error import PropertiesOptionError, ConfigError from tiramisu.error import PropertiesOptionError, ConfigError
from tiramisu.setting import groups, owners from tiramisu.setting import groups, owners
from tiramisu.storage import list_sessions from tiramisu.storage import list_sessions
@ -122,9 +122,11 @@ def test_symlink_getcallback():
def test_symlink_requires(config_type): def test_symlink_requires(config_type):
boolopt = BoolOption('b', '', default=True) boolopt = BoolOption('b', '', default=True)
stropt = StrOption('s', '', requires=[{'option': boolopt, disabled_property = Calculation(calc_value,
'expected': False, Params(ParamValue('disabled'),
'action': 'disabled'}]) kwargs={'condition': ParamOption(boolopt),
'expected': ParamValue(False)}))
stropt = StrOption('s', '', properties=(disabled_property,))
linkopt = SymLinkOption("c", stropt) linkopt = SymLinkOption("c", stropt)
descr = OptionDescription('opt', '', [boolopt, stropt, linkopt]) descr = OptionDescription('opt', '', [boolopt, stropt, linkopt])
cfg = Config(descr) cfg = Config(descr)

View File

@ -14,8 +14,8 @@
# 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 Params, ParamOption, ParamValue, ParamContext, \ from .function import tiramisu_copy, calc_value, calc_value_property_help
tiramisu_copy, calc_value from .autolib import Calculation, Params, ParamOption, ParamSelfOption, ParamValue, ParamIndex, ParamContext
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
@ -25,9 +25,12 @@ from .storage import default_storage, Storage, list_sessions, \
delete_session delete_session
allfuncs = ['Params', allfuncs = ['Calculation',
'ParamOption', 'Params',
'ParamOption',
'ParamSelfOption',
'ParamValue', 'ParamValue',
'ParamIndex',
'ParamContext', 'ParamContext',
'MetaConfig', 'MetaConfig',
'MixConfig', 'MixConfig',
@ -40,7 +43,8 @@ allfuncs = ['Params',
'list_sessions', 'list_sessions',
'delete_session', 'delete_session',
'tiramisu_copy', 'tiramisu_copy',
'calc_value'] 'calc_value',
'calc_value_property_help']
allfuncs.extend(all_options) allfuncs.extend(all_options)
del(all_options) del(all_options)
__all__ = tuple(allfuncs) __all__ = tuple(allfuncs)

View File

@ -384,8 +384,6 @@ class TiramisuOptionProperty(CommonTiramisuOption):
def get(self, def get(self,
only_raises=False): only_raises=False):
"""Get properties for an option""" """Get properties for an option"""
option = self._option_bag.option
#self._test_follower_index()
if not only_raises: if not only_raises:
return self._option_bag.properties return self._option_bag.properties
# do not check cache properties/permissives which are not save (unrestraint, ...) # do not check cache properties/permissives which are not save (unrestraint, ...)
@ -397,8 +395,8 @@ class TiramisuOptionProperty(CommonTiramisuOption):
if prop in FORBIDDEN_SET_PROPERTIES: if prop in FORBIDDEN_SET_PROPERTIES:
raise ConfigError(_('cannot add this property: "{0}"').format( raise ConfigError(_('cannot add this property: "{0}"').format(
' '.join(prop))) ' '.join(prop)))
props = self._settings.getproperties(self._option_bag, props = self._settings._p_.getproperties(self._option_bag.path,
apply_requires=False) option.impl_getproperties())
self._settings.setproperties(self._option_bag.path, self._settings.setproperties(self._option_bag.path,
props | {prop}, props | {prop},
self._option_bag, self._option_bag,
@ -407,8 +405,8 @@ class TiramisuOptionProperty(CommonTiramisuOption):
def pop(self, prop): def pop(self, prop):
"""Remove new property for an option""" """Remove new property for an option"""
option = self._option_bag.option option = self._option_bag.option
props = self._settings.getproperties(self._option_bag, props = self._settings._p_.getproperties(self._option_bag.path,
apply_requires=False) option.impl_getproperties())
self._settings.setproperties(self._option_bag.path, self._settings.setproperties(self._option_bag.path,
props - {prop}, props - {prop},
self._option_bag, self._option_bag,

View File

@ -19,22 +19,159 @@
# ____________________________________________________________ # ____________________________________________________________
"enables us to carry out a calculation and return an option's value" "enables us to carry out a calculation and return an option's value"
from typing import Any, Optional, Union, Callable, Dict, List from typing import Any, Optional, Union, Callable, Dict, List
from itertools import chain
from .error import PropertiesOptionError, ConfigError, LeadershipError from .error import PropertiesOptionError, ConfigError, LeadershipError
from .i18n import _ from .i18n import _
from .setting import undefined, ConfigBag, OptionBag, Undefined from .setting import undefined, ConfigBag, OptionBag, Undefined
from .storage import get_default_values_storages, get_default_settings_storages from .storage import get_default_values_storages, get_default_settings_storages
from .function import ParamValue, ParamContext, ParamIndex, ParamOption, Params
# ____________________________________________________________ # ____________________________________________________________
class Params:
__slots__ = ('args', 'kwargs')
def __init__(self, args=None, kwargs=None, **kwgs):
if args is None:
args = tuple()
if kwargs is None:
kwargs = {}
if kwgs:
kwargs.update(kwgs)
if isinstance(args, Param):
args = (args,)
else:
if not isinstance(args, tuple):
raise ValueError(_('args in params must be a tuple'))
for arg in args:
if not isinstance(arg, Param):
raise ValueError(_('arg in params must be a Param'))
if not isinstance(kwargs, dict):
raise ValueError(_('kwargs in params must be a dict'))
for arg in kwargs.values():
if not isinstance(arg, Param):
raise ValueError(_('arg in params must be a Param'))
self.args = args
self.kwargs = kwargs
class Param:
pass
class ParamOption(Param):
__slots__ = ('todict',
'error',
'option',
'notraisepropertyerror',
'raisepropertyerror')
def __init__(self,
option: 'Option',
notraisepropertyerror: bool=False,
raisepropertyerror: bool=False,
todict: bool=False) -> None:
if __debug__ and not hasattr(option, 'impl_is_symlinkoption'):
raise ValueError(_('paramoption needs an option not {}').format(type(option)))
if option.impl_is_symlinkoption():
cur_opt = option.impl_getopt()
else:
cur_opt = option
assert isinstance(notraisepropertyerror, bool), _('param must have a boolean not a {} for notraisepropertyerror').format(type(notraisepropertyerror))
assert isinstance(raisepropertyerror, bool), _('param must have a boolean not a {} for raisepropertyerror').format(type(raisepropertyerror))
self.todict = todict
self.option = cur_opt
self.notraisepropertyerror = notraisepropertyerror
self.raisepropertyerror = raisepropertyerror
class ParamSelfOption(Param):
__slots__ = ('todict',)
def __init__(self,
todict: bool=False) -> None:
self.todict = todict
class ParamValue(Param):
__slots__ = ('value',)
def __init__(self, value):
self.value = value
class ParamContext(Param):
__slots__ = tuple()
class ParamIndex(Param):
__slots__ = tuple()
class Calculation:
__slots__ = ('function',
'params',
'help_function',
'has_index')
def __init__(self,
function: Callable,
params: Optional[Params]=None,
help_function: Optional[Callable]=None):
assert isinstance(function, Callable), _('first argument ({0}) must be a function').format(function)
if help_function:
assert isinstance(help_function, Callable), _('help_function ({0}) must be a function').format(help_function)
self.help_function = help_function
else:
self.help_function = None
self.function = function
if params:
self.params = params
for arg in chain(self.params.args, self.params.kwargs.values()):
if isinstance(arg, ParamIndex):
self.has_index = True
break
else:
self.has_index = False
else:
self.has_index = False
def execute(self,
option_bag: OptionBag,
leadership_must_have_index: bool=False) -> Any:
if leadership_must_have_index and not self.has_index:
leadership_must_have_index = False
return carry_out_calculation(option_bag.option,
callback=self.function,
callback_params=self.params,
index=option_bag.index,
config_bag=option_bag.config_bag,
fromconsistency=option_bag.fromconsistency,
leadership_must_have_index=leadership_must_have_index)
def help(self,
option_bag: OptionBag,
leadership_must_have_index: bool=False) -> str:
if not self.help_function:
return self.execute(option_bag,
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,
callback=self.help_function,
callback_params=self.params,
index=option_bag.index,
config_bag=option_bag.config_bag,
fromconsistency=option_bag.fromconsistency,
leadership_must_have_index=leadership_must_have_index)
class Break(Exception):
pass
def manager_callback(callbk: Union[ParamOption, ParamValue], def manager_callback(callbk: Union[ParamOption, ParamValue],
option, option,
index: Optional[int], index: Optional[int],
orig_value, orig_value,
config_bag: ConfigBag, config_bag: ConfigBag,
fromconsistency: List) -> Any: fromconsistency: List,
leadership_must_have_index: bool) -> Any:
"""replace Param by true value""" """replace Param by true value"""
if isinstance(callbk, ParamValue): if isinstance(callbk, ParamValue):
return callbk.value return callbk.value
@ -46,17 +183,24 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
# Not an option, set full context # Not an option, set full context
return config_bag.context.duplicate(force_values=get_default_values_storages(), return config_bag.context.duplicate(force_values=get_default_values_storages(),
force_settings=get_default_settings_storages()) force_settings=get_default_settings_storages())
opt = callbk.option if isinstance(callbk, ParamSelfOption):
opt = option
else:
# it's ParamOption
opt = callbk.option
if opt.issubdyn(): if opt.issubdyn():
opt = opt.to_dynoption(option.rootpath, opt = opt.to_dynoption(option.rootpath,
option.impl_getsuffix()) option.impl_getsuffix())
path = opt.impl_getpath() path = opt.impl_getpath()
is_follower = opt.impl_is_follower()
if leadership_must_have_index and opt.impl_get_leadership() and index is None:
raise Break()
if index is not None and opt.impl_get_leadership() and \ if index is not None and opt.impl_get_leadership() and \
opt.impl_get_leadership().in_same_group(option): opt.impl_get_leadership().in_same_group(option):
if opt == option: if opt == option:
index_ = None index_ = None
with_index = False with_index = False
elif opt.impl_is_follower(): elif is_follower:
index_ = index index_ = index
with_index = False with_index = False
else: else:
@ -66,35 +210,43 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
index_ = None index_ = None
with_index = False with_index = False
if opt == option and orig_value is not undefined and \ if opt == option and orig_value is not undefined and \
(not opt.impl_is_follower() or index is None): (not is_follower or index is None):
return orig_value value = orig_value
# don't validate if option is option that we tried to validate else:
config_bag = config_bag.copy() # don't validate if option is option that we tried to validate
config_bag.set_permissive() config_bag = config_bag.copy()
config_bag.properties -= {'warnings'} config_bag.properties = config_bag.true_properties - {'warnings'}
option_bag = OptionBag() config_bag.set_permissive()
option_bag.set_option(opt, #config_bag.properties -= {'warnings'}
path, option_bag = OptionBag()
index_, option_bag.set_option(opt,
config_bag) path,
if fromconsistency: index_,
option_bag.fromconsistency = fromconsistency.copy() config_bag)
if opt == option: if fromconsistency:
option_bag.config_bag.unrestraint() option_bag.fromconsistency = fromconsistency.copy()
option_bag.config_bag.remove_validation() if opt == option:
try: option_bag.config_bag.unrestraint()
# get value option_bag.config_bag.remove_validation()
value = config_bag.context.getattr(path, # if we are in properties calculation, cannot calculated properties
option_bag) option_bag.properties = config_bag.context.cfgimpl_get_settings().getproperties(option_bag,
if with_index: apply_requires=False)
return value[index] try:
# get value
value = config_bag.context.getattr(path,
option_bag)
if with_index:
value = value[index]
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)
if not callbk.todict:
return value return value
except PropertiesOptionError as err: return {'name': opt.impl_get_display_name(),
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation 'value': value}
if callbk.notraisepropertyerror:
raise err
raise ConfigError(_('unable to carry out a calculation for "{}"'
', {}').format(option.impl_get_display_name(), err), err)
def carry_out_calculation(option, def carry_out_calculation(option,
@ -104,8 +256,8 @@ def carry_out_calculation(option,
config_bag: Optional[ConfigBag], config_bag: Optional[ConfigBag],
fromconsistency: List, fromconsistency: List,
orig_value=undefined, orig_value=undefined,
leadership_must_have_index: bool=False,
is_validator: int=False): is_validator: 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
@ -227,12 +379,18 @@ def carry_out_calculation(option,
index, index,
orig_value, orig_value,
config_bag, config_bag,
fromconsistency) fromconsistency,
leadership_must_have_index)
if value is undefined: if value is undefined:
return undefined return undefined
args.append(value) args.append(value)
except PropertiesOptionError: except PropertiesOptionError as err:
pass if callbk.raisepropertyerror:
raise err
if callbk.todict:
args.append({'propertyerror': str(err)})
except Break:
continue
for key, callbk in callback_params.kwargs.items(): for key, callbk in callback_params.kwargs.items():
try: try:
value = manager_callback(callbk, value = manager_callback(callbk,
@ -240,12 +398,18 @@ def carry_out_calculation(option,
index, index,
orig_value, orig_value,
config_bag, config_bag,
fromconsistency) fromconsistency,
leadership_must_have_index)
if value is undefined: if value is undefined:
return undefined return undefined
kwargs[key] = value kwargs[key] = value
except PropertiesOptionError: except PropertiesOptionError as err:
pass if callbk.raisepropertyerror:
raise err
if callbk.todict:
kwargs[key] = {'propertyerror': str(err)}
except Break:
continue
ret = calculate(option, ret = calculate(option,
callback, callback,
is_validator, is_validator,
@ -290,6 +454,8 @@ def calculate(option,
raise err raise err
error = err error = err
except Exception as err: except Exception as err:
#import traceback
#traceback.print_exc()
error = err error = err
if args or kwargs: if args or kwargs:
msg = _('unexpected error "{0}" in function "{1}" with arguments "{3}" and "{4}" ' msg = _('unexpected error "{0}" in function "{1}" with arguments "{3}" and "{4}" '

View File

@ -269,10 +269,9 @@ class SubConfig(object):
def getattr(self, def getattr(self,
name, name,
option_bag, option_bag,
from_follower=False): from_follower=False,
needs_re_verify_follower_properties=False):
""" """
attribute notation mechanism for accessing the value of an option
:param name: attribute name
:return: option's value if name is an option name, OptionDescription :return: option's value if name is an option name, OptionDescription
otherwise otherwise
""" """
@ -298,7 +297,7 @@ class SubConfig(object):
return context.getattr(soption_bag.path, return context.getattr(soption_bag.path,
soption_bag) soption_bag)
if not from_follower or option_bag.option.impl_getrequires(): if not from_follower or needs_re_verify_follower_properties:
self.cfgimpl_get_settings().validate_properties(option_bag) self.cfgimpl_get_settings().validate_properties(option_bag)
if option.impl_is_follower() and not from_follower: if option.impl_is_follower() and not from_follower:
@ -311,6 +310,8 @@ 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 \
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()
@ -322,7 +323,8 @@ class SubConfig(object):
try: try:
value.append(self.getattr(name, value.append(self.getattr(name,
soption_bag, soption_bag,
from_follower=True)) from_follower=True,
needs_re_verify_follower_properties=needs_re_verify_follower_properties))
except PropertiesOptionError as err: except PropertiesOptionError as err:
value.append(err) value.append(err)
else: else:
@ -412,40 +414,7 @@ class SubConfig(object):
withoption=None, withoption=None,
withvalue=undefined, withvalue=undefined,
fullpath=False): fullpath=False):
"""exports the whole config into a `dict`, for example: """exports the whole config into a `dict`
>>> print(cfg.make_dict())
{'od2.var4': None, 'od2.var5': None, 'od2.var6': None}
:param flatten: returns a dict(name=value) instead of a dict(path=value)
::
>>> print(cfg.make_dict(flatten=True))
{'var5': None, 'var4': None, 'var6': None}
:param withoption: returns the options that are present in the very same
`OptionDescription` than the `withoption` itself::
>>> print(cfg.make_dict(withoption='var1'))
{'od2.var4': None, 'od2.var5': None,
'od2.var6': None,
'od2.var1': u'value',
'od1.var1': None,
'od1.var3': None,
'od1.var2': None}
:param withvalue: returns the options that have the value `withvalue`
::
>>> print(c.make_dict(withoption='var1',
withvalue=u'value'))
{'od2.var4': None,
'od2.var5': None,
'od2.var6': None,
'od2.var1': u'value'}
:returns: dict of Option's name (or path) and values :returns: dict of Option's name (or path) and values
""" """
pathsvalues = {} pathsvalues = {}

View File

@ -30,7 +30,7 @@ def display_list(lst, separator='and', add_quote=False):
ret = lst[0] ret = lst[0]
if not isinstance(ret, str): if not isinstance(ret, str):
ret = str(ret) ret = str(ret)
if add_quote: if add_quote and not ret.startswith('"'):
ret = '"{}"'.format(ret) ret = '"{}"'.format(ret)
return ret return ret
else: else:
@ -39,13 +39,13 @@ def display_list(lst, separator='and', add_quote=False):
for l in lst[:-1]: for l in lst[:-1]:
if not isinstance(l, str): if not isinstance(l, str):
l = str(l) l = str(l)
if add_quote: if add_quote and not l.startswith('"'):
l = '"{}"'.format(l) l = '"{}"'.format(l)
lst_.append(_(l)) lst_.append(_(l))
last = lst[-1] last = lst[-1]
if not isinstance(last, str): if not isinstance(last, str):
last = str(_(last)) last = str(_(last))
if add_quote: if add_quote and not last.startswith('"'):
last = '"{}"'.format(last) last = '"{}"'.format(last)
return ', '.join(lst_) + _(' {} ').format(separator) + '{}'.format(last) return ', '.join(lst_) + _(' {} ').format(separator) + '{}'.format(last)
@ -91,7 +91,6 @@ class PropertiesOptionError(AttributeError):
return 'error' return 'error'
req = self._settings.apply_requires(self._option_bag, req = self._settings.apply_requires(self._option_bag,
True) True)
#if req != {} or self._orig_opt is not None:
if req != {}: if req != {}:
only_one = len(req) == 1 only_one = len(req) == 1
msg = [] msg = []
@ -99,8 +98,16 @@ class PropertiesOptionError(AttributeError):
msg.append('"{0}" ({1})'.format(action, display_list(msg_, add_quote=False))) msg.append('"{0}" ({1})'.format(action, display_list(msg_, add_quote=False)))
msg = display_list(msg, add_quote=False) msg = display_list(msg, add_quote=False)
else: else:
only_one = len(self.proptype) == 1 properties = list(self._settings.calc_raises_properties(self._option_bag,
msg = display_list(list(self.proptype), add_quote=True) 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 proptype == ['mandatory']
properties = self.proptype
only_one = len(properties) == 1
msg = display_list(properties, add_quote=True)
if only_one: if only_one:
prop_msg = _('property') prop_msg = _('property')
else: else:

View File

@ -14,276 +14,305 @@
# 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 .setting import undefined
from .i18n import _ from .i18n import _
from .setting import undefined
from .error import display_list
class Params:
__slots__ = ('args', 'kwargs')
def __init__(self, args=None, kwargs=None, **kwgs):
if args is None:
args = tuple()
if kwargs is None:
kwargs = {}
if kwgs:
kwargs.update(kwgs)
if isinstance(args, Param):
args = (args,)
else:
if not isinstance(args, tuple):
raise ValueError(_('args in params must be a tuple'))
for arg in args:
if not isinstance(arg, Param):
raise ValueError(_('arg in params must be a Param'))
if not isinstance(kwargs, dict):
raise ValueError(_('kwargs in params must be a dict'))
for arg in kwargs.values():
if not isinstance(arg, Param):
raise ValueError(_('arg in params must be a Param'))
self.args = args
self.kwargs = kwargs
class Param:
pass
class ParamOption(Param):
__slots__ = ('option',
'notraisepropertyerror')
def __init__(self,
option: 'Option',
notraisepropertyerror: bool=False) -> None:
if __debug__ and not hasattr(option, 'impl_is_symlinkoption'):
raise ValueError(_('paramoption needs an option not {}').format(type(option)))
if option.impl_is_symlinkoption():
cur_opt = option.impl_getopt()
else:
cur_opt = option
if not isinstance(notraisepropertyerror, bool):
raise ValueError(_('param must have a boolean'
' not a {} for notraisepropertyerror'
).format(type(notraisepropertyerror)))
self.option = cur_opt
self.notraisepropertyerror = notraisepropertyerror
class ParamValue(Param):
__slots__ = ('value',)
def __init__(self, value):
self.value = value
class ParamContext(Param):
__slots__ = tuple()
class ParamIndex(Param):
__slots__ = tuple()
def tiramisu_copy(val): # pragma: no cover def tiramisu_copy(val): # pragma: no cover
return val return val
def calc_value(*args: List[Any], class CalcValue:
multi: bool=False, def __call__(self,
default: Any=undefined, *args: List[Any],
condition: Any=undefined, multi: bool=False,
expected: Any=undefined, default: Any=undefined,
condition_operator: str='AND', condition: Any=undefined,
allow_none: bool=False, no_condition_is_invalid: Any=False,
remove_duplicate_value: bool=False, expected: Any=undefined,
join: Optional[str]=None, condition_operator: str='AND',
min_args_len: Optional[int]=None, inverse_condition: bool=False,
operator: Optional[str]=None, allow_none: bool=False,
index: Optional[int]=None, remove_duplicate_value: bool=False,
**kwargs) -> Any: join: Optional[str]=None,
"""calculate value min_args_len: Optional[int]=None,
:param multi: value returns must be a list of value operator: Optional[str]=None,
:param default: default value if condition is not matched or if args is empty index: Optional[int]=None,
if there is more than one default value, set default_0, default_1, ... **kwargs) -> Any:
:param condition: test if condition is equal to expected value """calculate value
if there is more than one condition, set condition_0, condition_1, ... :param args: list of value
:param expected: value expected for all conditions :param multi: value returns must be a list of value
if expected value is different between condition, set expected_0, expected_1, ... :param default: default value if condition is not matched or if args is empty
:param condition_operator: OR or AND operator for condition if there is more than one default value, set default_0, default_1, ...
:param allow_none: if False, do not return list in None is present in list :param condition: test if condition is equal to expected value
:param remove_duplicate_value: if True, remote duplicated value if there is more than one condition, set condition_0, condition_1, ...
:param join: join all args with specified characters :param expected: value expected for all conditions
:param min_args_len: if number of arguments is smaller than this value, return default value if expected value is different between condition, set expected_0, expected_1, ...
:param operator: operator :param no_condition_is_invalid: if no condition and not condition_0, condition_1, ... (for
example if option is disabled) consider that condition not matching
:param condition_operator: OR or AND operator for condition
:param allow_none: if False, do not return list in None is present in list
:param remove_duplicate_value: if True, remote duplicated value
:param join: join all args with specified characters
:param min_args_len: if number of arguments is smaller than this value, return default value
:param operator: 'add', 'mul', 'div' or 'sub' all args (args must be integer value)
:param index: index for follower
examples: examples:
* you want to copy value from an option to an other option: * you want to copy value from an option to an other option:
>>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption >>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption
>>> val1 = StrOption('val1', '', 'val1') >>> val1 = StrOption('val1', '', 'val1')
>>> val2 = StrOption('val2', '', callback=calc_value, callback_params=Params(ParamOption(val1))) >>> val2 = StrOption('val2', '', callback=calc_value, callback_params=Params(ParamOption(val1)))
>>> od = OptionDescription('root', '', [val1, val2]) >>> od = OptionDescription('root', '', [val1, val2])
>>> cfg = Config(od) >>> cfg = Config(od)
>>> cfg.value.dict() >>> cfg.value.dict()
{'val1': 'val1', 'val2': 'val1'} {'val1': 'val1', 'val2': 'val1'}
* you want to copy values from two options in one multi option * you want to copy values from two options in one multi option
>>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue >>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue
>>> val1 = StrOption('val1', "", 'val1') >>> val1 = StrOption('val1', "", 'val1')
>>> val2 = StrOption('val2', "", 'val2') >>> val2 = StrOption('val2', "", 'val2')
>>> val3 = StrOption('val3', "", multi=True, callback=calc_value, callback_params=Params((ParamOption(val1), ParamOption(val2)), multi=ParamValue(True))) >>> val3 = StrOption('val3', "", multi=True, callback=calc_value, callback_params=Params((ParamOption(val1), ParamOption(val2)), multi=ParamValue(True)))
>>> od = OptionDescription('root', '', [val1, val2, val3]) >>> od = OptionDescription('root', '', [val1, val2, val3])
>>> cfg = Config(od) >>> cfg = Config(od)
>>> cfg.value.dict() >>> cfg.value.dict()
{'val1': 'val1', 'val2': 'val2', 'val3': ['val1', 'val2']} {'val1': 'val1', 'val2': 'val2', 'val3': ['val1', 'val2']}
* you want to copy a value from an option is it not disabled, otherwise set 'default_value' * you want to copy a value from an option if it not disabled, otherwise set 'default_value'
>>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue >>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue
>>> val1 = StrOption('val1', '', 'val1') >>> val1 = StrOption('val1', '', 'val1')
>>> val2 = StrOption('val2', '', callback=calc_value, callback_params=Params(ParamOption(val1, True), default=ParamValue('default_value'))) >>> val2 = StrOption('val2', '', callback=calc_value, callback_params=Params(ParamOption(val1, True), default=ParamValue('default_value')))
>>> od = OptionDescription('root', '', [val1, val2]) >>> od = OptionDescription('root', '', [val1, val2])
>>> cfg = Config(od) >>> cfg = Config(od)
>>> cfg.property.read_write() >>> cfg.property.read_write()
>>> cfg.value.dict() >>> cfg.value.dict()
{'val1': 'val1', 'val2': 'val1'} {'val1': 'val1', 'val2': 'val1'}
>>> cfg.option('val1').property.add('disabled') >>> cfg.option('val1').property.add('disabled')
>>> cfg.value.dict() >>> cfg.value.dict()
{'val2': 'default_value'} {'val2': 'default_value'}
* you want to copy value from an option is an other is True, otherwise set 'default_value' * you want to copy value from an option if an other is True, otherwise set 'default_value'
>>> from tiramisu import calc_value, BoolOption, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue >>> from tiramisu import calc_value, BoolOption, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue
>>> boolean = BoolOption('boolean', '', True) >>> boolean = BoolOption('boolean', '', True)
>>> val1 = StrOption('val1', '', 'val1') >>> val1 = StrOption('val1', '', 'val1')
>>> val2 = StrOption('val2', '', callback=calc_value, callback_params=Params(ParamOption(val1, True), >>> val2 = StrOption('val2', '', callback=calc_value, callback_params=Params(ParamOption(val1, True),
... default=ParamValue('default_value'), ... default=ParamValue('default_value'),
... condition=ParamOption(boolean), ... condition=ParamOption(boolean),
... expected=ParamValue(True))) ... expected=ParamValue(True)))
>>> od = OptionDescription('root', '', [boolean, val1, val2]) >>> od = OptionDescription('root', '', [boolean, val1, val2])
>>> cfg = Config(od) >>> cfg = Config(od)
>>> cfg.property.read_write() >>> cfg.property.read_write()
>>> cfg.value.dict() >>> cfg.value.dict()
{'boolean': True, 'val1': 'val1', 'val2': 'val1'} {'boolean': True, 'val1': 'val1', 'val2': 'val1'}
>>> cfg.option('boolean').value.set(False) >>> cfg.option('boolean').value.set(False)
>>> cfg.value.dict() >>> cfg.value.dict()
{'boolean': False, 'val1': 'val1', 'val2': 'default_value'} {'boolean': False, 'val1': 'val1', 'val2': 'default_value'}
* you want to copy option even if None is present * you want to copy option even if None is present
>>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue >>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue
>>> val1 = StrOption('val1', "", 'val1') >>> val1 = StrOption('val1', "", 'val1')
>>> val2 = StrOption('val2', "") >>> val2 = StrOption('val2', "")
>>> val3 = StrOption('val3', "", multi=True, callback=calc_value, callback_params=Params((ParamOption(val1), ParamOption(val2)), multi=ParamValue(True), allow_none=ParamValue(True))) >>> val3 = StrOption('val3', "", multi=True, callback=calc_value, callback_params=Params((ParamOption(val1), ParamOption(val2)), multi=ParamValue(True), allow_none=ParamValue(True)))
>>> od = OptionDescription('root', '', [val1, val2, val3]) >>> od = OptionDescription('root', '', [val1, val2, val3])
>>> cfg = Config(od) >>> cfg = Config(od)
>>> cfg.value.dict() >>> cfg.value.dict()
{'val1': 'val1', 'val2': None, 'val3': ['val1', None]} {'val1': 'val1', 'val2': None, 'val3': ['val1', None]}
* you want uniq value * you want uniq value
>>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue >>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue
>>> val1 = StrOption('val1', "", 'val1') >>> val1 = StrOption('val1', "", 'val1')
>>> val2 = StrOption('val2', "", 'val1') >>> val2 = StrOption('val2', "", 'val1')
>>> val3 = StrOption('val3', "", multi=True, callback=calc_value, callback_params=Params((ParamOption(val1), ParamOption(val2)), multi=ParamValue(True), remove_duplicate_value=ParamValue(True))) >>> val3 = StrOption('val3', "", multi=True, callback=calc_value, callback_params=Params((ParamOption(val1), ParamOption(val2)), multi=ParamValue(True), remove_duplicate_value=ParamValue(True)))
>>> od = OptionDescription('root', '', [val1, val2, val3]) >>> od = OptionDescription('root', '', [val1, val2, val3])
>>> cfg = Config(od) >>> cfg = Config(od)
>>> cfg.value.dict() >>> cfg.value.dict()
{'val1': 'val1', 'val2': 'val1', 'val3': ['val1']} {'val1': 'val1', 'val2': 'val1', 'val3': ['val1']}
* you want to join two values with '.' * you want to join two values with '.'
>>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue >>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue
>>> val1 = StrOption('val1', "", 'val1') >>> val1 = StrOption('val1', "", 'val1')
>>> val2 = StrOption('val2', "", 'val2') >>> val2 = StrOption('val2', "", 'val2')
>>> val3 = StrOption('val3', "", callback=calc_value, callback_params=Params((ParamOption(val1), ParamOption(val2)), join=ParamValue('.'))) >>> val3 = StrOption('val3', "", callback=calc_value, callback_params=Params((ParamOption(val1), ParamOption(val2)), join=ParamValue('.')))
>>> od = OptionDescription('root', '', [val1, val2, val3]) >>> od = OptionDescription('root', '', [val1, val2, val3])
>>> cfg = Config(od) >>> cfg = Config(od)
>>> cfg.value.dict() >>> cfg.value.dict()
{'val1': 'val1', 'val2': 'val2', 'val3': 'val1.val2'} {'val1': 'val1', 'val2': 'val2', 'val3': 'val1.val2'}
* you want join three values, only if almost three values are set * you want join three values, only if almost three values are set
>>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue >>> from tiramisu import calc_value, StrOption, OptionDescription, Config, Params, ParamOption, ParamValue
>>> val1 = StrOption('val1', "", 'val1') >>> val1 = StrOption('val1', "", 'val1')
>>> val2 = StrOption('val2', "", 'val2') >>> val2 = StrOption('val2', "", 'val2')
>>> val3 = StrOption('val3', "", 'val3') >>> val3 = StrOption('val3', "", 'val3')
>>> val4 = StrOption('val4', "", callback=calc_value, callback_params=Params((ParamOption(val1), ParamOption(val2), ParamOption(val3, True)), join=ParamValue('.'), min_args_len=ParamValue(3))) >>> val4 = StrOption('val4', "", callback=calc_value, callback_params=Params((ParamOption(val1), ParamOption(val2), ParamOption(val3, True)), join=ParamValue('.'), min_args_len=ParamValue(3)))
>>> od = OptionDescription('root', '', [val1, val2, val3, val4]) >>> od = OptionDescription('root', '', [val1, val2, val3, val4])
>>> cfg = Config(od) >>> cfg = Config(od)
>>> cfg.property.read_write() >>> cfg.property.read_write()
>>> cfg.value.dict() >>> cfg.value.dict()
{'val1': 'val1', 'val2': 'val2', 'val3': 'val3', 'val4': 'val1.val2.val3'} {'val1': 'val1', 'val2': 'val2', 'val3': 'val3', 'val4': 'val1.val2.val3'}
>>> cfg.option('val3').property.add('disabled') >>> cfg.option('val3').property.add('disabled')
>>> cfg.value.dict() >>> cfg.value.dict()
{'val1': 'val1', 'val2': 'val2', 'val4': ''} {'val1': 'val1', 'val2': 'val2', 'val4': ''}
* you want to add all values * you want to add all values
>>> from tiramisu import calc_value, IntOption, OptionDescription, Config, Params, ParamOption, ParamValue >>> from tiramisu import calc_value, IntOption, OptionDescription, Config, Params, ParamOption, ParamValue
>>> val1 = IntOption('val1', "", 1) >>> val1 = IntOption('val1', "", 1)
>>> val2 = IntOption('val2', "", 2) >>> val2 = IntOption('val2', "", 2)
>>> val3 = IntOption('val3', "", callback=calc_value, callback_params=Params((ParamOption(val1), ParamOption(val2)), operator=ParamValue('add'))) >>> val3 = IntOption('val3', "", callback=calc_value, callback_params=Params((ParamOption(val1), ParamOption(val2)), operator=ParamValue('add')))
>>> od = OptionDescription('root', '', [val1, val2, val3]) >>> od = OptionDescription('root', '', [val1, val2, val3])
>>> cfg = Config(od) >>> cfg = Config(od)
>>> cfg.value.dict() >>> cfg.value.dict()
{'val1': 1, 'val2': 2, 'val3': 3} {'val1': 1, 'val2': 2, 'val3': 3}
""" """
def value_from_kwargs(value: Any, pattern: str, to_dict: bool=False) -> Any: self.args = args
self.condition = condition
self.expected = expected
self.condition_operator = condition_operator
self.inverse_condition = inverse_condition
self.kwargs = kwargs
self.no_condition_is_invalid = no_condition_is_invalid
value = self.get_value(default,
min_args_len)
if not multi:
if join is not None:
value = join.join(value)
elif value and operator:
new_value = value[0]
op = {'mul': mul,
'add': add,
'div': truediv,
'sub': sub}[operator]
for val in value[1:]:
new_value = op(new_value, val)
value = new_value
elif value == []:
value = None
else:
value = value[0]
if isinstance(value, list) and index is not None:
if len(value) > index:
value = value[index]
else:
value = None
elif None in value and not allow_none:
value = []
elif remove_duplicate_value:
new_value = []
for val in value:
if val not in new_value:
new_value.append(val)
value = new_value
return value
def value_from_kwargs(self,
value: Any,
pattern: str,
to_dict: bool=False,
empty_test=undefined) -> Any:
# if value attribute exist return it's value # if value attribute exist return it's value
# otherwise pattern_0, pattern_1, ... # otherwise pattern_0, pattern_1, ...
# otherwise undefined # otherwise undefined
if value is not undefined: if value is not empty_test:
if to_dict == 'all': if to_dict == 'all':
returns = {0: value} returns = {None: value}
else: else:
returns = value returns = value
else: else:
kwargs_matches = {} kwargs_matches = {}
len_pattern = len(pattern) len_pattern = len(pattern)
for key in kwargs.keys(): for key in self.kwargs.keys():
if key.startswith(pattern): if key.startswith(pattern):
index = int(key[len_pattern:]) index = int(key[len_pattern:])
kwargs_matches[index] = kwargs[key] pattern_value = self.kwargs[key]
if isinstance(pattern_value, dict):
pattern_value = pattern_value['value']
kwargs_matches[index] = pattern_value
if not kwargs_matches: if not kwargs_matches:
return undefined returns = undefined
keys = sorted(kwargs_matches)
if to_dict:
returns = {}
else: else:
returns = [] keys = sorted(kwargs_matches)
for key in keys:
if to_dict: if to_dict:
returns[key] = kwargs_matches[key] returns = {}
else: else:
returns.append(kwargs_matches[key]) returns = []
for key in keys:
if to_dict:
returns[key] = kwargs_matches[key]
else:
returns.append(kwargs_matches[key])
return returns return returns
def is_condition_matches(): def is_condition_matches(self,
calculated_conditions = value_from_kwargs(condition, 'condition_', to_dict='all') condition_value):
if condition is not undefined: calculated_conditions = self.value_from_kwargs(condition_value,
'condition_',
to_dict='all')
if calculated_conditions is undefined:
is_matches = not self.no_condition_is_invalid
else:
is_matches = None is_matches = None
calculated_expected = value_from_kwargs(expected, 'expected_', to_dict=True) calculated_expected = self.value_from_kwargs(self.expected,
'expected_',
to_dict=True)
calculated_inverse = self.value_from_kwargs(self.inverse_condition,
'inverse_condition_',
to_dict=True,
empty_test=False)
for idx, calculated_condition in calculated_conditions.items(): for idx, calculated_condition in calculated_conditions.items():
if isinstance(calculated_expected, dict): if isinstance(calculated_expected, dict):
current_matches = calculated_condition == calculated_expected[idx] if idx is not None:
current_matches = calculated_condition == calculated_expected[idx]
else:
current_matches = calculated_condition in calculated_expected.values()
else: else:
current_matches = calculated_condition == calculated_expected current_matches = calculated_condition == calculated_expected
if isinstance(calculated_inverse, dict) and idx in calculated_inverse:
inverse_condition = calculated_inverse[idx]
else:
inverse_condition = False
if is_matches is None: if is_matches is None:
is_matches = current_matches is_matches = current_matches
elif condition_operator == 'AND': if self.condition_operator == 'AND':
is_matches = is_matches and current_matches is_matches = is_matches and current_matches
elif condition_operator == 'OR': if inverse_condition:
is_matches = not is_matches
if not is_matches:
break
elif self.condition_operator == 'OR':
is_matches = is_matches or current_matches is_matches = is_matches or current_matches
if inverse_condition:
is_matches = not is_matches
if is_matches:
break
else: else:
raise ValueError(_('unexpected {} condition_operator in calc_value').format(condition_operator)) raise ValueError(_('unexpected {} condition_operator in calc_value').format(self.condition_operator))
else: is_matches = is_matches and not self.inverse_condition \
is_matches = True or not is_matches and self.inverse_condition
return is_matches return is_matches
def get_value(): def get_value(self,
if not is_condition_matches(): default,
min_args_len):
if isinstance(self.condition, dict):
if 'value' in self.condition:
condition_value = self.condition['value']
else:
condition_value = undefined
else:
condition_value = self.condition
condition_matches = self.is_condition_matches(condition_value)
if not condition_matches:
# force to default # force to default
value = [] value = []
else: else:
value = list(args) value = self.get_args()
if min_args_len and not len(value) >= min_args_len: if min_args_len and not len(value) >= min_args_len:
value = [] value = []
if value == []: if value == []:
# default value # default value
new_default = value_from_kwargs(default, 'default_') new_default = self.value_from_kwargs(default,
'default_')
if new_default is not undefined: if new_default is not undefined:
if not isinstance(new_default, list): if not isinstance(new_default, list):
value = [new_default] value = [new_default]
@ -291,34 +320,72 @@ def calc_value(*args: List[Any],
value = new_default value = new_default
return value return value
value = get_value() def get_args(self):
if not multi: return list(self.args)
if join is not None:
value = join.join(value)
elif value and operator: class CalcValuePropertyHelp(CalcValue):
new_value = value[0] def get_name(self):
op = {'mul': mul, return self.condition['name']
'add': add,
'div': truediv, def get_indexed_name(self, index):
'sub': sub}[operator] return self.kwargs.get(f'condition_{index}')['name']
for val in value[1:]:
new_value = op(new_value, val) def has_condition_kwargs(self):
value = new_value for condition in self.kwargs:
elif value == []: if condition.startswith('condition_'):
value = None return True
return False
def build_arg(self, name, value):
#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:
if not self.inverse_condition:
msg = _('the value of "{0}" is {1}').format(name, value)
else: else:
value = value[0] msg = _('the value of "{0}" is not {1}').format(name, value)
if isinstance(value, list) and index is not None: return msg
if len(value) > index:
value = value[index] def get_args(self):
args = super().get_args()
if args:
if len(self.args) != 1:
raise ValueError(_('only one property is allowed for a calculation'))
action = args[0]
calculated_expected = self.value_from_kwargs(self.expected,
'expected_',
to_dict=True)
if self.condition is not undefined:
if 'propertyerror' in self.condition:
msg = self.condition['propertyerror']
else: else:
value = None name = self.get_name()
elif None in value and not allow_none: if isinstance(calculated_expected, dict):
value = [] calc_values = calculated_expected.values()
elif remove_duplicate_value: else:
new_value = [] calc_values = [calculated_expected]
for val in value: display_value = display_list([str(val) for val in calc_values],
if val not in new_value: 'or',
new_value.append(val) add_quote=True)
value = new_value msg = self.build_arg(name, display_value)
return value elif self.has_condition_kwargs():
msgs = []
for key, value in calculated_expected.items():
name = self.get_indexed_name(key)
msgs.append(self.build_arg(name, f'"{value}"'))
msg = display_list(msgs, self.condition_operator.lower())
else:
return [f'"{action}"']
return [f'"{action}" ({msg})']
return
## calc_properties.setdefault(action, []).append(msg)
calc_value = CalcValue()
calc_value.__name__ = 'calc_value'
calc_value_property_help = CalcValuePropertyHelp()
calc_value_property_help.__name__ = 'calc_value_property_help'

View File

@ -29,7 +29,7 @@ from ..i18n import _
from ..setting import undefined, Settings from ..setting import undefined, Settings
from ..value import Values from ..value import Values
from ..error import ConfigError, display_list from ..error import ConfigError, display_list
from ..function import Params, ParamContext, ParamOption, ParamIndex from ..autolib import Calculation, Params, ParamContext, ParamOption, ParamIndex
STATIC_TUPLE = frozenset() STATIC_TUPLE = frozenset()
@ -83,16 +83,15 @@ class Base:
requires = undefined requires = undefined
if properties is None: if properties is None:
properties = frozenset() properties = frozenset()
if isinstance(properties, tuple): elif isinstance(properties, tuple):
properties = frozenset(properties) properties = frozenset(properties)
if is_multi and 'empty' not in properties: if is_multi and 'empty' not in properties:
# if option is a multi, it cannot be "empty" (None not allowed in the list) # if option is a multi, it cannot be "empty" (None not allowed in the list)
# "empty" is removed for follower's option # "empty" is removed for follower's option
properties = properties | {'empty'} properties = properties | {'empty'}
if not isinstance(properties, frozenset): assert isinstance(properties, frozenset), _('invalid properties type {0} for {1},'
raise TypeError(_('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, self.validate_properties(name,
calc_properties, calc_properties,
properties) properties)
@ -115,6 +114,17 @@ class Base:
raise ValueError(_('conflict: properties already set in requirement {0} for {1}' raise ValueError(_('conflict: properties already set in requirement {0} for {1}'
'').format(display_list(set_forbidden_properties, add_quote=True), '').format(display_list(set_forbidden_properties, add_quote=True),
name)) name))
assert isinstance(properties, frozenset), _('invalid properties type {0} for {1},'
' must be a frozenset').format(type(properties),
name)
for prop in properties:
if not isinstance(prop, str):
if not isinstance(prop, Calculation):
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(params.args, params.kwargs.values()):
if isinstance(param, ParamOption):
param.option._add_dependency(self)
def _get_function_args(self, def _get_function_args(self,
function: Callable) -> Tuple[Set[str], Set[str], bool, bool]: function: Callable) -> Tuple[Set[str], Set[str], bool, bool]:
@ -159,7 +169,7 @@ class Base:
""" """
:add_value: add value as first argument for validator :add_value: add value as first argument for validator
""" """
assert isinstance(calculator, FunctionType), _('{0} must be a function').format(type_) assert isinstance(calculator, Callable), _('{0} must be a function').format(type_)
if calculator_params is not None: if calculator_params is not None:
assert isinstance(calculator_params, Params), _('{0}_params must be a params' assert isinstance(calculator_params, Params), _('{0}_params must be a params'
'').format(type_) '').format(type_)

View File

@ -32,7 +32,7 @@ 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 RequirementError
from ..function import ParamOption from ..autolib import ParamOption
class Leadership(OptionDescription): class Leadership(OptionDescription):
@ -97,11 +97,8 @@ class Leadership(OptionDescription):
raise RequirementError(_('leader {} have requirement, but Leadership {} too' raise RequirementError(_('leader {} have requirement, but Leadership {} too'
'').format(leader.impl_getname(), '').format(leader.impl_getname(),
self.impl_getname())) self.impl_getname()))
leader_calproperties = getattr(leader, '_calc_properties', None) leader_calproperties = getattr(leader, '_requires', None)
if leader_calproperties: if leader_calproperties:
if __debug__ and properties is not None:
self.validate_properties(name, leader_calproperties, frozenset(properties))
setattr(self, '_calc_properties', leader_calproperties)
setattr(self, '_requires', leader_requires) setattr(self, '_requires', leader_requires)
delattr(leader, '_requires') delattr(leader, '_requires')
if __debug__: if __debug__:

View File

@ -26,10 +26,9 @@ from typing import Any, List, Callable, Optional, Dict, Union, Tuple
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 carry_out_calculation from ..autolib import carry_out_calculation, Params, ParamValue
from ..error import (ConfigError, ValueWarning, ValueErrorWarning, PropertiesOptionError, from ..error import (ConfigError, ValueWarning, ValueErrorWarning, PropertiesOptionError,
ValueOptionError, display_list) ValueOptionError, display_list)
from ..function import Params, ParamValue
from .syndynoption import SynDynOption from .syndynoption import SynDynOption
ALLOWED_CONST_LIST = ['_cons_not_equal'] ALLOWED_CONST_LIST = ['_cons_not_equal']

View File

@ -38,6 +38,9 @@ class SynDynOptionDescription:
subpath: str, subpath: str,
suffix: str) -> None: suffix: str) -> None:
self._opt = opt self._opt = opt
if subpath is None:
subpath = ''
assert isinstance(subpath, str), 'subpath must be a string, not {}'.format(type(subpath))
self._subpath = subpath self._subpath = subpath
self._suffix = suffix self._suffix = suffix

View File

@ -415,13 +415,13 @@ class Settings(object):
search_properties=None): search_properties=None):
""" """
""" """
opt = option_bag.option # FIXME search_properties
option = option_bag.option
config_bag = option_bag.config_bag config_bag = option_bag.config_bag
path = option_bag.path if option.impl_is_symlinkoption():
option = option.impl_getopt()
path = option.impl_getpath()
index = option_bag.index index = option_bag.index
if opt.impl_is_symlinkoption():
opt = opt.impl_getopt()
path = opt.impl_getpath()
if apply_requires: if apply_requires:
cache = config_bag.context._impl_properties_cache cache = config_bag.context._impl_properties_cache
@ -435,13 +435,28 @@ class Settings(object):
else: else:
is_cached = False is_cached = False
if not is_cached: if not is_cached:
props = self._p_.getproperties(path, props = set()
opt.impl_getproperties()) for prop in self._p_.getproperties(path,
option.impl_getproperties()):
if isinstance(prop, str):
props.add(prop)
elif apply_requires:
new_props = prop.execute(option_bag,
leadership_must_have_index=True)
if not new_props:
continue
elif not isinstance(new_props, str):
raise ValueError(_('invalid property type {} for {} with {} function').format(type(new_props),
option_bag.option.impl_getname(),
prop.function.__name__))
props.add(new_props)
# else:
# props.update(new_props)
if apply_requires: if apply_requires:
props |= self.apply_requires(option_bag, props |= self.apply_requires(option_bag,
False, False,
search_properties=search_properties) search_properties=search_properties)
props -= self.getpermissives(opt, props -= self.getpermissives(option,
path) path)
#if apply_requires and config_bag.properties == config_bag.true_properties: #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:
@ -453,6 +468,29 @@ class Settings(object):
True) True)
return props return props
def get_calculated_properties(self,
option_bag):
opt = option_bag.option
if opt.impl_is_symlinkoption():
opt = opt.impl_getopt()
path = opt.impl_getpath()
for prop in self._p_.getproperties(path,
opt.impl_getproperties()):
if not isinstance(prop, str):
yield prop
def has_properties_index(self,
option_bag):
opt = option_bag.option
if opt.impl_is_symlinkoption():
opt = opt.impl_getopt()
path = opt.impl_getpath()
for prop in self._p_.getproperties(path,
opt.impl_getproperties()):
if not isinstance(prop, str) and prop.has_index:
return True
return False
def get_context_permissives(self): def get_context_permissives(self):
return self.getpermissives(None, None) return self.getpermissives(None, None)
@ -670,7 +708,6 @@ class Settings(object):
"""save properties for specified path """save properties for specified path
(never save properties if same has option properties) (never save properties if same has option properties)
""" """
# should have index !!!
opt = option_bag.option opt = option_bag.option
if opt.impl_getrequires() is not None: if opt.impl_getrequires() is not None:
not_allowed_props = properties & \ not_allowed_props = properties & \

View File

@ -31,7 +31,7 @@ from os.path import split
from typing import Dict from typing import Dict
from ..error import ConfigError from ..error import ConfigError
from ..i18n import _ from ..i18n import _
from .util import Cache from .cacheobj import Cache
DEFAULT_STORAGE = MEMORY_STORAGE = 'dictionary' DEFAULT_STORAGE = MEMORY_STORAGE = 'dictionary'

View File

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
"utils used by storage" "cache used by storage"
# Copyright (C) 2013-2019 Team tiramisu (see AUTHORS for all contributors) # Copyright (C) 2013-2019 Team tiramisu (see AUTHORS for all contributors)
# #
# This program is free software: you can redistribute it and/or modify it # This program is free software: you can redistribute it and/or modify it

View File

@ -15,10 +15,11 @@
# 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/>.
# ____________________________________________________________ # ____________________________________________________________
import sqlite3
import warnings
from ...i18n import _ from ...i18n import _
from os.path import join from os.path import join
import sqlite3
from ...error import ConflictError from ...error import ConflictError
@ -55,9 +56,16 @@ def _gen_filename():
def list_sessions(): def list_sessions():
cursor = CONN.cursor() if not CONN:
names = [row[0] for row in cursor.execute("SELECT session FROM session").fetchall()] warnings.warn_explicit(Warning(_('Cannot list sessions, please connect to database first')),
return names category=Warning,
filename=__file__,
lineno=63)
return []
else:
cursor = CONN.cursor()
names = [row[0] for row in cursor.execute("SELECT session FROM session").fetchall()]
return names
def delete_session(session_id, def delete_session(session_id,

View File

@ -19,8 +19,7 @@ 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, RequirementError
from .setting import owners, undefined, forbidden_owners, OptionBag, ConfigBag from .setting import owners, undefined, forbidden_owners, OptionBag, ConfigBag
from .autolib import carry_out_calculation from .autolib import carry_out_calculation, Params
from .function import Params
from .i18n import _ from .i18n import _