feat: reorganise code

This commit is contained in:
egarette@silique.fr 2024-04-24 15:39:17 +02:00
parent ccf8ebc91e
commit 8e743131cd
33 changed files with 6704 additions and 6521 deletions

View file

@ -42,3 +42,24 @@ def global_owner(config, config_type):
@pytest.fixture(params=PARAMS)
def config_type(request):
return request.param
def parse_od_get(dico):
ret = {}
for k, v in dico.items():
if k.isoptiondescription():
if k.isleadership():
leader_path = k.leader().path()
ret_leadership = []
for variable, value in v.items():
if variable.path() == leader_path:
for val in value:
ret_leadership.append({leader_path: val})
else:
ret_leadership[variable.index()][variable.path()] = value
ret[leader_path] = ret_leadership
else:
ret.update(parse_od_get(v))
else:
ret[k.path()] = v
return ret

View file

@ -54,12 +54,13 @@ def test_cache_importation():
od1 = make_description()
cfg = Config(od1)
cfg.option('u2').value.set(1)
values = cfg._config_bag.context._impl_values_cache
export = cfg.value.exportation()
assert cfg.value.dict() == {'u1': [], 'u2': 1, 'u3': []}
compare(values.get_cached(), {'u2': {None: (1, None)}})
cfg.option('u2').value.set(2)
assert cfg.value.dict() == {'u1': [], 'u2': 2, 'u3': []}
compare(values.get_cached(), {'u2': {None: (2, None)}})
cfg.value.importation(export)
assert cfg.value.dict() == {'u1': [], 'u2': 1, 'u3': []}
compare(values.get_cached(), {})
# assert not list_sessions()
@ -309,7 +310,7 @@ def test_cache_callback():
od1 = OptionDescription('rootconfig', '', [val1, val2, val3, val4, val5])
cfg = Config(od1)
cfg.property.read_write()
cfg.value.dict()
cfg.value.get()
values = cfg._config_bag.context._impl_values_cache
settings = cfg._config_bag.context.properties_cache
compare(values.get_cached(), {'val1': {None: ('val', None)},
@ -321,7 +322,7 @@ def test_cache_callback():
compare(values.get_cached(), {'val3': {None: ('yes', None)},
'val1': {None: ('new', None)},
'val5': {None: (['yes'], None)}})
cfg.value.dict()
cfg.value.get()
compare(values.get_cached(), {'val1': {None: ('new', None)},
'val2': {None: ('new', None)},
'val3': {None: ('yes', None)},
@ -334,7 +335,7 @@ def test_cache_callback():
'val1': {None: ('new', None)},
'val3': {None: ('new2', None, True)},
'val5': {None: (['yes'], None)}})
cfg.value.dict()
cfg.value.get()
compare(values.get_cached(), {'val1': {None: ('new', None)},
'val2': {None: ('new', None)},
'val3': {None: ('new2', None)},
@ -346,7 +347,7 @@ def test_cache_callback():
'val3': {None: ('new2', None)},
'val4': {None: ('new3', None, True)},
'val5': {None: (['yes'], None)}})
cfg.value.dict()
cfg.value.get()
compare(values.get_cached(), {'val1': {None: ('new', None)},
'val2': {None: ('new', None)},
'val3': {None: ('new2', None)},
@ -362,7 +363,7 @@ def test_cache_leader_and_followers():
od1 = OptionDescription('rootconfig', '', [interface1])
cfg = Config(od1)
cfg.property.read_write()
cfg.value.dict()
cfg.value.get()
global_props = ['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']
val1_props = []
val1_val1_props = ['empty', 'unique']
@ -385,10 +386,10 @@ def test_cache_leader_and_followers():
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)},
# 'val1.val1': {None: (val1_val1_props, None)},
})
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
cfg.value.dict()
cfg.value.get()
#has value
idx_val2 = 0
val_val2 = None
@ -401,7 +402,7 @@ def test_cache_leader_and_followers():
'val1.val2': {idx_val2: (val_val2, None)},
})
cfg.option('val1.val1').value.set([None, None])
cfg.value.dict()
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(values.get_cached(), {'val1.val2': {1: ('oui', None, True)}})
@ -416,7 +417,7 @@ def test_cache_leader_callback():
od1 = OptionDescription('rootconfig', '', [interface1])
cfg = Config(od1)
cfg.property.read_write()
cfg.value.dict()
cfg.value.get()
global_props = ['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']
val1_props = []
val1_val1_props = ['empty', 'unique']
@ -434,11 +435,11 @@ def test_cache_leader_callback():
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)},
# 'val1.val1': {None: (val1_val1_props, None)},
})
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
cfg.value.dict()
cfg.value.get()
# assert not list_sessions()
@ -463,7 +464,7 @@ def test_cache_requires():
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
'activate_service': {None: (True, None)}})
cfg.value.dict()
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)}})
@ -475,7 +476,7 @@ def test_cache_requires():
'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.dict()
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)}})
@ -486,7 +487,7 @@ def test_cache_requires():
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)}})
compare(values.get_cached(), {'activate_service': {None: (False, None)}})
cfg.value.dict()
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)}})

View file

@ -3,7 +3,7 @@ from pytest 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 tiramisu import Config, IntOption, FloatOption, StrOption, ChoiceOption, \
BoolOption, FilenameOption, SymLinkOption, IPOption, \
@ -76,14 +76,12 @@ def test_make_dict(config_type):
cfg.property.read_write()
cfg.permissive.add('hidden')
cfg = get_config(cfg, config_type)
d = cfg.value.dict()
assert d == {"s1.a": False, "int": 42}
assert parse_od_get(cfg.value.get()) == {"s1.a": False, "int": 42}
cfg.option('int').value.set(43)
cfg.option('s1.a').value.set(True)
d = cfg.value.dict()
assert d == {"s1.a": True, "int": 43}
assert parse_od_get(cfg.value.get()) == {"s1.a": True, "int": 43}
if config_type == 'tiramisu':
assert cfg.forcepermissive.value.dict() == {"s1.a": True, "s1.b": False, "int": 43}
assert parse_od_get(cfg.forcepermissive.value.get()) == {"s1.a": True, "s1.b": False, "int": 43}
# assert not list_sessions()
@ -98,22 +96,7 @@ def test_make_dict_sub(config_type):
cfg.property.read_write()
cfg.permissive.add('hidden')
cfg = get_config(cfg, config_type)
assert cfg.option('s1').value.dict() == {'s1.a': False}
def test_make_dict_not_value(config_type):
"serialization part of config to a dict"
od1 = OptionDescription("opt", "", [
OptionDescription("s1", "", [
BoolOption("a", "", default=False),
BoolOption("b", "", default=False, properties=('hidden',))]),
IntOption("int", "", default=42)])
cfg = Config(od1)
cfg.property.read_write()
cfg.permissive.add('hidden')
cfg = get_config(cfg, config_type)
with raises(ConfigError):
cfg.option('s1.a').value.dict()
assert parse_od_get(cfg.option('s1').value.get()) == {'s1.a': False}
def test_make_dict_with_disabled(config_type):
@ -128,10 +111,10 @@ def test_make_dict_with_disabled(config_type):
cfg = Config(od1)
cfg.property.read_only()
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {"s1.a": False, "int": 42}
assert parse_od_get(cfg.value.get()) == {"s1.a": False, "int": 42}
if config_type == 'tiramisu':
assert cfg.forcepermissive.value.dict() == {"s1.a": False, "int": 42}
assert cfg.unrestraint.value.dict() == {"int": 42, "s1.a": False, "s1.b": False, "s2.a": False, "s2.b": False}
assert parse_od_get(cfg.forcepermissive.value.get()) == {"s1.a": False, "int": 42}
assert parse_od_get(cfg.unrestraint.value.get()) == {"int": 42, "s1.a": False, "s1.b": False, "s2.a": False, "s2.b": False}
# assert not list_sessions()
@ -147,8 +130,7 @@ def test_make_dict_with_disabled_in_callback(config_type):
cfg = Config(od1)
cfg.property.read_only()
cfg = get_config(cfg, config_type)
d = cfg.value.dict()
assert d == {"s1.a": False, "int": 42}
assert parse_od_get(cfg.value.get()) == {"s1.a": False, "int": 42}
# assert not list_sessions()
@ -166,150 +148,150 @@ def test_make_dict_fullpath(config_type):
cfg = Config(od1)
cfg.property.read_only()
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {"opt.s1.a": False, "opt.int": 42, "introot": 42}
assert cfg.option('opt').value.dict() == {"opt.s1.a": False, "opt.int": 42}
assert parse_od_get(cfg.value.get()) == {"opt.s1.a": False, "opt.int": 42, "introot": 42}
assert parse_od_get(cfg.option('opt').value.get()) == {"opt.s1.a": False, "opt.int": 42}
# assert not list_sessions()
def test_find_in_config():
"finds option in config"
od1 = make_description()
cfg = Config(od1)
cfg.property.read_only()
cfg.permissive.add('hidden')
ret = list(cfg.option.find('dummy'))
assert len(ret) == 1
_is_same_opt(ret[0].get(), cfg.option('gc.dummy').get())
#def test_find_in_config():
# "finds option in config"
# od1 = make_description()
# cfg = Config(od1)
# cfg.property.read_only()
# cfg.permissive.add('hidden')
# ret = list(cfg.option.find('dummy'))
# assert len(ret) == 1
# _is_same_opt(ret[0].get(), cfg.option('gc.dummy').get())
# #
# ret_find = cfg.option.find('dummy', first=True)
# ret = ret_find.get()
# _is_same_opt(ret, cfg.option('gc.dummy').get())
# #
# ret = list(cfg.option.find('float'))
# assert len(ret) == 2
# _is_same_opt(ret[0].get(), cfg.option('gc.float').get())
# _is_same_opt(ret[1].get(), cfg.option('float').get())
# #
# ret = cfg.option.find('bool', first=True)
# _is_same_opt(ret.get(), cfg.option('gc.gc2.bool').get())
# ret = cfg.option.find('bool', value=True, first=True)
# _is_same_opt(ret.get(), cfg.option('bool').get())
# ret = cfg.option.find('dummy', first=True)
# _is_same_opt(ret.get(), cfg.option('gc.dummy').get())
# ret = cfg.option.find('float', first=True)
# _is_same_opt(ret.get(), cfg.option('gc.float').get())
# ret = list(cfg.option.find('prop'))
# assert len(ret) == 1
# _is_same_opt(ret[0].get(), cfg.option('gc.prop').get())
# #
# ret = list(cfg.option.find('prop', value=None))
# assert len(ret) == 1
# ret = list(cfg.option.find('prop'))
# assert len(ret) == 1
# _is_same_opt(ret[0].get(), cfg.option('gc.prop').get())
# #
# cfg.property.read_write()
# with raises(AttributeError):
# ret = cfg.option.find('prop')
# assert ret.get()
# ret = list(cfg.unrestraint.option.find(name='prop'))
# assert len(ret) == 2
# _is_same_opt(ret[0].get(), cfg.unrestraint.option('gc.gc2.prop').get())
# _is_same_opt(ret[1].get(), cfg.forcepermissive.option('gc.prop').get())
# #
# ret = list(cfg.forcepermissive.option.find('prop'))
# assert len(ret) == 1
# _is_same_opt(ret[0].get(), cfg.forcepermissive.option('gc.prop').get())
# #
# ret = cfg.forcepermissive.option.find('prop', first=True)
# _is_same_opt(ret.get(), cfg.forcepermissive.option('gc.prop').get())
# # combinaison of filters
# ret = list(cfg.unrestraint.option.find('prop', type=BoolOption))
# assert len(ret) == 1
# _is_same_opt(ret[0].get(), cfg.unrestraint.option('gc.gc2.prop').get())
# ret = cfg.unrestraint.option.find('prop', type=BoolOption, first=True)
# _is_same_opt(ret.get(), cfg.unrestraint.option('gc.gc2.prop').get())
# #
# ret = list(cfg.option.find('dummy', value=False))
# assert len(ret) == 1
# _is_same_opt(ret[0].get(), cfg.option('gc.dummy').get())
# #
# ret = cfg.option.find('dummy', value=False, first=True)
# _is_same_opt(ret.get(), cfg.option('gc.dummy').get())
# #subcfgig
# ret = list(cfg.option('gc').find('dummy'))
# assert len(ret) == 1
# _is_same_opt(ret[0].get(), cfg.option('gc.dummy').get())
# #
# ret = list(cfg.option('gc').find('float'))
# assert len(ret) == 1
# _is_same_opt(ret[0].get(), cfg.option('gc.float').get())
# #
# ret = list(cfg.option('gc.gc2').find('bool'))
# assert len(ret) == 1
# _is_same_opt(ret[0].get(), cfg.option('gc.gc2.bool').get())
# ret = cfg.option('gc').find('bool', value=False, first=True)
# _is_same_opt(ret.get(), cfg.option('gc.gc2.bool').get())
# #
# with raises(AttributeError):
# ret = cfg.option('gc').find('bool', value=True, first=True)
# assert ret.get()
# #
# with raises(AttributeError):
# ret = cfg.option('gc').find('wantref')
# ret.get()
# #
# ret = list(cfg.unrestraint.option('gc').find('prop'))
# assert len(ret) == 2
# _is_same_opt(ret[0].get(), cfg.unrestraint.option('gc.gc2.prop').get())
# _is_same_opt(ret[1].get(), cfg.forcepermissive.option('gc.prop').get())
# #
# cfg.property.read_only()
# ret = list(cfg.option('gc').find('prop'))
# assert len(ret) == 1
# _is_same_opt(ret[0].get(), cfg.option('gc.prop').get())
# # not OptionDescription
# with raises(AttributeError):
# cfg.option.find('gc', first=True)
# with raises(AttributeError):
# cfg.option.find('gc2', first=True)
## assert not list_sessions()
#
ret_find = cfg.option.find('dummy', first=True)
ret = ret_find.get()
_is_same_opt(ret, cfg.option('gc.dummy').get())
#
ret = list(cfg.option.find('float'))
assert len(ret) == 2
_is_same_opt(ret[0].get(), cfg.option('gc.float').get())
_is_same_opt(ret[1].get(), cfg.option('float').get())
#def test_find_multi():
# b = BoolOption('bool', '', multi=True, properties=('notunique',))
# od1 = OptionDescription('od', '', [b])
# cfg = Config(od1)
# #
# with raises(AttributeError):
# list(cfg.option.find('bool', value=True))
# with raises(AttributeError):
# list(cfg.option.find('bool', value=True, first=True))
# cfg.option('bool').value.set([False])
# with raises(AttributeError):
# list(cfg.option.find('bool', value=True))
# with raises(AttributeError):
# list(cfg.option.find('bool', value=True, first=True))
# cfg.option('bool').value.set([False, False])
# with raises(AttributeError):
# list(cfg.option.find('bool', value=True))
# with raises(AttributeError):
# list(cfg.option.find('bool', value=True, first=True))
# cfg.option('bool').value.set([False, False, True])
# ret = list(cfg.option.find('bool', value=True))
# assert len(ret) == 1
# _is_same_opt(ret[0].get(), b)
# ret = cfg.option.find('bool', value=True, first=True)
# _is_same_opt(ret.get(), b)
## assert not list_sessions()
#
ret = cfg.option.find('bool', first=True)
_is_same_opt(ret.get(), cfg.option('gc.gc2.bool').get())
ret = cfg.option.find('bool', value=True, first=True)
_is_same_opt(ret.get(), cfg.option('bool').get())
ret = cfg.option.find('dummy', first=True)
_is_same_opt(ret.get(), cfg.option('gc.dummy').get())
ret = cfg.option.find('float', first=True)
_is_same_opt(ret.get(), cfg.option('gc.float').get())
ret = list(cfg.option.find('prop'))
assert len(ret) == 1
_is_same_opt(ret[0].get(), cfg.option('gc.prop').get())
#
ret = list(cfg.option.find('prop', value=None))
assert len(ret) == 1
ret = list(cfg.option.find('prop'))
assert len(ret) == 1
_is_same_opt(ret[0].get(), cfg.option('gc.prop').get())
#
cfg.property.read_write()
with raises(AttributeError):
ret = cfg.option.find('prop')
assert ret.get()
ret = list(cfg.unrestraint.option.find(name='prop'))
assert len(ret) == 2
_is_same_opt(ret[0].get(), cfg.unrestraint.option('gc.gc2.prop').get())
_is_same_opt(ret[1].get(), cfg.forcepermissive.option('gc.prop').get())
#
ret = list(cfg.forcepermissive.option.find('prop'))
assert len(ret) == 1
_is_same_opt(ret[0].get(), cfg.forcepermissive.option('gc.prop').get())
#
ret = cfg.forcepermissive.option.find('prop', first=True)
_is_same_opt(ret.get(), cfg.forcepermissive.option('gc.prop').get())
# combinaison of filters
ret = list(cfg.unrestraint.option.find('prop', type=BoolOption))
assert len(ret) == 1
_is_same_opt(ret[0].get(), cfg.unrestraint.option('gc.gc2.prop').get())
ret = cfg.unrestraint.option.find('prop', type=BoolOption, first=True)
_is_same_opt(ret.get(), cfg.unrestraint.option('gc.gc2.prop').get())
#
ret = list(cfg.option.find('dummy', value=False))
assert len(ret) == 1
_is_same_opt(ret[0].get(), cfg.option('gc.dummy').get())
#
ret = cfg.option.find('dummy', value=False, first=True)
_is_same_opt(ret.get(), cfg.option('gc.dummy').get())
#subcfgig
ret = list(cfg.option('gc').find('dummy'))
assert len(ret) == 1
_is_same_opt(ret[0].get(), cfg.option('gc.dummy').get())
#
ret = list(cfg.option('gc').find('float'))
assert len(ret) == 1
_is_same_opt(ret[0].get(), cfg.option('gc.float').get())
#
ret = list(cfg.option('gc.gc2').find('bool'))
assert len(ret) == 1
_is_same_opt(ret[0].get(), cfg.option('gc.gc2.bool').get())
ret = cfg.option('gc').find('bool', value=False, first=True)
_is_same_opt(ret.get(), cfg.option('gc.gc2.bool').get())
#
with raises(AttributeError):
ret = cfg.option('gc').find('bool', value=True, first=True)
assert ret.get()
#
with raises(AttributeError):
ret = cfg.option('gc').find('wantref')
ret.get()
#
ret = list(cfg.unrestraint.option('gc').find('prop'))
assert len(ret) == 2
_is_same_opt(ret[0].get(), cfg.unrestraint.option('gc.gc2.prop').get())
_is_same_opt(ret[1].get(), cfg.forcepermissive.option('gc.prop').get())
#
cfg.property.read_only()
ret = list(cfg.option('gc').find('prop'))
assert len(ret) == 1
_is_same_opt(ret[0].get(), cfg.option('gc.prop').get())
# not OptionDescription
with raises(AttributeError):
cfg.option.find('gc', first=True)
with raises(AttributeError):
cfg.option.find('gc2', first=True)
# assert not list_sessions()
def test_find_multi():
b = BoolOption('bool', '', multi=True, properties=('notunique',))
od1 = OptionDescription('od', '', [b])
cfg = Config(od1)
#
with raises(AttributeError):
list(cfg.option.find('bool', value=True))
with raises(AttributeError):
list(cfg.option.find('bool', value=True, first=True))
cfg.option('bool').value.set([False])
with raises(AttributeError):
list(cfg.option.find('bool', value=True))
with raises(AttributeError):
list(cfg.option.find('bool', value=True, first=True))
cfg.option('bool').value.set([False, False])
with raises(AttributeError):
list(cfg.option.find('bool', value=True))
with raises(AttributeError):
list(cfg.option.find('bool', value=True, first=True))
cfg.option('bool').value.set([False, False, True])
ret = list(cfg.option.find('bool', value=True))
assert len(ret) == 1
_is_same_opt(ret[0].get(), b)
ret = cfg.option.find('bool', value=True, first=True)
_is_same_opt(ret.get(), b)
# assert not list_sessions()
def test_does_not_find_in_config():
od1 = make_description()
cfg = Config(od1)
with raises(AttributeError):
list(cfg.option.find('IDontExist'))
# assert not list_sessions()
#def test_does_not_find_in_config():
# od1 = make_description()
# cfg = Config(od1)
# with raises(AttributeError):
# list(cfg.option.find('IDontExist'))
## assert not list_sessions()
def test_filename(config_type):

