This commit is contained in:
egarette@silique.fr 2024-06-20 12:56:27 +02:00
parent 8e743131cd
commit 897d4dd216
36 changed files with 4299 additions and 5314 deletions

File diff suppressed because it is too large Load diff

View file

@ -81,10 +81,10 @@ def test_cache_importation_property():
def test_cache_importation_permissive():
od1 = make_description()
cfg = Config(od1)
cfg.option('u2').permissive.set(frozenset(['prop']))
cfg.option('u2').permissive.add('prop')
export = cfg.permissive.exportation()
assert cfg.option('u2').permissive.get() == {'prop'}
cfg.option('u2').permissive.set(frozenset(['prop', 'prop2']))
cfg.option('u2').permissive.add('prop2')
assert cfg.option('u2').permissive.get() == {'prop', 'prop2'}
cfg.permissive.importation(export)
assert cfg.option('u2').permissive.get() == {'prop'}
@ -266,7 +266,7 @@ def test_cache_leadership():
#assert cache['ip_admin_eth0.netmask_admin_eth0'][None][0] == [None]
#assert cache['ip_admin_eth0.netmask_admin_eth0'][0][0] is None
cache = settings.get_cached()
assert set(cache.keys()) == set([None, 'ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert set(cache.keys()) == set(['ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert set(cache['ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == {0}
@ -284,7 +284,7 @@ def test_cache_leadership():
#assert cache['ip_admin_eth0.netmask_admin_eth0'][0][0] is None
#assert cache['ip_admin_eth0.netmask_admin_eth0'][1][0] is None
cache = settings.get_cached()
assert set(cache.keys()) == set([None, 'ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert set(cache.keys()) == set(['ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
assert set(cache['ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([0, 1])
@ -376,26 +376,22 @@ def test_cache_leader_and_followers():
idx_val2 = None
values = cfg._config_bag.context._impl_values_cache
settings = cfg._config_bag.context.properties_cache
compare(settings.get_cached(), {None: {None: (global_props, None)},
'val1': {None: (val1_props, None)},
'val1.val1': {None: (val1_val1_props, None)},
})
compare(settings.get_cached(), {'val1': {None: (val1_props, None)},
'val1.val1': {None: (val1_val1_props, None)},
})
# len is 0 so don't get any value
compare(values.get_cached(), {'val1.val1': {None: ([], None)}})
#
cfg.option('val1.val1').value.set([None])
val_val2_props = {idx_val2: (val1_val2_props, None), None: (set(), None)}
compare(settings.get_cached(), {None: {None: (set(global_props), None)},
# 'val1.val1': {None: (val1_val1_props, None)},
})
compare(settings.get_cached(), {'val1.val1': {None: ({'empty', 'unique'}, None, True)}})
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
cfg.value.get()
#has value
idx_val2 = 0
val_val2 = None
val_val2_props = {idx_val2: (val1_val2_props, None)}
compare(settings.get_cached(), {None: {None: (global_props, None)},
'val1': {None: (val1_props, None)},
compare(settings.get_cached(), {'val1': {None: (val1_props, None)},
'val1.val1': {None: (val1_val1_props, None)},
'val1.val2': val_val2_props})
compare(values.get_cached(), {'val1.val1': {None: ([None], None)},
@ -404,7 +400,7 @@ def test_cache_leader_and_followers():
cfg.option('val1.val1').value.set([None, None])
cfg.value.get()
cfg.option('val1.val2', 1).value.set('oui')
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)}})
compare(settings.get_cached(), {})
compare(values.get_cached(), {'val1.val2': {1: ('oui', None, True)}})
val1_val2_props = {0: (frozenset([]), None), 1: (frozenset([]), None)}
# assert not list_sessions()
@ -428,15 +424,12 @@ def test_cache_leader_callback():
val1_val2_props = frozenset(val1_val2_props)
values = cfg._config_bag.context._impl_values_cache
settings = cfg._config_bag.context.properties_cache
compare(settings.get_cached(), {None: {None: (global_props, None)},
'val1': {None: (val1_props, None)},
compare(settings.get_cached(), {'val1': {None: (val1_props, None)},
'val1.val1': {None: (val1_val1_props, None)},
})
compare(values.get_cached(), {'val1.val1': {None: ([], None)}})
cfg.option('val1.val1').value.set([None])
compare(settings.get_cached(), {None: {None: (set(global_props), None)},
# 'val1.val1': {None: (val1_val1_props, None)},
})
compare(settings.get_cached(), {'val1.val1': {None: ({'unique', 'empty'}, None, True)}})
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
cfg.value.get()
@ -458,39 +451,34 @@ def test_cache_requires():
settings = cfg._config_bag.context.properties_cache
assert values.get_cached() == {}
assert cfg.option('ip_address_service').value.get() == None
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}})
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}})
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
'activate_service': {None: (True, None)}})
cfg.value.get()
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}})
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}})
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
'activate_service': {None: (True, None)}})
'activate_service': {None: (True, None)}})
cfg.option('ip_address_service').value.set('1.1.1.1')
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
'activate_service': {None: (set([]), None)}})
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)}})
compare(values.get_cached(), {'activate_service': {None: (True, None)}, 'ip_address_service': {None: ('1.1.1.1', None, True)}})
cfg.value.get()
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}})
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}})
compare(values.get_cached(), {'ip_address_service': {None: ('1.1.1.1', None)},
'activate_service': {None: (True, None)}})
cfg.option('activate_service').value.set(False)
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)}})
compare(settings.get_cached(), {})
compare(values.get_cached(), {'activate_service': {None: (False, None)}})
cfg.value.get()
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set(['disabled']), None)}})
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set(['disabled']), None)}})
compare(values.get_cached(), {'activate_service': {None: (False, None)}})
# assert not list_sessions()
@ -511,22 +499,19 @@ def test_cache_global_properties():
settings = cfg._config_bag.context.properties_cache
assert values.get_cached() == {}
assert cfg.option('ip_address_service').value.get() == None
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}})
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}})
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
'activate_service': {None: (True, None)}})
cfg.property.remove('disabled')
assert cfg.option('ip_address_service').value.get() == None
compare(settings.get_cached(), {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}})
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}})
cfg.property.add('test')
assert cfg.option('ip_address_service').value.get() == None
compare(settings.get_cached(), {None: {None: (set(['cache', 'frozen', 'hidden', 'validator', 'warnings', 'test', 'force_store_value']), None)},
'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}})
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
'ip_address_service': {None: (set([]), None)}})
# assert not list_sessions()

View file

@ -1,10 +1,9 @@
# coding: utf-8
from py.test import raises
from .autopath import do_autopath
do_autopath()
from .config import config_type, get_config, value_list, global_owner
from .config import config_type, get_config, value_list, global_owner, parse_od_get
from pytest import raises
from tiramisu import ChoiceOption, StrOption, OptionDescription, Config, owners, Calculation, \
undefined, Params, ParamValue, ParamOption
from tiramisu.error import ConfigError
@ -76,6 +75,29 @@ def test_choiceoption_function(config_type):
# assert not list_sessions()
def test_choiceoption_subfunction(config_type):
choice = ChoiceOption('choice', '', values=(Calculation(return_val, Params(ParamValue('val1'))), Calculation(return_val, Params(ParamValue('val2')))))
od1 = OptionDescription('od', '', [choice])
cfg = Config(od1)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
owner = global_owner(cfg, config_type)
assert cfg.option('choice').owner.isdefault()
#
cfg.option('choice').value.set('val1')
assert cfg.option('choice').owner.get() == owner
#
cfg.option('choice').value.reset()
assert cfg.option('choice').owner.isdefault()
#
with raises(ValueError):
cfg.option('choice').value.set('no')
assert cfg.option('choice').owner.isdefault()
#
assert value_list(cfg.option('choice').value.list()) == ('val1', 'val2')
# assert not list_sessions()
def test_choiceoption_function_error():
choice = ChoiceOption('choice', '', values=Calculation(return_error))
od1 = OptionDescription('od', '', [choice])
@ -262,3 +284,13 @@ def test_choiceoption_calc_not_list():
with raises(ConfigError):
cfg.option('choice').value.set(['val1'])
# assert not list_sessions()
def test_choiceoption_calc_default_value():
var1 = StrOption("var1", '', default="val1")
var2 = StrOption("var2", '', default="val2")
choice = ChoiceOption("choice", '', values=(Calculation(return_val, Params((ParamOption(var1)))), Calculation(return_val, Params((ParamOption(var2))))), default="val1")
od2 = OptionDescription("rougail", '', children=[var1, var2, choice])
od1 = OptionDescription("baseoption", "", children=[od2])
cfg = Config(od1)
assert parse_od_get(cfg.value.get()) == {'rougail.var1': 'val1', 'rougail.var2': 'val2', 'rougail.choice': 'val1'}

View file

@ -26,8 +26,7 @@ def make_description():
floatoption = FloatOption('float', 'Test float option', default=2.3)
stroption = StrOption('str', 'Test string option', default="abc", properties=('mandatory', ))
boolop = BoolOption('boolop', 'Test boolean option op', default=True, properties=('hidden',))
wantref_option = BoolOption('wantref', 'Test requires', default=False)
wantref_option.impl_set_information('info', 'default value')
wantref_option = BoolOption('wantref', 'Test requires', default=False, informations={'info': 'default value'})
wantframework_option = BoolOption('wantframework', 'Test requires',
default=False)
@ -143,11 +142,11 @@ def test_information_config():
with pytest.raises(ValueError):
cfg.information.get('noinfo')
assert cfg.information.get('noinfo', 'default') == 'default'
cfg.information.reset('info')
cfg.information.remove('info')
with pytest.raises(ValueError):
cfg.information.get('info')
cfg.information.remove('info')
with pytest.raises(ValueError):
cfg.information.reset('noinfo')
cfg.information.remove('noinfo')
assert list(cfg.information.list()) == ['doc']
# assert not list_sessions()
@ -194,26 +193,23 @@ def test_information_option():
with pytest.raises(ValueError):
cfg.option('gc.name').information.get('noinfo')
assert cfg.option('gc.name').information.get('noinfo', 'default') == 'default'
cfg.option('gc.name').information.reset('info')
cfg.option('gc.name').information.remove('info')
with pytest.raises(ValueError):
cfg.option('gc.name').information.get('info')
with pytest.raises(ValueError):
cfg.option('gc.name').information.reset('noinfo')
cfg.option('gc.name').information.remove('noinfo')
assert list(cfg.option('gc.name').information.list()) == ['doc']
#
assert cfg.option('wantref').information.get('info') == 'default value'
cfg.option('wantref').information.set('info', 'default value')
assert cfg.option('wantref').information.get('info') == 'default value'
cfg.option('wantref').information.reset('info')
cfg.option('wantref').information.remove('info')
assert cfg.option('wantref').information.get('info') == 'default value'
# assert not list_sessions()
def test_information_option_2():
i1 = IntOption('test1', '')
i1.impl_set_information('info', 'value')
# it's a dict
assert set(i1.impl_list_information()) == {'info', 'doc'}
i1 = IntOption('test1', '', informations={'info': 'value'})
od1 = OptionDescription('test', '', [i1])
cfg = Config(od1)
# it's tuples
@ -234,11 +230,11 @@ def test_information_optiondescription():
with pytest.raises(ValueError):
cfg.option('gc').information.get('noinfo')
assert cfg.option('gc').information.get('noinfo', 'default') == 'default'
cfg.option('gc').information.reset('info')
cfg.option('gc').information.remove('info')
with pytest.raises(ValueError):
cfg.option('gc').information.get('info')
with pytest.raises(ValueError):
cfg.option('gc').information.reset('noinfo')
cfg.option('gc').information.remove('noinfo')
assert list(cfg.option('gc').information.list()) == ['doc']
# assert not list_sessions()

View file

@ -412,7 +412,6 @@ def test_help():
cfg = Config(od2)
cfg.help(_display=False)
cfg.config.help(_display=False)
cfg.option.help(_display=False)
cfg.option('o').help(_display=False)
cfg.option('o.s').help(_display=False)
# assert not list_sessions()
@ -430,7 +429,7 @@ def test_config_reset():
#
cfg.option('gc.gc2.bool').value.set(True)
cfg.option('boolop').property.add('test')
cfg.option('float').permissive.set(frozenset(['test']))
cfg.option('float').permissive.add('test')
cfg.option('wantref').information.set('info', 'info')
assert cfg.option('gc.gc2.bool').value.get()
assert cfg.option('boolop').property.get()

View file

@ -59,27 +59,27 @@ def test_copy_information():
ncfg = cfg.config.copy()
assert ncfg.information.get('key') == 'value'
# assert not list_sessions()
#
#
#def test_copy_force_store_value():
# od1 = make_description()
# conf = Config(od1)
# conf2 = Config(od1)
# assert conf.value.exportation() == {}
# assert conf2.value.exportation() == {}
# #
# conf.property.read_write()
# assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
# assert conf2.value.exportation() == {}
# #
# conf2.property.read_only()
# assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
# assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
# #
# conf.option('creole.general.wantref').value.set(True)
# assert conf.value.exportation() == {'creole.general.wantref': {None: [True, 'user']}}
# assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
## assert not list_sessions()
def test_copy_force_store_value():
od1 = make_description()
conf = Config(od1)
conf2 = Config(od1)
assert conf.value.exportation() == {}
assert conf2.value.exportation() == {}
#
conf.property.read_write()
assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
assert conf2.value.exportation() == {}
#
conf2.property.read_only()
assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
#
conf.option('creole.general.wantref').value.set(True)
assert conf.value.exportation() == {'creole.general.wantref': {None: [True, 'user']}}
assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
# assert not list_sessions()
#
#
#def test_copy_force_store_value_metaconfig():

File diff suppressed because it is too large Load diff

View file