View file

@ -59,36 +59,36 @@ 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']}}
#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()
#
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():
od1 = make_description()
meta = MetaConfig([], optiondescription=od1)
conf = meta.config.new()
assert meta.property.get() == conf.property.get()
assert meta.permissive.get() == conf.permissive.get()
conf.property.read_write()
assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
assert meta.value.exportation() == {}
# assert not list_sessions()
#
#def test_copy_force_store_value_metaconfig():
# od1 = make_description()
# meta = MetaConfig([], optiondescription=od1)
# conf = meta.config.new()
# assert meta.property.get() == conf.property.get()
# assert meta.permissive.get() == conf.permissive.get()
# conf.property.read_write()
# assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
# assert meta.value.exportation() == {}
## assert not list_sessions()

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
# coding: utf-8
#test_force_store_value coding: utf-8
"frozen and hidden values"
from .autopath import do_autopath
do_autopath()
@ -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

@ -1,7 +1,7 @@
# coding: utf-8
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
import pytest
from tiramisu.setting import groups, owners
@ -59,10 +59,10 @@ def test_base_config(config_type):
cfg = get_config(cfg, config_type)
assert cfg.option('creole.general.activer_proxy_client').value.get() is False
assert cfg.option('creole.general.nom_machine').value.get() == "eoleng"
if config_type != 'tiramisu-api':
ret = cfg.option.find('nom_machine', first=True)
assert ret.value.get() == "eoleng"
assert cfg.option('creole').value.dict() == {'creole.general.numero_etab': None, 'creole.general.nom_machine': 'eoleng', 'creole.general.nombre_interfaces': 1, 'creole.general.activer_proxy_client': False, 'creole.general.mode_conteneur_actif': False, 'creole.general.serveur_ntp': [], 'creole.general.time_zone': 'Paris', 'creole.interface1.ip_admin_eth0.ip_admin_eth0': None, 'creole.interface1.ip_admin_eth0.netmask_admin_eth0': None}
# if config_type != 'tiramisu-api':
# ret = cfg.option.find('nom_machine', first=True)
# assert ret.value.get() == "eoleng"
assert parse_od_get(cfg.option('creole').value.get()) == {'creole.general.numero_etab': None, 'creole.general.nom_machine': 'eoleng', 'creole.general.nombre_interfaces': 1, 'creole.general.activer_proxy_client': False, 'creole.general.mode_conteneur_actif': False, 'creole.general.serveur_ntp': [], 'creole.general.time_zone': 'Paris', 'creole.interface1.ip_admin_eth0.ip_admin_eth0': None, 'creole.interface1.ip_admin_eth0.netmask_admin_eth0': None}
if config_type == 'tiramisu-api':
cfg.send()
# assert not list_sessions()
@ -77,49 +77,40 @@ def test_get_group_type():
assert grp.group_type() == 'family'
assert isinstance(grp.group_type(), groups.GroupType)
# assert not list_sessions()
def test_iter_on_groups():
od1 = make_description()
cfg = Config(od1)
cfg.property.read_write()
result = cfg.option('creole').list('optiondescription',
group_type=groups.family,
)
group_names = [res.name() for res in result]
assert group_names == ['general', 'interface1']
for i in cfg.option('creole').list('optiondescription',
group_type=groups.family,
):
#test StopIteration
break
result = cfg.option('creole').list('option',
group_type=groups.family,
)
assert list(result) == []
result = cfg.option('creole.general').list('optiondescription',
group_type=groups.family,
)
assert list(result) == []
# assert not list_sessions()
#
#
#def test_iter_on_groups():
# od1 = make_description()
# cfg = Config(od1)
# cfg.property.read_write()
# result = cfg.option('creole').list('optiondescription',
# group_type=groups.family,
# )
# group_names = [res.name() for res in result]
# assert group_names == ['general', 'interface1']
# for i in cfg.option('creole').list('optiondescription',
# group_type=groups.family,
# ):
# #test StopIteration
# break
# result = cfg.option('creole').list('option',
# group_type=groups.family,
# )
# assert list(result) == []
# result = cfg.option('creole.general').list('optiondescription',
# group_type=groups.family,
# )
# assert list(result) == []
## assert not list_sessions()
def test_list_recursive():
od1 = make_description()
cfg = Config(od1)
cfg.property.read_write()
result = cfg.option('creole').list('all')
result = cfg.option('creole').list()
group_names = [res.name() for res in result]
assert group_names == ['general', 'interface1']
#
result = cfg.option.list(recursive=True)
group_names = [res.name() for res in result]
assert group_names == ['numero_etab', 'nom_machine', 'nombre_interfaces',
'activer_proxy_client', 'mode_conteneur_actif',
'serveur_ntp', 'time_zone', 'ip_admin_eth0',
'netmask_admin_eth0']
result = list(cfg.option.list(recursive=True, type='optiondescription'))
group_names = [res.name() for res in result]
assert group_names == ['creole', 'general', 'interface1', 'ip_admin_eth0']
# assert not list_sessions()
@ -147,8 +138,7 @@ def test_iter_group_on_groups_force_permissive():
cfg = Config(od1)
cfg.property.read_write()
cfg.permissive.add('hidden')
result = cfg.forcepermissive.option('creole').list(type='optiondescription',
group_type=groups.family)
result = cfg.forcepermissive.option('creole').list()
group_names = [res.name() for res in result]
assert group_names == ['general', 'interface1', 'new']
# assert not list_sessions()
@ -159,8 +149,7 @@ def test_iter_on_groups_props():
cfg = Config(od1)
cfg.property.read_write()
cfg.option('creole.interface1').property.add('disabled')
result = cfg.option('creole').list(type='optiondescription',
group_type=groups.family)
result = cfg.option('creole').list()
group_names = [res.name() for res in result]
assert group_names == ['general']
# assert not list_sessions()
@ -170,20 +159,11 @@ def test_iter_on_empty_group():
od1 = OptionDescription("name", "descr", [])
cfg = Config(od1)
cfg.property.read_write()
result = list(cfg.option.list(type='optiondescription'))
result = list(cfg.option.list())
assert result == []
# assert not list_sessions()
def test_iter_not_group():
od1 = OptionDescription("name", "descr", [])
cfg = Config(od1)
cfg.property.read_write()
with pytest.raises(AssertionError):
print(list(cfg.option.list(type='optiondescription', group_type='family')))
# assert not list_sessions()
def test_groups_with_leader():
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)
@ -221,25 +201,26 @@ def test_groups_is_leader(config_type):
def test_leader_list(config_type):
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", ['val1'], multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, default_multi='value')
interface1 = Leadership('leadership', '', [ip_admin_eth0, netmask_admin_eth0])
od1 = OptionDescription('od', '', [interface1])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
ret = cfg.option.list('all')
ret = cfg.option.list()
assert len(ret) == 1
assert ret[0].name() == 'leadership'
#
ret = cfg.option('leadership').list('all')
ret = cfg.option('leadership').list()
assert len(ret) == 2
assert ret[0].name() == 'ip_admin_eth0'
assert ret[1].name() == 'netmask_admin_eth0'
assert ret[1].index() == 0
#
cfg.option('leadership.ip_admin_eth0').value.set(['a', 'b'])
cfg.option('leadership.netmask_admin_eth0', 0).value.set('c')
cfg.option('leadership.netmask_admin_eth0', 1).value.set('d')
ret = cfg.option('leadership').list('all')
ret = cfg.option('leadership').list()
assert ret[0].name() == 'ip_admin_eth0'
assert ret[1].name() == 'netmask_admin_eth0'
# assert ret[1].option.index() == 0
@ -303,7 +284,7 @@ def test_groups_with_leader_make_dict(config_type):
od1 = OptionDescription('root', '', [interface1])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': []}
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': []}
if config_type != 'tiramisu-api':
# FIXME useful? already in leadership
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.len() == 0
@ -313,7 +294,7 @@ def test_groups_with_leader_make_dict(config_type):
# FIXME
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.len() == 2
assert cfg.option('ip_admin_eth0.netmask_admin_eth0').value.len() == 2
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'ip1', 'ip_admin_eth0.netmask_admin_eth0': None}, {'ip_admin_eth0.ip_admin_eth0': 'ip2', 'ip_admin_eth0.netmask_admin_eth0': None}]}
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'ip1', 'ip_admin_eth0.netmask_admin_eth0': None}, {'ip_admin_eth0.ip_admin_eth0': 'ip2', 'ip_admin_eth0.netmask_admin_eth0': None}]}
if config_type == 'tiramisu-api':
cfg.send()
# assert not list_sessions()
@ -336,7 +317,7 @@ def test_groups_with_leader_make_dict2(config_type):
od1 = OptionDescription('root', '', [interface1])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'other.ip_admin_eth0': []}
assert parse_od_get(cfg.value.get()) == {'other.ip_admin_eth0': []}
if config_type != 'tiramisu-api':
# FIXME useful? already in leadership
assert cfg.option('other.ip_admin_eth0').value.len() == 0
@ -346,7 +327,7 @@ def test_groups_with_leader_make_dict2(config_type):
# FIXME
assert cfg.option('other.ip_admin_eth0').value.len() == 2
assert cfg.option('other.netmask_admin_eth0').value.len() == 2
assert cfg.value.dict() == {'other.ip_admin_eth0': [{'other.ip_admin_eth0': 'ip1', 'other.netmask_admin_eth0': None}, {'other.ip_admin_eth0': 'ip2', 'other.netmask_admin_eth0': None}]}
assert parse_od_get(cfg.value.get()) == {'other.ip_admin_eth0': [{'other.ip_admin_eth0': 'ip1', 'other.netmask_admin_eth0': None}, {'other.ip_admin_eth0': 'ip2', 'other.netmask_admin_eth0': None}]}
if config_type == 'tiramisu-api':
cfg.send()
# assert not list_sessions()
@ -411,7 +392,7 @@ def test_groups_with_leader_hidden_in_config():
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()
assert cfg.value.dict() == {}
assert parse_od_get(cfg.value.get()) == {}
# assert not list_sessions()
@ -426,16 +407,13 @@ def test_groups_with_leader_hidden_in_config2():
assert cfg.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.get() == []
cfg.forcepermissive.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.1'])
assert cfg.forcepermissive.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.1']
with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['192.168.1.1']}
assert cfg.value.dict(leader_to_list=True) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]}
# assert not list_sessions()
def test_groups_with_leader_hidden_in_config2():
def test_groups_with_leader_hidden_in_config3():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('hidden',))
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
@ -1005,66 +983,66 @@ 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()
#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()
#
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():
#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',))
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])

View file

@ -1,6 +1,7 @@
# coding: utf-8
from .autopath import do_autopath
do_autopath()
from .config import parse_od_get
# FIXME from .config import config_type, get_config
import pytest
@ -50,18 +51,6 @@ def make_description2():
return descr
def make_description_sym():
stroption = StrOption('str', 'Test string option', default="abc",
properties=('mandatory', ))
stroption1 = StrOption('str1', 'Test string option',
properties=('mandatory', ))
stroption2 = SymLinkOption('unicode2', stroption1)
stroption3 = StrOption('str3', 'Test string option', multi=True,
properties=('mandatory', ))
descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3])
return descr
def make_description3():
stroption = StrOption('str', 'Test string option', default="abc",
properties=('mandatory', ))
@ -99,7 +88,7 @@ def test_mandatory_ro_dict():
cfg.property.read_only()
prop = []
try:
cfg.value.dict()
cfg.value.get()
except PropertiesOptionError as err:
prop = err.proptype
assert 'mandatory' in prop
@ -108,14 +97,14 @@ def test_mandatory_ro_dict():
cfg.option('unicode2').value.set('yes')
cfg.property.read_only()
try:
cfg.value.dict()
cfg.value.get()
except PropertiesOptionError as err:
prop = err.proptype
assert 'mandatory' in prop
cfg.property.read_write()
cfg.option('str3').value.set(['yes'])
cfg.property.read_only()
assert cfg.value.dict() == {'str': 'abc', 'str1': 'yes', 'str3': ['yes'], 'unicode2': 'yes'}
assert parse_od_get(cfg.value.get()) == {'str': 'abc', 'str1': 'yes', 'str3': ['yes'], 'unicode2': 'yes'}
# assert not list_sessions()
@ -414,7 +403,7 @@ def test_mandatory_leader():
with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
with pytest.raises(PropertiesOptionError):
cfg.value.dict()
cfg.value.get()
# assert not list_sessions()
@ -431,7 +420,7 @@ def test_mandatory_leader_sub():
with pytest.raises(PropertiesOptionError):
cfg.option('o.ip_admin_eth0.ip_admin_eth0').value.get()
with pytest.raises(PropertiesOptionError):
cfg.value.dict()
cfg.value.get()
# assert not list_sessions()
@ -529,7 +518,7 @@ def test_mandatory_follower():
cfg = Config(od1)
cfg.property.read_only()
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == []
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': []}
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': []}
#
cfg.property.read_write()
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['ip'])
@ -550,7 +539,7 @@ def test_mandatory_follower():
cfg.property.read_only()
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['ip']
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == 'ip'
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'ip', 'ip_admin_eth0.netmask_admin_eth0': 'ip'}]}
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'ip', 'ip_admin_eth0.netmask_admin_eth0': 'ip'}]}
# assert not list_sessions()
@ -572,7 +561,14 @@ def test_mandatory_warnings_follower():
def test_mandatory_warnings_symlink():
od1 = make_description_sym()
stroption = StrOption('str', 'Test string option', default="abc",
properties=('mandatory', ))
stroption1 = StrOption('str1', 'Test string option',
properties=('mandatory', ))
stroption2 = SymLinkOption('unicode2', stroption1)
stroption3 = StrOption('str3', 'Test string option', multi=True,
properties=('mandatory', ))
od1 = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3])
cfg = Config(od1)
cfg.option('str').value.set('')
cfg.property.read_write()
@ -692,25 +688,25 @@ def return_list(val=None, suffix=None):
return ['val1', 'val2']
def test_mandatory_dyndescription():
st = StrOption('st', '', properties=('mandatory',))
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
od = OptionDescription('od', '', [dod])
od2 = OptionDescription('od', '', [od])
cfg = Config(od2)
cfg.property.read_only()
compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
def test_mandatory_dyndescription_context():
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
st = StrOption('st', '', properties=('mandatory',))
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
od = OptionDescription('od', '', [dod, val1])
od2 = OptionDescription('od', '', [od])
cfg = Config(od2)
cfg.property.read_only()
compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
#def test_mandatory_dyndescription():
# st = StrOption('st', '', properties=('mandatory',))
# dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
# od = OptionDescription('od', '', [dod])
# od2 = OptionDescription('od', '', [od])
# cfg = Config(od2)
# cfg.property.read_only()
# compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
#
#
#def test_mandatory_dyndescription_context():
# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
# st = StrOption('st', '', properties=('mandatory',))
# dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
# od = OptionDescription('od', '', [dod, val1])
# od2 = OptionDescription('od', '', [od])
# cfg = Config(od2)
# cfg.property.read_only()
# compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
def test_mandatory_callback_leader_and_followers_leader():
@ -733,4 +729,4 @@ def test_mandatory_and_disabled():
od1 = OptionDescription('rootconfig', '', [username, password])
cfg = Config(od1)
cfg.property.read_write()
cfg.value.dict()
cfg.value.get()

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -15,76 +15,76 @@ def make_metaconfig():
return MetaConfig([], optiondescription=od2, name='metacfg1')
def test_multi_parents_path():
"""
metacfg1 (1) ---
| -- cfg1
metacfg2 (2) ---
"""
metacfg1 = make_metaconfig()
cfg1 = metacfg1.config.new(type='config', name="cfg1")
metacfg2 = MetaConfig([cfg1], name='metacfg2')
#def test_multi_parents_path():
# """
# metacfg1 (1) ---
# | -- cfg1
# metacfg2 (2) ---
# """
# metacfg1 = make_metaconfig()
# cfg1 = metacfg1.config.new(type='config', name="cfg1")
# metacfg2 = MetaConfig([cfg1], name='metacfg2')
# #
# assert metacfg1.config.path() == 'metacfg1'
# assert metacfg2.config.path() == 'metacfg2'
# assert cfg1.config.path() == 'metacfg2.metacfg1.cfg1'
#
assert metacfg1.config.path() == 'metacfg1'
assert metacfg2.config.path() == 'metacfg2'
assert cfg1.config.path() == 'metacfg2.metacfg1.cfg1'
def test_multi_parents_path_same():
"""
--- metacfg2 (1) ---
metacfg1 --| | -- cfg1
--- metacfg3 (2) ---
"""
metacfg1 = make_metaconfig()
metacfg2 = metacfg1.config.new(type='metaconfig', name="metacfg2")
metacfg3 = metacfg1.config.new(type='metaconfig', name="metacfg3")
cfg1 = metacfg2.config.new(type='config', name="cfg1")
metacfg3.config.add(cfg1)
#
assert metacfg2.config.path() == 'metacfg1.metacfg2'
assert metacfg3.config.path() == 'metacfg1.metacfg3'
assert cfg1.config.path() == 'metacfg1.metacfg3.metacfg1.metacfg2.cfg1'
metacfg1.option('od1.i1').value.set(1)
metacfg3.option('od1.i1').value.set(2)
assert cfg1.option('od1.i1').value.get() == 1
orideep = cfg1.config.deepcopy(metaconfig_prefix="test_", name='test_cfg1')
deep = orideep
while True:
try:
children = list(deep.config.list())
except:
break
assert len(children) < 2
deep = children[0]
assert deep.config.path() == 'test_metacfg3.test_metacfg1.test_metacfg2.test_cfg1'
assert cfg1.option('od1.i1').value.get() == 1
def test_multi_parents_value():
metacfg1 = make_metaconfig()
cfg1 = metacfg1.config.new(type='config', name="cfg1")
metacfg2 = MetaConfig([cfg1], name='metacfg2')
#def test_multi_parents_path_same():
# """
# --- metacfg2 (1) ---
# metacfg1 --| | -- cfg1
# --- metacfg3 (2) ---
# """
# metacfg1 = make_metaconfig()
# metacfg2 = metacfg1.config.new(type='metaconfig', name="metacfg2")
# metacfg3 = metacfg1.config.new(type='metaconfig', name="metacfg3")
# cfg1 = metacfg2.config.new(type='config', name="cfg1")
# metacfg3.config.add(cfg1)
# #
# assert metacfg2.config.path() == 'metacfg1.metacfg2'
# assert metacfg3.config.path() == 'metacfg1.metacfg3'
# assert cfg1.config.path() == 'metacfg1.metacfg3.metacfg1.metacfg2.cfg1'
# metacfg1.option('od1.i1').value.set(1)
# metacfg3.option('od1.i1').value.set(2)
# assert cfg1.option('od1.i1').value.get() == 1
# orideep = cfg1.config.deepcopy(metaconfig_prefix="test_", name='test_cfg1')
# deep = orideep
# while True:
# try:
# children = list(deep.config.list())
# except:
# break
# assert len(children) < 2
# deep = children[0]
# assert deep.config.path() == 'test_metacfg3.test_metacfg1.test_metacfg2.test_cfg1'
# assert cfg1.option('od1.i1').value.get() == 1
#
assert cfg1.option('od1.i1').value.get() == None
assert cfg1.option('od1.i2').value.get() == 1
assert cfg1.option('od1.i3').value.get() == None
#
assert metacfg1.option('od1.i1').value.get() == None
assert metacfg1.option('od1.i2').value.get() == 1
assert metacfg1.option('od1.i3').value.get() == None
#
assert metacfg2.option('od1.i1').value.get() == None
assert metacfg2.option('od1.i2').value.get() == 1
assert metacfg2.option('od1.i3').value.get() == None
#
metacfg1.option('od1.i3').value.set(3)
assert metacfg1.option('od1.i3').value.get() == 3
assert cfg1.option('od1.i3').value.get() == 3
assert metacfg2.option('od1.i2').value.get() == 1
#
metacfg2.option('od1.i2').value.set(4)
assert metacfg2.option('od1.i2').value.get() == 4
assert metacfg1.option('od1.i2').value.get() == 1
assert cfg1.option('od1.i2').value.get() == 4
#def test_multi_parents_value():
# metacfg1 = make_metaconfig()
# cfg1 = metacfg1.config.new(type='config', name="cfg1")
# metacfg2 = MetaConfig([cfg1], name='metacfg2')
# #
# assert cfg1.option('od1.i1').value.get() == None
# assert cfg1.option('od1.i2').value.get() == 1
# assert cfg1.option('od1.i3').value.get() == None
# #
# assert metacfg1.option('od1.i1').value.get() == None
# assert metacfg1.option('od1.i2').value.get() == 1
# assert metacfg1.option('od1.i3').value.get() == None
# #
# assert metacfg2.option('od1.i1').value.get() == None
# assert metacfg2.option('od1.i2').value.get() == 1
# assert metacfg2.option('od1.i3').value.get() == None
# #
# metacfg1.option('od1.i3').value.set(3)
# assert metacfg1.option('od1.i3').value.get() == 3
# assert cfg1.option('od1.i3').value.get() == 3
# assert metacfg2.option('od1.i2').value.get() == 1
# #
# metacfg2.option('od1.i2').value.set(4)
# assert metacfg2.option('od1.i2').value.get() == 4
# assert metacfg1.option('od1.i2').value.get() == 1
# assert cfg1.option('od1.i2').value.get() == 4

View file

@ -202,24 +202,9 @@ def test_optiondescription_list():
od2 = OptionDescription('od', '', [od1, od3])
od4 = OptionDescription('od', '', [od2])
cfg = Config(od4)
assert len(list(cfg.option('od').list('option'))) == 0
assert len(list(cfg.option('od').list('optiondescription'))) == 2
assert len(list(cfg.option('od').list('optiondescription', group_type=groups.family))) == 1
assert len(list(cfg.option('od').list('optiondescription', group_type=groups.notfamily1))) == 1
assert len(list(cfg.option('od.od').list('option'))) == 1
assert len(list(cfg.option('od.od2').list('option'))) == 1
try:
list(cfg.option('od').list('unknown'))
except AssertionError:
pass
else:
raise Exception('must raise')
try:
list(cfg.option('od').list('option', group_type='toto'))
except AssertionError:
pass
else:
raise Exception('must raise')
assert len(list(cfg.option('od').list())) == 2
assert len(list(cfg.option('od.od').list())) == 1
assert len(list(cfg.option('od.od2').list())) == 1
# assert not list_sessions()
@ -233,22 +218,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('option'))) == 0
assert len(list(cfg.option.list('optiondescription'))) == 2
assert len(list(cfg.option.list('optiondescription', group_type=groups.family))) == 1
assert len(list(cfg.option.list('optiondescription', group_type=groups.notfamily))) == 1
try:
list(cfg.option.list('unknown'))
except AssertionError:
pass
else:
raise Exception('must raise')
try:
list(cfg.option.list('option', group_type='toto'))
except AssertionError:
pass
else:
raise Exception('must raise')
assert len(list(cfg.option.list())) == 2
# assert not list_sessions()

View file

@ -13,7 +13,7 @@ from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \
valid_ip_netmask, ParamSelfOption, ParamInformation, ParamSelfInformation
from tiramisu.error import PropertiesOptionError, ConflictError, LeadershipError, ConfigError
from tiramisu.i18n import _
from .config import config_type, get_config
from .config import config_type, get_config, parse_od_get
def return_val():
@ -1528,7 +1528,7 @@ def test_calc_value_simple(config_type):
od1 = OptionDescription('root', '', [val1, val2])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'val1': 'val1', 'val2': 'val1'}
assert parse_od_get(cfg.value.get()) == {'val1': 'val1', 'val2': 'val1'}
# assert not list_sessions()
@ -1539,7 +1539,7 @@ def test_calc_value_multi(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'val1': 'val1', 'val2': 'val2', 'val3': ['val1', 'val2']}
assert parse_od_get(cfg.value.get()) == {'val1': 'val1', 'val2': 'val2', 'val3': ['val1', 'val2']}
# assert not list_sessions()
@ -1549,9 +1549,9 @@ def test_calc_value_disabled():
od1 = OptionDescription('root', '', [val1, val2])
cfg = Config(od1)
cfg.property.read_write()
assert cfg.value.dict() == {'val1': 'val1', 'val2': 'val1'}
assert parse_od_get(cfg.value.get()) == {'val1': 'val1', 'val2': 'val1'}
cfg.option('val1').property.add('disabled')
assert cfg.value.dict() == {'val2': 'default_value'}
assert parse_od_get(cfg.value.get()) == {'val2': 'default_value'}
# assert not list_sessions()
@ -1566,9 +1566,9 @@ def test_calc_value_condition(config_type):
cfg = Config(od1)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'boolean': True, 'val1': 'val1', 'val2': 'val1'}
assert parse_od_get(cfg.value.get()) == {'boolean': True, 'val1': 'val1', 'val2': 'val1'}
cfg.option('boolean').value.set(False)
assert cfg.value.dict() == {'boolean': False, 'val1': 'val1', 'val2': 'default_value'}
assert parse_od_get(cfg.value.get()) == {'boolean': False, 'val1': 'val1', 'val2': 'default_value'}
# assert not list_sessions()
@ -1579,7 +1579,7 @@ def test_calc_value_allow_none(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'val1': 'val1', 'val2': None, 'val3': ['val1', None]}
assert parse_od_get(cfg.value.get()) == {'val1': 'val1', 'val2': None, 'val3': ['val1', None]}
# assert not list_sessions()
@ -1590,7 +1590,7 @@ def test_calc_value_remove_duplicate(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'val1': 'val1', 'val2': 'val1', 'val3': ['val1']}
assert parse_od_get(cfg.value.get()) == {'val1': 'val1', 'val2': 'val1', 'val3': ['val1']}
# assert not list_sessions()
@ -1601,7 +1601,7 @@ def test_calc_value_remove_duplicate2(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'val1': ['val1', 'val1'], 'val2': ['val1', 'val1'], 'val3': ['val1-val1']}
assert parse_od_get(cfg.value.get()) == {'val1': ['val1', 'val1'], 'val2': ['val1', 'val1'], 'val3': ['val1-val1']}
# assert not list_sessions()
@ -1613,9 +1613,9 @@ def test_calc_value_join(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3, val4])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'val1': 'val1', 'val2': 'val2', 'val3': None, 'val4': None}
assert parse_od_get(cfg.value.get()) == {'val1': 'val1', 'val2': 'val2', 'val3': None, 'val4': None}
cfg.option('val3').value.set('val3')
assert cfg.value.dict() == {'val1': 'val1', 'val2': 'val2', 'val3': 'val3', 'val4': 'val1.val2.val3'}
assert parse_od_get(cfg.value.get()) == {'val1': 'val1', 'val2': 'val2', 'val3': 'val3', 'val4': 'val1.val2.val3'}
# assert not list_sessions()
@ -1625,9 +1625,9 @@ def test_calc_value_join_multi(config_type):
od1 = OptionDescription('root', '', [val1, val4])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'val1': [], 'val4': []}
assert parse_od_get(cfg.value.get()) == {'val1': [], 'val4': []}
cfg.option('val1').value.set(['val1'])
assert cfg.value.dict() == {'val1': ['val1'], 'val4': ['val1']}
assert parse_od_get(cfg.value.get()) == {'val1': ['val1'], 'val4': ['val1']}
# assert not list_sessions()
@ -1639,9 +1639,9 @@ def test_calc_value_join_multi_value(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3, val4])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'val1': ['val1'], 'val2': ['val2'], 'val3': [None], 'val4': []}
assert parse_od_get(cfg.value.get()) == {'val1': ['val1'], 'val2': ['val2'], 'val3': [None], 'val4': []}
cfg.option('val3').value.set(['val3'])
assert cfg.value.dict() == {'val1': ['val1'], 'val2': ['val2'], 'val3': ['val3'], 'val4': ['val1.val2.val3']}
assert parse_od_get(cfg.value.get()) == {'val1': ['val1'], 'val2': ['val2'], 'val3': ['val3'], 'val4': ['val1.val2.val3']}
# assert not list_sessions()
@ -1653,9 +1653,9 @@ def test_calc_value_min():
od1 = OptionDescription('root', '', [val1, val2, val3, val4])
cfg = Config(od1)
cfg.property.read_write()
assert cfg.value.dict() == {'val1': 'val1', 'val2': 'val2', 'val3': 'val3', 'val4': 'val1.val2.val3'}
assert parse_od_get(cfg.value.get()) == {'val1': 'val1', 'val2': 'val2', 'val3': 'val3', 'val4': 'val1.val2.val3'}
cfg.option('val3').property.add('disabled')
assert cfg.value.dict() == {'val1': 'val1', 'val2': 'val2', 'val4': ''}
assert parse_od_get(cfg.value.get()) == {'val1': 'val1', 'val2': 'val2', 'val4': ''}
# assert not list_sessions()
@ -1666,7 +1666,7 @@ def test_calc_value_add(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'val1': 1, 'val2': 2, 'val3': 3}
assert parse_od_get(cfg.value.get()) == {'val1': 1, 'val2': 2, 'val3': 3}
# assert not list_sessions()

View file