@ -160,57 +160,57 @@ def test_freeze_multi():
# assert not list_sessions()
#def test_force_store_value():
# od1 = make_description_freeze()
# cfg = Config(od1)
# compare(cfg.value.exportation(), {})
# cfg.property.read_write()
# compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
# cfg.option('bool').value.set(False)
# cfg.option('wantref').value.set(True)
# cfg.option('bool').value.reset()
# compare(cfg.value.exportation(), {'wantref': {None: [True, 'user']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
# cfg.option('bool').value.set(False)
# cfg.option('wantref').value.reset()
# cfg.option('bool').value.reset()
# compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
## assert not list_sessions()
#
#
#def test_force_store_value_leadership_sub():
# b = IntOption('int', 'Test int option', multi=True, properties=('force_store_value',))
# c = StrOption('str', 'Test string option', multi=True)
# descr = Leadership("int", "", [b, c])
# od1 = OptionDescription('odr', '', [descr])
# cfg = Config(od1)
# cfg.property.read_only()
# compare(cfg.value.exportation(), {'int.int': {None: [[], 'forced']}})
## assert not list_sessions()
#
#
#def test_force_store_value_callback():
# b = IntOption('int', 'Test int option', Calculation(return_val), properties=('force_store_value',))
# od1 = OptionDescription("int", "", [b])
# cfg = Config(od1)
# cfg.property.read_only()
# compare(cfg.value.exportation(), {'int': {None: [1, 'forced']}})
## assert not list_sessions()
#
#
#def test_force_store_value_callback_params():
# b = IntOption('int', 'Test int option', Calculation(return_val2, Params(kwargs={'value': ParamValue(2)})), properties=('force_store_value',))
# od1 = OptionDescription("int", "", [b])
# cfg = Config(od1)
# cfg.property.read_only()
# compare(cfg.value.exportation(), {'int': {None: [2, 'forced']}})
## assert not list_sessions()
#
#
#def test_force_store_value_callback_params_with_opt():
# a = IntOption('val1', "", 2)
# b = IntOption('int', 'Test int option', Calculation(return_val2, Params(kwargs={'value': ParamOption(a)})), properties=('force_store_value',))
# od1 = OptionDescription("int", "", [a, b])
# cfg = Config(od1)
# cfg.property.read_only()
# compare(cfg.value.exportation(), {'int': {None: [2, 'forced']}})
## assert not list_sessions()
def test_force_store_value():
od1 = make_description_freeze()
cfg = Config(od1)
compare(cfg.value.exportation(), {})
cfg.property.read_write()
compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
cfg.option('bool').value.set(False)
cfg.option('wantref').value.set(True)
cfg.option('bool').value.reset()
compare(cfg.value.exportation(), {'wantref': {None: [True, 'user']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
cfg.option('bool').value.set(False)
cfg.option('wantref').value.reset()
cfg.option('bool').value.reset()
compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
# assert not list_sessions()
def test_force_store_value_leadership_sub():
b = IntOption('int', 'Test int option', multi=True, properties=('force_store_value',))
c = StrOption('str', 'Test string option', multi=True)
descr = Leadership("int", "", [b, c])
od1 = OptionDescription('odr', '', [descr])
cfg = Config(od1)
cfg.property.read_only()
compare(cfg.value.exportation(), {'int.int': {None: [[], 'forced']}})
# assert not list_sessions()
def test_force_store_value_callback():
b = IntOption('int', 'Test int option', Calculation(return_val), properties=('force_store_value',))
od1 = OptionDescription("int", "", [b])
cfg = Config(od1)
cfg.property.read_only()
compare(cfg.value.exportation(), {'int': {None: [1, 'forced']}})
# assert not list_sessions()
def test_force_store_value_callback_params():
b = IntOption('int', 'Test int option', Calculation(return_val2, Params(kwargs={'value': ParamValue(2)})), properties=('force_store_value',))
od1 = OptionDescription("int", "", [b])
cfg = Config(od1)
cfg.property.read_only()
compare(cfg.value.exportation(), {'int': {None: [2, 'forced']}})
# assert not list_sessions()
def test_force_store_value_callback_params_with_opt():
a = IntOption('val1', "", 2)
b = IntOption('int', 'Test int option', Calculation(return_val2, Params(kwargs={'value': ParamOption(a)})), properties=('force_store_value',))
od1 = OptionDescription("int", "", [a, b])
cfg = Config(od1)
cfg.property.read_only()
compare(cfg.value.exportation(), {'int': {None: [2, 'forced']}})
# assert not list_sessions()

View file

@ -159,7 +159,7 @@ def test_iter_on_empty_group():
od1 = OptionDescription("name", "descr", [])
cfg = Config(od1)
cfg.property.read_write()
result = list(cfg.option.list())
result = list(cfg.list())
assert result == []
# assert not list_sessions()
@ -207,7 +207,7 @@ def test_leader_list(config_type):
od1 = OptionDescription('od', '', [interface1])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
ret = cfg.option.list()
ret = cfg.list()
assert len(ret) == 1
assert ret[0].name() == 'leadership'
#
@ -983,65 +983,65 @@ def test_follower_not_multi():
# assert not list_sessions()
#def test_follower_force_store_value_none():
# ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
# netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('force_store_value',))
# interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
# od1 = OptionDescription('od', '', [interface0])
# od2 = OptionDescription('toto', '', [od1])
# cfg = Config(od2)
# cfg.property.read_write()
# assert cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
## assert not list_sessions()
#
#
#def test_follower_force_store_value():
# ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
# netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
# interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
# od1 = OptionDescription('od', '', [interface0])
# od2 = OptionDescription('toto', '', [od1])
# cfg = Config(od2)
# cfg.property.read_write()
# assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
## assert not list_sessions()
#
#
#def test_follower_force_store_value_read_only():
# ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
# netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
# interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
# od1 = OptionDescription('od', '', [interface0])
# od2 = OptionDescription('toto', '', [od1])
# cfg = Config(od2)
# cfg.property.read_only()
# assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
## assert not list_sessions()
#
#
#def test_follower_force_store_value_reset():
# ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
# netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
# interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
# od1 = OptionDescription('od', '', [interface0])
# od2 = OptionDescription('toto', '', [od1])
# cfg = Config(od2)
# cfg.property.read_write()
# cfg.option('od.interface0.ip_admin_eth0').value.set(['1.1.1.1', '192.168.0.0'])
# assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
# assert not cfg.option('od.interface0.netmask_admin_eth0', 1).owner.isdefault()
# #
# cfg.option('od.interface0.netmask_admin_eth0', 1).value.reset()
# assert not cfg.option('od.interface0.netmask_admin_eth0', 1).owner.isdefault()
# #
# cfg.option('od.interface0.ip_admin_eth0').value.pop(0)
# cfg.option('od.interface0.ip_admin_eth0').value.pop(0)
# assert cfg.option('od.interface0.ip_admin_eth0').value.get() == []
# cfg.option('od.interface0.ip_admin_eth0').value.reset()
# assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
## assert not list_sessions()
#
#
def test_follower_force_store_value_none():
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('force_store_value',))
interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
od1 = OptionDescription('od', '', [interface0])
od2 = OptionDescription('toto', '', [od1])
cfg = Config(od2)
cfg.property.read_write()
assert cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
# assert not list_sessions()
def test_follower_force_store_value():
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
od1 = OptionDescription('od', '', [interface0])
od2 = OptionDescription('toto', '', [od1])
cfg = Config(od2)
cfg.property.read_write()
assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
# assert not list_sessions()
def test_follower_force_store_value_read_only():
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
od1 = OptionDescription('od', '', [interface0])
od2 = OptionDescription('toto', '', [od1])
cfg = Config(od2)
cfg.property.read_only()
assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
# assert not list_sessions()
def test_follower_force_store_value_reset():
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
od1 = OptionDescription('od', '', [interface0])
od2 = OptionDescription('toto', '', [od1])
cfg = Config(od2)
cfg.property.read_write()
cfg.option('od.interface0.ip_admin_eth0').value.set(['1.1.1.1', '192.168.0.0'])
assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
assert not cfg.option('od.interface0.netmask_admin_eth0', 1).owner.isdefault()
#
cfg.option('od.interface0.netmask_admin_eth0', 1).value.reset()
assert not cfg.option('od.interface0.netmask_admin_eth0', 1).owner.isdefault()
#
cfg.option('od.interface0.ip_admin_eth0').value.pop(0)
cfg.option('od.interface0.ip_admin_eth0').value.pop(0)
assert cfg.option('od.interface0.ip_admin_eth0').value.get() == []
cfg.option('od.interface0.ip_admin_eth0').value.reset()
assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
# assert not list_sessions()
#def test_follower_properties():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('aproperty',))

View file

@ -34,20 +34,6 @@ def test_option_valid_name():
i = SymLinkOption("test1", i)
def test_option_get_information():
description = "it's ok"
string = 'some informations'
i = IntOption('test', description)
with pytest.raises(ValueError):
i.impl_get_information('noinfo')
i.impl_set_information('info', string)
assert i.impl_get_information('info') == string
with pytest.raises(ValueError):
i.impl_get_information('noinfo')
assert i.impl_get_information('noinfo', 'default') == 'default'
assert i.impl_get_information('doc') == description
def test_option_get_information_config():
description = "it's ok"
string = 'some informations'
@ -55,21 +41,16 @@ def test_option_get_information_config():
od = OptionDescription('od', '', [i])
cfg = Config(od)
with pytest.raises(ValueError):
i.impl_get_information('noinfo')
with pytest.raises(AttributeError):
i.impl_set_information('info', string)
with pytest.raises(ValueError):
i.impl_get_information('noinfo')
assert i.impl_get_information('noinfo', 'default') == 'default'
assert i.impl_get_information('doc') == description
cfg.option('test').information.get('noinfo')
assert cfg.option('test').information.get('noinfo', 'default') == 'default'
assert cfg.option('test').information.get('doc') == description
# assert not list_sessions()
def test_option_unknown():
description = "it's ok"
string = 'some informations'
i = IntOption('test', description)
i.impl_set_information('noinfo', 'optdefault')
i = IntOption('test', description, informations={'noinfo': 'optdefault'})
od = OptionDescription('od', '', [i])
cfg = Config(od)
#
@ -93,8 +74,7 @@ def test_option_description():
def test_option_get_information_default():
description = "it's ok"
string = 'some informations'
i = IntOption('test', description)
i.impl_set_information('noinfo', 'optdefault')
i = IntOption('test', description, informations={'noinfo': 'optdefault'})
od = OptionDescription('od', '', [i])
cfg = Config(od)
#
@ -108,32 +88,30 @@ def test_option_get_information_default():
def test_option_get_information_config2():
description = "it's ok"
string = 'some informations'
i = IntOption('test', description)
i.impl_set_information('info', string)
i = IntOption('test', description, informations={'info': string})
od = OptionDescription('od', '', [i])
cfg = Config(od)
with pytest.raises(ValueError):
i.impl_get_information('noinfo')
with pytest.raises(AttributeError):
i.impl_set_information('info', 'hello')
assert i.impl_get_information('info') == string
cfg.option('test').information.get('noinfo')
assert cfg.option('test').information.get('info') == string
with pytest.raises(ValueError):
i.impl_get_information('noinfo')
assert i.impl_get_information('noinfo', 'default') == 'default'
assert i.impl_get_information('doc') == description
cfg.option('test').information.get('noinfo')
assert cfg.option('test').information.get('noinfo', 'default') == 'default'
assert cfg.option('test').information.get('doc') == description
# assert not list_sessions()
def test_optiondescription_get_information():
description = "it's ok"
string = 'some informations'
o = OptionDescription('test', description, [])
o.impl_set_information('info', string)
assert o.impl_get_information('info') == string
o = OptionDescription('test', description, [], informations={'info': string})
od = OptionDescription('od', '', [o])
cfg = Config(od)
assert cfg.option('test').information.get('info') == string
with pytest.raises(ValueError):
o.impl_get_information('noinfo')
assert o.impl_get_information('noinfo', 'default') == 'default'
assert o.impl_get_information('doc') == description
cfg.option('test').information.get('noinfo')
assert cfg.option('test').information.get('noinfo', 'default') == 'default'
assert cfg.option('test').information.get('doc') == description
# assert not list_sessions()
@ -218,7 +196,7 @@ def test_optiondescription_group():
od3.impl_set_group_type(groups.notfamily)
od2 = OptionDescription('od', '', [od1, od3])
cfg = Config(od2)
assert len(list(cfg.option.list())) == 2
assert len(list(cfg.list())) == 2
# assert not list_sessions()

View file

@ -415,8 +415,7 @@ def test_callback_information(config_type):
def test_callback_information2(config_type):
val1 = StrOption('val1', "", Calculation(return_value, Params(ParamSelfInformation('information', 'no_value'))))
val2 = StrOption('val2', "", Calculation(return_value, Params(ParamSelfInformation('information'))))
val2.impl_set_information('information', 'new_value')
val2 = StrOption('val2', "", Calculation(return_value, Params(ParamSelfInformation('information'))), informations={'information': 'new_value'})
val3 = StrOption('val3', "", Calculation(return_value, Params(ParamSelfInformation('information'))))
od1 = OptionDescription('rootconfig', '', [val1, val2, val3])
cfg = Config(od1)
@ -432,9 +431,8 @@ def test_callback_information2(config_type):
def test_callback_information3(config_type):
val1 = StrOption('val1', "")
val1 = StrOption('val1', "", informations={'information': 'new_value'})
val2 = StrOption('val2', "", Calculation(return_value, Params(ParamInformation('information', option=val1))))
val1.impl_set_information('information', 'new_value')
od1 = OptionDescription('rootconfig', '', [val1, val2])
cfg = Config(od1)
cfg.property.read_write()
@ -1691,3 +1689,38 @@ def test_calc_dependencies(config_type):
def test_callback__kwargs_wrong(config_type):
with pytest.raises(ValueError):
Params(kwargs='string')
def test_callback_information_parent(config_type):
information = ParamInformation('information')
val1 = StrOption('val1', "", Calculation(return_value, Params(information)))
od2 = OptionDescription('od', '', [val1], informations={'information': 'new_value'})
information.set_option(od2)
od1 = OptionDescription('rootconfig', '', [od2])
cfg = Config(od1)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
assert cfg.option('od.val1').value.get() == 'new_value'
cfg.option('od').information.set('information', 'new_value2')
assert cfg.option('od.val1').value.get() == 'new_value2'
def test_callback_information_redefined(config_type):
val1 = StrOption('val1', "")
information = ParamInformation('information', option=val1)
val2 = StrOption('val2', "", Calculation(return_value, Params(information)))
od2 = OptionDescription('od', '', [val1, val2], informations={'information': 'new_value'})
with pytest.raises(ConfigError):
information.set_option(od2)
def test_callback_information_redefined_after(config_type):
information = ParamInformation('information')
val1 = StrOption('val1', "", Calculation(return_value, Params(information)))
od2 = OptionDescription('od', '', [val1], informations={'information': 'new_value'})
od1 = OptionDescription('rootconfig', '', [od2])
cfg = Config(od1)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
with pytest.raises(ConfigError):
information.set_option(od2)

View file

@ -166,28 +166,6 @@ def test_force_default_on_freeze_multi():
# assert not list_sessions()
def test_force_default_on_freeze_leader_frozen():
dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('force_default_on_freeze', 'frozen'))
dummy2 = BoolOption('dummy2', 'Test string option', multi=True)
descr = Leadership("dummy1", "", [dummy1, dummy2])
od1 = OptionDescription("root", "", [descr])
cfg = Config(od1)
with pytest.raises(LeadershipError):
cfg.option('dummy1.dummy1').property.remove('frozen')
# assert not list_sessions()
def test_force_metaconfig_on_freeze_leader_frozen():
dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('force_metaconfig_on_freeze', 'frozen'))
dummy2 = BoolOption('dummy2', 'Test string option', multi=True)
descr = Leadership("dummy1", "", [dummy1, dummy2])
od1 = OptionDescription("root", "", [descr])
cfg = Config(od1)
with pytest.raises(LeadershipError):
cfg.option('dummy1.dummy1').property.remove('frozen')
# assert not list_sessions()
def test_force_default_on_freeze_follower(config_type):
dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('notunique',))
dummy2 = BoolOption('dummy2', 'Test string option', multi=True, properties=('force_default_on_freeze',))

View file

@ -82,7 +82,7 @@ def test_mod_read_only_write():
'empty',
}
#
config.property.setdefault(frozenset(['cache']))
# config.property.setdefault(frozenset(['cache']))
config.property.setdefault(type='read_only', when='append', properties=frozenset(['disabled']))
config.property.setdefault(type='read_only', when='remove', properties=frozenset(['hidden']))
config.property.setdefault(type='read_write', when='append', properties=frozenset(['disabled', 'hidden']))
@ -94,7 +94,7 @@ def test_mod_read_only_write():
with pytest.raises(TypeError):
config.property.setdefault(type='read_only', when='append', properties=['disabled'])
assert config.property.default() == {'cache'}
assert config.property.default() == {'warnings', 'validator', 'cache'}
assert config.property.default('read_only', 'append') == {'disabled'}
assert config.property.default('read_only', 'remove') == {'hidden'}
assert config.property.default('read_write', 'append') == {'disabled',
@ -102,11 +102,11 @@ def test_mod_read_only_write():
assert config.property.default('read_write', 'remove') == set([])
#
config.property.read_only()
assert config.property.get() == {'cache', 'disabled'}
assert config.property.get() == {'warnings', 'validator', 'cache', 'disabled'}
config.property.read_write()
assert config.property.get() == {'cache', 'disabled', 'hidden'}
assert config.property.get() == {'warnings', 'validator', 'cache', 'disabled', 'hidden'}
config.property.read_only()
assert config.property.get() == {'cache', 'disabled'}
assert config.property.get() == {'warnings', 'validator', 'cache', 'disabled'}
#
assert config2.property.default() == {'cache', 'validator', 'warnings'}
assert config2.property.default('read_only', 'append') == {'frozen',
@ -138,6 +138,19 @@ def test_mod_read_only_write():
# assert not list_sessions()
def test_setting_tree(config_type):
s = StrOption("string", "", default=["string", "sdfsdf"], default_multi="prout", multi=True)
od4 = OptionDescription("option4", "", [s])
od3 = OptionDescription("option3", "", [od4])
od2 = OptionDescription("option2", "", [od3], properties=('hidden',))
od1 = OptionDescription("root", "", [od2])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
cfg.property.read_write()
with pytest.raises(PropertiesOptionError):
cfg.option('option2.option3.option4.string').value.get()
def test_setitem(config_type):
s = StrOption("string", "", default=["string", "sdfsdf"], default_multi="prout", multi=True)
od1 = OptionDescription("options", "", [s])
@ -365,8 +378,7 @@ def test_apply_requires_from_config():
with pytest.raises(PropertiesOptionError):
cfg.option('opt.str').value.get()
assert 'hidden' in cfg.forcepermissive.option('opt.str').property.get()
assert 'hidden' not in cfg.forcepermissive.option('opt.str').properties()
assert 'hidden' not in cfg.forcepermissive.option('opt.str').properties(only_raises=True)
assert 'hidden' not in cfg.forcepermissive.option('opt.str').property.get(only_raises=True)
# assert not list_sessions()
@ -386,8 +398,7 @@ def test_apply_requires_with_disabled():
cfg.option('int').value.set(1)
with pytest.raises(PropertiesOptionError):
cfg.option('opt.str').value.get()
assert 'disabled' not in cfg.unrestraint.option('opt.str').properties()
assert 'disabled' not in cfg.unrestraint.option('opt.str').properties(only_raises=True)
assert 'disabled' not in cfg.unrestraint.option('opt.str').property.get(only_raises=True, apply_requires=False)
assert 'disabled' in cfg.unrestraint.option('opt.str').property.get()
# assert not list_sessions()
@ -607,7 +618,7 @@ def test_properties_get_add_reset():
cfg.property.add('frozen')
assert cfg.property.get() == {'validator', 'warnings', 'cache', 'frozen'}
cfg.property.reset()
assert cfg.property.get() == {'validator', 'warnings', 'cache'}
assert cfg.property.get() == frozenset()
def test_reset_properties_force_store_value():
@ -615,28 +626,25 @@ def test_reset_properties_force_store_value():
gcgroup = OptionDescription('gc', '', [gcdummy])
od1 = OptionDescription('tiramisu', '', [gcgroup])
cfg = Config(od1)
assert cfg.property.exportation() == {}
assert cfg.property.exportation() == {None: {None: frozenset({'validator', 'warnings', 'cache'})}}
cfg.property.add('frozen')
assert cfg.property.exportation() == \
{None: {None: set(('frozen', 'cache', 'validator', 'warnings'))}}
cfg.property.reset()
assert cfg.property.exportation() == {None: {}}
cfg.option('gc.dummy').property.add('test')
assert cfg.property.exportation() == {None: {}, 'gc.dummy': {None: set(('test', 'force_store_value'))}}
assert cfg.property.exportation() == {None: {}, 'gc.dummy': {None: frozenset({'test'})}}
cfg.property.reset()
assert cfg.property.exportation() == {None: {}, 'gc.dummy': {None: set(('test', 'force_store_value'))}}
assert cfg.property.exportation() == {None: {}, 'gc.dummy': {None: frozenset({'test'})}}
cfg.property.add('frozen')
assert cfg.property.exportation() == \
{None: {None: set(('frozen', 'validator', 'cache', 'warnings'))},
'gc.dummy': {None: set(('test', 'force_store_value'))}}
{None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}}
cfg.property.add('frozen')
assert cfg.property.exportation() == \
{None: {None: set(('frozen', 'validator', 'cache', 'warnings'))},
'gc.dummy': {None: set(('test', 'force_store_value'))}}
{None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}}
cfg.option('gc.dummy').property.add('test')
assert cfg.property.exportation() == \
{None: {None: set(('frozen', 'validator', 'cache', 'warnings'))},
'gc.dummy': {None: set(('test', 'force_store_value'))}}
{None: {None: frozenset({'frozen'})}, 'gc.dummy': {None: frozenset({'test'})}}
# assert not list_sessions()
@ -666,7 +674,7 @@ def test_set_modified_value():
gcgroup = OptionDescription('gc', '', [gcdummy])
od1 = OptionDescription('tiramisu', '', [gcgroup])
cfg = Config(od1)
assert cfg.property.exportation() == {}
assert cfg.property.exportation() == {None: {None: frozenset({'warnings', 'validator', 'cache'})}}
cfg.property.importation({None: {None: set(('frozen', 'cache', 'validator', 'warnings'))}})
assert cfg.property.exportation() == \
{None: {None: set(('frozen', 'cache', 'validator', 'warnings'))}}

View file

@ -64,7 +64,10 @@ def test_is_hidden(config_type):
def test_group_is_hidden(config_type):
od1 = make_description()
gcdummy = BoolOption('dummy', 'dummy', default=False, properties=(('hidden'),))
floatoption = FloatOption('float', 'Test float option', default=2.3)
gcgroup = OptionDescription('gc', '', [gcdummy, floatoption])
od1 = OptionDescription('trs', '', [gcgroup])
cfg_ori = Config(od1)
cfg_ori.property.read_write()
cfg_ori.option('gc').property.add('hidden')
@ -73,14 +76,14 @@ def test_group_is_hidden(config_type):
cfg.option('gc.dummy').value.get()
if config_type == 'tiramisu-api':
cfg.send()
assert 'hidden' in cfg_ori.forcepermissive.option('gc').property.get()
assert 'hidden' in cfg_ori.option('gc').property.get()
cfg = get_config(cfg_ori, config_type)
with pytest.raises(PropertiesOptionError):
cfg.option('gc.float').value.get()
# manually set the subconfigs to "show"
if config_type == 'tiramisu-api':
cfg.send()
cfg_ori.forcepermissive.option('gc').property.remove('hidden')
cfg_ori.option('gc').property.remove('hidden')
cfg = get_config(cfg_ori, config_type)
assert not 'hidden' in cfg.option('gc').property.get()
assert cfg.option('gc.float').value.get() == 2.3

View file

@ -1260,18 +1260,24 @@ def test_consistency_not_equal_has_dependency():
def test_validator_information(config_type):
opt1 = StrOption('opt1', '', validators=[Calculation(return_true, Params((ParamSelfInformation('key'), ParamValue('yes'))))], default='val')
opt2 = StrOption('opt2', '', validators=[Calculation(return_true, Params((ParamInformation('key'), ParamValue('yes'))))], default='val')
od1 = OptionDescription('root', '', [opt1, opt2])
opt3 = StrOption('opt3', '', validators=[Calculation(return_true, Params((ParamInformation('key', option=opt1), ParamValue('yes'))))], default='val')
od1 = OptionDescription('root', '', [opt1, opt2, opt3])
cfg = Config(od1)
with pytest.raises(ConfigError):
cfg.option('opt1').value.get()
with pytest.raises(ConfigError):
cfg.option('opt3').value.get()
cfg.option('opt1').information.set('key', 'val')
assert cfg.option('opt1').value.get() == 'val'
assert cfg.option('opt3').value.get() == 'val'
cfg.option('opt1').information.set('key', 'val1')
with pytest.raises(ValueError):
cfg.option('opt1').value.get()
with pytest.raises(ValueError):
cfg.option('opt3').value.get()
#
with pytest.raises(ConfigError):
assert cfg.option('opt2').value.get()
cfg.option('opt2').value.get()
cfg.information.set('key', 'val')
assert cfg.option('opt2').value.get() == 'val'
cfg.information.set('key', 'val1')

View file

@ -22,7 +22,7 @@ def test_forcepermissive_and_unrestraint(config_type):
cfg_ori.property.read_write()
cfg = get_config(cfg_ori, config_type)
with pytest.raises(ConfigError):
cfg_ori.unrestraint.forcepermissive.add('disabled')
cfg_ori.forcepermissive.add('disabled')
def test_permissive(config_type):
@ -39,9 +39,9 @@ def test_permissive(config_type):
assert set(props) == {'disabled'}
if config_type == 'tiramisu-api':
cfg.send()
cfg_ori.unrestraint.permissive.add('disabled')
cfg_ori.unrestraint.permissive.remove('hidden')
assert cfg_ori.unrestraint.permissive.get() == frozenset(['disabled'])
cfg_ori.permissive.add('disabled')
cfg_ori.permissive.remove('hidden')
assert cfg_ori.permissive.get() == frozenset(['disabled'])
cfg = get_config(cfg_ori, config_type)
props = frozenset()
try:
@ -81,8 +81,8 @@ def test_permissive_add(config_type):
assert set(props) == {'disabled'}
if config_type == 'tiramisu-api':
cfg.send()
cfg_ori.unrestraint.permissive.add('disabled')
assert cfg_ori.unrestraint.permissive.get() == frozenset(['hidden', 'disabled'])
cfg_ori.permissive.add('disabled')
assert cfg_ori.permissive.get() == frozenset(['hidden', 'disabled'])
cfg = get_config(cfg_ori, config_type)
props = frozenset()
try:
@ -119,10 +119,10 @@ def test_permissive_pop():
except PropertiesOptionError as err:
props = err.proptype
assert set(props) == {'disabled'}
cfg.unrestraint.permissive.add('disabled')
assert cfg.unrestraint.permissive.get() == frozenset(['hidden', 'disabled'])
cfg.permissive.add('disabled')
assert cfg.permissive.get() == frozenset(['hidden', 'disabled'])
cfg.forcepermissive.option('u1').value.get()
cfg.unrestraint.permissive.remove('disabled')
cfg.permissive.remove('disabled')
props = frozenset()
try:
cfg.forcepermissive.option('u1').value.get()
@ -136,14 +136,14 @@ def test_permissive_reset():
od1 = make_description()
cfg = Config(od1)
cfg.property.read_write()
assert cfg.unrestraint.permissive.get() == frozenset(['hidden'])
assert cfg.permissive.get() == frozenset(['hidden'])
#
cfg.unrestraint.permissive.add('disabled')
cfg.unrestraint.permissive.remove('hidden')
assert cfg.unrestraint.permissive.get() == frozenset(['disabled'])
cfg.permissive.add('disabled')
cfg.permissive.remove('hidden')
assert cfg.permissive.get() == frozenset(['disabled'])
#
cfg.unrestraint.permissive.reset()
assert cfg.unrestraint.permissive.get() == frozenset()
cfg.permissive.reset()
assert cfg.permissive.get() == frozenset(['hidden'])
# assert not list_sessions()
@ -157,9 +157,9 @@ def test_permissive_mandatory():
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.unrestraint.permissive.add('mandatory')
cfg.unrestraint.permissive.add('disabled')
assert cfg.unrestraint.permissive.get() == frozenset(['mandatory', 'disabled'])
cfg.permissive.add('mandatory')
cfg.permissive.add('disabled')
assert cfg.permissive.get() == frozenset(['hidden', 'mandatory', 'disabled'])
cfg.property.add('permissive')
cfg.option('u1').value.get()
cfg.property.remove('permissive')
@ -175,10 +175,10 @@ def test_permissive_frozen():
od1 = make_description()
cfg = Config(od1)
cfg.property.read_write()
cfg.unrestraint.permissive.remove('hidden')
cfg.unrestraint.permissive.add('frozen')
cfg.unrestraint.permissive.add('disabled')
assert cfg.unrestraint.permissive.get() == frozenset(['frozen', 'disabled'])
cfg.permissive.remove('hidden')
cfg.permissive.add('frozen')
cfg.permissive.add('disabled')
assert cfg.permissive.get() == frozenset(['frozen', 'disabled'])
assert cfg.permissive.get() == frozenset(['frozen', 'disabled'])
try:
cfg.option('u1').value.set(1)
@ -229,7 +229,7 @@ def test_permissive_option(config_type):
if config_type == 'tiramisu-api':
cfg.send()
cfg_ori.unrestraint.option('u1').permissive.set(frozenset(['disabled']))
cfg_ori.option('u1').permissive.add('disabled')
cfg = get_config(cfg_ori, config_type)
props = frozenset()
try:
@ -293,7 +293,7 @@ def test_permissive_option_cache():
props = err.proptype
assert set(props) == {'disabled'}
cfg.unrestraint.option('u1').permissive.set(frozenset(['disabled']))
cfg.option('u1').permissive.add('disabled')
props = frozenset()
try:
cfg.option('u1').value.get()
@ -342,8 +342,9 @@ def test_permissive_option_mandatory():
except PropertiesOptionError as err:
props = err.proptype
assert frozenset(props) == frozenset(['disabled'])
cfg.unrestraint.option('u1').permissive.set(frozenset(['mandatory', 'disabled']))
assert cfg.unrestraint.option('u1').permissive.get() == frozenset(['mandatory', 'disabled'])
cfg.option('u1').permissive.add('mandatory')
cfg.option('u1').permissive.add('disabled')
assert cfg.option('u1').permissive.get() == frozenset(['mandatory', 'disabled'])
cfg.property.add('permissive')
cfg.option('u1').value.get()
cfg.property.remove('permissive')
@ -359,7 +360,8 @@ def test_permissive_option_frozen():
od1 = make_description()
cfg = Config(od1)
cfg.property.read_write()
cfg.unrestraint.option('u1').permissive.set(frozenset(['frozen', 'disabled']))
cfg.option('u1').permissive.add('disabled')
cfg.option('u1').permissive.add('frozen')
cfg.option('u1').value.set(1)
assert cfg.option('u1').value.get() == 1
cfg.property.add('permissive')
@ -369,15 +371,6 @@ def test_permissive_option_frozen():
# assert not list_sessions()
def test_invalid_option_permissive():
od1 = make_description()
cfg = Config(od1)
cfg.property.read_write()
with pytest.raises(TypeError):
cfg.unrestraint.option('u1').permissive.set(['frozen', 'disabled'])
# assert not list_sessions()
def test_remove_option_permissive(config_type):
var1 = StrOption('var1', '', u'value', properties=('hidden',))
od1 = OptionDescription('od1', '', [var1])
@ -389,13 +382,13 @@ def test_remove_option_permissive(config_type):
cfg.option('od1.var1').value.get()
if config_type == 'tiramisu-api':
cfg.send()
cfg_ori.forcepermissive.option('od1.var1').permissive.set(frozenset(['hidden']))
cfg_ori.forcepermissive.option('od1.var1').permissive.add('hidden')
assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset(['hidden'])
cfg = get_config(cfg_ori, config_type)
assert cfg.option('od1.var1').value.get() == 'value'
if config_type == 'tiramisu-api':
cfg.send()
cfg_ori.forcepermissive.option('od1.var1').permissive.set(frozenset())
cfg_ori.forcepermissive.option('od1.var1').permissive.reset()
assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset()
cfg = get_config(cfg_ori, config_type)
with pytest.raises(PropertiesOptionError):
@ -414,7 +407,7 @@ def test_reset_option_permissive(config_type):
cfg.option('od1.var1').value.get()
if config_type == 'tiramisu-api':
cfg.send()
cfg_ori.forcepermissive.option('od1.var1').permissive.set(frozenset(['hidden']))
cfg_ori.forcepermissive.option('od1.var1').permissive.add('hidden')
assert cfg_ori.forcepermissive.option('od1.var1').permissive.get() == frozenset(['hidden'])
cfg = get_config(cfg_ori, config_type)
assert cfg.option('od1.var1').value.get() == 'value'

View file

@ -31,12 +31,12 @@ def test_properties(config_type):
assert frozenset(props) == frozenset(['disabled'])
if config_type == 'tiramisu-api':
cfg.send()
cfg_ori.unrestraint.option('ip_address_service').property.remove('disabled')
cfg_ori.unrestraint.option('ip_address_service').permissive.add('disabled')
cfg = get_config(cfg_ori, config_type)
cfg.option('ip_address_service').value.get()
if config_type == 'tiramisu-api':
cfg.send()
cfg_ori.unrestraint.option('ip_address_service').property.add('disabled')
cfg_ori.unrestraint.option('ip_address_service').permissive.remove('disabled')
cfg = get_config(cfg_ori, config_type)
props = []
try:
@ -47,8 +47,8 @@ def test_properties(config_type):
# pop twice
if config_type == 'tiramisu-api':
cfg.send()
cfg_ori.unrestraint.option('ip_address_service').property.remove('disabled')
cfg_ori.unrestraint.option('ip_address_service').property.remove('disabled')
cfg_ori.unrestraint.option('ip_address_service').permissive.add('disabled')
cfg_ori.unrestraint.option('ip_address_service').permissive.remove('disabled')
# assert not list_sessions()
@ -613,6 +613,7 @@ def test_requires_transitive_hidden_disabled_multiple(config_type):
del req
#
cfg_ori.permissive.reset()
cfg_ori.permissive.remove('hidden')
if config_type == 'tiramisu-api':
try:
cfg = get_config(cfg_ori, config_type)

View file

@ -141,7 +141,7 @@ def test_symlink_getpermissive():
od1 = OptionDescription('opt', '', [boolopt, linkopt])
cfg = Config(od1)
cfg.property.read_write()
cfg.option('b').permissive.set(frozenset(['perm']))
cfg.option('b').permissive.add('perm')
cfg.option('c').permissive.get() == frozenset(['perm'])
# assert not list_sessions()
@ -266,14 +266,26 @@ def test_symlink_owner(config_type):
def test_symlink_get_information():
boolopt = BoolOption("b", "", default=False)
boolopt = BoolOption("b", "", default=False, informations={'test': 'test'})
linkopt = SymLinkOption("c", boolopt)
boolopt.impl_set_information('test', 'test')
assert boolopt.impl_get_information('test') == 'test'
assert linkopt.impl_get_information('test') == 'test'
boolopt.impl_set_information('test', 'test2')
assert boolopt.impl_get_information('test') == 'test2'
assert linkopt.impl_get_information('test') == 'test2'
od1 = OptionDescription('opt', '', [linkopt, boolopt])
cfg = Config(od1)
assert cfg.option('b').information.get('test') == 'test'
assert cfg.option('c').information.get('test') == 'test'
cfg.option('b').information.set('test', 'test2')
assert cfg.option('b').information.get('test') == 'test2'
assert cfg.option('c').information.get('test') == 'test2'
def test_symlink_informations():
boolopt = BoolOption("b", "", default=False)
with pytest.raises(TypeError):
linkopt = SymLinkOption("c", boolopt, informations={'test': 'test'})
linkopt = SymLinkOption("c", boolopt)
od1 = OptionDescription('opt', '', [linkopt, boolopt])
cfg = Config(od1)
with pytest.raises(ConfigError):
cfg.option('c').information.set('test', 'test2')
def test_symlink_leader():
@ -359,9 +371,9 @@ def test_symlink_dependency():
[linkopt, OptionDescription("s1", "", [boolopt])])
cfg = Config(od1)
assert cfg.option('s1.b').has_dependency() is False
assert cfg.option('c').has_dependency() is True
assert cfg.option('c').has_dependency() is False
assert cfg.option('s1.b').has_dependency(False) is True
assert cfg.option('c').has_dependency(False) is False
assert cfg.option('c').has_dependency(False) is True
# assert not list_sessions()
@ -385,7 +397,7 @@ def test_symlink_list(config_type):
[linkopt, OptionDescription("s1", "", [boolopt])])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert [opt.path() for opt in cfg.option.list()] == ['c', 's1']
assert [opt.path() for opt in cfg.list()] == ['c', 's1']
#
assert [opt.path() for opt in cfg.option('s1').list()] == ['s1.b']
# assert not list_sessions()

File diff suppressed because it is too large Load diff

View file