@ -14,7 +14,7 @@ from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \
calc_value, calc_value_property_help, ParamInformation
from tiramisu.error import PropertiesOptionError
import warnings
from .config import config_type, get_config
from .config import config_type, get_config, parse_od_get
def make_description():
@ -228,7 +228,7 @@ def test_default_with_multi():
def test_idontexist():
od1 = make_description()
cfg = Config(od1)
cfg.value.dict()
cfg.value.get()
with pytest.raises(AttributeError):
cfg.option('idontexist').value.get()
# assert not list_sessions()
@ -535,12 +535,8 @@ def test_allow_multiple_changes_from_config():
def test_access_by_get():
od1 = make_description()
cfg = Config(od1)
with pytest.raises(AttributeError):
list(cfg.option.find('idontexist'))
ret = cfg.option.find('wantref', first=True)
assert ret.value.get() is False
ret = cfg.option.find('dummy', first=True)
assert ret.value.get() is False
assert cfg.option('wantref').value.get() is False
assert cfg.option('gc.dummy').value.get() is False
# assert not list_sessions()
@ -555,8 +551,7 @@ def test_access_by_get_whith_hide():
cfg = Config(od1)
cfg.property.read_write()
with pytest.raises(AttributeError):
ret = cfg.option.find('b1')
ret.value.get()
cfg.option('b1').value.get()
# assert not list_sessions()
@ -645,27 +640,27 @@ def test_reset_properties_force_store_value():
# assert not list_sessions()
def test_importation_force_store_value():
gcdummy = BoolOption('dummy', 'dummy', default=False,
properties=('force_store_value',))
gcgroup = OptionDescription('gc', '', [gcdummy])
od1 = OptionDescription('tiramisu', '', [gcgroup])
config1 = Config(od1)
assert config1.value.exportation() == {}
config1.property.add('frozen')
assert config1.value.exportation() == {}
config1.property.add('force_store_value')
assert config1.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
exportation = config1.property.exportation()
config2 = Config(od1)
assert config2.value.exportation() == {}
config2.property.importation(exportation)
assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
config2.property.importation(exportation)
assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
# assert not list_sessions()
#def test_importation_force_store_value():
# gcdummy = BoolOption('dummy', 'dummy', default=False,
# properties=('force_store_value',))
# gcgroup = OptionDescription('gc', '', [gcdummy])
# od1 = OptionDescription('tiramisu', '', [gcgroup])
# config1 = Config(od1)
# assert config1.value.exportation() == {}
# config1.property.add('frozen')
# assert config1.value.exportation() == {}
# config1.property.add('force_store_value')
# assert config1.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
# exportation = config1.property.exportation()
# config2 = Config(od1)
# assert config2.value.exportation() == {}
# config2.property.importation(exportation)
# assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
# config2.property.importation(exportation)
# assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
## assert not list_sessions()
#
#
def test_set_modified_value():
gcdummy = BoolOption('dummy', 'dummy', default=False, properties=('force_store_value',))
gcgroup = OptionDescription('gc', '', [gcdummy])
@ -678,18 +673,18 @@ def test_set_modified_value():
# assert not list_sessions()
def test_none_is_not_modified():
gcdummy = StrOption('dummy', 'dummy', properties=('force_store_value',))
gcdummy1 = StrOption('dummy1', 'dummy1', default="str", properties=('force_store_value',))
gcgroup = OptionDescription('gc', '', [gcdummy, gcdummy1])
od1 = OptionDescription('tiramisu', '', [gcgroup])
cfg = Config(od1)
assert cfg.value.exportation() == {}
cfg.property.read_write()
assert cfg.value.exportation() == {'gc.dummy1': {None: ['str', 'forced']}}
# assert not list_sessions()
#def test_none_is_not_modified():
# gcdummy = StrOption('dummy', 'dummy', properties=('force_store_value',))
# gcdummy1 = StrOption('dummy1', 'dummy1', default="str", properties=('force_store_value',))
# gcgroup = OptionDescription('gc', '', [gcdummy, gcdummy1])
# od1 = OptionDescription('tiramisu', '', [gcgroup])
# cfg = Config(od1)
# assert cfg.value.exportation() == {}
# cfg.property.read_write()
# assert cfg.value.exportation() == {'gc.dummy1': {None: ['str', 'forced']}}
## assert not list_sessions()
#
#
def test_pprint():
msg_error = _("cannot access to {0} \"{1}\" because has {2} {3}")
msg_is_not = _('the value of "{0}" is not {1}')
@ -893,7 +888,9 @@ def test_settings_list_with_follower():
descr = Leadership("root", "", [leader, option, ip])
cfg = Config(OptionDescription('root', 'root', [descr]))
cfg.property.read_write()
assert len(cfg.option('root').list('all')) == 2
assert parse_od_get(cfg.option('root').value.get()) == {'root.leader': ['leader']}
assert len(cfg.option('root').list()) == 1
assert len(cfg.option('root').list(validate_properties=False)) == 3
def return_none(*args):
@ -908,4 +905,4 @@ def test_settings_disable_set_information(config_type):
cfg = Config(od1)
cfg.property.read_only()
cfg.information.set('key', 'val')
assert cfg.value.dict() == {'leadership.opt1': [{'leadership.opt1': 'val', 'leadership.opt2': 'test'}]}
assert parse_od_get(cfg.value.get()) == {'leadership.opt1': [{'leadership.opt1': 'val', 'leadership.opt2': 'test'}]}

View file

@ -441,7 +441,7 @@ def test_validator_warning_leadership(config_type):
with warnings.catch_warnings(record=True) as w:
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val'])
if config_type != 'tiramisu-api':
assert w[0].message.opt() == ip_admin_eth0
assert w and w[0].message.opt() == ip_admin_eth0
assert str(w[0].message) == msg_err.format('val', ip_admin_eth0.get_type(), display_name_ip) + ', test error return_false'
else:
assert len(w) == 2
@ -965,7 +965,7 @@ def test_validator_broadcast_default_1():
od1 = OptionDescription('a', '', [a, b, c])
cfg = Config(od1)
with pytest.raises(ValueError):
cfg.value.dict()
cfg.value.get()
# assert not list_sessions()
@ -975,7 +975,7 @@ def test_validator_broadcast_default_2():
d = BroadcastOption('d', '', '192.168.1.127', validators=[Calculation(valid_broadcast, Params((ParamOption(a), ParamOption(b), ParamSelfOption())))])
od1 = OptionDescription('a', '', [a, b, d])
cfg = Config(od1)
assert cfg.value.dict()
assert cfg.value.get()
# assert not list_sessions()
@ -1001,7 +1001,7 @@ def test_validator_network_netmask_mandatory(config_type):
cfg = Config(od1)
cfg.property.read_only()
cfg = get_config(cfg, config_type)
cfg.value.dict()
cfg.value.get()
# assert not list_sessions()
@ -1109,7 +1109,7 @@ def test_validator_not_equal_leadership(config_type):
cfg.option('a.b', 0).value.set(2)
cfg.option('a.a').value.reset()
cfg.option('a.a').value.set([1])
cfg.value.dict()
cfg.value.get()
# assert not list_sessions()

View file

@ -13,7 +13,7 @@ from tiramisu import IPOption, OptionDescription, BoolOption, IntOption, StrOpti
calc_value_property_help
from tiramisu.error import PropertiesOptionError, ConfigError, display_list
import pytest
from .config import config_type, get_config
from .config import config_type, get_config, parse_od_get
def test_properties(config_type):
@ -1106,19 +1106,19 @@ def test_leadership_requires(config_type):
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() is None
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('255.255.255.255')
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == '255.255.255.255'
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2', 'ip_admin_eth0.netmask_admin_eth0': None},
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2', 'ip_admin_eth0.netmask_admin_eth0': None},
{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2', 'ip_admin_eth0.netmask_admin_eth0': '255.255.255.255'}]}
#
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.1'])
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get()
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2',
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2',
'ip_admin_eth0.netmask_admin_eth0': None},
{'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]}
#
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.255')
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2',
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2',
'ip_admin_eth0.netmask_admin_eth0': '255.255.255.255'},
{'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]}
# assert not list_sessions()
@ -1158,7 +1158,7 @@ def test_leadership_requires_leader(config_type):
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()
assert cfg.value.dict() == {'activate': False}
assert parse_od_get(cfg.value.get()) == {'activate': False}
# assert not list_sessions()
@ -1200,7 +1200,7 @@ def test_leadership_requires_leadership(config_type):
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()
assert cfg.value.dict() == {'activate': False}
assert parse_od_get(cfg.value.get()) == {'activate': False}
# assert not list_sessions()
@ -1238,7 +1238,7 @@ def test_leadership_requires_no_leader(config_type):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()
with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get()
assert cfg.value.dict() == {'activate': False, 'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2'}, {'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]}
assert parse_od_get(cfg.value.get()) == {'activate': False, 'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2'}, {'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]}
# assert not list_sessions()
@ -1299,10 +1299,10 @@ def test_leadership_requires_complet(config_type):
cfg = get_config(cfg, config_type)
cfg.option('options.unicode.unicode').value.set(['test', 'trah'])
cfg.option('options.unicode.unicode2', 0).value.set('test')
assert cfg.value.dict() == {'options.unicode.unicode': [{'options.unicode.unicode': 'test', 'options.unicode.unicode1': None, 'options.unicode.unicode2': 'test', 'options.unicode.unicode3': None, 'options.unicode.unicode4': None}, {'options.unicode.unicode': 'trah', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}], 'options.unicodetoto': None}
assert parse_od_get(cfg.value.get()) == {'options.unicode.unicode': [{'options.unicode.unicode': 'test', 'options.unicode.unicode1': None, 'options.unicode.unicode2': 'test', 'options.unicode.unicode3': None, 'options.unicode.unicode4': None}, {'options.unicode.unicode': 'trah', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}], 'options.unicodetoto': None}
#
cfg.option('options.unicodetoto').value.set('test')
assert cfg.value.dict() == {'options.unicode.unicode': [{'options.unicode.unicode': 'test', 'options.unicode.unicode1': None, 'options.unicode.unicode2': 'test', 'options.unicode.unicode3': None, 'options.unicode.unicode4': None, 'options.unicode.unicode5': None, 'options.unicode.unicode6': None, 'options.unicode.unicode7': None}, {'options.unicode.unicode': 'trah', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None, 'options.unicode.unicode5': None}], 'options.unicodetoto': 'test'}
assert parse_od_get(cfg.value.get()) == {'options.unicode.unicode': [{'options.unicode.unicode': 'test', 'options.unicode.unicode1': None, 'options.unicode.unicode2': 'test', 'options.unicode.unicode3': None, 'options.unicode.unicode4': None, 'options.unicode.unicode5': None, 'options.unicode.unicode6': None, 'options.unicode.unicode7': None}, {'options.unicode.unicode': 'trah', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None, 'options.unicode.unicode5': None}], 'options.unicodetoto': 'test'}
# assert not list_sessions()
@ -1339,24 +1339,24 @@ def test_leadership_requires_transitive1(config_type):
cfg = Config(od1)
cfg.property.read_write()
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'options.unicode.unicode': [], 'options.unicodetoto': None}
assert parse_od_get(cfg.value.get()) == {'options.unicode.unicode': [], 'options.unicodetoto': None}
#
cfg.option('options.unicodetoto').value.set('test')
assert cfg.value.dict() == {'options.unicode.unicode': [], 'options.unicodetoto': 'test'}
assert parse_od_get(cfg.value.get()) == {'options.unicode.unicode': [], 'options.unicodetoto': 'test'}
#
cfg.option('options.unicode.unicode').value.set(['a', 'b', 'c'])
assert cfg.value.dict() == {'options.unicode.unicode': [{'options.unicode.unicode': 'a', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}, {'options.unicode.unicode': 'b', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}, {'options.unicode.unicode': 'c', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}], 'options.unicodetoto': 'test'}
assert parse_od_get(cfg.value.get()) == {'options.unicode.unicode': [{'options.unicode.unicode': 'a', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}, {'options.unicode.unicode': 'b', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}, {'options.unicode.unicode': 'c', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}], 'options.unicodetoto': 'test'}
cfg.option('options.unicode.unicode2', 1).value.set('test')
cfg.option('options.unicode.unicode3', 1).value.set('test')
assert cfg.value.dict() == {'options.unicode.unicode': [{'options.unicode.unicode': 'a', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}, {'options.unicode.unicode': 'b', 'options.unicode.unicode1': None, 'options.unicode.unicode2': 'test', 'options.unicode.unicode3': 'test', 'options.unicode.unicode4': None}, {'options.unicode.unicode': 'c', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}], 'options.unicodetoto': 'test'}
assert parse_od_get(cfg.value.get()) == {'options.unicode.unicode': [{'options.unicode.unicode': 'a', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}, {'options.unicode.unicode': 'b', 'options.unicode.unicode1': None, 'options.unicode.unicode2': 'test', 'options.unicode.unicode3': 'test', 'options.unicode.unicode4': None}, {'options.unicode.unicode': 'c', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}], 'options.unicodetoto': 'test'}
#
cfg.option('options.unicode.unicode2', 1).value.set('rah')
assert cfg.value.dict() == {'options.unicode.unicode': [{'options.unicode.unicode': 'a', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}, {'options.unicode.unicode': 'b', 'options.unicode.unicode1': None, 'options.unicode.unicode2': 'rah'}, {'options.unicode.unicode': 'c', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}], 'options.unicodetoto': 'test'}
assert parse_od_get(cfg.value.get()) == {'options.unicode.unicode': [{'options.unicode.unicode': 'a', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}, {'options.unicode.unicode': 'b', 'options.unicode.unicode1': None, 'options.unicode.unicode2': 'rah'}, {'options.unicode.unicode': 'c', 'options.unicode.unicode1': None, 'options.unicode.unicode2': None}], 'options.unicodetoto': 'test'}
#
cfg.option('options.unicode.unicode2', 1).value.set('test')
cfg.option('options.unicodetoto').value.set('rah')
assert cfg.value.dict() == {'options.unicode.unicode': [{'options.unicode.unicode': 'a', 'options.unicode.unicode1': None}, {'options.unicode.unicode': 'b', 'options.unicode.unicode1': None}, {'options.unicode.unicode': 'c', 'options.unicode.unicode1': None}], 'options.unicodetoto': 'rah'}
assert parse_od_get(cfg.value.get()) == {'options.unicode.unicode': [{'options.unicode.unicode': 'a', 'options.unicode.unicode1': None}, {'options.unicode.unicode': 'b', 'options.unicode.unicode1': None}, {'options.unicode.unicode': 'c', 'options.unicode.unicode1': None}], 'options.unicodetoto': 'rah'}
# assert not list_sessions()

View file

@ -528,43 +528,43 @@ def test_submulti_unique():
# assert not list_sessions()
def test_multi_submulti_meta():
multi = StrOption('multi', '', multi=submulti)
od1 = OptionDescription('od', '', [multi])
cfg = Config(od1, name='cfg')
cfg.property.read_write()
cfg2 = Config(od1)
cfg2.property.read_write()
meta = MetaConfig([cfg, cfg2])
meta.property.read_write()
meta.option('multi').value.set([['val']])
assert meta.option('multi').value.get() == [['val']]
newcfg = meta.config('cfg')
newcfg.option('multi').value.set([['val', None]])
assert cfg.option('multi').value.get() == [['val', None]]
newcfg = meta.config('cfg')
assert newcfg.option('multi').value.get() == [['val', None]]
assert meta.option('multi').value.get() == [['val']]
# assert not list_sessions()
def test_multi_submulti_meta_no_cache():
multi = StrOption('multi', '', multi=submulti)
multi = StrOption('multi', '', multi=submulti)
od1 = OptionDescription('od', '', [multi])
cfg = Config(od1, name='cfg')
cfg.property.read_write()
cfg2 = Config(od1)
cfg.property.read_write()
meta = MetaConfig([cfg, cfg2])
meta.property.read_write()
meta.property.remove('cache')
meta.option('multi').value.set([['val']])
assert meta.option('multi').value.get() == [['val']]
newcfg = meta.config('cfg')
newcfg.option('multi').value.set([['val', None]])
assert cfg.option('multi').value.get() == [['val', None]]
newcfg = meta.config('cfg')
assert newcfg.option('multi').value.get() == [['val', None]]
assert meta.option('multi').value.get() == [['val']]
# assert not list_sessions()
#def test_multi_submulti_meta():
# multi = StrOption('multi', '', multi=submulti)
# od1 = OptionDescription('od', '', [multi])
# cfg = Config(od1, name='cfg')
# cfg.property.read_write()
# cfg2 = Config(od1)
# cfg2.property.read_write()
# meta = MetaConfig([cfg, cfg2])
# meta.property.read_write()
# meta.option('multi').value.set([['val']])
# assert meta.option('multi').value.get() == [['val']]
# newcfg = meta.config('cfg')
# newcfg.option('multi').value.set([['val', None]])
# assert cfg.option('multi').value.get() == [['val', None]]
# newcfg = meta.config('cfg')
# assert newcfg.option('multi').value.get() == [['val', None]]
# assert meta.option('multi').value.get() == [['val']]
## assert not list_sessions()
#
#
#def test_multi_submulti_meta_no_cache():
# multi = StrOption('multi', '', multi=submulti)
# multi = StrOption('multi', '', multi=submulti)
# od1 = OptionDescription('od', '', [multi])
# cfg = Config(od1, name='cfg')
# cfg.property.read_write()
# cfg2 = Config(od1)
# cfg.property.read_write()
# meta = MetaConfig([cfg, cfg2])
# meta.property.read_write()
# meta.property.remove('cache')
# meta.option('multi').value.set([['val']])
# assert meta.option('multi').value.get() == [['val']]
# newcfg = meta.config('cfg')
# newcfg.option('multi').value.set([['val', None]])
# assert cfg.option('multi').value.get() == [['val', None]]
# newcfg = meta.config('cfg')
# assert newcfg.option('multi').value.get() == [['val', None]]
# assert meta.option('multi').value.get() == [['val']]
## assert not list_sessions()

View file

@ -2,7 +2,7 @@
import pytest
from .autopath import do_autopath
do_autopath()
from .config import config_type, get_config
from .config import config_type, get_config, parse_od_get
from tiramisu import BoolOption, StrOption, SymLinkOption, submulti, \
OptionDescription, Leadership, Config, Calculation, calc_value, Params, ParamOption, ParamValue
@ -300,9 +300,9 @@ def test_symlink_with_leader(config_type):
od1 = OptionDescription('root', '', [interface1, leader])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [], 'leader': []}
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': [], 'leader': []}
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val2'])
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'val1', 'ip_admin_eth0.netmask_admin_eth0': None}, {'ip_admin_eth0.ip_admin_eth0': 'val2', 'ip_admin_eth0.netmask_admin_eth0': None}], 'leader': ['val1', 'val2']}
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'val1', 'ip_admin_eth0.netmask_admin_eth0': None}, {'ip_admin_eth0.ip_admin_eth0': 'val2', 'ip_admin_eth0.netmask_admin_eth0': None}], 'leader': ['val1', 'val2']}
cfg.option('ip_admin_eth0.ip_admin_eth0').value.pop(0)
with pytest.raises(ConfigError):
cfg.option('leader').value.pop(0)
@ -318,9 +318,9 @@ def test_symlink_with_follower(config_type):
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert not cfg.option('follower').isoptiondescription()
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [], 'follower': []}
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': [], 'follower': []}
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val1', 'val2'])
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'val1', 'ip_admin_eth0.netmask_admin_eth0': None}, {'ip_admin_eth0.ip_admin_eth0': 'val2', 'ip_admin_eth0.netmask_admin_eth0': None}], 'follower': [None, None]}
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'val1', 'ip_admin_eth0.netmask_admin_eth0': None}, {'ip_admin_eth0.ip_admin_eth0': 'val2', 'ip_admin_eth0.netmask_admin_eth0': None}], 'follower': [None, None]}
#
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).owner.get() == 'default'
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).owner.get() == 'default'
@ -335,7 +335,7 @@ def test_symlink_with_follower(config_type):
assert cfg.option('follower').value.get() == [None, None]
#
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val3')
assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'val1', 'ip_admin_eth0.netmask_admin_eth0': None}, {'ip_admin_eth0.ip_admin_eth0': 'val2', 'ip_admin_eth0.netmask_admin_eth0': 'val3'}], 'follower': [None, 'val3']}
assert parse_od_get(cfg.value.get()) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': 'val1', 'ip_admin_eth0.netmask_admin_eth0': None}, {'ip_admin_eth0.ip_admin_eth0': 'val2', 'ip_admin_eth0.netmask_admin_eth0': 'val3'}], 'follower': [None, 'val3']}
#
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == None
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'val3'
@ -372,9 +372,9 @@ def test_symlink_makedict(config_type):
[linkopt, OptionDescription("s1", "", [boolopt])])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
assert cfg.value.dict() == {'c': False, 's1.b': False}
assert parse_od_get(cfg.value.get()) == {'c': False, 's1.b': False}
cfg.option('s1.b').value.set(True)
assert cfg.value.dict() == {'c': True, 's1.b': True}
assert parse_od_get(cfg.value.get()) == {'c': True, 's1.b': True}
# assert not list_sessions()
@ -385,15 +385,9 @@ def test_symlink_list(config_type):
[linkopt, OptionDescription("s1", "", [boolopt])])
cfg = Config(od1)
cfg = get_config(cfg, config_type)
list_opt = []
for opt in cfg.option.list():
list_opt.append(opt.path())
assert list_opt == ['c']
assert [opt.path() for opt in cfg.option.list()] == ['c', 's1']
#
list_opt = []
for opt in cfg.option.list(recursive=True):
list_opt.append(opt.path())
assert list_opt == ['c', 's1.b']
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,11 +19,12 @@
# ____________________________________________________________
"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
from .error import PropertiesOptionError, ConfigError, LeadershipError, ValueWarning
from .i18n import _
from .setting import undefined, ConfigBag, OptionBag, Undefined
from .setting import undefined, ConfigBag, Undefined
from .function import FUNCTION_WAITING_FOR_DICT
# ____________________________________________________________
@ -55,6 +56,7 @@ class Params:
class Param:
__slots__ = tuple()
pass
@ -82,11 +84,14 @@ class ParamOption(Param):
class ParamDynOption(ParamOption):
__slots__ = ('subpath',)
__slots__ = ('suffixes',
'dynoptiondescription',
'optional',
)
def __init__(self,
option: 'Option',
subpath: str,
dynoptiondescription: 'DynOptionDescription',
suffixes: list[str],
dynoptiondescription: 'DynOptionDescription'=None,
notraisepropertyerror: bool=False,
raisepropertyerror: bool=False,
optional: bool=False,
@ -95,7 +100,7 @@ class ParamDynOption(ParamOption):
notraisepropertyerror,
raisepropertyerror,
)
self.subpath = subpath
self.suffixes = suffixes
self.dynoptiondescription = dynoptiondescription
self.optional = optional
@ -179,17 +184,18 @@ class Calculation:
self.warnings_only = warnings_only
def execute(self,
option_bag: OptionBag,
subconfig: "SubConfig",
*,
orig_value: Any=undefined,
allow_value_error: bool=False,
force_value_warning: bool=False,
for_settings: bool=False,
) -> Any:
return carry_out_calculation(option_bag.option,
return carry_out_calculation(subconfig,
callback=self.function,
callback_params=self.params,
index=option_bag.index,
config_bag=option_bag.config_bag,
index=subconfig.index,
config_bag=subconfig.config_bag,
orig_value=orig_value,
allow_value_error=allow_value_error,
force_value_warning=force_value_warning,
@ -197,18 +203,18 @@ class Calculation:
)
def help(self,
option_bag: OptionBag,
subconfig: "SubConfig",
for_settings: bool=False,
) -> str:
if not self.help_function:
return self.execute(option_bag,
return self.execute(subconfig,
for_settings=for_settings,
)
return carry_out_calculation(option_bag.option,
return carry_out_calculation(subconfig,
callback=self.help_function,
callback_params=self.params,
index=option_bag.index,
config_bag=option_bag.config_bag,
index=subconfig.index,
config_bag=subconfig.config_bag,
for_settings=for_settings,
)
@ -218,76 +224,63 @@ class Calculation:
def manager_callback(callback: Callable,
param: Param,
option,
subconfig: 'SubConfig',
index: Optional[int],
orig_value,
config_bag: ConfigBag,
for_settings: bool,
) -> Any:
"""replace Param by true value"""
def calc_index(param, index, same_leadership):
if index is not None:
if hasattr(param, 'whole'):
whole = param.whole
else:
# if value is same_leadership, follower are isolate by default
# otherwise option is a whole option
whole = not same_leadership
if not whole:
return index
return None
option = subconfig.option
def calc_apply_index(param,
same_leadership,
):
return index is not None and \
not getattr(param, 'whole', not same_leadership)
def calc_self(param,
option,
index,
value,
config_bag,
):
# index must be apply only if follower
is_follower = option.impl_is_follower()
apply_index = calc_index(param, index, is_follower)
if value is undefined or (apply_index is None and is_follower):
path = option.impl_getpath()
option_bag = OptionBag(option,
None,
config_bag,
properties=None,
is_follower = subconfig.option.impl_is_follower()
# FIXME "same_leadership" or "is_follower"?
apply_index = calc_apply_index(param,
is_follower,
)
properties = config_bag.context.get_settings().getproperties(option_bag,
if value is undefined or (apply_index is False and is_follower):
path = subconfig.path
properties = config_bag.context.get_settings().getproperties(subconfig,
uncalculated=True,
)
new_value = get_value(config_bag,
option,
subconfig,
param,
apply_index,
True,
properties,
apply_index=apply_index,
properties=properties,
)
if apply_index is None and is_follower:
if apply_index is False and is_follower:
new_value[index] = value
value = new_value
elif apply_index is not None and not is_follower:
value = value[apply_index]
elif apply_index is not False and not is_follower:
value = value[index]
return value
def get_value(config_bag,
option,
subconfig,
param,
index,
self_calc,
*,
apply_index=True,
properties=undefined,
):
parent_option_bag, option_bag = get_option_bag(config_bag,
option,
param,
index,
self_calc,
properties=properties,
)
if option.impl_is_follower() and index is None:
option = subconfig.option
if option.impl_is_follower() and apply_index is False:
value = []
for idx in range(config_bag.context.get_length_leadership(parent_option_bag)):
parent_option_bag, option_bag = get_option_bag(config_bag,
for idx in range(subconfig.parent.get_length_leadership()):
subconfig = get_option_bag(config_bag,
option,
param,
idx,
@ -295,36 +288,36 @@ def manager_callback(callback: Callable,
properties=properties,
)
value.append(_get_value(param,
option_bag,
subconfig,
))
else:
value = _get_value(param,
option_bag,
subconfig,
)
return value
def _get_value(param: Params,
option_bag: OptionBag,
subconfig: SubConfig,
) -> Any:
try:
# get value
value = config_bag.context.get_value(option_bag)
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:
raise err from err
display_name = option_bag.option.impl_get_display_name()
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_bag.option.impl_get_display_name(), err)) from err
display_name = subconfig.option.impl_get_display_name()
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:
# cannot acces, simulate a propertyerror
raise PropertiesOptionError(option_bag,
raise PropertiesOptionError(subconfig,
['configerror'],
config_bag.context.get_settings(),
)
display_name = option_bag.option.impl_get_display_name()
display_name = subconfig.option.impl_get_display_name()
raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
return value
@ -333,6 +326,7 @@ def manager_callback(callback: Callable,
param,
index_,
self_calc,
*,
properties=undefined,
):
# don't validate if option is option that we tried to validate
@ -345,12 +339,9 @@ def manager_callback(callback: Callable,
if self_calc:
config_bag.unrestraint()
config_bag.remove_validation()
root_option_bag = OptionBag(config_bag.context.get_description(),
None,
config_bag,
)
# root = config_bag.context.get_root(config_bag)
try:
options_bag = config_bag.context.get_sub_option_bag(root_option_bag,
subconfig = config_bag.context.get_sub_config(config_bag,
opt.impl_getpath(),
index_,
validate_properties=not self_calc,
@ -373,30 +364,36 @@ def manager_callback(callback: Callable,
)
display_name = option.impl_get_display_name()
raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
if len(options_bag) > 1:
parent_option_bag = options_bag[-2]
else:
parent_option_bag = None
return parent_option_bag, options_bag[-1]
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
if isinstance(param, ParamValue):
return param.value
if isinstance(param, ParamInformation):
if isinstance(param, ParamSelfInformation):
option_bag = OptionBag(option,
index,
config_bag,
)
isubconfig = subconfig
elif param.option:
option_bag = OptionBag(param.option,
isubconfig = get_option_bag(config_bag,
param.option,
param,
None,
config_bag,
False,
#properties=properties,
)
else:
option_bag = None
isubconfig = None
try:
return config_bag.context.get_values().get_information(option_bag,
return config_bag.context.get_values().get_information(isubconfig,
param.information_name,
param.default_value,
)
@ -409,13 +406,12 @@ def manager_callback(callback: Callable,
if isinstance(param, ParamSuffix):
if not option.issubdyn():
display_name = option_bag.option.impl_get_display_name()
display_name = subconfig.option.impl_get_display_name()
raise ConfigError(_('option "{display_name}" is not in a dynoptiondescription'))
return option.get_suffixes()[-1]
return subconfig.suffixes[-1]
if isinstance(param, ParamSelfOption):
value = calc_self(param,
option,
index,
orig_value,
config_bag,
@ -429,51 +425,30 @@ def manager_callback(callback: Callable,
if isinstance(param, ParamOption):
callbk_option = param.option
callbk_options = None
subconfigs = None
if callbk_option.issubdyn():
found = False
if isinstance(param, ParamDynOption):
od_path = param.dynoptiondescription.impl_getpath()
if "." in od_path:
rootpath = od_path.rsplit('.', 1)[0] + '.'
else:
rootpath = ''
full_path = rootpath + param.subpath
root_option_bag = OptionBag(config_bag.context.get_description(),
None,
config_bag,
)
try:
soptions_bag = config_bag.context.get_sub_option_bag(root_option_bag,
full_path,
#FIXME index?
index=None,
validate_properties=True,
properties=None,
)
except AttributeError as err:
raise ConfigError(_(f'option "{option.impl_get_display_name()}" is not in a dynoptiondescription: {err}'))
callbk_option = soptions_bag[-1].option
# SUBDYN INSIDE CURRENT != SUBDYN OUTSIDE ?
callbk_option = callbk_option.to_sub_dyoption(param.suffixes)
found = True
elif option.impl_is_dynsymlinkoption():
rootpath = option.rootpath
call_path = callbk_option.impl_getpath()
in_same_dyn = False
if not option.opt.issubdyn() and callbk_option.getsubdyn() == option.opt:
# First dyn
in_same_dyn = True
elif option.opt.issubdyn():
# Search if callback and option has a common subdyn
callbk_subdyn = callbk_option.getsubdyn()
sub_dyn = option
while True:
sub_dyn = sub_dyn.getsubdyn()
if sub_dyn == callbk_subdyn:
in_same_dyn = True
break
if not sub_dyn.issubdyn():
break
if in_same_dyn:
callbk_option = callbk_option.to_sub_dyoption(option.get_suffixes())
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 = []
@ -482,12 +457,6 @@ def manager_callback(callback: Callable,
index=None,
):
callbk_options.append(doption_bag.option)
if callbk_options is None:
callbk_options = [callbk_option]
values = None
else:
values = []
for callbk_option in callbk_options:
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():
@ -501,11 +470,28 @@ def manager_callback(callback: Callable,
else:
index_ = None
with_index = False
value = get_value(config_bag,
if subconfigs is None:
subconfigs = [get_option_bag(config_bag,
callbk_option,
param,
index_,
False,
#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,
subconfig,
param,
False,
)
if with_index:
value = value[index]
@ -519,7 +505,7 @@ def manager_callback(callback: Callable,
'value': value}
def carry_out_calculation(option,
def carry_out_calculation(subconfig: 'SubConfig',
callback: Callable,
callback_params: Optional[Params],
index: Optional[int],
@ -545,6 +531,7 @@ def carry_out_calculation(option,
- tuple with option and boolean's force_permissive (True when don't raise
if PropertiesOptionError)
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!')
def fake_items(iterator):
@ -556,7 +543,7 @@ def carry_out_calculation(option,
try:
value = manager_callback(callback,
param,
option,
subconfig,
index,
orig_value,
config_bag,

View file

@ -26,24 +26,24 @@ class Cache:
def __init__(self):
self._cache = {}
def _get_path_index(self, option_bag):
if option_bag is None:
def _get_path_index(self, subconfig):
if subconfig is None:
path = None
index = None
else:
path = option_bag.path
index = option_bag.index
path = subconfig.path
index = subconfig.index
return path, index
def getcache(self,
option_bag,
subconfig,
type_,
expiration=True,
):
"""get the cache value fot a specified path
"""
no_cache = False, None, False
path, index = self._get_path_index(option_bag)
path, index = self._get_path_index(subconfig)
if path not in self._cache or index not in self._cache[path]:
return no_cache
value, timestamp, validated = self._cache[path][index]
@ -52,26 +52,26 @@ class Cache:
props = value
self_props = {}
else:
props = option_bag.config_bag.properties
props = subconfig.config_bag.properties
if type_ == 'self_props':
# cached value is self_props
self_props = value
else:
self_props = option_bag.properties
self_props = subconfig.properties
if 'cache' in props or \
'cache' in self_props:
if expiration and timestamp and \
('expire' in props or \
'expire' in self_props):
ntime = int(time())
if timestamp + option_bag.config_bag.expiration_time >= ntime:
if timestamp + subconfig.config_bag.expiration_time >= ntime:
return True, value, validated
else:
return True, value, validated
return no_cache
def setcache(self,
option_bag,
subconfig,
val,
type_='values',
validated=True,
@ -80,13 +80,13 @@ class Cache:
if follower, add index
"""
if type_ == 'values':
if 'cache' not in option_bag.config_bag.properties and \
'cache' not in option_bag.properties:
if 'cache' not in subconfig.config_bag.properties and \
'cache' not in subconfig.properties:
return
elif (option_bag is None or 'cache' not in option_bag.config_bag.properties) and \
elif (subconfig is None or 'cache' not in subconfig.config_bag.properties) and \
'cache' not in val:
return
path, index = self._get_path_index(option_bag)
path, index = self._get_path_index(subconfig)
self._cache.setdefault(path, {})[index] = (val, int(time()), validated)
def delcache(self, path):

File diff suppressed because it is too large Load diff

View file

@ -54,7 +54,7 @@ def display_list(lst, separator='and', add_quote=False):
class PropertiesOptionError(AttributeError):
"attempt to access to an option with a property that is not allowed"
def __init__(self,
option_bag,
subconfig,
proptype,
settings,
opt_type=None,
@ -66,13 +66,12 @@ class PropertiesOptionError(AttributeError):
self._name = name
self._orig_opt = orig_opt
else:
if option_bag.option.impl_is_optiondescription():
if subconfig.option.impl_is_optiondescription():
self._opt_type = 'optiondescription'
else:
self._opt_type = 'option'
self._name = option_bag.option.impl_get_display_name()
self._name = subconfig.option.impl_get_display_name()
self._orig_opt = None
self._option_bag = option_bag
self.proptype = proptype
self.help_properties = help_properties
self._settings = settings

View file

@ -22,11 +22,10 @@
"""
from .optiondescription import OptionDescription
from .dynoptiondescription import DynOptionDescription
from .syndynoptiondescription import SynDynOptionDescription, SynDynLeadership
from .leadership import Leadership
from .baseoption import submulti
from .symlinkoption import SymLinkOption
from .syndynoption import SynDynOption
#from .syndynoption import SynDynOption, SynDynOptionDescription, SynDynLeadership
from .option import Option
from .choiceoption import ChoiceOption
from .booloption import BoolOption
@ -50,8 +49,9 @@ from .permissionsoption import PermissionsOption
__all__ = ('Leadership', 'OptionDescription', 'DynOptionDescription',
'SynDynOptionDescription', 'SynDynLeadership', 'Option', 'SymLinkOption',
'SynDynOption', 'ChoiceOption', 'BoolOption', 'DateOption',
# 'SynDynOptionDescription', 'SynDynLeadership','SynDynOption',
'Option', 'SymLinkOption',
'ChoiceOption', 'BoolOption', 'DateOption',
'IntOption', 'FloatOption', 'StrOption',
'IPOption', 'PortOption', 'NetworkOption', 'NetmaskOption',
'BroadcastOption', 'DomainnameOption', 'EmailOption', 'URLOption',

View file

@ -22,7 +22,7 @@
"""
from typing import Any
from ..setting import undefined, OptionBag
from ..setting import undefined
from ..i18n import _
from .option import Option
from ..autolib import Calculation
@ -57,12 +57,12 @@ class ChoiceOption(Option):
**kwargs)
def impl_get_values(self,
option_bag: OptionBag,
subconfig: "SubConfig",
):
"""get values allowed by option
"""
if isinstance(self._choice_values, Calculation):
values = self._choice_values.execute(option_bag)
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()))
@ -78,12 +78,12 @@ class ChoiceOption(Option):
def validate_with_option(self,
value: Any,
option_bag: OptionBag,
subconfig: "SubConfig",
loaded: bool,
) -> None:
if loaded and isinstance(self._choice_values, Calculation):
return
values = self.impl_get_values(option_bag)
values = self.impl_get_values(subconfig)
self.validate_values(value, values)
def validate_values(self,

View file

@ -20,26 +20,22 @@
# ____________________________________________________________
"""DynOptionDescription
"""
import re
import weakref
from typing import List, Any, Optional, Tuple
from typing import List, Any, Optional
from itertools import chain
from ..autolib import ParamOption
from ..i18n import _
from .optiondescription import OptionDescription
from .syndynoptiondescription import SynDynLeadership
from .syndynoption import CommonDyn #, SynDynLeadership
from .baseoption import BaseOption
from ..setting import OptionBag, ConfigBag, undefined
from ..setting import ConfigBag, undefined
from ..error import ConfigError
from ..autolib import Calculation
NAME_REGEXP = re.compile(r'^[a-zA-Z\d\-_]*$')
class DynOptionDescription(OptionDescription):
class DynOptionDescription(OptionDescription, CommonDyn):
"""dyn option description
"""
__slots__ = ('_suffixes',
@ -86,111 +82,13 @@ class DynOptionDescription(OptionDescription):
suffix = suffix.replace('.', '_')
return suffix
def get_suffixes(self,
config_bag: ConfigBag,
*,
dynoption=None,
) -> List[str]:
"""get dynamic suffixes
"""
if dynoption:
self_opt = dynoption
else:
self_opt = self
option_bag = OptionBag(self_opt,
None,
config_bag,
properties=None,
)
values = self._suffixes.execute(option_bag)
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 impl_is_dynoptiondescription(self) -> bool:
return True
def option_is_self(self,
option,
) -> bool:
return option == self or \
(option.impl_is_sub_dyn_optiondescription() and option.opt == self)
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
def get_sub_children(self,
option,
config_bag,
*,
index=None,
properties=undefined,
dynoption=None,
):
root_path, sub_path = self.split_path(option,
dynoption=dynoption,
)
for suffix in self.get_suffixes(config_bag,
dynoption=dynoption,
):
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
)
return option == self
def impl_getname(self, suffix=None) -> str:
"""get name

View file

@ -24,9 +24,9 @@ from typing import List, Iterator, Optional
from ..i18n import _
from ..setting import groups, undefined, OptionBag, ALLOWED_LEADER_PROPERTIES
from ..setting import groups, undefined, ALLOWED_LEADER_PROPERTIES
from .optiondescription import OptionDescription
from .syndynoptiondescription import SynDynLeadership
# from .syndynoption import SynDynLeadership
from .baseoption import BaseOption
from .option import Option
from ..error import LeadershipError
@ -116,7 +116,9 @@ class Leadership(OptionDescription):
"""the option is the leader
"""
leader = self.get_leader()
return opt == leader or (opt.impl_is_dynsymlinkoption() and opt.opt == leader)
if opt.impl_is_dynsymlinkoption():
opt = opt.opt
return opt == leader
def get_leader(self) -> Option:
"""get leader
@ -138,60 +140,66 @@ class Leadership(OptionDescription):
opt = opt.opt
return opt in self._children[1]
def reset(self, config_bag: 'ConfigBag') -> None:
def reset(self, parent: "SubConfig") -> None:
"""reset follower value
"""
values = config_bag.context.get_values()
config_bag = config_bag.copy()
config_bag.remove_validation()
#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():
soption_bag = OptionBag(follower,
subconfig_follower = parent.get_child(follower,
None,
config_bag,
)
values.reset(soption_bag)
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,
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,
# )
def pop(self,
subconfig: 'SubConfig',
index: int,
config_bag: 'ConfigBag',
*,
followers: Optional[List[Option]]=undefined,
) -> None:
"""pop leader value and follower's one
@ -199,17 +207,18 @@ class Leadership(OptionDescription):
if followers is undefined:
# followers are not undefined only in SynDynLeadership
followers = self.get_followers()
config_bag = config_bag.copy()
config_bag = subconfig.config_bag.copy()
config_bag.remove_validation()
values = config_bag.context.get_values()
for follower in followers:
soption_bag = OptionBag(follower,
sub_subconfig = subconfig.parent.get_child(follower,
index,
config_bag,
True,
properties=set(), # do not check force_default_on_freeze
# or force_metaconfig_on_freeze
config_bag=config_bag,
)
values.reduce_index(soption_bag)
values.reduce_index(sub_subconfig)
def reset_cache(self,
path: str,
@ -234,23 +243,28 @@ class Leadership(OptionDescription):
config_bag,
resetted_opts,
)
leader.reset_cache(leader.impl_getpath(),
leader_path = leader.impl_getpath()
if leader_path not in resetted_opts:
leader.reset_cache(leader_path,
config_bag,
None)
resetted_opts,
)
for follower in followers:
follower.reset_cache(follower.impl_getpath(),
follower_path = follower.impl_getpath()
if follower_path not in resetted_opts:
follower.reset_cache(follower_path,
config_bag,
None,
resetted_opts,
)
def impl_is_leadership(self) -> None:
return True
def to_dynoption(self,
rootpath: str,
suffixes: Optional[list],
) -> SynDynLeadership:
return SynDynLeadership(self,
rootpath,
suffixes,
)
#
# def to_dynoption(self,
# rootpath: str,
# suffixes: Optional[list],
# ) -> SynDynLeadership:
# return SynDynLeadership(self,
# rootpath,
# suffixes,
# )

View file

@ -25,7 +25,7 @@ from itertools import chain
from .baseoption import BaseOption, submulti
from ..i18n import _
from ..setting import undefined, OptionBag
from ..setting import undefined
from ..autolib import Calculation, ParamOption, ParamInformation, ParamSelfInformation
from ..error import ValueWarning, ValueErrorWarning, ValueOptionError
from .syndynoption import SynDynOption
@ -110,15 +110,15 @@ class Option(BaseOption):
def test_multi_value(value):
if isinstance(value, Calculation):
return
option_bag = OptionBag(self,
None,
undefined,
properties=None,
)
# option_bag = OptionBag(self,
# None,
# undefined,
# properties=None,
# )
try:
self.validate(value)
self.validate_with_option(value,
option_bag,
None,
loaded=True,
)
except ValueError as err:
@ -143,17 +143,17 @@ class Option(BaseOption):
else:
test_multi_value(default_multi)
_setattr(self, '_default_multi', default_multi)
option_bag = OptionBag(self,
None,
undefined,
properties=None,
)
self.impl_validate(default,
option_bag,
# option_bag = OptionBag(self,
# None,
# undefined,
# properties=None,
# )
self.impl_validate(None,
default,
loaded=True,
)
self.impl_validate(default,
option_bag,
self.impl_validate(None,
default,
check_error=False,
loaded=True,
)
@ -262,25 +262,28 @@ class Option(BaseOption):
#__________________________________________________________________________
# validator
def impl_validate(self,
subconfig: Optional["SubConfig"],
value: Any,
option_bag: OptionBag,
*,
check_error: bool=True,
loaded: bool=False,
) -> bool:
"""Return True if value is really valid
If not validate or invalid return it returns False
"""
config_bag = option_bag.config_bag
force_index = option_bag.index
is_warnings_only = getattr(self, '_warnings_only', False)
if check_error and config_bag is not undefined and \
not 'validator' in config_bag.properties:
if check_error and subconfig and \
not 'validator' in subconfig.config_bag.properties:
return False
if subconfig:
force_index = subconfig.index
else:
force_index = None
is_warnings_only = getattr(self, '_warnings_only', False)
def _is_not_unique(value, option_bag):
def _is_not_unique(value):
# if set(value) has not same length than value
if config_bag is undefined or not check_error or \
'unique' not in option_bag.properties:
if not subconfig or not check_error or \
'unique' not in subconfig.properties:
return
lvalue = [val for val in value if val is not None]
if len(set(lvalue)) == len(lvalue):
@ -303,14 +306,23 @@ class Option(BaseOption):
kwargs = {'allow_value_error': True,
'force_value_warning': calc_is_warnings_only,
}
if _index is not None and option_bag.index == _index:
soption_bag = option_bag
if _index is not None and subconfig.index == _index:
lsubconfig = subconfig
else:
soption_bag = option_bag.copy()
soption_bag.index = _index
suffix = subconfig.suffixes
if suffix is not None:
suffix = suffix[-1]
lsubconfig = subconfig.parent.get_child(subconfig.option,
_index,
False,
properties=subconfig.properties,
suffix=suffix,
name=subconfig.path.rsplit('.', 1)[-1],
check_index=False,
)
kwargs['orig_value'] = value
validator.execute(soption_bag,
validator.execute(lsubconfig,
**kwargs,
)
except ValueWarning as warn:
@ -327,23 +339,23 @@ class Option(BaseOption):
_index,
):
#
if _value is None:
return
if isinstance(_value, list):
raise ValueError(_('which must not be a list').format(_value,
self.impl_get_display_name()),
)
if isinstance(_value, Calculation) and config_bag is undefined:
if isinstance(_value, Calculation) and not subconfig:
return
if _value is not None:
if check_error:
# option validation
if check_error:
self.validate(_value)
self.validate_with_option(_value,
option_bag,
subconfig,
loaded=loaded,
)
if ((check_error and not is_warnings_only) or
(not check_error and is_warnings_only)):
# second level validation
if (check_error and not is_warnings_only) or (not check_error and is_warnings_only):
try:
self.second_level_validation(_value,
is_warnings_only)
@ -357,7 +369,8 @@ class Option(BaseOption):
ValueWarning,
self.__class__.__name__, 0)
else:
raise err
raise err from err
# ?
if not loaded:
calculation_validator(_value,
_index,
@ -366,7 +379,9 @@ class Option(BaseOption):
err_index = force_index
try:
if not self.impl_is_multi():
do_validation(val, None)
do_validation(val,
None,
)
elif force_index is not None:
if self.impl_is_submulti():
if not isinstance(value, list):
@ -375,14 +390,12 @@ class Option(BaseOption):
do_validation(val,
force_index,
)
_is_not_unique(value,
option_bag,
)
_is_not_unique(value)
else:
do_validation(val,
force_index,
)
elif isinstance(value, Calculation) and config_bag is undefined:
elif isinstance(value, Calculation) and not subconfig:
pass
elif self.impl_is_submulti():
for err_index, lval in enumerate(value):
@ -394,7 +407,7 @@ class Option(BaseOption):
for val in lval:
do_validation(val,
err_index)
_is_not_unique(lval, option_bag)
_is_not_unique(lval)
elif not isinstance(value, list):
raise ValueError(_('which must be a list'))
else:
@ -403,18 +416,18 @@ class Option(BaseOption):
do_validation(val,
err_index,
)
_is_not_unique(value, option_bag)
_is_not_unique(value)
except ValueError as err:
if config_bag is undefined or \
'demoting_error_warning' not in config_bag.properties:
if not subconfig or \
'demoting_error_warning' not in subconfig.config_bag.properties:
raise ValueOptionError(val,
self.get_type(),
option_bag.ori_option,
self,
str(err),
err_index) from err
warnings.warn_explicit(ValueErrorWarning(val,
self.get_type(),
option_bag.ori_option,
self,
str(err),
err_index),
ValueErrorWarning,
@ -424,7 +437,8 @@ class Option(BaseOption):
def validate_with_option(self,
value: Any,
option_bag: OptionBag,
subconfig: "SubConfig",
*,
loaded: bool,
) -> None:
"""validation function with option

View file

@ -25,9 +25,9 @@ from typing import Optional, Iterator, Union, List
from ..i18n import _
from ..setting import ConfigBag, OptionBag, groups, undefined, owners, Undefined
from ..setting import ConfigBag, groups, undefined, owners, Undefined
from .baseoption import BaseOption
from .syndynoptiondescription import SubDynOptionDescription, SynDynOptionDescription
# from .syndynoption import SubDynOptionDescription, SynDynOptionDescription
from ..error import ConfigError, ConflictError
@ -71,9 +71,7 @@ class CacheOptionDescription(BaseOption):
# cache already set
raise ConfigError(_('option description seems to be part of an other '
'config'))
for option in self.get_children(config_bag=undefined, # pylint: disable=no-member
dyn=False,
):
for option in self.get_children():
if __debug__:
cache_option.append(option)
sub_currpath = currpath + [option.impl_getname()]
@ -107,71 +105,71 @@ 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_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
# 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,
# )
class OptionDescriptionWalk(CacheOptionDescription):
@ -179,6 +177,14 @@ class OptionDescriptionWalk(CacheOptionDescription):
"""
__slots__ = ('_children',)
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_child_not_dynamic(self,
name,
allow_dynoption,
@ -194,9 +200,11 @@ class OptionDescriptionWalk(CacheOptionDescription):
def get_child(self,
name: str,
config_bag: ConfigBag,
parent: 'SubConfig',
*,
with_suffix: bool=False,
allow_dynoption: bool=False,
) -> Union[BaseOption, SynDynOptionDescription]:
) -> Union[BaseOption]:
"""get a child
"""
# if not dyn
@ -209,12 +217,12 @@ class OptionDescriptionWalk(CacheOptionDescription):
for child in self._children[1]: # pylint: disable=no-member
if not child.impl_is_dynoptiondescription():
continue
for suffix in child.get_suffixes(config_bag):
for suffix in child.get_suffixes(parent):
if name != child.impl_getname(suffix):
continue
return child.to_dynoption(self.impl_getpath(),
[suffix],
)
if not with_suffix:
return child
return suffix, child
if self.impl_get_group_type() == groups.root: # pylint: disable=no-member
raise AttributeError(_(f'unknown option "{name}" '
'in root optiondescription'
@ -223,52 +231,18 @@ class OptionDescriptionWalk(CacheOptionDescription):
f'in optiondescription "{self.impl_get_display_name()}"'
))
def get_children(self,
config_bag: Union[ConfigBag, Undefined],
*,
dyn: bool=True,
#path: Optional[str]=None,
dynoption=None,
) -> Union[BaseOption, SynDynOptionDescription]:
def get_children(self) -> List[BaseOption]:
"""get children
"""
for child in self._children[1]:
if dyn and child.impl_is_dynoptiondescription():
yield from self.get_suffixed_children(dynoption,
[],
config_bag,
child,
)
else:
yield child
def get_path(self,
config_bag,
dynoption,
):
if dynoption:
self_opt = dynoption
else:
self_opt = self
if config_bag is undefined or \
config_bag.context.get_description() == self:
return ''
return self_opt.impl_getpath()
def get_suffixed_children(self,
dynoption,
option_suffixes: list,
config_bag: ConfigBag,
child,
):
root_path = self.get_path(config_bag, dynoption)
for suffix in child.get_suffixes(config_bag,
dynoption=dynoption,
):
yield child.to_dynoption(root_path,
option_suffixes + [suffix],
)
return self._children[1]
# for child in self._children[1]:
# if config_bag is not undefined and child.impl_is_dynoptiondescription():
# yield from self.get_suffixed_children([],
# config_bag,
# child,
# )
# else:
# yield child
def get_children_recursively(self,
bytype: Optional[BaseOption],
@ -277,12 +251,12 @@ class OptionDescriptionWalk(CacheOptionDescription):
self_opt: BaseOption=None,
*,
option_suffixes: Optional[list]=None
) -> Iterator[Union[BaseOption, SynDynOptionDescription]]:
) -> Iterator[Union[BaseOption]]:
"""get children recursively
"""
if self_opt is None:
self_opt = self
for option in self_opt.get_children(config_bag):
for option in self_opt.get_children():
if option.impl_is_optiondescription():
for subopt in option.get_children_recursively(bytype,
byname,
@ -391,22 +365,22 @@ class OptionDescription(OptionDescriptionWalk):
"""get the group type of option description
"""
return self._group_type
def to_dynoption(self,
rootpath: str,
suffixes: Optional[list],
#ori_dyn,
) -> Union[SubDynOptionDescription, SynDynOptionDescription]:
"""get syn dyn option description
"""
if self.impl_is_dynoptiondescription():
obj = SynDynOptionDescription
else:
obj = SubDynOptionDescription
return obj(self,
rootpath,
suffixes,
)
#
# def to_dynoption(self,
# rootpath: str,
# suffixes: Optional[list],
# #ori_dyn,
# ) -> Union[SubDynOptionDescription]:
# """get syn dyn option description
# """
# if self.impl_is_dynoptiondescription():
# obj = SynDynOptionDescription
# else:
# obj = SubDynOptionDescription
# return obj(self,
# rootpath,
# suffixes,
# )
def impl_is_dynsymlinkoption(self) -> bool:
"""option is not a dyn symlink option

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*-
# Copyright (C) 2018-2023 Team tiramisu (see AUTHORS for all contributors)
# 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
@ -20,16 +20,93 @@
# ____________________________________________________________
"""SynDynOption internal option, it's an instanciate synoption
"""
from typing import Any
import re
from typing import Optional, Iterator, Any, List, Tuple
from .baseoption import BaseOption
from ..i18n import _
from ..setting import ConfigBag, undefined
class SynDynOption:
"""SynDynOption is an Option include un DynOptionDescription with specified prefix
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',
'suffixes',
'_current_suffixes',
'__weakref__')
def __init__(self,
@ -39,28 +116,28 @@ class SynDynOption:
) -> None:
self.opt = opt
self.rootpath = rootpath
self.suffixes = suffixes
self._current_suffixes = suffixes
def __getattr__(self,
name: str) -> Any:
name: str,
) -> Any:
# if not in SynDynOptionDescription, get value in self.opt
return getattr(self.opt,
name,
)
def impl_getname(self) -> str:
"""get option name
"""
return self.opt.impl_getname()
def impl_get_display_name(self) -> str:
"""get option display name
"""
return self.opt.impl_get_display_name(self)
def get_suffixes(self) -> str:
"""get suffix
def get_current_suffixes(self) -> str:
"""get suffixes
"""
return self.suffixes
return self.current__suffixes
def impl_is_dynsymlinkoption(self) -> bool:
"""it's a dynsymlinkoption
"""
return True
def impl_getpath(self) -> str:
"""get path
@ -70,10 +147,109 @@ class SynDynOption:
path = f'{self.rootpath}.{path}'
return path
def impl_is_dynsymlinkoption(self) -> bool:
"""it's a dynsymlinkoption
class SynDescr(Syn):
__slots__ = ('opt',
'rootpath',
'_current_suffixes',
)
def get_child(self,
name: str,
config_bag: ConfigBag,
*,
allow_dynoption: bool=False,
):
"""get children
"""
return True
# 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?
@ -82,5 +258,94 @@ class SynDynOption:
if leadership:
rootpath = self.rootpath.rsplit('.', 1)[0]
return leadership.to_dynoption(rootpath,
self.suffixes,
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

@ -156,72 +156,63 @@ 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
)
# pylint: disable=too-many-arguments
def __init__(self,
option,
index,
config_bag,
path=None,
properties=undefined,
ori_option=None,
apply_requires=True,
):
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 path:
self.path = path
elif option:
self.path = option.impl_getpath()
context = config_bag.context
if self.path is None:
self.properties = None
elif properties is undefined:
settings = context.get_settings()
try:
self.properties = settings.getproperties(self,
apply_requires=apply_requires,
)
except ConfigError:
self.properties = None
if properties is not undefined:
self.properties = properties
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 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:
@ -453,7 +444,8 @@ class Settings:
return self._properties[path][index]
def getproperties(self,
option_bag,
subconfig: 'SubConfig',
*,
apply_requires=True,
uncalculated=False,
help_property=False,
@ -462,12 +454,12 @@ class Settings:
"""get properties
"""
# pylint: disable=too-many-branches
option = option_bag.option
option = subconfig.option
if option.impl_is_symlinkoption():
option = option.impl_getopt()
if apply_requires and not uncalculated and not help_property:
cache = option_bag.config_bag.context.properties_cache
is_cached, props, validated = cache.getcache(option_bag, # pylint: disable=unused-variable
cache = subconfig.config_bag.context.properties_cache
is_cached, props, validated = cache.getcache(subconfig, # pylint: disable=unused-variable
'self_props',
)
else:
@ -475,14 +467,14 @@ class Settings:
if not is_cached:
props = set()
# if index, get option's properties (without index) too
p_props = self.get_stored_properties(option_bag.path,
p_props = self.get_stored_properties(subconfig.path,
None,
option.impl_getproperties(),
)
if option_bag.index is not None:
if subconfig.index is not None:
p_props = chain(p_props,
self.get_stored_properties(option_bag.path,
option_bag.index,
self.get_stored_properties(subconfig.path,
subconfig.index,
option.impl_getproperties(),
)
)
@ -495,11 +487,11 @@ class Settings:
elif apply_requires:
try:
if not help_property:
new_prop = prop.execute(option_bag,
new_prop = prop.execute(subconfig,
for_settings=True,
)
else:
new_prop = prop.help(option_bag,
new_prop = prop.help(subconfig,
for_settings=True,
)
if isinstance(new_prop, str):
@ -513,18 +505,18 @@ class Settings:
if (not help_property and not isinstance(new_prop, str)) or \
(help_property and not isinstance(new_prop, tuple)):
raise ValueError(_('invalid property type {type(new_prop)} for '
'{option_bag.option.impl_getname()} with '
'{subconfig.option.impl_getname()} with '
'{prop.function.__name__} function'))
if not option.impl_is_optiondescription() and \
option.impl_is_leader() and \
new_prop not in ALLOWED_LEADER_PROPERTIES:
raise LeadershipError(_('leader cannot have "{new_prop}" property'))
props.add(new_prop)
props -= self.getpermissives(option_bag)
props -= self.getpermissives(subconfig)
if not uncalculated and apply_requires and \
not option_bag.config_bag.is_unrestraint and \
not subconfig.config_bag.is_unrestraint and \
not help_property and transitive_raise:
cache.setcache(option_bag,
cache.setcache(subconfig,
props,
type_='properties',
)
@ -546,21 +538,21 @@ class Settings:
return ret
def getpermissives(self,
option_bag,
subconfig: "SubConfig",
):
"""get permissive
"""
if option_bag is None:
if subconfig is None:
path = None
index = None
else:
opt = option_bag.option
opt = subconfig.option
if opt.impl_is_symlinkoption():
opt = opt.impl_getopt()
path = opt.impl_getpath()
else:
path = option_bag.path
index = option_bag.index
path = subconfig.path
index = subconfig.index
permissives = self._getpermissives(path,
None,
)
@ -578,13 +570,13 @@ class Settings:
context.reset_cache(None)
def setproperties(self,
option_bag,
subconfig,
properties,
):
"""save properties for specified path
(never save properties if same has option properties)
"""
opt = option_bag.option
opt = subconfig.option
if not opt.impl_is_optiondescription() and opt.impl_is_leader():
not_allowed_properties = properties - ALLOWED_LEADER_PROPERTIES
if not_allowed_properties:
@ -595,10 +587,10 @@ class Settings:
raise LeadershipError(_('a leader ({opt.impl_get_display_name()}) cannot have '
'"force_default_on_freeze" or '
'"force_metaconfig_on_freeze" property without "frozen"'))
self._properties.setdefault(option_bag.path, {})[option_bag.index] = properties
self._properties.setdefault(subconfig.path, {})[subconfig.index] = properties
# values too because of follower values could have a PropertiesOptionError has value
option_bag.config_bag.context.reset_cache(option_bag)
option_bag.properties = properties
subconfig.config_bag.context.reset_cache(subconfig)
subconfig.properties = properties
def set_context_permissives(self,
permissives,
@ -610,7 +602,7 @@ class Settings:
)
def setpermissives(self,
option_bag,
subconfig,
permissives,
):
"""
@ -624,9 +616,9 @@ class Settings:
"""
if not isinstance(permissives, frozenset):
raise TypeError(_('permissive must be a frozenset'))
if option_bag is not None:
path = option_bag.path
index = option_bag.index
if subconfig is not None:
path = subconfig.path
index = subconfig.index
else:
path = None
index = None
@ -635,165 +627,166 @@ class Settings:
raise ConfigError(_('cannot add those permissives: {0}').format(
' '.join(forbidden_permissives)))
self._permissives.setdefault(path, {})[index] = permissives
if option_bag is not None:
option_bag.config_bag.context.reset_cache(option_bag)
if subconfig is not None:
subconfig.config_bag.context.reset_cache(subconfig)
#____________________________________________________________
# reset methods
def _get_path_index_config_option(self,
bag: Union[OptionBag, ConfigBag],
bag: Union['SubConfig', ConfigBag],
msg: str,
):
if isinstance(bag, ConfigBag):
path = None
index = None
config_bag = bag
option_bag = None
subconfig= None
else:
assert not bag.option.impl_is_symlinkoption(), \
_(msg).format(bag.option.impl_get_display_name())
path = bag.path
index = bag.index
config_bag = bag.config_bag
option_bag = bag
return path, index, config_bag, option_bag
subconfig = bag
return path, index, config_bag, subconfig
def reset(self,
bag: Union[OptionBag, ConfigBag],
bag: Union['SubConfig', ConfigBag],
):
"""reset property
"""
path, index, config_bag, option_bag = \
path, index, config_bag, subconfig = \
self._get_path_index_config_option(bag,
"can't reset properties to "
"the symlinkoption \"{}\"",
)
if path in self._properties and index in self._properties[path]:
del self._properties[path][index]
config_bag.context.reset_cache(option_bag)
config_bag.context.reset_cache(subconfig)
def reset_permissives(self,
bag: Union[OptionBag, ConfigBag],
bag: Union['SubConfig', ConfigBag],
):
"""reset permission
"""
path, index, config_bag, option_bag = \
path, index, config_bag, subconfig = \
self._get_path_index_config_option(bag,
"can't reset permissives to "
"the symlinkoption \"{}\"",
)
if path in self._permissives and index in self._permissives[path]:
del self._permissives[path][index]
config_bag.context.reset_cache(option_bag)
config_bag.context.reset_cache(subconfig)
#____________________________________________________________
# validate properties
def calc_raises_properties(self,
option_bag,
subconfig,
apply_requires=True,
uncalculated=False,
transitive_raise=True,
):
"""raise if needed
"""
if not uncalculated and apply_requires and option_bag.properties is not None:
option_properties = option_bag.properties
if not uncalculated and apply_requires and subconfig.properties is not None:
option_properties = subconfig.properties
else:
option_properties = self.getproperties(option_bag,
option_properties = self.getproperties(subconfig,
apply_requires=apply_requires,
uncalculated=uncalculated,
transitive_raise=transitive_raise,
)
return self._calc_raises_properties(option_bag,
return self._calc_raises_properties(subconfig,
option_properties,
)
def _calc_raises_properties(self,
option_bag,
subconfig,
option_properties,
):
raises_properties = option_bag.config_bag.properties - SPECIAL_PROPERTIES
raises_properties = subconfig.config_bag.properties - SPECIAL_PROPERTIES
# remove global permissive properties
if raises_properties and 'permissive' in raises_properties:
raises_properties -= option_bag.config_bag.permissives
raises_properties -= subconfig.config_bag.permissives
properties = option_properties & raises_properties
# at this point it should not remain any property for the option
return properties
def validate_properties(self,
option_bag,
subconfig,
*,
need_help=True,
):
"""check properties
"""
config_properties = option_bag.config_bag.properties
config_properties = subconfig.config_bag.properties
if not config_properties or config_properties == frozenset(['cache']):
# if no global property
return
for transitive_raise in [False, True]:
properties = self.calc_raises_properties(option_bag,
properties = self.calc_raises_properties(subconfig,
transitive_raise=transitive_raise,
)
if properties != frozenset():
if need_help:
help_properties = dict(self.getproperties(option_bag,
help_properties = dict(self.getproperties(subconfig,
help_property=True,
transitive_raise=transitive_raise,
))
calc_properties = []
for property_ in self._calc_raises_properties(option_bag,
for property_ in self._calc_raises_properties(subconfig,
set(help_properties.keys()),
):
calc_properties.append(help_properties[property_])
calc_properties = frozenset(calc_properties)
else:
calc_properties = properties
raise PropertiesOptionError(option_bag,
raise PropertiesOptionError(subconfig,
properties,
self,
help_properties=calc_properties,
)
def validate_mandatory(self,
subconfig,
value,
option_bag,
):
"""verify if option is mandatory without value
"""
if 'mandatory' not in option_bag.config_bag.properties:
if 'mandatory' not in subconfig.config_bag.properties:
return
values = option_bag.config_bag.context.get_values()
if not ('permissive' in option_bag.config_bag.properties and
'mandatory' in option_bag.config_bag.permissives) and \
'mandatory' in option_bag.properties and values.isempty(option_bag,
values = subconfig.config_bag.context.get_values()
if not ('permissive' in subconfig.config_bag.properties and
'mandatory' in subconfig.config_bag.permissives) and \
'mandatory' in subconfig.properties and values.isempty(subconfig,
value,
False,
):
raise PropertiesOptionError(option_bag,
raise PropertiesOptionError(subconfig,
['mandatory'],
self,
)
if 'empty' in option_bag.properties and values.isempty(option_bag,
if 'empty' in subconfig.properties and values.isempty(subconfig,
value,
True,
):
raise PropertiesOptionError(option_bag,
raise PropertiesOptionError(subconfig,
['empty'],
self,
)
def validate_frozen(self,
option_bag,
subconfig,
):
"""verify if option is frozen
"""
if option_bag.config_bag.properties and \
('everything_frozen' in option_bag.config_bag.properties or
('frozen' in option_bag.config_bag.properties and \
'frozen' in option_bag.properties)) and \
not (('permissive' in option_bag.config_bag.properties) and
'frozen' in option_bag.config_bag.permissives):
raise PropertiesOptionError(option_bag,
if subconfig.config_bag.properties and \
('everything_frozen' in subconfig.config_bag.properties or
('frozen' in subconfig.config_bag.properties and \
'frozen' in subconfig.properties)) and \
not (('permissive' in subconfig.config_bag.properties) and
'frozen' in subconfig.config_bag.permissives):
raise PropertiesOptionError(subconfig,
['frozen'],
self,
)

View file

@ -6,7 +6,8 @@ from copy import copy
from itertools import chain
from .error import ValueWarning, ValueErrorWarning, PropertiesOptionError, ConfigError
from .setting import undefined
from . import SynDynOption, RegexpOption, ChoiceOption, ParamOption
from .option.syndynoption import SynDynOption
from . import RegexpOption, ChoiceOption, ParamOption
from .i18n import _

View file

@ -17,7 +17,7 @@
# ____________________________________________________________
from typing import Union, Optional, List, Any
from .error import ConfigError
from .setting import owners, undefined, forbidden_owners, OptionBag
from .setting import owners, undefined, forbidden_owners
from .autolib import Calculation
from .i18n import _
@ -50,7 +50,7 @@ class Values:
#______________________________________________________________________
# get value
def get_cached_value(self,
option_bag: OptionBag,
subconfig: "SubConfig",
) -> Any:
"""get value directly in cache if set
otherwise calculated value and set it in cache
@ -58,28 +58,28 @@ class Values:
:returns: value
"""
# try to retrive value in cache
setting_properties = option_bag.config_bag.properties
cache = option_bag.config_bag.context.get_values_cache()
is_cached, value, validated = cache.getcache(option_bag,
setting_properties = subconfig.config_bag.properties
cache = subconfig.config_bag.context.get_values_cache()
is_cached, value, validated = cache.getcache(subconfig,
'values',
)
# no cached value so get value
if not is_cached:
value, has_calculation = self.get_value(option_bag)
value, has_calculation = self.get_value(subconfig)
# validates and warns value
if not validated:
validate = option_bag.option.impl_validate(value,
option_bag,
validate = subconfig.option.impl_validate(subconfig,
value,
check_error=True,
)
if 'warnings' in setting_properties:
option_bag.option.impl_validate(value,
option_bag,
subconfig.option.impl_validate(subconfig,
value,
check_error=False,
)
# set value to cache
if not is_cached and not has_calculation:
cache.setcache(option_bag,
cache.setcache(subconfig,
value,
validated=validate,
)
@ -90,7 +90,7 @@ class Values:
return value
def get_value(self,
option_bag: OptionBag,
subconfig: "SubConfig",
) -> Any:
"""actually retrieves the stored value or the default value (value modified by user)
@ -98,80 +98,82 @@ class Values:
"""
# get owner and value from store
default_value = [undefined, owners.default]
value, owner = self._values.get(option_bag.path, {}).get(option_bag.index, default_value)
value, owner = self._values.get(subconfig.path, {}).get(subconfig.index, default_value)
if owner == owners.default or \
('frozen' in option_bag.properties and \
('force_default_on_freeze' in option_bag.properties or \
self.check_force_to_metaconfig(option_bag))):
('frozen' in subconfig.properties and \
('force_default_on_freeze' in subconfig.properties or \
self.check_force_to_metaconfig(subconfig))):
# the value is a default value
# get it
value = self.get_default_value(option_bag)
value, has_calculation = self.get_calculated_value(option_bag,
value = self.get_default_value(subconfig)
value, has_calculation = self.get_calculated_value(subconfig,
value,
)
return value, has_calculation
def get_default_value(self,
option_bag: OptionBag,
subconfig: "SubConfig",
) -> Any:
"""get default value:
- get parents config value or
- get calculated value or
- get default value
"""
moption_bag = self._get_modified_parent(option_bag)
if moption_bag is not None:
msubconfig = self._get_modified_parent(subconfig)
if msubconfig is not None:
# retrieved value from parent config
return moption_bag.config_bag.context.get_values().get_cached_value(moption_bag)
return msubconfig.config_bag.context.get_values().get_cached_value(msubconfig)
# now try to get calculated value:
value, _has_calculation = self.get_calculated_value(option_bag,
option_bag.option.impl_getdefault(),
value, _has_calculation = self.get_calculated_value(subconfig,
subconfig.option.impl_getdefault(),
)
if option_bag.index is not None and isinstance(value, (list, tuple)) \
and (not option_bag.option.impl_is_submulti() or \
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)):
# if index (so slave), must return good value for this index
# for submulti, first index is a list, assume other data are list too
if len(value) > option_bag.index:
value = value[option_bag.index]
index = subconfig.index
if len(value) > index:
value = value[index]
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(option_bag,
option_bag.option.impl_getdefault_multi(),
value, _has_calculation = self.get_calculated_value(subconfig,
subconfig.option.impl_getdefault_multi(),
)
return value
def get_calculated_value(self,
option_bag,
value,
reset_cache=True,
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(option_bag)
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(option_bag,
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(option_bag,
self.reset_cache_after_calculation(subconfig,
value,
)
return value, has_calculation
#______________________________________________________________________
def check_force_to_metaconfig(self,
option_bag: OptionBag,
subconfig: "OptionBag",
) -> bool:
"""Check if the value must be retrieve from parent metaconfig or not
"""
@ -179,25 +181,25 @@ class Values:
# => to metaconfig
# force_metaconfig_on_freeze is set *explicitly* to an option and context is a
# kernelmetaconfig => to sub metaconfig
if 'force_metaconfig_on_freeze' in option_bag.properties:
settings = option_bag.config_bag.context.get_settings()
if option_bag.config_bag.context.impl_type == 'config':
if 'force_metaconfig_on_freeze' in subconfig.properties:
settings = subconfig.config_bag.context.get_settings()
if subconfig.config_bag.context.impl_type == 'config':
return True
# it's a not a config, force to metaconfig only in *explicitly* set
return 'force_metaconfig_on_freeze' in settings.get_stored_properties(option_bag.path,
option_bag.index,
return 'force_metaconfig_on_freeze' in settings.get_stored_properties(subconfig.path,
subconfig.index,
frozenset(),
)
return False
def reset_cache_after_calculation(self,
option_bag,
subconfig,
value,
):
"""if value is modification after calculation, invalid cache
"""
cache = option_bag.config_bag.context.get_values_cache()
is_cache, cache_value, _ = cache.getcache(option_bag,
cache = subconfig.config_bag.context.get_values_cache()
is_cache, cache_value, _ = cache.getcache(subconfig,
'values',
expiration=False,
)
@ -206,27 +208,29 @@ class Values:
# so do not invalidate cache
return
# calculated value is a new value, so reset cache
option_bag.config_bag.context.reset_cache(option_bag)
subconfig.config_bag.context.reset_cache(subconfig)
# and manage force_store_value
self._set_force_value_suffix(option_bag)
# self._set_force_value_suffix(subconfig)
def isempty(self,
option_bag: OptionBag,
subconfig: "SubConfig",
value: Any,
force_allow_empty_list: bool,
) -> bool:
"""convenience method to know if an option is empty
"""
if option_bag.index is None and option_bag.option.impl_is_submulti():
index = subconfig.index
option = subconfig.option
if index is None and option.impl_is_submulti():
# index is not set
isempty = True
for val in value:
isempty = self._isempty_multi(val, force_allow_empty_list)
if isempty:
break
elif (option_bag.index is None or \
(option_bag.index is not None and option_bag.option.impl_is_submulti())) and \
option_bag.option.impl_is_multi():
elif (index is None or \
(index is not None and option.impl_is_submulti())) and \
option.impl_is_multi():
# it's a single list
isempty = self._isempty_multi(value, force_allow_empty_list)
else:
@ -244,86 +248,86 @@ class Values:
#______________________________________________________________________
# set value
def set_value(self,
option_bag: OptionBag,
subconfig: "SubConfig",
value: Any,
) -> None:
"""set value to option
"""
owner = self.get_context_owner()
setting_properties = option_bag.config_bag.properties
setting_properties = subconfig.config_bag.properties
ori_value = value
if 'validator' in setting_properties:
value, has_calculation = self.setvalue_validation(value,
option_bag,
value, has_calculation = self.setvalue_validation(subconfig,
value,
)
elif isinstance(value, list):
# copy
value = value.copy()
self._setvalue(option_bag,
self._setvalue(subconfig,
ori_value,
owner,
)
validator = 'validator' in setting_properties and \
'demoting_error_warning' not in setting_properties
if validator and not has_calculation:
cache = option_bag.config_bag.context.get_values_cache()
cache.setcache(option_bag,
cache = subconfig.config_bag.context.get_values_cache()
cache.setcache(subconfig,
value,
validated=validator,
)
elif 'validator' in setting_properties and has_calculation:
cache = option_bag.config_bag.context.get_values_cache()
cache.delcache(option_bag.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,
)
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,
# )
def setvalue_validation(self,
value,
option_bag,
subconfig: "SubConfig",
value: Any,
):
"""validate value before set value
"""
settings = option_bag.config_bag.context.get_settings()
settings = subconfig.config_bag.context.get_settings()
# First validate properties with this value
opt = option_bag.option
settings.validate_frozen(option_bag)
val, has_calculation = self.get_calculated_value(option_bag,
opt = subconfig.option
settings.validate_frozen(subconfig)
val, has_calculation = self.get_calculated_value(subconfig,
value,
False,
reset_cache=False,
)
settings.validate_mandatory(val,
option_bag,
settings.validate_mandatory(subconfig,
val,
)
# Value must be valid for option
opt.impl_validate(val,
option_bag,
opt.impl_validate(subconfig,
val,
check_error=True,
)
if 'warnings' in option_bag.config_bag.properties:
if 'warnings' in subconfig.config_bag.properties:
# No error found so emit warnings
opt.impl_validate(val,
option_bag,
opt.impl_validate(subconfig,
val,
check_error=False,
)
return val, has_calculation
def _setvalue(self,
option_bag: OptionBag,
subconfig: "SubConfig",
value: Any,
owner: str,
) -> None:
option_bag.config_bag.context.reset_cache(option_bag)
self.set_storage_value(option_bag.path,
option_bag.index,
subconfig.config_bag.context.reset_cache(subconfig)
self.set_storage_value(subconfig.path,
subconfig.index,
value,
owner,
)
self._set_force_value_suffix(option_bag)
# self._set_force_value_suffix(option_bag)
def set_storage_value(self,
path,
@ -335,64 +339,66 @@ 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,
# 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 _get_modified_parent(self,
option_bag: OptionBag,
) -> Optional[OptionBag]:
subconfig: "SubConfig",
) -> Optional["SubConfig"]:
""" Search in differents parents a Config with a modified value
If not found, return None
For follower option, return the Config where leader is modified
"""
def build_option_bag(option_bag, parent):
doption_bag = option_bag.copy()
config_bag = option_bag.config_bag.copy()
def build_option_bag(subconfig, parent):
doption_bag = subconfig.copy()
config_bag = subconfig.config_bag.copy()
config_bag.context = parent
config_bag.unrestraint()
doption_bag.config_bag = config_bag
return doption_bag
for parent in option_bag.config_bag.context.get_parents():
doption_bag = build_option_bag(option_bag, parent)
if 'force_metaconfig_on_freeze' in option_bag.properties:
for parent in subconfig.config_bag.context.get_parents():
doption_bag = build_option_bag(subconfig, parent)
if 'force_metaconfig_on_freeze' in subconfig.properties:
# remove force_metaconfig_on_freeze only if option in metaconfig
# hasn't force_metaconfig_on_freeze properties
ori_properties = doption_bag.properties
@ -403,6 +409,7 @@ class Values:
else:
doption_bag.properties = ori_properties
parent_owner = parent.get_values().getowner(doption_bag,
parent,
only_default=True,
)
if parent_owner != owners.default:
@ -415,18 +422,20 @@ class Values:
# owner
def is_default_owner(self,
option_bag: OptionBag,
subconfig: "SubConfig",
*,
validate_meta: bool=True,
) -> bool:
"""is default owner for an option
"""
return self.getowner(option_bag,
return self.getowner(subconfig,
validate_meta=validate_meta,
only_default=True,
) == owners.default
def hasvalue(self,
path,
*,
index=None,
):
"""if path has a value
@ -440,7 +449,8 @@ class Values:
return False
def getowner(self,
option_bag,
subconfig: "SubConfig",
*,
validate_meta=True,
only_default=False,
):
@ -452,111 +462,114 @@ class Values:
was present
:returns: a `setting.owners.Owner` object
"""
context = option_bag.config_bag.context
opt = option_bag.option
if opt.impl_is_symlinkoption():
option_bag.ori_option = opt
opt = opt.impl_getopt()
option_bag.option = opt
option_bag.path = opt.impl_getpath()
context = subconfig.config_bag.context
settings = context.get_settings()
settings.validate_properties(option_bag)
if 'frozen' in option_bag.properties and \
'force_default_on_freeze' in option_bag.properties:
settings.validate_properties(subconfig)
if 'frozen' in subconfig.properties and \
'force_default_on_freeze' in subconfig.properties:
return owners.default
if only_default:
if self.hasvalue(option_bag.path,
index=option_bag.index,
if self.hasvalue(subconfig.path,
index=subconfig.index,
):
owner = 'not_default'
else:
owner = owners.default
else:
owner = self._values.get(option_bag.path, {}).get(option_bag.index,
owner = self._values.get(subconfig.path, {}).get(subconfig.index,
[undefined, owners.default],
)[1]
if validate_meta is not False and (owner is owners.default or
'frozen' in option_bag.properties and
'force_metaconfig_on_freeze' in option_bag.properties):
moption_bag = self._get_modified_parent(option_bag)
if moption_bag is not None:
values = moption_bag.config_bag.context.get_values()
owner = values.getowner(moption_bag,
'frozen' in subconfig.properties and
'force_metaconfig_on_freeze' in subconfig.properties):
msubconfig = self._get_modified_parent(subconfig)
if msubconfig is not None:
values = msubconfig.config_bag.context.get_values()
owner = values.getowner(msubconfig,
parent,
only_default=only_default,
)
elif 'force_metaconfig_on_freeze' in option_bag.properties:
elif 'force_metaconfig_on_freeze' in subconfig.properties:
return owners.default
return owner
def set_owner(self,
option_bag,
subconfig,
owner,
):
"""
sets a owner to an option
:param option_bag: the `OptionBag` object
:param subconfig: the `OptionBag` object
:param owner: a valid owner, that is a `setting.owners.Owner` object
"""
if owner in forbidden_owners:
raise ValueError(_('set owner "{0}" is forbidden').format(str(owner)))
if not self.hasvalue(option_bag.path,
index=option_bag.index,
if not self.hasvalue(subconfig.path,
index=subconfig.index,
):
raise ConfigError(_(f'no value for {option_bag.path} cannot change owner to {owner}'))
option_bag.config_bag.context.get_settings().validate_frozen(option_bag)
self._values[option_bag.path][option_bag.index][1] = owner
raise ConfigError(_(f'no value for {subconfig.path} cannot change owner to {owner}'))
subconfig.config_bag.context.get_settings().validate_frozen(subconfig)
self._values[subconfig.path][subconfig.index][1] = owner
#______________________________________________________________________
# reset
def reset(self, option_bag: OptionBag) -> None:
def reset(self,
subconfig: "SubConfig",
) -> None:
"""reset value for an option
"""
context = option_bag.config_bag.context
hasvalue = self.hasvalue(option_bag.path)
setting_properties = option_bag.config_bag.properties
if hasvalue and 'validator' in option_bag.config_bag.properties:
fake_context = context.gen_fake_values()
config_bag = option_bag.config_bag.copy()
config_bag.remove_validation()
config_bag.context = fake_context
soption_bag = option_bag.copy()
soption_bag.config_bag = config_bag
fake_value = fake_context.get_values()
fake_value.reset(soption_bag)
soption_bag.config_bag.properties = option_bag.config_bag.properties
value = fake_value.get_default_value(soption_bag)
fake_value.setvalue_validation(value,
soption_bag,
config_bag = subconfig.config_bag
context = config_bag.context
hasvalue = self.hasvalue(subconfig.path)
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,
)
opt = option_bag.option
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,
)
opt = subconfig.option
if opt.impl_is_leader():
opt.impl_get_leadership().reset(option_bag.config_bag)
opt.impl_get_leadership().reset(subconfig.parent)
if hasvalue:
if 'force_store_value' in option_bag.config_bag.properties and \
'force_store_value' in option_bag.properties:
value = self.get_default_value(option_bag)
if 'force_store_value' in subconfig.config_bag.properties and \
'force_store_value' in subconfig.properties:
value = self.get_default_value(subconfig)
self._setvalue(option_bag,
self._setvalue(subconfig,
value,
owners.forced,
)
else:
# for leader only
value = None
if option_bag.path in self._values:
del self._values[option_bag.path]
context.reset_cache(option_bag)
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)
leader = option_bag.option.impl_get_leadership()
leader.follower_force_store_value(value,
option_bag.config_bag,
owners.forced,
)
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,
# )
#______________________________________________________________________
# Follower
@ -569,73 +582,86 @@ class Values:
return 0
def reset_follower(self,
option_bag: OptionBag,
subconfig: "SubConfig",
) -> None:
"""reset value for a follower
"""
if not self.hasvalue(option_bag.path,
index=option_bag.index,
if not self.hasvalue(subconfig.path,
index=subconfig.index,
):
return
context = option_bag.config_bag.context
setting_properties = option_bag.config_bag.properties
config_bag = subconfig.config_bag
context = config_bag.context
setting_properties = config_bag.properties
if 'validator' in setting_properties:
fake_context = context.gen_fake_values()
fake_value = fake_context.get_values()
config_bag = option_bag.config_bag.copy()
config_bag.remove_validation()
config_bag.context = fake_context
soption_bag = option_bag.copy()
soption_bag.config_bag = config_bag
fake_value.reset_follower(soption_bag)
value = fake_value.get_default_value(soption_bag)
fake_value.setvalue_validation(value,
soption_bag)
if 'force_store_value' in setting_properties and \
'force_store_value' in option_bag.properties:
value = self.get_default_value(option_bag)
self._setvalue(option_bag,
value,
owners.forced,
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,
)
else:
self.resetvalue_index(option_bag)
context.reset_cache(option_bag)
fake_values = fake_context.get_values()
fake_values.reset_follower(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 '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)
def resetvalue_index(self, option_bag: OptionBag) -> None:
def resetvalue_index(self,
subconfig: "SubConfig",
) -> None:
"""reset a value for a follower at an index
"""
if option_bag.path in self._values and option_bag.index in self._values[option_bag.path]:
del self._values[option_bag.path][option_bag.index]
if subconfig.path in self._values and subconfig.index in self._values[subconfig.path]:
del self._values[subconfig.path][subconfig.index]
def reduce_index(self, option_bag: OptionBag) -> None:
def reduce_index(self,
subconfig: "SubConfig",
) -> None:
"""reduce follower's value from a specified index
"""
self.resetvalue_index(option_bag)
for index in range(option_bag.index + 1, self.get_max_length(option_bag.path)):
if self.hasvalue(option_bag.path,
self.resetvalue_index(subconfig)
for index in range(subconfig.index + 1, self.get_max_length(subconfig.path)):
if self.hasvalue(subconfig.path,
index=index,
):
self._values[option_bag.path][index - 1] = self._values[option_bag.path].pop(index)
self._values[subconfig.path][index - 1] = self._values[subconfig.path].pop(index)
def reset_leadership(self,
option_bag: OptionBag,
leadership_option_bag: OptionBag,
subconfig: "SubConfig",
index: int,
) -> None:
"""reset leadershop from an index
"""reset leadership from an index
"""
current_value = self.get_cached_value(option_bag)
current_value = self.get_cached_value(subconfig)
length = len(current_value)
if index >= length:
raise IndexError(_('index {index} is greater than the length {length} '
'for option "{option_bag.option.impl_get_display_name()}"'))
'for option "{subconfig.option.impl_get_display_name()}"'))
current_value.pop(index)
leadership_option_bag.option.pop(index,
option_bag.config_bag,
leadership_subconfig = subconfig.parent
leadership_subconfig.option.pop(subconfig,
index,
)
self.set_value(option_bag,
self.set_value(subconfig,
current_value,
)
@ -643,7 +669,7 @@ class Values:
# information
def set_information(self,
option_bag,
subconfig,
key,
value,
):
@ -652,24 +678,27 @@ class Values:
:param key: information's key (ex: "help", "doc"
:param value: information's value (ex: "the help string")
"""
if option_bag is None:
if subconfig is None:
path = None
else:
path = option_bag.path
path = subconfig.path
self._informations.setdefault(path, {})[key] = value
if path is None:
return
for key, options in option_bag.option.get_dependencies_information().items():
config_bag = subconfig.config_bag
context = config_bag.context
for key, options in subconfig.option.get_dependencies_information().items():
for option in options:
cache_option_bag = OptionBag(option,
option_subconfig = context.get_sub_config(config_bag,
option.impl_getpath(),
None,
option_bag.config_bag,
properties=None,
validate_properties=False,
follower_not_apply_requires=False,
)
cache_option_bag.config_bag.context.reset_cache(cache_option_bag)
context.reset_cache(option_subconfig)
def get_information(self,
option_bag,
subconfig,
name,
default,
):
@ -677,15 +706,15 @@ class Values:
:param name: the item string (ex: "help")
"""
if option_bag is None:
if subconfig is None:
path = None
else:
path = option_bag.path
path = subconfig.path
try:
return self._informations[path][name]
except KeyError as err:
if option_bag:
return option_bag.option.impl_get_information(name, default)
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