@ -19,16 +19,47 @@
# ____________________________________________________________
"enables us to carry out a calculation and return an option's value"
from typing import Any, Optional, Union, Callable, Dict, List
from os.path import commonprefix
from itertools import chain
import weakref
from .error import PropertiesOptionError, ConfigError, LeadershipError, ValueWarning
from .i18n import _
from .setting import undefined, ConfigBag, Undefined
from .setting import undefined, ConfigBag
from .function import FUNCTION_WAITING_FOR_DICT
# ____________________________________________________________
def get_calculated_value(subconfig: "SubConfig",
value: Any,
*,
reset_cache: bool=True,
validate_properties: bool=True,
) -> Any:
"""value could be a calculation, in this case do calculation
"""
has_calculation = False
if isinstance(value, Calculation):
if subconfig is None:
return undefined, False
value = value.execute(subconfig,
validate_properties=validate_properties,
)
has_calculation = True
elif isinstance(value, list):
# if value is a list, do subcalculation
for idx, val in enumerate(value):
value[idx], _has_calculation = get_calculated_value(subconfig,
val,
reset_cache=False,
validate_properties=validate_properties,
)
if value[idx] is undefined:
return undefined, False
if _has_calculation:
has_calculation = True
return value, has_calculation
class Params:
__slots__ = ('args', 'kwargs')
def __init__(self, args=None, kwargs=None, **kwgs):
@ -85,13 +116,11 @@ class ParamOption(Param):
class ParamDynOption(ParamOption):
__slots__ = ('suffixes',
'dynoptiondescription',
'optional',
)
def __init__(self,
option: 'Option',
suffixes: list[str],
dynoptiondescription: 'DynOptionDescription'=None,
notraisepropertyerror: bool=False,
raisepropertyerror: bool=False,
optional: bool=False,
@ -101,7 +130,6 @@ class ParamDynOption(ParamOption):
raisepropertyerror,
)
self.suffixes = suffixes
self.dynoptiondescription = dynoptiondescription
self.optional = optional
@ -125,6 +153,7 @@ class ParamInformation(Param):
__slots__ = ('information_name',
'default_value',
'option',
'self_option',
)
def __init__(self,
information_name: str,
@ -133,7 +162,22 @@ class ParamInformation(Param):
) -> None:
self.information_name = information_name
self.default_value = default_value
self.self_option = None
self.option = None
if option:
self.set_option(option)
def set_self_option(self, option):
self.self_option = option
def set_option(self,
option: 'Option'=None
) -> None:
if not hasattr(self, 'self_option'):
raise ConfigError('cannot add option in information after creating config')
if self.option:
raise ConfigError('cannot redefine option in information')
if not option.impl_is_optiondescription():
if option.impl_is_symlinkoption():
raise ValueError(_('option in ParamInformation cannot be a symlinkoption'))
if option.impl_is_follower():
@ -141,10 +185,27 @@ class ParamInformation(Param):
if option.impl_is_dynsymlinkoption():
raise ValueError(_('option in ParamInformation cannot be a dynamic option'))
self.option = option
if self.self_option:
informations = self.self_option._dependencies_information
if set(informations) == {None, self.information_name}:
del self.self_option._dependencies_information
else:
informations.remove(None)
if not getattr(option, '_dependencies_information', {}):
option._dependencies_information = {None: []}
option._dependencies_information[None].append(self)
option._dependencies_information.setdefault(self.information_name, []).append(weakref.ref(self.self_option))
class ParamSelfInformation(ParamInformation):
__slots__ = tuple()
def __init__(self,
information_name: str,
default_value: Any=undefined,
) -> None:
return super().__init__(information_name,
default_value,
)
class ParamIndex(Param):
@ -152,7 +213,11 @@ class ParamIndex(Param):
class ParamSuffix(Param):
__slots__ = tuple()
__slots__ = ('suffix_index',)
def __init__(self,
suffix_index: int=-1,
) -> None:
self.suffix_index = suffix_index
class Calculation:
@ -190,6 +255,7 @@ class Calculation:
allow_value_error: bool=False,
force_value_warning: bool=False,
for_settings: bool=False,
validate_properties: bool=True,
) -> Any:
return carry_out_calculation(subconfig,
callback=self.function,
@ -200,6 +266,7 @@ class Calculation:
allow_value_error=allow_value_error,
force_value_warning=force_value_warning,
for_settings=for_settings,
validate_properties=validate_properties,
)
def help(self,
@ -229,6 +296,7 @@ def manager_callback(callback: Callable,
orig_value,
config_bag: ConfigBag,
for_settings: bool,
validate_properties: bool,
) -> Any:
"""replace Param by true value"""
option = subconfig.option
@ -297,18 +365,18 @@ def manager_callback(callback: Callable,
return value
def _get_value(param: Params,
subconfig: SubConfig,
subconfig: 'SubConfig',
) -> Any:
try:
# get value
value = config_bag.context.get_value(subconfig)
except PropertiesOptionError as err:
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
if param.notraisepropertyerror or param.raisepropertyerror:
if isinstance(param, ParamSelfOption) or param.notraisepropertyerror or param.raisepropertyerror:
raise err from err
raise ConfigError(_('unable to carry out a calculation for "{}", {}').format(display_name, err)) from err
except ValueError as err:
display_name = subconfig.option.impl_get_display_name()
display_name = subconfig.option.impl_get_display_name(subconfig)
raise ValueError(_('the option "{0}" is used in a calculation but is invalid ({1})').format(display_name, err)) from err
except AttributeError as err:
if isinstance(param, ParamDynOption) and param.optional:
@ -317,7 +385,7 @@ def manager_callback(callback: Callable,
['configerror'],
config_bag.context.get_settings(),
)
display_name = subconfig.option.impl_get_display_name()
display_name = subconfig.option.impl_get_display_name(subconfig)
raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
return value
@ -341,20 +409,20 @@ def manager_callback(callback: Callable,
config_bag.remove_validation()
# root = config_bag.context.get_root(config_bag)
try:
subconfig = config_bag.context.get_sub_config(config_bag,
opt.impl_getpath(),
index_,
validate_properties=not self_calc,
properties=properties,
)
subsubconfig = config_bag.context.get_sub_config(config_bag,
opt.impl_getpath(),
index_,
validate_properties=not self_calc,
properties=properties,
)
except PropertiesOptionError as err:
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
if param.notraisepropertyerror or param.raisepropertyerror:
raise err from err
display_name = option.impl_get_display_name()
display_name = option.impl_get_display_name(subconfig)
raise ConfigError(_('unable to carry out a calculation for "{}", {}').format(display_name, err)) from err
except ValueError as err:
raise ValueError(_('the option "{0}" is used in a calculation but is invalid ({1})').format(option.impl_get_display_name(), err)) from err
raise ValueError(_('the option "{0}" is used in a calculation but is invalid ({1})').format(option.impl_get_display_name(subconfig), err)) from err
except AttributeError as err:
if isinstance(param, ParamDynOption) and param.optional:
# cannot acces, simulate a propertyerror
@ -362,19 +430,9 @@ def manager_callback(callback: Callable,
['configerror'],
config_bag.context.get_settings(),
)
display_name = option.impl_get_display_name()
display_name = option.impl_get_display_name(subconfig)
raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
return subconfig
def get_common_path(path1, path2):
common_path = commonprefix([path1, path2])
if common_path in [path1, path2]:
return common_path
if common_path.endswith('.'):
return common_path[:-1]
if '.' in common_path:
return common_path.rsplit('.', 1)[0]
return None
return subsubconfig
if isinstance(param, ParamValue):
return param.value
@ -383,22 +441,30 @@ def manager_callback(callback: Callable,
if isinstance(param, ParamSelfInformation):
isubconfig = subconfig
elif param.option:
isubconfig = get_option_bag(config_bag,
param.option,
param,
None,
False,
#properties=properties,
)
if param.option.issubdyn():
search_option = param.option
isubconfig = subconfig.get_common_child(search_option,
true_path=subconfig.path,
)
if isinstance(isubconfig, list):
raise ConfigError(f'cannot find information for "{option.impl_get_display_name(subconfig)}", "{search_option.impl_get_display_name(None)}" is a dynamic option')
else:
isubconfig = get_option_bag(config_bag,
param.option,
param,
None,
False,
#properties=properties,
)
else:
isubconfig = None
isubconfig = config_bag.context.get_root(config_bag)
try:
return config_bag.context.get_values().get_information(isubconfig,
param.information_name,
param.default_value,
)
except ValueError as err:
display_name = option.impl_get_display_name()
display_name = option.impl_get_display_name(subconfig)
raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
if isinstance(param, ParamIndex):
@ -406,9 +472,9 @@ def manager_callback(callback: Callable,
if isinstance(param, ParamSuffix):
if not option.issubdyn():
display_name = subconfig.option.impl_get_display_name()
display_name = subconfig.option.impl_get_display_name(subconfig)
raise ConfigError(_('option "{display_name}" is not in a dynoptiondescription'))
return subconfig.suffixes[-1]
return subconfig.suffixes[param.suffix_index]
if isinstance(param, ParamSelfOption):
value = calc_self(param,
@ -418,45 +484,13 @@ def manager_callback(callback: Callable,
)
if callback.__name__ not in FUNCTION_WAITING_FOR_DICT:
return value
return {'name': option.impl_get_display_name(),
return {'name': option.impl_get_display_name(subconfig),
'value': value,
}
if isinstance(param, ParamOption):
callbk_option = param.option
callbk_options = None
subconfigs = None
if callbk_option.issubdyn():
found = False
if isinstance(param, ParamDynOption):
# SUBDYN INSIDE CURRENT != SUBDYN OUTSIDE ?
callbk_option = callbk_option.to_sub_dyoption(param.suffixes)
found = True
else:
search_option = param.option
current_option_path = option.impl_getpath()
search_option_path = search_option.impl_getpath()
common_path = get_common_path(current_option_path, search_option_path)
if common_path:
parent_number = current_option_path[len(common_path) + 2:].count('.')
if parent_number:
raise Exception('pfff')
subconfig = subconfig.parent.get_child(search_option,
None,
True,
)
else:
raise Exception('pfff')
subconfigs = [subconfig]
found = True
if not found:
callbk_options = []
for doption_bag in callbk_option.getsubdyn().get_sub_children(callbk_option,
config_bag,
index=None,
):
callbk_options.append(doption_bag.option)
config_bag = subconfig.config_bag
if index is not None and callbk_option.impl_get_leadership() and \
callbk_option.impl_get_leadership().in_same_leadership(option):
if not callbk_option.impl_is_follower():
@ -470,7 +504,69 @@ def manager_callback(callback: Callable,
else:
index_ = None
with_index = False
if subconfigs is None:
if callbk_option.issubdyn():
if isinstance(param, ParamDynOption):
#callbk_option = callbk_option.to_sub_dyoption(param.suffixes)
suffixes = param.suffixes.copy()
paths = callbk_option.impl_getpath().split('.')
parents = [config_bag.context.get_root(config_bag)]
subconfigs_is_a_list = False
for name in paths:
new_parents = []
for parent in parents:
doption = parent.option.get_child(name,
config_bag,
parent,
allow_dynoption=True,
)
if doption.impl_is_dynoptiondescription():
if suffixes:
suffix = suffixes.pop(0)
name = doption.impl_getname(suffix)
try:
doption = parent.option.get_child(name,
config_bag,
parent,
)
except AttributeError as err:
raise ConfigError(err) from err
new_parents.append(parent.get_child(doption,
None,
True,
name=name,
suffix=suffix,
))
else:
subconfigs_is_a_list = True
new_parents.extend(parent.dyn_to_subconfig(doption,
True,
)
)
else:
new_parents.append(parent.get_child(doption,
None,
True,
name=name,
))
parents = new_parents
if subconfigs_is_a_list:
subconfigs = parents
else:
subconfigs = parents[0]
else:
search_option = param.option
subconfigs = subconfig.get_common_child(search_option,
true_path=subconfig.path,
validate_properties=validate_properties,
)
if isinstance(subconfigs, list):
values = []
else:
values = None
subconfigs = [subconfigs]
else:
subconfigs = [get_option_bag(config_bag,
callbk_option,
param,
@ -479,13 +575,7 @@ def manager_callback(callback: Callable,
#properties=properties,
)
]
# callbk_options = [callbk_option]
values = None
else:
values = []
#FIXME
values = None
# for callbk_option in callbk_options:
for subconfig in subconfigs:
callbk_option = subconfig.option
value = get_value(config_bag,
@ -501,7 +591,7 @@ def manager_callback(callback: Callable,
value = values
if callback.__name__ not in FUNCTION_WAITING_FOR_DICT:
return value
return {'name': callbk_option.impl_get_display_name(),
return {'name': callbk_option.impl_get_display_name(subconfig),
'value': value}
@ -514,6 +604,8 @@ def carry_out_calculation(subconfig: 'SubConfig',
allow_value_error: bool=False,
force_value_warning: bool=False,
for_settings: bool=False,
*,
validate_properties: bool=True,
):
"""a function that carries out a calculation for an option's value
@ -533,7 +625,7 @@ def carry_out_calculation(subconfig: 'SubConfig',
Values could have multiple values only when key is ''."""
option = subconfig.option
if not option.impl_is_optiondescription() and option.impl_is_follower() and index is None:
raise Exception('follower must have index in carry_out_calculation!')
raise ConfigError(f'the follower "{option.impl_get_display_name(subconfig)}" must have index in carry_out_calculation!')
def fake_items(iterator):
return ((None, i) for i in iterator)
args = []
@ -548,20 +640,21 @@ def carry_out_calculation(subconfig: 'SubConfig',
orig_value,
config_bag,
for_settings,
validate_properties,
)
if key is None:
args.append(value)
else:
kwargs[key] = value
except PropertiesOptionError as err:
if param.raisepropertyerror:
if isinstance(param, ParamSelfOption) or param.raisepropertyerror:
raise err
if callback.__name__ in FUNCTION_WAITING_FOR_DICT:
if key is None:
args.append({'propertyerror': str(err), 'name': option.impl_get_display_name()})
args.append({'propertyerror': str(err), 'name': option.impl_get_display_name(subconfig)})
else:
kwargs[key] = {'propertyerror': str(err), 'name': option.impl_get_display_name()}
ret = calculate(option,
kwargs[key] = {'propertyerror': str(err), 'name': option.impl_get_display_name(subconfig)}
ret = calculate(subconfig,
callback,
allow_value_error,
force_value_warning,
@ -579,17 +672,17 @@ def carry_out_calculation(subconfig: 'SubConfig',
args,
kwargs,
ret,
option.impl_get_display_name()))
option.impl_get_display_name(subconfig)))
else:
raise LeadershipError(_('the "{}" function must not return a list ("{}") '
'for the follower option "{}"'
'').format(callback.__name__,
ret,
option.impl_get_display_name()))
option.impl_get_display_name(subconfig)))
return ret
def calculate(option,
def calculate(subconfig,
callback: Callable,
allow_value_error: bool,
force_value_warning: bool,
@ -617,12 +710,12 @@ def calculate(option,
msg = _('unexpected error "{0}" in function "{1}" with arguments "{3}" and "{4}" '
'for option "{2}"').format(str(error),
callback.__name__,
option.impl_get_display_name(),
subconfig.option.impl_get_display_name(subconfig),
args,
kwargs)
else:
msg = _('unexpected error "{0}" in function "{1}" for option "{2}"'
'').format(str(error),
callback.__name__,
option.impl_get_display_name())
subconfig.option.impl_get_display_name(subconfig))
raise ConfigError(msg) from error

View file

@ -47,17 +47,12 @@ class Cache:
if path not in self._cache or index not in self._cache[path]:
return no_cache
value, timestamp, validated = self._cache[path][index]
if type_ == 'context_props':
# cached value is settings properties so value is props
props = value
self_props = {}
props = subconfig.config_bag.properties
if type_ == 'self_props':
# cached value is self_props
self_props = value
else:
props = subconfig.config_bag.properties
if type_ == 'self_props':
# cached value is self_props
self_props = value
else:
self_props = subconfig.properties
self_props = subconfig.properties
if 'cache' in props or \
'cache' in self_props:
if expiration and timestamp and \

View file

@ -23,6 +23,7 @@
import weakref
from copy import copy, deepcopy
from typing import Optional, List, Any, Union
from os.path import commonprefix
from .error import PropertiesOptionError, ConfigError, ConflictError, \
LeadershipError
@ -35,6 +36,17 @@ from .autolib import Calculation
from . import autolib
def get_common_path(path1, path2):
common_path = commonprefix([path1, path2])
if common_path in [path1, path2]:
return common_path
if common_path.endswith('.'):
return common_path[:-1]
if '.' in common_path:
return common_path.rsplit('.', 1)[0]
return None
class CCache:
__slots__ = tuple()
# =============================================================================
@ -171,6 +183,7 @@ class SubConfig:
'path',
'true_path',
'properties',
'raises_properties',
'is_dynamic',
'suffixes',
'_length',
@ -187,8 +200,6 @@ class SubConfig:
properties: Union[list[str], undefined]=undefined,
validate_properties: bool=True,
) -> None:
if path and '.' in path and not parent:
raise Exception('pff connard')
self.index = index
self.suffixes = suffixes
self.option = option
@ -198,12 +209,14 @@ class SubConfig:
self.path = path
if true_path is None:
true_path = path
is_follower = not option.impl_is_optiondescription() and option.impl_is_follower()
apply_requires = not is_follower or index is not None
self.true_path = true_path
settings = config_bag.context.get_settings()
if properties is undefined:
if path is None:
self.properties = frozenset()
else:
settings = config_bag.context.get_settings()
self.properties = frozenset()
if validate_properties:
self.properties = settings.getproperties(self,
@ -211,7 +224,7 @@ class SubConfig:
)
self.config_bag.context.get_settings().validate_properties(self)
self.properties = settings.getproperties(self,
apply_requires=True,
apply_requires=apply_requires,
)
else:
self.properties = properties
@ -221,6 +234,15 @@ class SubConfig:
self.is_dynamic = False
if validate_properties:
self.config_bag.context.get_settings().validate_properties(self)
if self.option.impl_is_optiondescription():
if self.properties is not None:
self.raises_properties = settings.calc_raises_properties(self,
apply_requires=apply_requires,
not_unrestraint=True,
)
else:
self.raises_properties = frozenset()
def __repr__(self):
return f'<SubConfig path={self.path}, index={self.index}>'
@ -228,7 +250,8 @@ class SubConfig:
def dyn_to_subconfig(self,
child: Option,
validate_properties: bool,
follower_not_apply_requires: bool=False,
*,
true_path: Optional[str]=None,
) -> List['SubConfig']:
config_bag = self.config_bag
for suffix in child.get_suffixes(self):
@ -241,10 +264,10 @@ class SubConfig:
yield self.get_child(child,
None,
validate_properties,
follower_not_apply_requires=follower_not_apply_requires,
suffix=suffix,
name=name,
properties=properties,
true_path=true_path,
)
except PropertiesOptionError as err:
if err.proptype in (['mandatory'], ['empty']):
@ -298,7 +321,6 @@ class SubConfig:
validate_properties: bool,
*,
properties=undefined,
follower_not_apply_requires: bool=False,
allow_dynoption: bool=False,
suffix: Optional[str]=None,
name: Optional[str]=None,
@ -312,24 +334,6 @@ class SubConfig:
if not self.option.impl_is_optiondescription():
raise TypeError(f'"{self.path}" is not an optiondescription')
if check_index and index is not None:
if option.impl_is_optiondescription() or \
option.impl_is_symlinkoption() or \
not option.impl_is_follower():
raise ConfigError('index must be set only with a follower option')
length = self.get_length_leadership()
if index >= length:
raise LeadershipError(_(f'index "{index}" is greater than the leadership '
f'length "{length}" for option '
f'"{option.impl_get_display_name()}"'))
if properties is undefined and not validate_properties:
# not transitive property error
apply_requires = False
else:
apply_requires = not follower_not_apply_requires or \
option.impl_is_optiondescription() or \
not option.impl_is_follower()
path = self.get_path(name,
option,
)
@ -340,16 +344,27 @@ class SubConfig:
suffixes = self.suffixes + [suffix]
else:
suffixes = [suffix]
return SubConfig(option,
index,
path,
self.config_bag,
self,
suffixes,
properties=properties,
validate_properties=validate_properties,
true_path=true_path,
)
subsubconfig = SubConfig(option,
index,
path,
self.config_bag,
self,
suffixes,
properties=properties,
validate_properties=validate_properties,
true_path=true_path,
)
if check_index and index is not None:
if option.impl_is_optiondescription() or \
option.impl_is_symlinkoption() or \
not option.impl_is_follower():
raise ConfigError('index must be set only with a follower option')
length = self.get_length_leadership()
if index >= length:
raise LeadershipError(_(f'index "{index}" is greater than the leadership '
f'length "{length}" for option '
f'"{option.impl_get_display_name(subsubconfig)}"'))
return subsubconfig
def get_path(self,
name: str,
@ -379,10 +394,77 @@ class SubConfig:
cconfig_bag,
self,
self.suffixes,
validate_properties=False,
)
self._length = len(cconfig_bag.context.get_value(subconfig))
return self._length
autolib.SubConfig = SubConfig
def get_common_child(self,
search_option: 'BaseOption',
true_path: Optional[str]=None,
validate_properties: bool=True,
):
current_option_path = self.option.impl_getpath()
search_option_path = search_option.impl_getpath()
common_path = get_common_path(current_option_path, search_option_path)
config_bag = self.config_bag
index = None
if not self.option.impl_is_optiondescription() and \
self.option.impl_is_follower() and search_option.impl_is_follower() and \
self.parent.option == search_option.impl_get_leadership():
index = self.index
search_child_number = 0
parents = [self.parent]
else:
if common_path:
parent = self.parent
common_parent_number = common_path.count('.') + 1
for idx in range(current_option_path.count('.') - common_parent_number):
parent = parent.parent
parents = [parent]
else:
common_parent_number = 0
parents = [config_bag.context.get_root(config_bag)]
search_child_number = search_option_path.count('.') - common_parent_number
subconfigs_is_a_list = False
if search_child_number:
if common_parent_number:
parent_paths = search_option_path.rsplit('.', search_child_number + 1)[1:-1]
else:
parent_paths = search_option_path.split('.')[:-1]
for parent_path in parent_paths:
new_parents = []
for parent in parents:
sub_option = parent.option.get_child(parent_path,
config_bag,
parent,
allow_dynoption=True,
)
if sub_option.impl_is_dynoptiondescription():
new_parents.extend(parent.dyn_to_subconfig(sub_option,
True,
true_path=true_path,
)
)
subconfigs_is_a_list = True
else:
new_parents.append(parent.get_child(sub_option,
None,
validate_properties,
true_path=true_path,
)
)
parents = new_parents
subconfigs = []
for parent in parents:
subconfigs.append(parent.get_child(search_option,
index,
validate_properties,
)
)
if subconfigs_is_a_list:
return subconfigs
return subconfigs[0]
class _Config(CCache):
@ -486,7 +568,6 @@ class _Config(CCache):
path,
None,
validate_properties=True,
follower_not_apply_requires=False,
)
except PropertiesOptionError:
continue
@ -541,7 +622,6 @@ class _Config(CCache):
index,
*,
validate_properties: bool=True,
follower_not_apply_requires: bool=False,
properties=undefined,
true_path: Optional[str]=None,
):
@ -577,7 +657,6 @@ class _Config(CCache):
subconfig = subconfig.get_child(option,
index_,
validate_properties,
follower_not_apply_requires=follower_not_apply_requires,
properties=properties,
name=name,
suffix=suffix,
@ -647,17 +726,6 @@ class _Config(CCache):
# =============================================================================
# Manage value
def set_value(self,
subconfig: SubConfig,
value: Any,
) -> Any:
"""set value
"""
self.get_settings().validate_properties(subconfig)
return self.get_values().set_value(subconfig,
value
)
def get_value(self,
subconfig,
need_help=True,
@ -672,8 +740,9 @@ class _Config(CCache):
if isinstance(subconfig, list):
value = []
follower_subconfig = None
is_follower = not subconfig or subconfig[0].option.impl_is_follower()
for sconfig in subconfig:
if follower_subconfig is None:
if not is_follower or follower_subconfig is None:
follower_subconfig = self.get_sub_config(sconfig.config_bag,
sconfig.path,
sconfig.index,
@ -692,7 +761,7 @@ class _Config(CCache):
length = subconfig.parent.get_length_leadership()
follower_len = self.get_values().get_max_length(subconfig.path)
if follower_len > length:
option_name = subconfig.option.impl_get_display_name()
option_name = subconfig.option.impl_get_display_name(subconfig)
raise LeadershipError(_(f'the follower option "{option_name}" '
f'has greater length ({follower_len}) than the leader '
f'length ({length})'))
@ -704,6 +773,7 @@ class _Config(CCache):
def _get(self,
subconfig: "SubConfig",
need_help: bool,
validate_properties: bool=True,
) -> "OptionBag":
# pylint: disable=too-many-locals
option = subconfig.option
@ -712,17 +782,15 @@ class _Config(CCache):
suboption = option.impl_getopt()
if suboption.issubdyn():
dynopt = suboption.getsubdyn()
return list(dynopt.get_sub_children(suboption,
suboption.config_bag,
index=suboption.index,
true_path=subconfig.path,
))
return subconfig.get_common_child(suboption,
true_path=subconfig.path,
validate_properties=validate_properties,
)
if suboption.impl_is_follower():
subconfig = self.get_sub_config(subconfig.config_bag, # pylint: disable=no-member
suboption.impl_getpath(),
None,
validate_properties=True,
follower_not_apply_requires=False,
validate_properties=validate_properties,
true_path=subconfig.path,
)
leadership_length = subconfig.parent.get_length_leadership()
@ -739,8 +807,7 @@ class _Config(CCache):
s_subconfig = self.get_sub_config(subconfig.config_bag, # pylint: disable=no-member
suboption.impl_getpath(),
None,
validate_properties=True,
follower_not_apply_requires=False,
validate_properties=validate_properties,
true_path=subconfig.path,
)
return self._get(s_subconfig,
@ -818,6 +885,7 @@ class _CommonConfig(_Config):
self.reset_cache(option_bag)
def impl_get_information(self,
subconfig,
key,
default,
):
@ -893,7 +961,7 @@ class _CommonConfig(_Config):
duplicated_settings.rw_append = self.get_settings().rw_append
duplicated_settings.ro_remove = self.get_settings().ro_remove
duplicated_settings.rw_remove = self.get_settings().rw_remove
duplicated_settings.default_properties = self.get_settings().default_properties
# duplicated_settings.default_properties = self.get_settings().default_properties
duplicated_config.reset_cache(None, None)
if child is not None:
duplicated_config._impl_children.append(child) # pylint: disable=protected-access
@ -1412,7 +1480,7 @@ class KernelMixConfig(KernelGroupConfig):
)
# Copy context properties/permissives
settings = config.get_settings()
properties = settings.get_context_properties(config.properties_cache)
properties = settings.get_context_properties()
settings.set_context_properties(properties,
config,
)
@ -1421,7 +1489,7 @@ class KernelMixConfig(KernelGroupConfig):
settings.rw_append = settings.rw_append
settings.ro_remove = settings.ro_remove
settings.rw_remove = settings.rw_remove
settings.default_properties = settings.default_properties
# settings.default_properties = settings.default_properties
config.parents.append(weakref.ref(self))
self._impl_children.append(config)

View file

@ -70,8 +70,9 @@ class PropertiesOptionError(AttributeError):
self._opt_type = 'optiondescription'
else:
self._opt_type = 'option'
self._name = subconfig.option.impl_get_display_name()
self._name = subconfig.option.impl_get_display_name(subconfig)
self._orig_opt = None
self._subconfig = subconfig
self.proptype = proptype
self.help_properties = help_properties
self._settings = settings
@ -108,8 +109,9 @@ class PropertiesOptionError(AttributeError):
else:
msg = 'cannot access to {0} "{1}" because has {2} {3}'
if self._orig_opt:
# FIXME _orig_opt ?
self.msg = _(msg).format(self._opt_type,
self._orig_opt.impl_get_display_name(),
self._orig_opt.impl_get_display_name(subconfig),
self._name,
prop_msg,
properties_msg)
@ -156,6 +158,7 @@ class ConstError(TypeError):
class _CommonError:
def __init__(self,
subconfig,
val,
display_type,
opt,
@ -164,7 +167,7 @@ class _CommonError:
self.val = val
self.display_type = display_type
self.opt = weakref.ref(opt)
self.name = opt.impl_get_display_name()
self.name = opt.impl_get_display_name(subconfig)
self.err_msg = err_msg
self.index = index
super().__init__(self.err_msg)

View file

@ -944,7 +944,7 @@ msgstr "option \"{0}\" inconnue dans l'optiondescription \"{1}\""
#: tiramisu/option/optiondescription.py:279
msgid "children in optiondescription \"{}\" must be a list"
msgstr "les enfants d'une optiondescription \"{}\" doit être une liste"
msgstr "les enfants d'une optiondescription \"{}\" doivent être une liste"
#: tiramisu/option/optiondescription.py:303
msgid "duplicate option name: \"{0}\""

View file

@ -20,14 +20,14 @@
# ____________________________________________________________
"""base option
"""
from typing import FrozenSet, Set, Any, List
from typing import FrozenSet, Set, Any, List, Optional, Dict
import weakref
from itertools import chain
from ..i18n import _
from ..setting import undefined
from ..autolib import Calculation, ParamOption
from ..autolib import Calculation, ParamOption, ParamInformation, ParamSelfInformation
STATIC_TUPLE = frozenset()
@ -57,6 +57,7 @@ class Base:
'_properties',
'_has_dependency',
'_dependencies',
'_dependencies_information',
'_suffixes_dependencies',
'__weakref__'
)
@ -64,8 +65,11 @@ class Base:
def __init__(self,
name: str,
doc: str,
informations: Optional[Dict],
*,
properties=None,
is_multi: bool=False) -> None:
is_multi: bool=False,
) -> None:
if not valid_name(name):
raise ValueError(_('"{0}" is an invalid name for an option').format(name))
if properties is None:
@ -83,6 +87,9 @@ class Base:
assert isinstance(properties, frozenset), _('invalid properties type {0} for {1},'
' must be a frozenset').format(type(properties),
name)
_setattr = object.__setattr__
_setattr(self, '_name', name)
_setattr(self, '_informations', {'doc': doc})
for prop in properties:
if not isinstance(prop, str):
if not isinstance(prop, Calculation):
@ -91,11 +98,19 @@ class Base:
for param in chain(prop.params.args, prop.params.kwargs.values()):
if isinstance(param, ParamOption):
param.option._add_dependency(self)
_setattr = object.__setattr__
_setattr(self, '_name', name)
_setattr(self, '_informations', {'doc': doc})
if properties:
_setattr(self, '_properties', properties)
self.set_informations(informations)
def set_informations(self,
informations: Optional[Dict],
) -> None:
if not informations:
return
for key, value in informations.items():
self._set_information(key,
value,
)
def impl_has_dependency(self,
self_is_dep: bool=True,
@ -196,10 +211,11 @@ class Base:
# ____________________________________________________________
# information
def impl_get_information(self,
key: str,
default: Any=undefined,
) -> Any:
def _get_information(self,
subconfig: "SubConfig",
key: str,
default: Any=undefined,
) -> Any:
"""retrieves one information's item
:param key: the item string (ex: "help")
@ -217,13 +233,13 @@ class Base:
if default is not undefined:
return default
# pylint: disable=no-member
raise ValueError(_(f'information\'s item for "{self.impl_get_display_name()}" '
raise ValueError(_(f'information\'s item for "{self.impl_get_display_name(subconfig)}" '
f'not found: "{key}"'))
def impl_set_information(self,
key: str,
value: Any,
) -> None:
def _set_information(self,
key: str,
value: Any,
) -> None:
"""updates the information's attribute
(which is a dictionary)
@ -237,13 +253,13 @@ class Base:
key))
self._informations[key] = value # pylint: disable=no-member
def impl_list_information(self) -> Any:
def _list_information(self) -> Any:
"""get the list of information keys
"""
dico = self._informations # pylint: disable=no-member
if isinstance(dico, tuple):
return list(dico[0])
if isinstance(dico, str):
if not isinstance(dico, dict):
return ['doc']
# it's a dict
return list(dico.keys())
@ -272,7 +288,7 @@ class BaseOption(Base):
if self.impl_is_readonly():
raise AttributeError(_('"{}" ({}) object attribute "{}" is'
' read-only').format(self.__class__.__name__,
self.impl_get_display_name(),
self.impl_get_display_name(None),
name))
super().__setattr__(name, value)
@ -282,21 +298,22 @@ class BaseOption(Base):
try:
return self._path
except AttributeError as err:
raise AttributeError(_(f'"{self.impl_get_display_name()}" not part of any Config')) \
raise AttributeError(_(f'"{self.impl_get_display_name(None)}" not part of any Config')) \
from err
def impl_get_display_name(self,
dynopt=None,
subconfig: "SubConfig",
) -> str:
"""get display name
"""
if dynopt is None:
dynopt = self
if hasattr(self, '_display_name_function'):
return self._display_name_function(dynopt)
name = self.impl_get_information('doc', None)
return self._display_name_function(self, subconfig)
name = self._get_information(subconfig, 'doc', None)
if name is None or name == '':
name = dynopt.impl_getname()
if subconfig and subconfig.path:
name = subconfig.path.rsplit('.', 1)[-1]
else:
name = self._name
return name
def reset_cache(self,
@ -322,33 +339,43 @@ class BaseOption(Base):
"""
return getattr(self, '_dependencies_information', {})
def to_sub_dyoption(self,
suffixes: list[str],
):
sub_dyn = self
# retrieve all subdyn options
sub_dyns = []
while True:
sub_dyn = sub_dyn.getsubdyn()
sub_dyns.append(sub_dyn)
if not sub_dyn.issubdyn():
break
paths = []
parent_path = self.impl_getpath().rsplit('.', 1)[0]
suffix_idx = len(sub_dyns) - 1
for sub_dyn in sub_dyns:
dyn_path = sub_dyn.impl_getpath()
if dyn_path.count('.') == parent_path.count('.'):
*root_paths, dyn_path_ = parent_path.split('.', dyn_path.count('.') + 1)
else:
*root_paths, dyn_path_, child_path = parent_path.split('.', dyn_path.count('.') + 1)
paths.insert(0, child_path)
paths.insert(0, sub_dyn.impl_getname(suffixes[suffix_idx]))
suffix_idx -= 1
parent_path = '.'.join(root_paths)
if parent_path:
paths.insert(0, parent_path)
full_parent_path = '.'.join(paths)
return self.to_dynoption(full_parent_path,
suffixes,
)
def value_dependencies(self,
value: Any,
is_suffix: bool=False,
) -> Any:
"""parse dependancies to add dependencies
"""
if isinstance(value, list):
for val in value:
if isinstance(value, list):
self.value_dependencies(val, is_suffix)
elif isinstance(value, Calculation):
self.value_dependency(val, is_suffix)
elif isinstance(value, Calculation):
self.value_dependency(value, is_suffix)
def value_dependency(self,
value: Any,
is_suffix: bool=False,
) -> Any:
"""parse dependancy to add dependencies
"""
for param in chain(value.params.args, value.params.kwargs.values()):
if isinstance(param, ParamOption):
# pylint: disable=protected-access
param.option._add_dependency(self, is_suffix=is_suffix)
self._has_dependency = True
elif isinstance(param, ParamInformation):
dest = self
if isinstance(param, ParamSelfInformation):
opt = weakref.ref(self)
elif param.option:
dest = param.option
opt = weakref.ref(self)
else:
param.set_self_option(self)
opt = None
if not getattr(dest, '_dependencies_information', {}):
dest._dependencies_information = {None: []}
dest._dependencies_information[None].append(param)
dest._dependencies_information.setdefault(param.information_name, []).append(opt)

View file

@ -25,7 +25,7 @@ from typing import Any
from ..setting import undefined
from ..i18n import _
from .option import Option
from ..autolib import Calculation
from ..autolib import Calculation, get_calculated_value
from ..error import ConfigError, display_list
@ -61,13 +61,16 @@ class ChoiceOption(Option):
):
"""get values allowed by option
"""
if isinstance(self._choice_values, Calculation):
values = self._choice_values.execute(subconfig)
if values is not undefined and not isinstance(values, list):
raise ConfigError(_('the calculated values "{0}" for "{1}" is not a list'
'').format(values, self.impl_getname()))
else:
values = self._choice_values
choices = self._choice_values
if isinstance(choices, tuple):
choices = list(choices)
values = get_calculated_value(subconfig,
choices,
)[0]
if values != undefined and not isinstance(values, (list, tuple)):
raise ConfigError(_('the calculated values "{0}" for "{1}" is not a list'
'').format(values, self.impl_getname()))
return values
def validate(self,

View file

@ -20,22 +20,23 @@
# ____________________________________________________________
"""DynOptionDescription
"""
import re
import weakref
from typing import List, Any, Optional
from typing import List, Any, Optional, Dict
from itertools import chain
from ..autolib import ParamOption
from ..i18n import _
from .optiondescription import OptionDescription
from .syndynoption import CommonDyn #, SynDynLeadership
from .baseoption import BaseOption
from ..setting import ConfigBag, undefined
from ..error import ConfigError
from ..autolib import Calculation
from ..autolib import Calculation, get_calculated_value
class DynOptionDescription(OptionDescription, CommonDyn):
NAME_REGEXP = re.compile(r'^[a-zA-Z\d\-_]*$')
class DynOptionDescription(OptionDescription):
"""dyn option description
"""
__slots__ = ('_suffixes',
@ -48,25 +49,28 @@ class DynOptionDescription(OptionDescription, CommonDyn):
children: List[BaseOption],
suffixes: Calculation,
properties=None,
informations: Optional[Dict]=None,
) -> None:
# pylint: disable=too-many-arguments
super().__init__(name,
doc,
children,
properties,
informations=informations,
)
# check children + set relation to this dynoptiondescription
wself = weakref.ref(self)
for child in children:
child._setsubdyn(wself)
# add suffixes
if __debug__ and not isinstance(suffixes, Calculation):
raise ConfigError(_('suffixes in dynoptiondescription has to be a calculation'))
for param in chain(suffixes.params.args, suffixes.params.kwargs.values()):
if isinstance(param, ParamOption):
param.option._add_dependency(self,
is_suffix=True,
)
self.value_dependencies(suffixes, is_suffix=True)
# if __debug__ and not isinstance(suffixes, Calculation):
# raise ConfigError(_('suffixes in dynoptiondescription has to be a calculation'))
# for param in chain(suffixes.params.args, suffixes.params.kwargs.values()):
# if isinstance(param, ParamOption):
# param.option._add_dependency(self,
# is_suffix=True,
# )
self._suffixes = suffixes
def convert_suffix_to_path(self,
@ -98,3 +102,42 @@ class DynOptionDescription(OptionDescription, CommonDyn):
return name
path_suffix = self.convert_suffix_to_path(suffix)
return name + path_suffix
def get_suffixes(self,
parent: 'SubConfig',
) -> List[str]:
"""get dynamic suffixes
"""
subconfig = parent.get_child(self,
None,
False,
properties=None,
)
suffixes = self._suffixes
if isinstance(suffixes, list):
suffixes = suffixes.copy()
values = get_calculated_value(subconfig,
suffixes,
validate_properties=False,
)[0]
if values is None:
values = []
values_ = []
if __debug__:
if not isinstance(values, list):
raise ValueError(_('DynOptionDescription suffixes for '
f'option "{self.impl_get_display_name(subconfig)}", is not '
f'a list ({values})'))
for val in values:
cval = self.convert_suffix_to_path(val)
if not isinstance(cval, str) or re.match(NAME_REGEXP, cval) is None:
if __debug__ and cval is not None:
raise ValueError(_('invalid suffix "{}" for option "{}"'
'').format(cval,
self.impl_get_display_name(subconfig)))
else:
values_.append(val)
if __debug__ and len(values_) > len(set(values_)):
raise ValueError(_(f'DynOptionDescription "{self._name}" suffixes return a list with '
f'same values "{values_}"'''))
return values_

View file

@ -75,15 +75,15 @@ class Leadership(OptionDescription):
def _check_child_is_valid(self, child: BaseOption):
if child.impl_is_symlinkoption():
raise ValueError(_('leadership "{0}" shall not have '
"a symlinkoption").format(self.impl_get_display_name()))
"a symlinkoption").format(self.impl_get_display_name(None)))
if not isinstance(child, Option):
raise ValueError(_('leadership "{0}" shall not have '
'a subgroup').format(self.impl_get_display_name()))
'a subgroup').format(self.impl_get_display_name(None)))
if not child.impl_is_multi():
raise ValueError(_('only multi option allowed in leadership "{0}" but option '
'"{1}" is not a multi'
'').format(self.impl_get_display_name(),
child.impl_get_display_name()))
'').format(self.impl_get_display_name(None),
child.impl_get_display_name(None)))
def _check_default_value(self, child: BaseOption):
default = child.impl_getdefault()
@ -100,8 +100,8 @@ class Leadership(OptionDescription):
calculation = isinstance(default, Calculation)
if not calculation:
raise ValueError(_('not allowed default value for follower option '
f'"{child.impl_get_display_name()}" in leadership '
f'"{self.impl_get_display_name()}"'))
f'"{child.impl_get_display_name(None)}" in leadership '
f'"{self.impl_get_display_name(None)}"'))
def _setsubdyn(self,
subdyn,
@ -143,58 +143,54 @@ class Leadership(OptionDescription):
def reset(self, parent: "SubConfig") -> None:
"""reset follower value
"""
#config_bag = parent.option_bag.config_bag
values = parent.config_bag.context.get_values()
#config_bag = config_bag.copy()
#config_bag.remove_validation()
for follower in self.get_followers():
subconfig_follower = parent.get_child(follower,
None,
False,
)
# OptionBag(follower,
# None,
# config_bag,
# )
values.reset(subconfig_follower)
#
# def follower_force_store_value(self,
# value,
# config_bag: 'ConfigBag',
# owner,
# dyn=None,
# ) -> None:
# """apply force_store_value to follower
# """
# if value:
# if dyn is None:
# dyn = self
# values = config_bag.context.get_values()
# for idx, follower in enumerate(dyn.get_children(config_bag)):
# if not idx:
# # it's a master
# apply_requires = True
# indexes = [None]
# else:
# apply_requires = False
# indexes = range(len(value))
# foption_bag = OptionBag(follower,
# None,
# config_bag,
# apply_requires=apply_requires,
# )
# if 'force_store_value' not in foption_bag.properties:
# continue
# for index in indexes:
# foption_bag_index = OptionBag(follower,
# index,
# config_bag,
# )
# values.set_storage_value(foption_bag_index.path,
# index,
# values.get_value(foption_bag_index)[0],
# owner,
# )
values.reset(subconfig_follower,
validate=False,
)
def follower_force_store_value(self,
value,
subconfig: 'SubConfig',
owner,
) -> None:
"""apply force_store_value to follower
"""
if not value:
return
config_bag = subconfig.config_bag
values = config_bag.context.get_values()
for idx, follower in enumerate(self.get_children()):
sub_subconfig = subconfig.get_child(follower,
None,
False,
config_bag=config_bag,
)
if 'force_store_value' not in sub_subconfig.properties:
continue
self_path = sub_subconfig.path
if not idx:
# it's a master
apply_requires = True
indexes = [None]
else:
apply_requires = False
indexes = range(len(value))
for index in indexes:
i_sub_subconfig = subconfig.get_child(follower,
index,
False,
config_bag=config_bag,
)
values.set_storage_value(self_path,
index,
values.get_value(i_sub_subconfig)[0],
owner,
)
def pop(self,
subconfig: 'SubConfig',

View file

@ -26,9 +26,8 @@ from itertools import chain
from .baseoption import BaseOption, submulti
from ..i18n import _
from ..setting import undefined
from ..autolib import Calculation, ParamOption, ParamInformation, ParamSelfInformation
from ..autolib import Calculation
from ..error import ValueWarning, ValueErrorWarning, ValueOptionError
from .syndynoption import SynDynOption
class Option(BaseOption):
@ -48,7 +47,6 @@ class Option(BaseOption):
#
'_validators',
#
'_dependencies_information',
'_leadership',
'_choice_values',
'_choice_values_params',
@ -63,7 +61,9 @@ class Option(BaseOption):
validators: Optional[List[Calculation]]=None,
properties: Optional[List[str]]=None,
warnings_only: bool=False,
extra: Optional[Dict]=None):
extra: Optional[Dict]=None,
informations: Optional[Dict]=None,
):
_setattr = object.__setattr__
if not multi and default_multi is not None:
raise ValueError(_("default_multi is set whereas multi is False"
@ -92,8 +92,10 @@ class Option(BaseOption):
default = []
super().__init__(name,
doc,
informations,
properties=properties,
is_multi=is_multi)
is_multi=is_multi,
)
if validators is not None:
if __debug__ and not isinstance(validators, list):
raise ValueError(_(f'validators must be a list of Calculation for "{name}"'))
@ -126,10 +128,10 @@ class Option(BaseOption):
if not str_err:
raise ValueError(_('invalid default_multi value "{0}" '
'for option "{1}"').format(str(value),
self.impl_get_display_name())
self.impl_get_display_name(None))
) from err
raise ValueError(_(f'invalid default_multi value "{value}" for option '
f'"{self.impl_get_display_name()}", {str_err}')
f'"{self.impl_get_display_name(None)}", {str_err}')
) from err
if _multi is submulti:
if not isinstance(default_multi, Calculation):
@ -137,7 +139,7 @@ class Option(BaseOption):
raise ValueError(_('invalid default_multi value "{0}" '
'for option "{1}", must be a list for a submulti'
'').format(str(default_multi),
self.impl_get_display_name()))
self.impl_get_display_name(None)))
for value in default_multi:
test_multi_value(value)
else:
@ -164,43 +166,6 @@ class Option(BaseOption):
default = tuple(default)
_setattr(self, '_default', default)
def value_dependencies(self,
value: Any,
) -> Any:
"""parse dependancies to add dependencies
"""
if isinstance(value, list):
for val in value:
if isinstance(value, list):
self.value_dependencies(val)
elif isinstance(value, Calculation):
self.value_dependency(val)
elif isinstance(value, Calculation):
self.value_dependency(value)
def value_dependency(self,
value: Any,
) -> Any:
"""parse dependancy to add dependencies
"""
for param in chain(value.params.args, value.params.kwargs.values()):
if isinstance(param, ParamOption):
# pylint: disable=protected-access
param.option._add_dependency(self)
self._has_dependency = True
elif isinstance(param, ParamInformation):
dest = self
if isinstance(param, ParamSelfInformation):
opt = self
elif param.option:
dest = param.option
opt = self
else:
opt = None
if not getattr(dest, '_dependencies_information', {}):
dest._dependencies_information = {}
dest._dependencies_information.setdefault(param.information_name, []).append(opt)
#__________________________________________________________________________
# option's information
@ -326,7 +291,8 @@ class Option(BaseOption):
**kwargs,
)
except ValueWarning as warn:
warnings.warn_explicit(ValueWarning(val,
warnings.warn_explicit(ValueWarning(subconfig,
val,
self.get_type(),
self,
str(warn),
@ -343,7 +309,7 @@ class Option(BaseOption):
return
if isinstance(_value, list):
raise ValueError(_('which must not be a list').format(_value,
self.impl_get_display_name()),
self.impl_get_display_name(subconfig)),
)
if isinstance(_value, Calculation) and not subconfig:
return
@ -361,7 +327,8 @@ class Option(BaseOption):
is_warnings_only)
except ValueError as err:
if is_warnings_only:
warnings.warn_explicit(ValueWarning(_value,
warnings.warn_explicit(ValueWarning(subconfig,
_value,
self.get_type(),
self,
str(err),
@ -420,12 +387,14 @@ class Option(BaseOption):
except ValueError as err:
if not subconfig or \
'demoting_error_warning' not in subconfig.config_bag.properties:
raise ValueOptionError(val,
raise ValueOptionError(subconfig,
val,
self.get_type(),
self,
str(err),
err_index) from err
warnings.warn_explicit(ValueErrorWarning(val,
warnings.warn_explicit(ValueErrorWarning(subconfig,
val,
self.get_type(),
self,
str(err),
@ -476,16 +445,6 @@ class Option(BaseOption):
#pylint: disable=not-callable
return leadership()
def to_dynoption(self,
rootpath: str,
suffixes: list[str],
) -> SynDynOption:
"""tranforme a dynoption to a syndynoption
"""
return SynDynOption(self,
rootpath,
suffixes,
)
def validate(self, value: Any):
"""option needs a validate function
"""

View file

@ -21,7 +21,7 @@
"""OptionDescription
"""
import weakref
from typing import Optional, Iterator, Union, List
from typing import Optional, Iterator, Union, List, Dict
from ..i18n import _
@ -87,6 +87,10 @@ class CacheOptionDescription(BaseOption):
dependencies_information,
)
else:
informations = option.get_dependencies_information()
if informations:
for param in informations.pop(None):
del param.self_option
for information, options in option.get_dependencies_information().items():
if None in options:
dependencies_information.setdefault(information, []).append(option)
@ -105,71 +109,86 @@ class CacheOptionDescription(BaseOption):
self._cache_dependencies_information = dependencies_information # pylint: disable=attribute-defined-outside-init
self._path = None # pylint: disable=attribute-defined-outside-init,no-member
self._set_readonly()
#
# def impl_build_force_store_values(self,
# config_bag: ConfigBag,
# ) -> None:
# """set value to force_store_values option
# """
# # pylint: disable=too-many-branches
# def do_option_bags(option):
# if option.issubdyn():
# dynopt = option.getsubdyn()
# yield from dynopt.get_sub_children(option,
# config_bag,
# index=None,
# )
# else:
# yield OptionBag(option,
# None,
# config_bag,
# properties=None,
# )
# if 'force_store_value' not in config_bag.properties:
# return
# values = config_bag.context.get_values()
# for option in self._cache_force_store_values:
# if option.impl_is_follower():
# leader = option.impl_get_leadership().get_leader()
# for leader_option_bag in do_option_bags(leader):
# leader_option_bag.properties = frozenset()
# follower_len = len(values.get_value(leader_option_bag)[0])
# if option.issubdyn():
# doption = option.to_dynoption(leader_option_bag.option.rootpath,
# leader_option_bag.option.get_current_suffixes(),
# )
# else:
# doption = option
# subpath = doption.impl_getpath()
# for index in range(follower_len):
# option_bag = OptionBag(doption,
# index,
# config_bag,
# properties=frozenset(),
# )
# if values.hasvalue(subpath, index=index):
# continue
# value = values.get_value(option_bag)[0]
# if value is None:
# continue
# values.set_storage_value(subpath,
# index,
# value,
# owners.forced,
# )
# else:
# for option_bag in do_option_bags(option):
# option_bag.properties = frozenset()
# value = values.get_value(option_bag)[0]
# if value is None:
# continue
# if values.hasvalue(option_bag.path):
# continue
# values.set_storage_value(option_bag.path,
# None,
# value,
# owners.forced,
# )
def impl_build_force_store_values(self,
config_bag: ConfigBag,
) -> None:
"""set value to force_store_values option
"""
# pylint: disable=too-many-branches
context = config_bag.context
if 'force_store_value' not in config_bag.properties:
return
values = config_bag.context.get_values()
for option in self._cache_force_store_values:
if option.issubdyn():
paths = option.impl_getpath().split('.')
parents = [config_bag.context.get_root(config_bag)]
for name in paths:
new_parents = []
for parent in parents:
doption = parent.option.get_child(name,
config_bag,
parent,
allow_dynoption=True,
)
if doption.impl_is_dynoptiondescription():
new_parents.extend(parent.dyn_to_subconfig(doption,
True,
)
)
else:
new_parents.append(parent.get_child(doption,
None,
True,
name=name,
))
parents = new_parents
subconfigs = new_parents
else:
subconfigs = [context.get_sub_config(config_bag,
option.impl_getpath(),
None,
properties=None,
validate_properties=False,
)]
if option.impl_is_follower():
for follower_subconfig in subconfigs:
parent = follower_subconfig.parent
follower_len = parent.get_length_leadership()
for index in range(follower_len):
if values.hasvalue(follower_subconfig.path,
index=index,
):
continue
idx_follower_subconfig = parent.get_child(follower_subconfig.option,
index,
validate_properties=False,
)
value = values.get_value(idx_follower_subconfig)[0]
if value is None:
continue
values.set_storage_value(follower_subconfig.path,
index,
value,
owners.forced,
)
else:
for subconfig in subconfigs:
subconfig.properties = frozenset()
value = values.get_value(subconfig)[0]
if value is None:
continue
if values.hasvalue(subconfig.path):
continue
values.set_storage_value(subconfig.path,
None,
value,
owners.forced,
)
class OptionDescriptionWalk(CacheOptionDescription):
@ -228,7 +247,7 @@ class OptionDescriptionWalk(CacheOptionDescription):
'in root optiondescription'
))
raise AttributeError(_(f'unknown option "{name}" '
f'in optiondescription "{self.impl_get_display_name()}"'
f'in optiondescription "{self.impl_get_display_name(parent)}"'
))
def get_children(self) -> List[BaseOption]:
@ -278,7 +297,9 @@ class OptionDescription(OptionDescriptionWalk):
name: str,
doc: str,
children: List[BaseOption],
properties=None) -> None:
properties=None,
informations: Optional[Dict]=None,
) -> None:
"""
:param children: a list of options (including optiondescriptions)
@ -286,8 +307,10 @@ class OptionDescription(OptionDescriptionWalk):
assert isinstance(children, list), _('children in optiondescription "{}" '
'must be a list').format(name)
super().__init__(name,
doc=doc,
properties=properties)
doc,
informations,
properties=properties,
)
child_names = []
if __debug__:
dynopt_names = []

View file

@ -20,7 +20,7 @@
# ____________________________________________________________
"""SymLinkOption link to an other option
"""
from typing import Any
from typing import Any, Optional, Dict
from .baseoption import BaseOption, valid_name
from ..error import ConfigError
from ..i18n import _
@ -41,55 +41,46 @@ class SymLinkOption(BaseOption):
if not isinstance(opt, BaseOption) or \
opt.impl_is_optiondescription() or \
opt.impl_is_symlinkoption():
raise ValueError(_('malformed symlinkoption must be an option for symlink {0}'
'').format(name))
_setattr = object.__setattr__
_setattr(self, '_name', name)
_setattr(self, '_opt', opt)
raise ValueError(_(f'malformed symlink second parameters must be an option for "{name}", not {opt}'))
self._name = name
self._opt = opt
opt._add_dependency(self)
def __getattr__(self,
name: str,
) -> Any:
if name == '_subdyns':
return None
if name == '_path':
raise AttributeError()
return getattr(self._opt, name)
def _setsubdyn(self,
subdyn,
) -> None:
raise ConfigError(_('cannot set symlinkoption in a '
'dynoptiondescription'))
def impl_has_dependency(self,
self_is_dep: bool=True,
) -> bool:
"""If self_is_dep is True, it has dependency (self._opt), so return True
if self_is_dep is False, cannot has validation or callback, so return False
"""
return self_is_dep
def impl_is_symlinkoption(self) -> bool:
"""it's a symlinkoption
"""
return True
def impl_is_leader(self) -> bool:
return False
def impl_is_follower(self) -> bool:
return False
def impl_getopt(self) -> BaseOption:
"""get to linked option
"""
return self._opt
def issubdyn(self) -> bool:
"""it's not a sub dyn option
"""
return False
def impl_is_multi(self) -> bool:
"""is it a multi?
"""
if self._opt.issubdyn():
if self._opt.impl_is_multi():
return True
return self._opt.impl_is_multi()
if self._opt.issubdyn() or self.issubdyn():
if self.issubdyn() != self._opt.issubdyn():
return self._opt.issubdyn()
return self._opt.issubdyn() in self.get_sub_dyns()
return False
def impl_is_submulti(self) -> bool:
"""is it a submulti?

View file

@ -1,351 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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/>.
#
# The original `Config` design model is unproudly borrowed from
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
# the whole pypy projet is under MIT licence
# ____________________________________________________________
"""SynDynOption internal option, it's an instanciate synoption
"""
import re
from typing import Optional, Iterator, Any, List, Tuple
from .baseoption import BaseOption
from ..i18n import _
from ..setting import ConfigBag, undefined
NAME_REGEXP = re.compile(r'^[a-zA-Z\d\-_]*$')
class CommonDyn:
def get_path(self,
config_bag,
):
if config_bag is undefined or \
config_bag.context.get_description() == self:
return ''
return self.impl_getpath()
def get_suffixes(self,
parent: 'SubConfig',
) -> List[str]:
"""get dynamic suffixes
"""
subconfig = parent.get_child(self,
None,
False,
properties=None,
)
values = self._suffixes.execute(subconfig)
if values is None:
values = []
values_ = []
if __debug__:
if not isinstance(values, list):
raise ValueError(_('DynOptionDescription suffixes for '
f'option "{self.impl_get_display_name()}", is not '
f'a list ({values})'))
for val in values:
cval = self.convert_suffix_to_path(val)
if not isinstance(cval, str) or re.match(NAME_REGEXP, cval) is None:
if __debug__ and cval is not None:
raise ValueError(_('invalid suffix "{}" for option "{}"'
'').format(cval,
self.impl_get_display_name()))
else:
values_.append(val)
if __debug__ and len(values_) > len(set(values_)):
raise ValueError(_(f'DynOptionDescription "{self._name}" suffixes return a list with '
f'same values "{values_}"'''))
return values_
def split_path(self,
option,
*,
dynoption=None,
) -> Tuple[str, str]:
"""self.impl_getpath() is something like root.xxx.dynoption_path
option.impl_getpath() is something like root.xxx.dynoption_path.sub.path
must return ('root.xxx.', '.sub')
"""
if dynoption is None:
self_path = self.impl_getpath()
else:
self_path = dynoption.impl_getpath()
root_path = self_path.rsplit('.', 1)[0] if '.' in self_path else None
#
if self.option_is_self(option):
sub_path = ''
else:
option_path = option.impl_getpath()
if root_path:
if isinstance(option, SynDynLeadership):
count_root_path = option_path.count('.') - root_path.count('.')
root_path = option_path.rsplit('.', count_root_path)[0]
root_path += '.'
self_number_child = self_path.count('.') + 1
option_sub_path = option_path.split('.', self_number_child)[-1]
sub_path = '.' + option_sub_path.rsplit('.', 1)[0] if '.' in option_sub_path else ''
return root_path, sub_path
class Syn:
__slots__ = ('rootpath',
'opt',
'_current_suffixes',
'__weakref__')
def __init__(self,
opt: BaseOption,
rootpath: str,
suffixes: list,
) -> None:
self.opt = opt
self.rootpath = rootpath
self._current_suffixes = suffixes
def __getattr__(self,
name: str,
) -> Any:
# if not in SynDynOptionDescription, get value in self.opt
return getattr(self.opt,
name,
)
def impl_get_display_name(self) -> str:
return self.opt.impl_get_display_name(self)
def get_current_suffixes(self) -> str:
"""get suffixes
"""
return self.current__suffixes
def impl_is_dynsymlinkoption(self) -> bool:
"""it's a dynsymlinkoption
"""
return True
def impl_getpath(self) -> str:
"""get path
"""
path = self.impl_getname()
if self.rootpath:
path = f'{self.rootpath}.{path}'
return path
class SynDescr(Syn):
__slots__ = ('opt',
'rootpath',
'_current_suffixes',
)
def get_child(self,
name: str,
config_bag: ConfigBag,
*,
allow_dynoption: bool=False,
):
"""get children
"""
# if not dyn
option = self.get_child_not_dynamic(name,
allow_dynoption,
)
if option:
if allow_dynoption and option.impl_is_dynoptiondescription():
return option
return option.to_dynoption(self.impl_getpath(),
self._current_suffixes,
)
for child in self.opt._children[1]: # pylint: disable=no-member
if not child.impl_is_dynoptiondescription():
continue
for suffix in child.get_suffixes(config_bag):
if name != child.impl_getname(suffix):
continue
return child.to_dynoption(self.impl_getpath(),
self._current_suffixes + [suffix],
)
raise AttributeError(_(f'unknown option "{name}" '
f'in optiondescription "{self.impl_get_display_name()}"'
))
def get_children(self,
config_bag: ConfigBag,
):
# pylint: disable=unused-argument
"""get children
"""
for child in self.opt._children[1]:
if child.impl_is_dynoptiondescription():
dynchild = self.get_child(child.impl_getname(),
config_bag,
allow_dynoption=True,
)
for d in dynchild.get_sub_children(dynchild,
config_bag,
):
yield d.option
# yield from dynchild.get_sub_children(dynchild,
# config_bag,
# )
#for suffix in dynchild.get_suffixes(config_bag):
# yield child.to_dynoption(self.impl_getpath(),
# self._suffixes + [suffix],
# )
else:
yield child.to_dynoption(self.impl_getpath(),
self._current_suffixes,
)
def get_children_recursively(self,
bytype: Optional[BaseOption],
byname: Optional[str],
config_bag: ConfigBag,
self_opt: BaseOption=None,
) -> BaseOption:
# pylint: disable=unused-argument
"""get children recursively
"""
for option in self.opt.get_children_recursively(bytype,
byname,
config_bag,
self,
):
yield option
def get_child_not_dynamic(self,
name,
allow_dynoption,
):
children = self.opt._children
if name in children[0]: # pylint: disable=no-member
option = children[1][children[0].index(name)] # pylint: disable=no-member
if option.impl_is_dynoptiondescription() and not allow_dynoption:
raise AttributeError(_(f'unknown option "{name}" '
"in root optiondescription (it's a dynamic option)"
))
return SubDynOptionDescription(option,
self.impl_getpath(),
self._current_suffixes,
)
class SynDynOption(Syn):
"""SynDynOption is an Option include un DynOptionDescription with specified prefix
"""
__slots__ = ()
def impl_get_leadership(self): # pylint: disable=inconsistent-return-statements
"""is it a leadership?
"""
leadership = self.opt.impl_get_leadership()
if leadership:
rootpath = self.rootpath.rsplit('.', 1)[0]
return leadership.to_dynoption(rootpath,
self._current_suffixes,
)
#
#
#class SubDynOptionDescription(SynDescr, CommonDyn):
# def option_is_self(self,
# option,
# ) -> bool:
# return self.opt.option_is_self(option.opt)
#
# def get_sub_children(self,
# option,
# config_bag,
# *,
# index=None,
# properties=undefined,
# ):
# root_path, sub_path = self.split_path(option)
# for suffix in self.get_suffixes(config_bag):
# if self.option_is_self(option):
# parent_path = root_path
# elif root_path:
# parent_path = root_path + self.impl_getname(suffix) + sub_path
# else:
# parent_path = self.impl_getname(suffix) + sub_path
# yield OptionBag(option.to_dynoption(parent_path,
# [suffix],
# ),
# index,
# config_bag,
# properties=properties,
# ori_option=option
# )
#
#
#class SynDynOptionDescription(SynDescr):
# """SynDynOptionDescription internal option, it's an instanciate synoptiondescription
# """
# def impl_getname(self) -> str:
# """get name
# """
# if self.opt.impl_is_dynoptiondescription():
# return self.opt.impl_getname(self._current_suffixes[-1])
# return self.opt.impl_getname()
#
# def getsubdyn(self):
# return self.opt
#
#
#class SynDynLeadership(SynDynOptionDescription):
# """SynDynLeadership internal option, it's an instanciate synoptiondescription
# """
# def get_leader(self) -> SynDynOption:
# """get the leader
# """
# return self.opt.get_leader().to_dynoption(self.impl_getpath(),
# self._current_suffixes,
# )
#
# def get_followers(self) -> Iterator[SynDynOption]:
# """get followers
# """
# subpath = self.impl_getpath()
# for follower in self.opt.get_followers():
# yield follower.to_dynoption(subpath,
# self._current_suffixes,
# )
#
# def pop(self,
# *args,
# **kwargs,
# ) -> None:
# """pop value for a follower
# """
# self.opt.pop(*args,
# followers=self.get_followers(),
# **kwargs,
# )
#
# def follower_force_store_value(self,
# value,
# config_bag,
# owner,
# ) -> None:
# """force store value for a follower
# """
# self.opt.follower_force_store_value(value,
# config_bag,
# owner,
# dyn=self,
# )

View file

@ -1,235 +0,0 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2017-2023 Team tiramisu (see AUTHORS for all contributors)
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the
# Free Software Foundation, either version 3 of the License, or (at your
# option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
# details.
#
# 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/>.
#
# The original `Config` design model is unproudly borrowed from
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
# the whole pypy projet is under MIT licence
# ____________________________________________________________
"""SynDynOptionDescription and SynDynLeadership internal option
it's an instanciate synoptiondescription
"""
from typing import Optional, Iterator, Any, List
from ..i18n import _
from ..setting import ConfigBag, undefined
from .baseoption import BaseOption
from .syndynoption import SynDynOption
class Syn:
__slots__ = ('opt',
'rootpath',
'_suffixes',
)
def __init__(self,
opt: BaseOption,
rootpath: str,
suffixes: list,
) -> None:
self.opt = opt
self.rootpath = rootpath
self._suffixes = suffixes
def impl_get_display_name(self) -> str:
return self.opt.impl_get_display_name(self)
def get_child(self,
name: str,
config_bag: ConfigBag,
*,
allow_dynoption: bool=False,
):
"""get children
"""
# if not dyn
option = self.opt.get_child_not_dynamic(name,
allow_dynoption,
)
if option:
if allow_dynoption and option.impl_is_dynoptiondescription():
return option
return option.to_dynoption(self.impl_getpath(),
self._suffixes,
)
for child in self.opt._children[1]: # pylint: disable=no-member
if not child.impl_is_dynoptiondescription():
continue
for suffix in child.get_suffixes(config_bag,
dynoption=self,
):
if name != child.impl_getname(suffix):
continue
return child.to_dynoption(self.impl_getpath(),
self._suffixes + [suffix],
)
raise AttributeError(_(f'unknown option "{name}" '
f'in optiondescription "{self.impl_get_display_name()}"'
))
def get_children(self,
config_bag: ConfigBag,
):
# pylint: disable=unused-argument
"""get children
"""
for child in self.opt._children[1]:
if child.impl_is_dynoptiondescription():
for suffix in child.get_suffixes(config_bag,
dynoption=self,
):
yield child.to_dynoption(self.impl_getpath(),
self._suffixes + [suffix],
)
else:
yield child.to_dynoption(self.impl_getpath(),
self._suffixes,
)
def get_children_recursively(self,
bytype: Optional[BaseOption],
byname: Optional[str],
config_bag: ConfigBag,
self_opt: BaseOption=None,
) -> BaseOption:
# pylint: disable=unused-argument
"""get children recursively
"""
for option in self.opt.get_children_recursively(bytype,
byname,
config_bag,
self,
):
yield option
def get_suffixes(self) -> str:
"""get suffixes
"""
return self._suffixes
def impl_is_dynsymlinkoption(self) -> bool:
"""it's a dynsymlinkoption
"""
return True
class SubDynOptionDescription(Syn):
def impl_getpath(self) -> str:
"""get path
"""
path = self.opt.impl_getname()
if self.rootpath:
path = f'{self.rootpath}.{path}'
return path
def getsubdyn(self):
return self.opt.getsubdyn()
def impl_is_optiondescription(self):
return True
def impl_is_symlinkoption(self):
return False
def impl_is_leadership(self):
return False
def impl_is_dynoptiondescription(self) -> bool:
return True
def impl_getproperties(self):
return self.opt.impl_getproperties()
class SynDynOptionDescription(Syn):
"""SynDynOptionDescription internal option, it's an instanciate synoptiondescription
"""
def __getattr__(self,
name: str,
) -> Any:
# if not in SynDynOptionDescription, get value in self.opt
return getattr(self.opt,
name,
)
def impl_getname(self) -> str:
"""get name
"""
if self.opt.impl_is_dynoptiondescription():
return self.opt.impl_getname(self._suffixes[-1])
return self.opt.impl_getname()
def impl_getpath(self) -> str:
"""get path
"""
path = self.impl_getname()
if self.rootpath:
path = f'{self.rootpath}.{path}'
return path
def getsubdyn(self):
return self.opt
class SynDynLeadership(SynDynOptionDescription):
"""SynDynLeadership internal option, it's an instanciate synoptiondescription
"""
def get_leader(self) -> SynDynOption:
"""get the leader
"""
return self.opt.get_leader().to_dynoption(self.impl_getpath(),
self._suffixes,
)
def get_followers(self) -> Iterator[SynDynOption]:
"""get followers
"""
subpath = self.impl_getpath()
for follower in self.opt.get_followers():
yield follower.to_dynoption(subpath,
self._suffixes,
)
def pop(self,
*args,
**kwargs,
) -> None:
"""pop value for a follower
"""
self.opt.pop(*args,
followers=self.get_followers(),
**kwargs,
)
def follower_force_store_value(self,
value,
config_bag,
owner,
) -> None:
"""force store value for a follower
"""
self.opt.follower_force_store_value(value,
config_bag,
owner,
dyn=self,
)
def get_suffixes(self) -> str:
"""get suffix
"""
return self._suffixes

View file

@ -17,7 +17,7 @@
# ____________________________________________________________
from typing import Union, Set
from itertools import chain
from .error import PropertiesOptionError, ConstError, ConfigError, LeadershipError
from .error import PropertiesOptionError, ConstError, ConfigError, LeadershipError, display_list
from .i18n import _
@ -156,63 +156,6 @@ class Undefined:
undefined = Undefined()
#
#
#class OptionBag:
# """Object to store information for an option
# """
# __slots__ = ('option', # current option
# 'path',
# 'index',
# 'config_bag',
# 'ori_option', # original option (for example useful for symlinkoption)
# 'properties', # properties of current option
# 'apply_requires', # apply requires or not for this option
# 'suffixes',
# )
#
# # pylint: disable=too-many-arguments
# def __init__(self,
# option,
# index,
# config_bag,
# *,
# path=None,
# properties=undefined,
# parent: 'SubConfig'=None,
# ori_option=None,
# apply_requires=True,
# suffixes=None
# ):
# self.index = index
# self.config_bag = config_bag
# self.option = option
# if ori_option is not None:
# self.ori_option = ori_option
# if config_bag is undefined:
# self.path = path
# elif option:
# if properties is not undefined:
# self.properties = properties
# self.suffixes = suffixes
#
# def __getattr__(self, key):
# if key == 'ori_option':
# return self.option
# if key == 'apply_requires':
# return True
# return None
#
# def copy(self):
# """copy OptionBag
# """
# option_bag = OptionBag(None,
# None,
# None,
# )
# for key in self.__slots__:
# setattr(option_bag, key, getattr(self, key))
# return option_bag
class ConfigBag:
@ -390,7 +333,6 @@ class Settings:
'ro_remove',
'rw_append',
'rw_remove',
'default_properties',
)
def __init__(self):
@ -401,9 +343,8 @@ class Settings:
:param storage: the storage type
"""
# generic owner
self._properties = {}
self._properties = {None: {None: DEFAULT_PROPERTIES}}
self._permissives = {}
self.default_properties = DEFAULT_PROPERTIES
self.ro_append = RO_APPEND
self.ro_remove = RO_REMOVE
self.rw_append = RW_APPEND
@ -412,35 +353,19 @@ class Settings:
# ____________________________________________________________
# get properties and permissive methods
def get_context_properties(self,
cache,
):
def get_context_properties(self):
"""get context properties
"""
is_cached, props, _ = cache.getcache(None,
'context_props',
expiration=False,
)
if not is_cached:
props = self.get_stored_properties(None,
None,
self.default_properties,
)
cache.setcache(None,
props,
type_='properties',
)
return props
return self.get_personalize_properties()
def get_stored_properties(self,
path: Union[None, str],
index: Union[None, int],
default_properties: Set[str],
) -> Set[str]:
def get_personalize_properties(self,
path: Union[None, str]=None,
index: Union[None, int]=None,
) -> Set[str]:
"""Get the properties modified by user for a path or index
"""
if path not in self._properties or index not in self._properties[path]:
return frozenset(default_properties)
return frozenset()
return self._properties[path][index]
def getproperties(self,
@ -467,18 +392,17 @@ class Settings:
if not is_cached:
props = set()
# if index, get option's properties (without index) too
p_props = self.get_stored_properties(subconfig.path,
None,
option.impl_getproperties(),
)
p_props = [option.impl_getproperties()]
props_config = self.get_personalize_properties(subconfig.path)
if props_config:
p_props.append(props_config)
if subconfig.index is not None:
p_props = chain(p_props,
self.get_stored_properties(subconfig.path,
subconfig.index,
option.impl_getproperties(),
)
)
for prop in p_props:
props_config = self.get_personalize_properties(subconfig.path,
subconfig.index,
)
if props_config:
p_props.append(props_config)
for prop in chain(*p_props):
if uncalculated or isinstance(prop, str):
if not help_property:
props.add(prop)
@ -520,6 +444,12 @@ class Settings:
props,
type_='properties',
)
if subconfig.parent and subconfig.parent.raises_properties:
parent_properties = subconfig.parent.raises_properties
parent_properties -= self.getpermissives(subconfig)
if help_property:
parent_properties = {(prop, prop) for prop in parent_properties}
return props | parent_properties
return props
def get_context_permissives(self):
@ -566,7 +496,7 @@ class Settings:
def set_context_properties(self, properties, context):
"""set context properties
"""
self._properties.setdefault(None, {})[None] = properties
self._properties[None][None] = properties
context.reset_cache(None)
def setproperties(self,
@ -580,8 +510,8 @@ class Settings:
if not opt.impl_is_optiondescription() and opt.impl_is_leader():
not_allowed_properties = properties - ALLOWED_LEADER_PROPERTIES
if not_allowed_properties:
raise LeadershipError(_('leader cannot have "{list(not_allowed_properties)}" '
'property'))
raise LeadershipError(_(f'leader cannot have "{display_list(not_allowed_properties)}" '
'property'))
if ('force_default_on_freeze' in properties or \
'force_metaconfig_on_freeze' in properties) and 'frozen' not in properties:
raise LeadershipError(_('a leader ({opt.impl_get_display_name()}) cannot have '
@ -682,9 +612,11 @@ class Settings:
# validate properties
def calc_raises_properties(self,
subconfig,
*,
apply_requires=True,
uncalculated=False,
transitive_raise=True,
not_unrestraint=False,
):
"""raise if needed
"""
@ -698,16 +630,23 @@ class Settings:
)
return self._calc_raises_properties(subconfig,
option_properties,
not_unrestraint,
)
def _calc_raises_properties(self,
subconfig,
option_properties,
not_unrestraint,
):
raises_properties = subconfig.config_bag.properties - SPECIAL_PROPERTIES
config_bag =subconfig.config_bag
if not_unrestraint and config_bag.is_unrestraint:
context_properties = config_bag.true_properties
else:
context_properties = config_bag.properties
raises_properties = context_properties - SPECIAL_PROPERTIES
# remove global permissive properties
if raises_properties and 'permissive' in raises_properties:
raises_properties -= subconfig.config_bag.permissives
raises_properties -= config_bag.permissives
properties = option_properties & raises_properties
# at this point it should not remain any property for the option
return properties
@ -736,6 +675,7 @@ class Settings:
calc_properties = []
for property_ in self._calc_raises_properties(subconfig,
set(help_properties.keys()),
False,
):
calc_properties.append(help_properties[property_])
calc_properties = frozenset(calc_properties)
@ -799,10 +739,7 @@ class Settings:
append,
config_bag,
):
props = self.get_stored_properties(None,
None,
self.default_properties,
)
props = self.get_personalize_properties()
modified = False
if remove & props:
props = props - remove

View file

@ -6,7 +6,7 @@ from copy import copy
from itertools import chain
from .error import ValueWarning, ValueErrorWarning, PropertiesOptionError, ConfigError
from .setting import undefined
from .option.syndynoption import SynDynOption
#from .option.syndynoption import SynDynOption
from . import RegexpOption, ChoiceOption, ParamOption
from .i18n import _
@ -233,8 +233,8 @@ class Requires(object):
def add(self, path, childapi, form):
#collect id of all options
child = childapi.get()
if isinstance(child, SynDynOption):
child = child.opt
# if isinstance(child, SynDynOption):
# child = child.opt
self.options[child] = path
current_action = None

View file

@ -18,7 +18,7 @@
from typing import Union, Optional, List, Any
from .error import ConfigError
from .setting import owners, undefined, forbidden_owners
from .autolib import Calculation
from .autolib import Calculation, get_calculated_value
from .i18n import _
@ -106,9 +106,9 @@ class Values:
# the value is a default value
# get it
value = self.get_default_value(subconfig)
value, has_calculation = self.get_calculated_value(subconfig,
value,
)
value, has_calculation = get_calculated_value(subconfig,
value,
)
return value, has_calculation
def get_default_value(self,
@ -125,9 +125,9 @@ class Values:
return msubconfig.config_bag.context.get_values().get_cached_value(msubconfig)
# now try to get calculated value:
value, _has_calculation = self.get_calculated_value(subconfig,
subconfig.option.impl_getdefault(),
)
value, _has_calculation = get_calculated_value(subconfig,
subconfig.option.impl_getdefault(),
)
if subconfig.index is not None and isinstance(value, (list, tuple)) \
and (not subconfig.option.impl_is_submulti() or \
not value or isinstance(value[0], list)):
@ -139,38 +139,14 @@ class Values:
else:
# no value for this index, retrieve default multi value
# default_multi is already a list for submulti
value, _has_calculation = self.get_calculated_value(subconfig,
subconfig.option.impl_getdefault_multi(),
)
value, _has_calculation = get_calculated_value(subconfig,
subconfig.option.impl_getdefault_multi(),
)
self.reset_cache_after_calculation(subconfig,
value,
)
return value
def get_calculated_value(self,
subconfig: "SubConfig",
value: Any,
*,
reset_cache: bool=True,
) -> Any:
"""value could be a calculation, in this case do calculation
"""
has_calculation = False
if isinstance(value, Calculation):
value = value.execute(subconfig)
has_calculation = True
elif isinstance(value, list):
# if value is a list, do subcalculation
for idx, val in enumerate(value):
value[idx], _has_calculation = self.get_calculated_value(subconfig,
val,
reset_cache=False,
)
if _has_calculation:
has_calculation = True
if reset_cache:
self.reset_cache_after_calculation(subconfig,
value,
)
return value, has_calculation
#______________________________________________________________________
def check_force_to_metaconfig(self,
subconfig: "OptionBag",
@ -210,7 +186,9 @@ class Values:
# calculated value is a new value, so reset cache
subconfig.config_bag.context.reset_cache(subconfig)
# and manage force_store_value
# self._set_force_value_suffix(subconfig)
self._set_force_value_suffix(subconfig,
value,
)
def isempty(self,
subconfig: "SubConfig",
@ -279,12 +257,14 @@ class Values:
elif 'validator' in setting_properties and has_calculation:
cache = subconfig.config_bag.context.get_values_cache()
cache.delcache(subconfig.path)
# if 'force_store_value' in setting_properties and option_bag.option.impl_is_leader():
# leader = option_bag.option.impl_get_leadership()
# leader.follower_force_store_value(value,
# option_bag.config_bag,
# owners.forced,
# )
if 'force_store_value' in setting_properties and subconfig.option.impl_is_leader():
leader = subconfig.option.impl_get_leadership()
parent = subconfig.parent
parent._length = len(value)
leader.follower_force_store_value(value,
parent,
owners.forced,
)
def setvalue_validation(self,
subconfig: "SubConfig",
@ -296,10 +276,9 @@ class Values:
# First validate properties with this value
opt = subconfig.option
settings.validate_frozen(subconfig)
val, has_calculation = self.get_calculated_value(subconfig,
value,
reset_cache=False,
)
val, has_calculation = get_calculated_value(subconfig,
value,
)
settings.validate_mandatory(subconfig,
val,
)
@ -327,7 +306,9 @@ class Values:
value,
owner,
)
# self._set_force_value_suffix(option_bag)
self._set_force_value_suffix(subconfig,
value,
)
def set_storage_value(self,
path,
@ -339,47 +320,44 @@ class Values:
"""
self._values.setdefault(path, {})[index] = [value, owner]
# def _set_force_value_suffix(self,
# option_bag: OptionBag,
# ) -> None:
# """ force store value for an option for suffixes
# """
# # pylint: disable=too-many-locals
# if 'force_store_value' not in option_bag.config_bag.properties:
# return
#
# for woption in option_bag.option._get_suffixes_dependencies(): # pylint: disable=protected-access
# # options from dependencies are weakref
# option = woption()
# force_store_options = []
# for coption in option.get_children_recursively(None,
# None,
# option_bag.config_bag,
# option_suffixes=[],
# ):
# if 'force_store_value' in coption.impl_getproperties():
# force_store_options.append(coption)
# if not force_store_options:
# continue
# for coption in force_store_options:
# if coption.impl_is_follower():
# leader = coption.impl_get_leadership().get_leader()
# loption_bag = OptionBag(leader,
# None,
# option_bag.config_bag,
# properties=frozenset(),
# )
# indexes = range(len(self.get_value(loption_bag)[0]))
# else:
# indexes = [None]
# for index in indexes:
# for coption_bag in option.get_sub_children(coption,
# option_bag.config_bag,
# index=index,
# properties=frozenset(),
# ):
# default_value = [self.get_value(coption_bag)[0], owners.forced]
# self._values.setdefault(coption_bag.path, {})[index] = default_value
def _set_force_value_suffix(self,
subconfig: 'SubConfig',
suffix_values,
) -> None:
""" force store value for an option for suffixes
"""
# pylint: disable=too-many-locals
if 'force_store_value' not in subconfig.config_bag.properties:
return
config_bag = subconfig.config_bag
context = config_bag.context
for woption in subconfig.option._get_suffixes_dependencies(): # pylint: disable=protected-access
options = subconfig.get_common_child(woption(),
true_path=subconfig.path,
validate_properties=False,
)
if not isinstance(options, list):
options = [options]
for option in options:
parent = option.parent
for suffix in suffix_values:
name = option.option.impl_getname(suffix)
opt_subconfig = parent.get_child(option.option,
None,
False,
suffix=suffix,
name=name,
)
for walk_subconfig in context.walk(opt_subconfig,
no_value=True,
validate_properties=False,
):
if 'force_store_value' not in walk_subconfig.properties:
continue
default_value = [self.get_value(walk_subconfig)[0], owners.forced]
self._values.setdefault(walk_subconfig.path, {})[walk_subconfig.index] = default_value
def _get_modified_parent(self,
subconfig: "SubConfig",
@ -462,9 +440,9 @@ class Values:
was present
:returns: a `setting.owners.Owner` object
"""
context = subconfig.config_bag.context
settings = context.get_settings()
settings.validate_properties(subconfig)
# context = subconfig.config_bag.context
# settings = context.get_settings()
# settings.validate_properties(subconfig)
if 'frozen' in subconfig.properties and \
'force_default_on_freeze' in subconfig.properties:
return owners.default
@ -509,7 +487,7 @@ class Values:
if not self.hasvalue(subconfig.path,
index=subconfig.index,
):
raise ConfigError(_(f'no value for {subconfig.path} cannot change owner to {owner}'))
raise ConfigError(_(f'"{subconfig.path}" is a default value, so we cannot change owner to "{owner}"'))
subconfig.config_bag.context.get_settings().validate_frozen(subconfig)
self._values[subconfig.path][subconfig.index][1] = owner
#______________________________________________________________________
@ -517,59 +495,58 @@ class Values:
def reset(self,
subconfig: "SubConfig",
*,
validate: bool=True,
) -> None:
"""reset value for an option
"""
config_bag = subconfig.config_bag
context = config_bag.context
hasvalue = self.hasvalue(subconfig.path)
context = config_bag.context
setting_properties = config_bag.properties
if hasvalue and 'validator' in config_bag.properties:
fake_context = context.gen_fake_context()
fake_config_bag = config_bag.copy()
fake_config_bag.remove_validation()
fake_config_bag.context = fake_context
fake_subconfig = fake_context.get_sub_config(fake_config_bag,
subconfig.path,
subconfig.index,
validate_properties=False,
follower_not_apply_requires=False,
)
fake_values = fake_context.get_values()
fake_values.reset(fake_subconfig)
fake_subconfig.config_bag.properties = setting_properties
value = fake_values.get_default_value(fake_subconfig)
fake_values.setvalue_validation(fake_subconfig,
value,
)
if validate:
if hasvalue and 'validator' in setting_properties:
fake_context = context.gen_fake_context()
fake_config_bag = config_bag.copy()
fake_config_bag.remove_validation()
fake_config_bag.context = fake_context
fake_subconfig = fake_context.get_sub_config(fake_config_bag,
subconfig.path,
subconfig.index,
validate_properties=False,
)
fake_values = fake_context.get_values()
fake_values.reset(fake_subconfig)
fake_subconfig.config_bag.properties = setting_properties
value = fake_values.get_default_value(fake_subconfig)
fake_values.setvalue_validation(fake_subconfig,
value,
)
# if hasvalue:
opt = subconfig.option
if opt.impl_is_leader():
opt.impl_get_leadership().reset(subconfig.parent)
if hasvalue:
if 'force_store_value' in subconfig.config_bag.properties and \
'force_store_value' in subconfig.properties:
value = self.get_default_value(subconfig)
if 'force_store_value' in setting_properties and \
'force_store_value' in subconfig.properties:
value = self.get_default_value(subconfig)
self._setvalue(subconfig,
value,
owners.forced,
)
else:
# for leader only
value = None
if subconfig.path in self._values:
del self._values[subconfig.path]
context.reset_cache(subconfig)
# if 'force_store_value' in setting_properties and option_bag.option.impl_is_leader():
# if value is None:
# value = self.get_default_value(option_bag,
# parent,
# )
# leader = option_bag.option.impl_get_leadership()
# leader.follower_force_store_value(value,
# option_bag.config_bag,
# owners.forced,
# )
self._setvalue(subconfig,
value,
owners.forced,
)
else:
value = None
if subconfig.path in self._values:
del self._values[subconfig.path]
if 'force_store_value' in setting_properties and subconfig.option.impl_is_leader():
if value is None:
value = self.get_default_value(subconfig)
leader = subconfig.option.impl_get_leadership()
leader.follower_force_store_value(value,
subconfig.parent,
owners.forced,
)
context.reset_cache(subconfig)
#______________________________________________________________________
# Follower
@ -602,7 +579,6 @@ class Values:
subconfig.path,
subconfig.index,
validate_properties=False,
follower_not_apply_requires=False,
)
fake_values = fake_context.get_values()
fake_values.reset_follower(fake_subconfig)
@ -611,19 +587,18 @@ class Values:
fake_values.setvalue_validation(fake_subconfig,
value,
)
# if 'force_store_value' in setting_properties and \
# 'force_store_value' in option_bag.properties:
# value = self.get_default_value(option_bag,
# parent,
# )
#
# self._setvalue(option_bag,
# value,
# owners.forced,
# )
# else:
self.resetvalue_index(subconfig)
context.reset_cache(subconfig)
if 'force_store_value' in setting_properties and \
'force_store_value' in subconfig.properties:
value = self.get_default_value(subconfig,
)
self._setvalue(subconfig,
value,
owners.forced,
)
else:
self.resetvalue_index(subconfig)
context.reset_cache(subconfig)
def resetvalue_index(self,
subconfig: "SubConfig",
@ -688,14 +663,26 @@ class Values:
config_bag = subconfig.config_bag
context = config_bag.context
for key, options in subconfig.option.get_dependencies_information().items():
for option in options:
option_subconfig = context.get_sub_config(config_bag,
option.impl_getpath(),
None,
validate_properties=False,
follower_not_apply_requires=False,
)
context.reset_cache(option_subconfig)
if key is None:
continue
for woption in options:
if woption is None:
continue
option = woption()
if option.issubdyn():
option_subconfigs = subconfig.get_common_child(option,
validate_properties=False,
)
if not isinstance(option_subconfigs, list):
option_subconfigs = [option_subconfigs]
else:
option_subconfigs = [context.get_sub_config(config_bag,
option.impl_getpath(),
None,
validate_properties=False,
)]
for option_subconfig in option_subconfigs:
context.reset_cache(option_subconfig)
def get_information(self,
subconfig,
@ -706,18 +693,25 @@ class Values:
:param name: the item string (ex: "help")
"""
if subconfig is None:
path = None
if subconfig.option.impl_is_symlinkoption():
option = subconfig.option.impl_getopt()
path = option.impl_getpath()
else:
option = subconfig.option
path = subconfig.path
try:
return self._informations[path][name]
except KeyError as err:
if subconfig:
return subconfig.option.impl_get_information(name, default)
if default is not undefined:
return default
raise ValueError(_("information's item not found: {0}").format(name)) from err
pass
if option is not None:
return option._get_information(subconfig,
name,
default,
)
return subconfig.config_bag.context.get_description()._get_information(subconfig,
name,
default,
)
def del_information(self,
key: Any,