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

View file

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

View file

@ -59,36 +59,36 @@ def test_copy_information():
ncfg = cfg.config.copy() ncfg = cfg.config.copy()
assert ncfg.information.get('key') == 'value' assert ncfg.information.get('key') == 'value'
# assert not list_sessions() # assert not list_sessions()
#
#
def test_copy_force_store_value(): #def test_copy_force_store_value():
od1 = make_description() # od1 = make_description()
conf = Config(od1) # conf = Config(od1)
conf2 = Config(od1) # conf2 = Config(od1)
assert conf.value.exportation() == {} # assert conf.value.exportation() == {}
assert conf2.value.exportation() == {} # assert conf2.value.exportation() == {}
# # #
conf.property.read_write() # conf.property.read_write()
assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}} # assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
assert conf2.value.exportation() == {} # assert conf2.value.exportation() == {}
# # #
conf2.property.read_only() # conf2.property.read_only()
assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}} # assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
assert conf2.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) # conf.option('creole.general.wantref').value.set(True)
assert conf.value.exportation() == {'creole.general.wantref': {None: [True, 'user']}} # assert conf.value.exportation() == {'creole.general.wantref': {None: [True, 'user']}}
assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}} # assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
# assert not list_sessions() ## assert not list_sessions()
#
#
def test_copy_force_store_value_metaconfig(): #def test_copy_force_store_value_metaconfig():
od1 = make_description() # od1 = make_description()
meta = MetaConfig([], optiondescription=od1) # meta = MetaConfig([], optiondescription=od1)
conf = meta.config.new() # conf = meta.config.new()
assert meta.property.get() == conf.property.get() # assert meta.property.get() == conf.property.get()
assert meta.permissive.get() == conf.permissive.get() # assert meta.permissive.get() == conf.permissive.get()
conf.property.read_write() # conf.property.read_write()
assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}} # assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
assert meta.value.exportation() == {} # assert meta.value.exportation() == {}
# assert not list_sessions() ## 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" "frozen and hidden values"
from .autopath import do_autopath from .autopath import do_autopath
do_autopath() do_autopath()
@ -160,57 +160,57 @@ def test_freeze_multi():
# assert not list_sessions() # assert not list_sessions()
def test_force_store_value(): #def test_force_store_value():
od1 = make_description_freeze() # od1 = make_description_freeze()
cfg = Config(od1) # cfg = Config(od1)
compare(cfg.value.exportation(), {}) # compare(cfg.value.exportation(), {})
cfg.property.read_write() # cfg.property.read_write()
compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}}) # compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
cfg.option('bool').value.set(False) # cfg.option('bool').value.set(False)
cfg.option('wantref').value.set(True) # cfg.option('wantref').value.set(True)
cfg.option('bool').value.reset() # cfg.option('bool').value.reset()
compare(cfg.value.exportation(), {'wantref': {None: [True, 'user']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}}) # compare(cfg.value.exportation(), {'wantref': {None: [True, 'user']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
cfg.option('bool').value.set(False) # cfg.option('bool').value.set(False)
cfg.option('wantref').value.reset() # cfg.option('wantref').value.reset()
cfg.option('bool').value.reset() # cfg.option('bool').value.reset()
compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}}) # compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
# assert not list_sessions() ## assert not list_sessions()
#
#
def test_force_store_value_leadership_sub(): #def test_force_store_value_leadership_sub():
b = IntOption('int', 'Test int option', multi=True, properties=('force_store_value',)) # b = IntOption('int', 'Test int option', multi=True, properties=('force_store_value',))
c = StrOption('str', 'Test string option', multi=True) # c = StrOption('str', 'Test string option', multi=True)
descr = Leadership("int", "", [b, c]) # descr = Leadership("int", "", [b, c])
od1 = OptionDescription('odr', '', [descr]) # od1 = OptionDescription('odr', '', [descr])
cfg = Config(od1) # cfg = Config(od1)
cfg.property.read_only() # cfg.property.read_only()
compare(cfg.value.exportation(), {'int.int': {None: [[], 'forced']}}) # compare(cfg.value.exportation(), {'int.int': {None: [[], 'forced']}})
# assert not list_sessions() ## assert not list_sessions()
#
#
def test_force_store_value_callback(): #def test_force_store_value_callback():
b = IntOption('int', 'Test int option', Calculation(return_val), properties=('force_store_value',)) # b = IntOption('int', 'Test int option', Calculation(return_val), properties=('force_store_value',))
od1 = OptionDescription("int", "", [b]) # od1 = OptionDescription("int", "", [b])
cfg = Config(od1) # cfg = Config(od1)
cfg.property.read_only() # cfg.property.read_only()
compare(cfg.value.exportation(), {'int': {None: [1, 'forced']}}) # compare(cfg.value.exportation(), {'int': {None: [1, 'forced']}})
# assert not list_sessions() ## assert not list_sessions()
#
#
def test_force_store_value_callback_params(): #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',)) # b = IntOption('int', 'Test int option', Calculation(return_val2, Params(kwargs={'value': ParamValue(2)})), properties=('force_store_value',))
od1 = OptionDescription("int", "", [b]) # od1 = OptionDescription("int", "", [b])
cfg = Config(od1) # cfg = Config(od1)
cfg.property.read_only() # cfg.property.read_only()
compare(cfg.value.exportation(), {'int': {None: [2, 'forced']}}) # compare(cfg.value.exportation(), {'int': {None: [2, 'forced']}})
# assert not list_sessions() ## assert not list_sessions()
#
#
def test_force_store_value_callback_params_with_opt(): #def test_force_store_value_callback_params_with_opt():
a = IntOption('val1', "", 2) # a = IntOption('val1', "", 2)
b = IntOption('int', 'Test int option', Calculation(return_val2, Params(kwargs={'value': ParamOption(a)})), properties=('force_store_value',)) # b = IntOption('int', 'Test int option', Calculation(return_val2, Params(kwargs={'value': ParamOption(a)})), properties=('force_store_value',))
od1 = OptionDescription("int", "", [a, b]) # od1 = OptionDescription("int", "", [a, b])
cfg = Config(od1) # cfg = Config(od1)
cfg.property.read_only() # cfg.property.read_only()
compare(cfg.value.exportation(), {'int': {None: [2, 'forced']}}) # compare(cfg.value.exportation(), {'int': {None: [2, 'forced']}})
# assert not list_sessions() ## assert not list_sessions()

View file

@ -1,7 +1,7 @@
# coding: utf-8 # coding: utf-8
from .autopath import do_autopath from .autopath import do_autopath
do_autopath() do_autopath()
from .config import config_type, get_config, value_list, global_owner from .config import config_type, get_config, value_list, global_owner, parse_od_get
import pytest import pytest
from tiramisu.setting import groups, owners from tiramisu.setting import groups, owners
@ -59,10 +59,10 @@ def test_base_config(config_type):
cfg = get_config(cfg, 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.activer_proxy_client').value.get() is False
assert cfg.option('creole.general.nom_machine').value.get() == "eoleng" assert cfg.option('creole.general.nom_machine').value.get() == "eoleng"
if config_type != 'tiramisu-api': # if config_type != 'tiramisu-api':
ret = cfg.option.find('nom_machine', first=True) # ret = cfg.option.find('nom_machine', first=True)
assert ret.value.get() == "eoleng" # 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} 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': if config_type == 'tiramisu-api':
cfg.send() cfg.send()
# assert not list_sessions() # assert not list_sessions()
@ -77,49 +77,40 @@ def test_get_group_type():
assert grp.group_type() == 'family' assert grp.group_type() == 'family'
assert isinstance(grp.group_type(), groups.GroupType) assert isinstance(grp.group_type(), groups.GroupType)
# assert not list_sessions() # assert not list_sessions()
#
#
def test_iter_on_groups(): #def test_iter_on_groups():
od1 = make_description() # od1 = make_description()
cfg = Config(od1) # cfg = Config(od1)
cfg.property.read_write() # cfg.property.read_write()
result = cfg.option('creole').list('optiondescription', # result = cfg.option('creole').list('optiondescription',
group_type=groups.family, # group_type=groups.family,
) # )
group_names = [res.name() for res in result] # group_names = [res.name() for res in result]
assert group_names == ['general', 'interface1'] # assert group_names == ['general', 'interface1']
for i in cfg.option('creole').list('optiondescription', # for i in cfg.option('creole').list('optiondescription',
group_type=groups.family, # group_type=groups.family,
): # ):
#test StopIteration # #test StopIteration
break # break
result = cfg.option('creole').list('option', # result = cfg.option('creole').list('option',
group_type=groups.family, # group_type=groups.family,
) # )
assert list(result) == [] # assert list(result) == []
result = cfg.option('creole.general').list('optiondescription', # result = cfg.option('creole.general').list('optiondescription',
group_type=groups.family, # group_type=groups.family,
) # )
assert list(result) == [] # assert list(result) == []
# assert not list_sessions() ## assert not list_sessions()
def test_list_recursive(): def test_list_recursive():
od1 = make_description() od1 = make_description()
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
result = cfg.option('creole').list('all') result = cfg.option('creole').list()
group_names = [res.name() for res in result] group_names = [res.name() for res in result]
assert group_names == ['general', 'interface1'] 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() # assert not list_sessions()
@ -147,8 +138,7 @@ def test_iter_group_on_groups_force_permissive():
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
cfg.permissive.add('hidden') cfg.permissive.add('hidden')
result = cfg.forcepermissive.option('creole').list(type='optiondescription', result = cfg.forcepermissive.option('creole').list()
group_type=groups.family)
group_names = [res.name() for res in result] group_names = [res.name() for res in result]
assert group_names == ['general', 'interface1', 'new'] assert group_names == ['general', 'interface1', 'new']
# assert not list_sessions() # assert not list_sessions()
@ -159,8 +149,7 @@ def test_iter_on_groups_props():
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
cfg.option('creole.interface1').property.add('disabled') cfg.option('creole.interface1').property.add('disabled')
result = cfg.option('creole').list(type='optiondescription', result = cfg.option('creole').list()
group_type=groups.family)
group_names = [res.name() for res in result] group_names = [res.name() for res in result]
assert group_names == ['general'] assert group_names == ['general']
# assert not list_sessions() # assert not list_sessions()
@ -170,20 +159,11 @@ def test_iter_on_empty_group():
od1 = OptionDescription("name", "descr", []) od1 = OptionDescription("name", "descr", [])
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
result = list(cfg.option.list(type='optiondescription')) result = list(cfg.option.list())
assert result == [] assert result == []
# assert not list_sessions() # 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(): def test_groups_with_leader():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True)
@ -221,25 +201,26 @@ def test_groups_is_leader(config_type):
def test_leader_list(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') 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]) interface1 = Leadership('leadership', '', [ip_admin_eth0, netmask_admin_eth0])
od1 = OptionDescription('od', '', [interface1]) od1 = OptionDescription('od', '', [interface1])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) cfg = get_config(cfg, config_type)
ret = cfg.option.list('all') ret = cfg.option.list()
assert len(ret) == 1 assert len(ret) == 1
assert ret[0].name() == 'leadership' assert ret[0].name() == 'leadership'
# #
ret = cfg.option('leadership').list('all') ret = cfg.option('leadership').list()
assert len(ret) == 2 assert len(ret) == 2
assert ret[0].name() == 'ip_admin_eth0' assert ret[0].name() == 'ip_admin_eth0'
assert ret[1].name() == 'netmask_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.ip_admin_eth0').value.set(['a', 'b'])
cfg.option('leadership.netmask_admin_eth0', 0).value.set('c') cfg.option('leadership.netmask_admin_eth0', 0).value.set('c')
cfg.option('leadership.netmask_admin_eth0', 1).value.set('d') 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[0].name() == 'ip_admin_eth0'
assert ret[1].name() == 'netmask_admin_eth0' assert ret[1].name() == 'netmask_admin_eth0'
# assert ret[1].option.index() == 0 # assert ret[1].option.index() == 0
@ -303,7 +284,7 @@ def test_groups_with_leader_make_dict(config_type):
od1 = OptionDescription('root', '', [interface1]) od1 = OptionDescription('root', '', [interface1])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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': if config_type != 'tiramisu-api':
# FIXME useful? already in leadership # FIXME useful? already in leadership
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.len() == 0 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 # FIXME
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.len() == 2 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.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': if config_type == 'tiramisu-api':
cfg.send() cfg.send()
# assert not list_sessions() # assert not list_sessions()
@ -336,7 +317,7 @@ def test_groups_with_leader_make_dict2(config_type):
od1 = OptionDescription('root', '', [interface1]) od1 = OptionDescription('root', '', [interface1])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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': if config_type != 'tiramisu-api':
# FIXME useful? already in leadership # FIXME useful? already in leadership
assert cfg.option('other.ip_admin_eth0').value.len() == 0 assert cfg.option('other.ip_admin_eth0').value.len() == 0
@ -346,7 +327,7 @@ def test_groups_with_leader_make_dict2(config_type):
# FIXME # FIXME
assert cfg.option('other.ip_admin_eth0').value.len() == 2 assert cfg.option('other.ip_admin_eth0').value.len() == 2
assert cfg.option('other.netmask_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': if config_type == 'tiramisu-api':
cfg.send() cfg.send()
# assert not list_sessions() # 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() cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() 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() # 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() == [] 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']) 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 assert cfg.forcepermissive.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
with pytest.raises(PropertiesOptionError): assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['192.168.1.1']
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() 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() # 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) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('hidden',)) netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('hidden',))
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
@ -1005,66 +983,66 @@ def test_follower_not_multi():
# assert not list_sessions() # assert not list_sessions()
def test_follower_force_store_value_none(): #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']) # 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',)) # 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]) # interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
od1 = OptionDescription('od', '', [interface0]) # od1 = OptionDescription('od', '', [interface0])
od2 = OptionDescription('toto', '', [od1]) # od2 = OptionDescription('toto', '', [od1])
cfg = Config(od2) # cfg = Config(od2)
cfg.property.read_write() # cfg.property.read_write()
assert cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault() # assert cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
# assert not list_sessions() ## assert not list_sessions()
#
#
def test_follower_force_store_value(): #def test_follower_force_store_value():
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1']) # 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',)) # 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]) # interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
od1 = OptionDescription('od', '', [interface0]) # od1 = OptionDescription('od', '', [interface0])
od2 = OptionDescription('toto', '', [od1]) # od2 = OptionDescription('toto', '', [od1])
cfg = Config(od2) # cfg = Config(od2)
cfg.property.read_write() # cfg.property.read_write()
assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault() # assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
# assert not list_sessions() ## assert not list_sessions()
#
#
def test_follower_force_store_value_read_only(): #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']) # 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',)) # 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]) # interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
od1 = OptionDescription('od', '', [interface0]) # od1 = OptionDescription('od', '', [interface0])
od2 = OptionDescription('toto', '', [od1]) # od2 = OptionDescription('toto', '', [od1])
cfg = Config(od2) # cfg = Config(od2)
cfg.property.read_only() # cfg.property.read_only()
assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault() # assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
# assert not list_sessions() ## assert not list_sessions()
#
#
def test_follower_force_store_value_reset(): #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']) # 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',)) # 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]) # interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
od1 = OptionDescription('od', '', [interface0]) # od1 = OptionDescription('od', '', [interface0])
od2 = OptionDescription('toto', '', [od1]) # od2 = OptionDescription('toto', '', [od1])
cfg = Config(od2) # cfg = Config(od2)
cfg.property.read_write() # cfg.property.read_write()
cfg.option('od.interface0.ip_admin_eth0').value.set(['1.1.1.1', '192.168.0.0']) # 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', 0).owner.isdefault()
assert not cfg.option('od.interface0.netmask_admin_eth0', 1).owner.isdefault() # assert not cfg.option('od.interface0.netmask_admin_eth0', 1).owner.isdefault()
# # #
cfg.option('od.interface0.netmask_admin_eth0', 1).value.reset() # cfg.option('od.interface0.netmask_admin_eth0', 1).value.reset()
assert not cfg.option('od.interface0.netmask_admin_eth0', 1).owner.isdefault() # 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)
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() == [] # assert cfg.option('od.interface0.ip_admin_eth0').value.get() == []
cfg.option('od.interface0.ip_admin_eth0').value.reset() # cfg.option('od.interface0.ip_admin_eth0').value.reset()
assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault() # assert not cfg.option('od.interface0.netmask_admin_eth0', 0).owner.isdefault()
# assert not list_sessions() ## assert not list_sessions()
#
#
def test_follower_properties(): #def test_follower_properties():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('aproperty',)) 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]) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])

View file

@ -1,6 +1,7 @@
# coding: utf-8 # coding: utf-8
from .autopath import do_autopath from .autopath import do_autopath
do_autopath() do_autopath()
from .config import parse_od_get
# FIXME from .config import config_type, get_config # FIXME from .config import config_type, get_config
import pytest import pytest
@ -50,18 +51,6 @@ def make_description2():
return descr 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(): def make_description3():
stroption = StrOption('str', 'Test string option', default="abc", stroption = StrOption('str', 'Test string option', default="abc",
properties=('mandatory', )) properties=('mandatory', ))
@ -99,7 +88,7 @@ def test_mandatory_ro_dict():
cfg.property.read_only() cfg.property.read_only()
prop = [] prop = []
try: try:
cfg.value.dict() cfg.value.get()
except PropertiesOptionError as err: except PropertiesOptionError as err:
prop = err.proptype prop = err.proptype
assert 'mandatory' in prop assert 'mandatory' in prop
@ -108,14 +97,14 @@ def test_mandatory_ro_dict():
cfg.option('unicode2').value.set('yes') cfg.option('unicode2').value.set('yes')
cfg.property.read_only() cfg.property.read_only()
try: try:
cfg.value.dict() cfg.value.get()
except PropertiesOptionError as err: except PropertiesOptionError as err:
prop = err.proptype prop = err.proptype
assert 'mandatory' in prop assert 'mandatory' in prop
cfg.property.read_write() cfg.property.read_write()
cfg.option('str3').value.set(['yes']) cfg.option('str3').value.set(['yes'])
cfg.property.read_only() 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() # assert not list_sessions()
@ -414,7 +403,7 @@ def test_mandatory_leader():
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.value.dict() cfg.value.get()
# assert not list_sessions() # assert not list_sessions()
@ -431,7 +420,7 @@ def test_mandatory_leader_sub():
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.option('o.ip_admin_eth0.ip_admin_eth0').value.get() cfg.option('o.ip_admin_eth0.ip_admin_eth0').value.get()
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.value.dict() cfg.value.get()
# assert not list_sessions() # assert not list_sessions()
@ -529,7 +518,7 @@ def test_mandatory_follower():
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_only() cfg.property.read_only()
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] 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.property.read_write()
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['ip']) cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['ip'])
@ -550,7 +539,7 @@ def test_mandatory_follower():
cfg.property.read_only() cfg.property.read_only()
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['ip'] 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.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() # assert not list_sessions()
@ -572,7 +561,14 @@ def test_mandatory_warnings_follower():
def test_mandatory_warnings_symlink(): 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 = Config(od1)
cfg.option('str').value.set('') cfg.option('str').value.set('')
cfg.property.read_write() cfg.property.read_write()
@ -692,25 +688,25 @@ def return_list(val=None, suffix=None):
return ['val1', 'val2'] return ['val1', 'val2']
def test_mandatory_dyndescription(): #def test_mandatory_dyndescription():
st = StrOption('st', '', properties=('mandatory',)) # st = StrOption('st', '', properties=('mandatory',))
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list)) # dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
od = OptionDescription('od', '', [dod]) # od = OptionDescription('od', '', [dod])
od2 = OptionDescription('od', '', [od]) # od2 = OptionDescription('od', '', [od])
cfg = Config(od2) # cfg = Config(od2)
cfg.property.read_only() # cfg.property.read_only()
compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st']) # compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
#
#
def test_mandatory_dyndescription_context(): #def test_mandatory_dyndescription_context():
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True) # val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
st = StrOption('st', '', properties=('mandatory',)) # st = StrOption('st', '', properties=('mandatory',))
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1)))) # dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
od = OptionDescription('od', '', [dod, val1]) # od = OptionDescription('od', '', [dod, val1])
od2 = OptionDescription('od', '', [od]) # od2 = OptionDescription('od', '', [od])
cfg = Config(od2) # cfg = Config(od2)
cfg.property.read_only() # cfg.property.read_only()
compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st']) # compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
def test_mandatory_callback_leader_and_followers_leader(): def test_mandatory_callback_leader_and_followers_leader():
@ -733,4 +729,4 @@ def test_mandatory_and_disabled():
od1 = OptionDescription('rootconfig', '', [username, password]) od1 = OptionDescription('rootconfig', '', [username, password])
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() 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') return MetaConfig([], optiondescription=od2, name='metacfg1')
def test_multi_parents_path(): #def test_multi_parents_path():
""" # """
metacfg1 (1) --- # metacfg1 (1) ---
| -- cfg1 # | -- cfg1
metacfg2 (2) --- # metacfg2 (2) ---
""" # """
metacfg1 = make_metaconfig() # metacfg1 = make_metaconfig()
cfg1 = metacfg1.config.new(type='config', name="cfg1") # cfg1 = metacfg1.config.new(type='config', name="cfg1")
metacfg2 = MetaConfig([cfg1], name='metacfg2') # metacfg2 = MetaConfig([cfg1], name='metacfg2')
# # #
assert metacfg1.config.path() == 'metacfg1' # assert metacfg1.config.path() == 'metacfg1'
assert metacfg2.config.path() == 'metacfg2' # assert metacfg2.config.path() == 'metacfg2'
assert cfg1.config.path() == 'metacfg2.metacfg1.cfg1' # assert cfg1.config.path() == 'metacfg2.metacfg1.cfg1'
#
#
def test_multi_parents_path_same(): #def test_multi_parents_path_same():
""" # """
--- metacfg2 (1) --- # --- metacfg2 (1) ---
metacfg1 --| | -- cfg1 # metacfg1 --| | -- cfg1
--- metacfg3 (2) --- # --- metacfg3 (2) ---
""" # """
metacfg1 = make_metaconfig() # metacfg1 = make_metaconfig()
metacfg2 = metacfg1.config.new(type='metaconfig', name="metacfg2") # metacfg2 = metacfg1.config.new(type='metaconfig', name="metacfg2")
metacfg3 = metacfg1.config.new(type='metaconfig', name="metacfg3") # metacfg3 = metacfg1.config.new(type='metaconfig', name="metacfg3")
cfg1 = metacfg2.config.new(type='config', name="cfg1") # cfg1 = metacfg2.config.new(type='config', name="cfg1")
metacfg3.config.add(cfg1) # metacfg3.config.add(cfg1)
# # #
assert metacfg2.config.path() == 'metacfg1.metacfg2' # assert metacfg2.config.path() == 'metacfg1.metacfg2'
assert metacfg3.config.path() == 'metacfg1.metacfg3' # assert metacfg3.config.path() == 'metacfg1.metacfg3'
assert cfg1.config.path() == 'metacfg1.metacfg3.metacfg1.metacfg2.cfg1' # assert cfg1.config.path() == 'metacfg1.metacfg3.metacfg1.metacfg2.cfg1'
metacfg1.option('od1.i1').value.set(1) # metacfg1.option('od1.i1').value.set(1)
metacfg3.option('od1.i1').value.set(2) # metacfg3.option('od1.i1').value.set(2)
assert cfg1.option('od1.i1').value.get() == 1 # assert cfg1.option('od1.i1').value.get() == 1
orideep = cfg1.config.deepcopy(metaconfig_prefix="test_", name='test_cfg1') # orideep = cfg1.config.deepcopy(metaconfig_prefix="test_", name='test_cfg1')
deep = orideep # deep = orideep
while True: # while True:
try: # try:
children = list(deep.config.list()) # children = list(deep.config.list())
except: # except:
break # break
assert len(children) < 2 # assert len(children) < 2
deep = children[0] # deep = children[0]
assert deep.config.path() == 'test_metacfg3.test_metacfg1.test_metacfg2.test_cfg1' # 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() == 1
#
#
#
def test_multi_parents_value(): #def test_multi_parents_value():
metacfg1 = make_metaconfig() # metacfg1 = make_metaconfig()
cfg1 = metacfg1.config.new(type='config', name="cfg1") # cfg1 = metacfg1.config.new(type='config', name="cfg1")
metacfg2 = MetaConfig([cfg1], name='metacfg2') # metacfg2 = MetaConfig([cfg1], name='metacfg2')
# # #
assert cfg1.option('od1.i1').value.get() == None # assert cfg1.option('od1.i1').value.get() == None
assert cfg1.option('od1.i2').value.get() == 1 # assert cfg1.option('od1.i2').value.get() == 1
assert cfg1.option('od1.i3').value.get() == None # assert cfg1.option('od1.i3').value.get() == None
# # #
assert metacfg1.option('od1.i1').value.get() == None # assert metacfg1.option('od1.i1').value.get() == None
assert metacfg1.option('od1.i2').value.get() == 1 # assert metacfg1.option('od1.i2').value.get() == 1
assert metacfg1.option('od1.i3').value.get() == None # assert metacfg1.option('od1.i3').value.get() == None
# # #
assert metacfg2.option('od1.i1').value.get() == None # assert metacfg2.option('od1.i1').value.get() == None
assert metacfg2.option('od1.i2').value.get() == 1 # assert metacfg2.option('od1.i2').value.get() == 1
assert metacfg2.option('od1.i3').value.get() == None # assert metacfg2.option('od1.i3').value.get() == None
# # #
metacfg1.option('od1.i3').value.set(3) # metacfg1.option('od1.i3').value.set(3)
assert metacfg1.option('od1.i3').value.get() == 3 # assert metacfg1.option('od1.i3').value.get() == 3
assert cfg1.option('od1.i3').value.get() == 3 # assert cfg1.option('od1.i3').value.get() == 3
assert metacfg2.option('od1.i2').value.get() == 1 # assert metacfg2.option('od1.i2').value.get() == 1
# # #
metacfg2.option('od1.i2').value.set(4) # metacfg2.option('od1.i2').value.set(4)
assert metacfg2.option('od1.i2').value.get() == 4 # assert metacfg2.option('od1.i2').value.get() == 4
assert metacfg1.option('od1.i2').value.get() == 1 # assert metacfg1.option('od1.i2').value.get() == 1
assert cfg1.option('od1.i2').value.get() == 4 # assert cfg1.option('od1.i2').value.get() == 4

View file

@ -202,24 +202,9 @@ def test_optiondescription_list():
od2 = OptionDescription('od', '', [od1, od3]) od2 = OptionDescription('od', '', [od1, od3])
od4 = OptionDescription('od', '', [od2]) od4 = OptionDescription('od', '', [od2])
cfg = Config(od4) cfg = Config(od4)
assert len(list(cfg.option('od').list('option'))) == 0 assert len(list(cfg.option('od').list())) == 2
assert len(list(cfg.option('od').list('optiondescription'))) == 2 assert len(list(cfg.option('od.od').list())) == 1
assert len(list(cfg.option('od').list('optiondescription', group_type=groups.family))) == 1 assert len(list(cfg.option('od.od2').list())) == 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 not list_sessions() # assert not list_sessions()
@ -233,22 +218,7 @@ def test_optiondescription_group():
od3.impl_set_group_type(groups.notfamily) od3.impl_set_group_type(groups.notfamily)
od2 = OptionDescription('od', '', [od1, od3]) od2 = OptionDescription('od', '', [od1, od3])
cfg = Config(od2) cfg = Config(od2)
assert len(list(cfg.option.list('option'))) == 0 assert len(list(cfg.option.list())) == 2
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 not list_sessions() # assert not list_sessions()

View file

@ -13,7 +13,7 @@ from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \
valid_ip_netmask, ParamSelfOption, ParamInformation, ParamSelfInformation valid_ip_netmask, ParamSelfOption, ParamInformation, ParamSelfInformation
from tiramisu.error import PropertiesOptionError, ConflictError, LeadershipError, ConfigError from tiramisu.error import PropertiesOptionError, ConflictError, LeadershipError, ConfigError
from tiramisu.i18n import _ from tiramisu.i18n import _
from .config import config_type, get_config from .config import config_type, get_config, parse_od_get
def return_val(): def return_val():
@ -1528,7 +1528,7 @@ def test_calc_value_simple(config_type):
od1 = OptionDescription('root', '', [val1, val2]) od1 = OptionDescription('root', '', [val1, val2])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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() # assert not list_sessions()
@ -1539,7 +1539,7 @@ def test_calc_value_multi(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3]) od1 = OptionDescription('root', '', [val1, val2, val3])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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() # assert not list_sessions()
@ -1549,9 +1549,9 @@ def test_calc_value_disabled():
od1 = OptionDescription('root', '', [val1, val2]) od1 = OptionDescription('root', '', [val1, val2])
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() 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') 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() # assert not list_sessions()
@ -1566,9 +1566,9 @@ def test_calc_value_condition(config_type):
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
cfg = get_config(cfg, config_type) 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) 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() # assert not list_sessions()
@ -1579,7 +1579,7 @@ def test_calc_value_allow_none(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3]) od1 = OptionDescription('root', '', [val1, val2, val3])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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() # assert not list_sessions()
@ -1590,7 +1590,7 @@ def test_calc_value_remove_duplicate(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3]) od1 = OptionDescription('root', '', [val1, val2, val3])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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() # assert not list_sessions()
@ -1601,7 +1601,7 @@ def test_calc_value_remove_duplicate2(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3]) od1 = OptionDescription('root', '', [val1, val2, val3])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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() # assert not list_sessions()
@ -1613,9 +1613,9 @@ def test_calc_value_join(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3, val4]) od1 = OptionDescription('root', '', [val1, val2, val3, val4])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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') 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() # assert not list_sessions()
@ -1625,9 +1625,9 @@ def test_calc_value_join_multi(config_type):
od1 = OptionDescription('root', '', [val1, val4]) od1 = OptionDescription('root', '', [val1, val4])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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']) 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() # assert not list_sessions()
@ -1639,9 +1639,9 @@ def test_calc_value_join_multi_value(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3, val4]) od1 = OptionDescription('root', '', [val1, val2, val3, val4])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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']) 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() # assert not list_sessions()
@ -1653,9 +1653,9 @@ def test_calc_value_min():
od1 = OptionDescription('root', '', [val1, val2, val3, val4]) od1 = OptionDescription('root', '', [val1, val2, val3, val4])
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() 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') 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() # assert not list_sessions()
@ -1666,7 +1666,7 @@ def test_calc_value_add(config_type):
od1 = OptionDescription('root', '', [val1, val2, val3]) od1 = OptionDescription('root', '', [val1, val2, val3])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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() # assert not list_sessions()

View file

@ -14,7 +14,7 @@ from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \
calc_value, calc_value_property_help, ParamInformation calc_value, calc_value_property_help, ParamInformation
from tiramisu.error import PropertiesOptionError from tiramisu.error import PropertiesOptionError
import warnings import warnings
from .config import config_type, get_config from .config import config_type, get_config, parse_od_get
def make_description(): def make_description():
@ -228,7 +228,7 @@ def test_default_with_multi():
def test_idontexist(): def test_idontexist():
od1 = make_description() od1 = make_description()
cfg = Config(od1) cfg = Config(od1)
cfg.value.dict() cfg.value.get()
with pytest.raises(AttributeError): with pytest.raises(AttributeError):
cfg.option('idontexist').value.get() cfg.option('idontexist').value.get()
# assert not list_sessions() # assert not list_sessions()
@ -535,12 +535,8 @@ def test_allow_multiple_changes_from_config():
def test_access_by_get(): def test_access_by_get():
od1 = make_description() od1 = make_description()
cfg = Config(od1) cfg = Config(od1)
with pytest.raises(AttributeError): assert cfg.option('wantref').value.get() is False
list(cfg.option.find('idontexist')) assert cfg.option('gc.dummy').value.get() is False
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 not list_sessions() # assert not list_sessions()
@ -555,8 +551,7 @@ def test_access_by_get_whith_hide():
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
with pytest.raises(AttributeError): with pytest.raises(AttributeError):
ret = cfg.option.find('b1') cfg.option('b1').value.get()
ret.value.get()
# assert not list_sessions() # assert not list_sessions()
@ -645,27 +640,27 @@ def test_reset_properties_force_store_value():
# assert not list_sessions() # assert not list_sessions()
def test_importation_force_store_value(): #def test_importation_force_store_value():
gcdummy = BoolOption('dummy', 'dummy', default=False, # gcdummy = BoolOption('dummy', 'dummy', default=False,
properties=('force_store_value',)) # properties=('force_store_value',))
gcgroup = OptionDescription('gc', '', [gcdummy]) # gcgroup = OptionDescription('gc', '', [gcdummy])
od1 = OptionDescription('tiramisu', '', [gcgroup]) # od1 = OptionDescription('tiramisu', '', [gcgroup])
config1 = Config(od1) # config1 = Config(od1)
assert config1.value.exportation() == {} # assert config1.value.exportation() == {}
config1.property.add('frozen') # config1.property.add('frozen')
assert config1.value.exportation() == {} # assert config1.value.exportation() == {}
config1.property.add('force_store_value') # config1.property.add('force_store_value')
assert config1.value.exportation() == {'gc.dummy': {None: [False, 'forced']}} # assert config1.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
exportation = config1.property.exportation() # exportation = config1.property.exportation()
config2 = Config(od1) # config2 = Config(od1)
assert config2.value.exportation() == {} # assert config2.value.exportation() == {}
config2.property.importation(exportation) # config2.property.importation(exportation)
assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}} # assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
config2.property.importation(exportation) # config2.property.importation(exportation)
assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}} # assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
# assert not list_sessions() ## assert not list_sessions()
#
#
def test_set_modified_value(): def test_set_modified_value():
gcdummy = BoolOption('dummy', 'dummy', default=False, properties=('force_store_value',)) gcdummy = BoolOption('dummy', 'dummy', default=False, properties=('force_store_value',))
gcgroup = OptionDescription('gc', '', [gcdummy]) gcgroup = OptionDescription('gc', '', [gcdummy])
@ -678,18 +673,18 @@ def test_set_modified_value():
# assert not list_sessions() # assert not list_sessions()
def test_none_is_not_modified(): #def test_none_is_not_modified():
gcdummy = StrOption('dummy', 'dummy', properties=('force_store_value',)) # gcdummy = StrOption('dummy', 'dummy', properties=('force_store_value',))
gcdummy1 = StrOption('dummy1', 'dummy1', default="str", properties=('force_store_value',)) # gcdummy1 = StrOption('dummy1', 'dummy1', default="str", properties=('force_store_value',))
gcgroup = OptionDescription('gc', '', [gcdummy, gcdummy1]) # gcgroup = OptionDescription('gc', '', [gcdummy, gcdummy1])
od1 = OptionDescription('tiramisu', '', [gcgroup]) # od1 = OptionDescription('tiramisu', '', [gcgroup])
cfg = Config(od1) # cfg = Config(od1)
assert cfg.value.exportation() == {} # assert cfg.value.exportation() == {}
cfg.property.read_write() # cfg.property.read_write()
assert cfg.value.exportation() == {'gc.dummy1': {None: ['str', 'forced']}} # assert cfg.value.exportation() == {'gc.dummy1': {None: ['str', 'forced']}}
# assert not list_sessions() ## assert not list_sessions()
#
#
def test_pprint(): def test_pprint():
msg_error = _("cannot access to {0} \"{1}\" because has {2} {3}") msg_error = _("cannot access to {0} \"{1}\" because has {2} {3}")
msg_is_not = _('the value of "{0}" is not {1}') 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]) descr = Leadership("root", "", [leader, option, ip])
cfg = Config(OptionDescription('root', 'root', [descr])) cfg = Config(OptionDescription('root', 'root', [descr]))
cfg.property.read_write() 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): def return_none(*args):
@ -908,4 +905,4 @@ def test_settings_disable_set_information(config_type):
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_only() cfg.property.read_only()
cfg.information.set('key', 'val') 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: with warnings.catch_warnings(record=True) as w:
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val']) cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['val'])
if config_type != 'tiramisu-api': 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' assert str(w[0].message) == msg_err.format('val', ip_admin_eth0.get_type(), display_name_ip) + ', test error return_false'
else: else:
assert len(w) == 2 assert len(w) == 2
@ -965,7 +965,7 @@ def test_validator_broadcast_default_1():
od1 = OptionDescription('a', '', [a, b, c]) od1 = OptionDescription('a', '', [a, b, c])
cfg = Config(od1) cfg = Config(od1)
with pytest.raises(ValueError): with pytest.raises(ValueError):
cfg.value.dict() cfg.value.get()
# assert not list_sessions() # 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())))]) d = BroadcastOption('d', '', '192.168.1.127', validators=[Calculation(valid_broadcast, Params((ParamOption(a), ParamOption(b), ParamSelfOption())))])
od1 = OptionDescription('a', '', [a, b, d]) od1 = OptionDescription('a', '', [a, b, d])
cfg = Config(od1) cfg = Config(od1)
assert cfg.value.dict() assert cfg.value.get()
# assert not list_sessions() # assert not list_sessions()
@ -1001,7 +1001,7 @@ def test_validator_network_netmask_mandatory(config_type):
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_only() cfg.property.read_only()
cfg = get_config(cfg, config_type) cfg = get_config(cfg, config_type)
cfg.value.dict() cfg.value.get()
# assert not list_sessions() # 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.b', 0).value.set(2)
cfg.option('a.a').value.reset() cfg.option('a.a').value.reset()
cfg.option('a.a').value.set([1]) cfg.option('a.a').value.set([1])
cfg.value.dict() cfg.value.get()
# assert not list_sessions() # assert not list_sessions()

View file

@ -13,7 +13,7 @@ from tiramisu import IPOption, OptionDescription, BoolOption, IntOption, StrOpti
calc_value_property_help calc_value_property_help
from tiramisu.error import PropertiesOptionError, ConfigError, display_list from tiramisu.error import PropertiesOptionError, ConfigError, display_list
import pytest import pytest
from .config import config_type, get_config from .config import config_type, get_config, parse_od_get
def test_properties(config_type): 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 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') 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.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'}]} {'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']) 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 assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() is None
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() 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.netmask_admin_eth0': None},
{'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]} {'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') 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.netmask_admin_eth0': '255.255.255.255'},
{'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]} {'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]}
# assert not list_sessions() # 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() cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() 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() # 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() cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() 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() # 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() cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() 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() # assert not list_sessions()
@ -1299,10 +1299,10 @@ def test_leadership_requires_complet(config_type):
cfg = get_config(cfg, config_type) cfg = get_config(cfg, config_type)
cfg.option('options.unicode.unicode').value.set(['test', 'trah']) cfg.option('options.unicode.unicode').value.set(['test', 'trah'])
cfg.option('options.unicode.unicode2', 0).value.set('test') 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') 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() # assert not list_sessions()
@ -1339,24 +1339,24 @@ def test_leadership_requires_transitive1(config_type):
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
cfg = get_config(cfg, config_type) 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') 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']) 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.unicode2', 1).value.set('test')
cfg.option('options.unicode.unicode3', 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') 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.unicode.unicode2', 1).value.set('test')
cfg.option('options.unicodetoto').value.set('rah') 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() # assert not list_sessions()

View file

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

View file

@ -2,7 +2,7 @@
import pytest import pytest
from .autopath import do_autopath from .autopath import do_autopath
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, \ from tiramisu import BoolOption, StrOption, SymLinkOption, submulti, \
OptionDescription, Leadership, Config, Calculation, calc_value, Params, ParamOption, ParamValue 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]) od1 = OptionDescription('root', '', [interface1, leader])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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']) 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) cfg.option('ip_admin_eth0.ip_admin_eth0').value.pop(0)
with pytest.raises(ConfigError): with pytest.raises(ConfigError):
cfg.option('leader').value.pop(0) cfg.option('leader').value.pop(0)
@ -318,9 +318,9 @@ def test_symlink_with_follower(config_type):
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) cfg = get_config(cfg, config_type)
assert not cfg.option('follower').isoptiondescription() 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']) 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', 0).owner.get() == 'default'
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).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] assert cfg.option('follower').value.get() == [None, None]
# #
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('val3') 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', 0).value.get() == None
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'val3' 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])]) [linkopt, OptionDescription("s1", "", [boolopt])])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) 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) 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() # assert not list_sessions()
@ -382,18 +382,12 @@ def test_symlink_list(config_type):
boolopt = BoolOption("b", "", default=False) boolopt = BoolOption("b", "", default=False)
linkopt = SymLinkOption("c", boolopt) linkopt = SymLinkOption("c", boolopt)
od1 = OptionDescription("opt", "", od1 = OptionDescription("opt", "",
[linkopt, OptionDescription("s1", "", [boolopt])]) [linkopt, OptionDescription("s1", "", [boolopt])])
cfg = Config(od1) cfg = Config(od1)
cfg = get_config(cfg, config_type) cfg = get_config(cfg, config_type)
list_opt = [] assert [opt.path() for opt in cfg.option.list()] == ['c', 's1']
for opt in cfg.option.list():
list_opt.append(opt.path())
assert list_opt == ['c']
# #
list_opt = [] assert [opt.path() for opt in cfg.option('s1').list()] == ['s1.b']
for opt in cfg.option.list(recursive=True):
list_opt.append(opt.path())
assert list_opt == ['c', 's1.b']
# assert not list_sessions() # 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" "enables us to carry out a calculation and return an option's value"
from typing import Any, Optional, Union, Callable, Dict, List from typing import Any, Optional, Union, Callable, Dict, List
from os.path import commonprefix
from itertools import chain from itertools import chain
from .error import PropertiesOptionError, ConfigError, LeadershipError, ValueWarning from .error import PropertiesOptionError, ConfigError, LeadershipError, ValueWarning
from .i18n import _ from .i18n import _
from .setting import undefined, ConfigBag, OptionBag, Undefined from .setting import undefined, ConfigBag, Undefined
from .function import FUNCTION_WAITING_FOR_DICT from .function import FUNCTION_WAITING_FOR_DICT
# ____________________________________________________________ # ____________________________________________________________
@ -55,6 +56,7 @@ class Params:
class Param: class Param:
__slots__ = tuple()
pass pass
@ -82,11 +84,14 @@ class ParamOption(Param):
class ParamDynOption(ParamOption): class ParamDynOption(ParamOption):
__slots__ = ('subpath',) __slots__ = ('suffixes',
'dynoptiondescription',
'optional',
)
def __init__(self, def __init__(self,
option: 'Option', option: 'Option',
subpath: str, suffixes: list[str],
dynoptiondescription: 'DynOptionDescription', dynoptiondescription: 'DynOptionDescription'=None,
notraisepropertyerror: bool=False, notraisepropertyerror: bool=False,
raisepropertyerror: bool=False, raisepropertyerror: bool=False,
optional: bool=False, optional: bool=False,
@ -95,7 +100,7 @@ class ParamDynOption(ParamOption):
notraisepropertyerror, notraisepropertyerror,
raisepropertyerror, raisepropertyerror,
) )
self.subpath = subpath self.suffixes = suffixes
self.dynoptiondescription = dynoptiondescription self.dynoptiondescription = dynoptiondescription
self.optional = optional self.optional = optional
@ -179,17 +184,18 @@ class Calculation:
self.warnings_only = warnings_only self.warnings_only = warnings_only
def execute(self, def execute(self,
option_bag: OptionBag, subconfig: "SubConfig",
*,
orig_value: Any=undefined, orig_value: Any=undefined,
allow_value_error: bool=False, allow_value_error: bool=False,
force_value_warning: bool=False, force_value_warning: bool=False,
for_settings: bool=False, for_settings: bool=False,
) -> Any: ) -> Any:
return carry_out_calculation(option_bag.option, return carry_out_calculation(subconfig,
callback=self.function, callback=self.function,
callback_params=self.params, callback_params=self.params,
index=option_bag.index, index=subconfig.index,
config_bag=option_bag.config_bag, config_bag=subconfig.config_bag,
orig_value=orig_value, orig_value=orig_value,
allow_value_error=allow_value_error, allow_value_error=allow_value_error,
force_value_warning=force_value_warning, force_value_warning=force_value_warning,
@ -197,18 +203,18 @@ class Calculation:
) )
def help(self, def help(self,
option_bag: OptionBag, subconfig: "SubConfig",
for_settings: bool=False, for_settings: bool=False,
) -> str: ) -> str:
if not self.help_function: if not self.help_function:
return self.execute(option_bag, return self.execute(subconfig,
for_settings=for_settings, for_settings=for_settings,
) )
return carry_out_calculation(option_bag.option, return carry_out_calculation(subconfig,
callback=self.help_function, callback=self.help_function,
callback_params=self.params, callback_params=self.params,
index=option_bag.index, index=subconfig.index,
config_bag=option_bag.config_bag, config_bag=subconfig.config_bag,
for_settings=for_settings, for_settings=for_settings,
) )
@ -218,113 +224,100 @@ class Calculation:
def manager_callback(callback: Callable, def manager_callback(callback: Callable,
param: Param, param: Param,
option, subconfig: 'SubConfig',
index: Optional[int], index: Optional[int],
orig_value, orig_value,
config_bag: ConfigBag, config_bag: ConfigBag,
for_settings: bool, for_settings: bool,
) -> Any: ) -> Any:
"""replace Param by true value""" """replace Param by true value"""
def calc_index(param, index, same_leadership): option = subconfig.option
if index is not None: def calc_apply_index(param,
if hasattr(param, 'whole'): same_leadership,
whole = param.whole ):
else: return index is not None and \
# if value is same_leadership, follower are isolate by default not getattr(param, 'whole', not same_leadership)
# otherwise option is a whole option
whole = not same_leadership
if not whole:
return index
return None
def calc_self(param, def calc_self(param,
option,
index, index,
value, value,
config_bag, config_bag,
): ):
# index must be apply only if follower # index must be apply only if follower
is_follower = option.impl_is_follower() is_follower = subconfig.option.impl_is_follower()
apply_index = calc_index(param, index, is_follower) # FIXME "same_leadership" or "is_follower"?
if value is undefined or (apply_index is None and is_follower): apply_index = calc_apply_index(param,
path = option.impl_getpath() is_follower,
option_bag = OptionBag(option, )
None, if value is undefined or (apply_index is False and is_follower):
config_bag, path = subconfig.path
properties=None, properties = config_bag.context.get_settings().getproperties(subconfig,
)
properties = config_bag.context.get_settings().getproperties(option_bag,
uncalculated=True, uncalculated=True,
) )
new_value = get_value(config_bag, new_value = get_value(config_bag,
option, subconfig,
param, param,
apply_index,
True, 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 new_value[index] = value
value = new_value value = new_value
elif apply_index is not None and not is_follower: elif apply_index is not False and not is_follower:
value = value[apply_index] value = value[index]
return value return value
def get_value(config_bag, def get_value(config_bag,
option, subconfig,
param, param,
index,
self_calc, self_calc,
*,
apply_index=True,
properties=undefined, properties=undefined,
): ):
parent_option_bag, option_bag = get_option_bag(config_bag, option = subconfig.option
option, if option.impl_is_follower() and apply_index is False:
param,
index,
self_calc,
properties=properties,
)
if option.impl_is_follower() and index is None:
value = [] value = []
for idx in range(config_bag.context.get_length_leadership(parent_option_bag)): for idx in range(subconfig.parent.get_length_leadership()):
parent_option_bag, option_bag = get_option_bag(config_bag, subconfig = get_option_bag(config_bag,
option, option,
param, param,
idx, idx,
self_calc, self_calc,
properties=properties, properties=properties,
) )
value.append(_get_value(param, value.append(_get_value(param,
option_bag, subconfig,
)) ))
else: else:
value = _get_value(param, value = _get_value(param,
option_bag, subconfig,
) )
return value return value
def _get_value(param: Params, def _get_value(param: Params,
option_bag: OptionBag, subconfig: SubConfig,
) -> Any: ) -> Any:
try: try:
# get value # get value
value = config_bag.context.get_value(option_bag) value = config_bag.context.get_value(subconfig)
except PropertiesOptionError as err: except PropertiesOptionError as err:
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation # raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
if param.notraisepropertyerror or param.raisepropertyerror: if param.notraisepropertyerror or param.raisepropertyerror:
raise err from err 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 raise ConfigError(_('unable to carry out a calculation for "{}", {}').format(display_name, err)) from err
except ValueError as 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: except AttributeError as err:
if isinstance(param, ParamDynOption) and param.optional: if isinstance(param, ParamDynOption) and param.optional:
# cannot acces, simulate a propertyerror # cannot acces, simulate a propertyerror
raise PropertiesOptionError(option_bag, raise PropertiesOptionError(subconfig,
['configerror'], ['configerror'],
config_bag.context.get_settings(), 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 raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
return value return value
@ -333,6 +326,7 @@ def manager_callback(callback: Callable,
param, param,
index_, index_,
self_calc, self_calc,
*,
properties=undefined, properties=undefined,
): ):
# don't validate if option is option that we tried to validate # don't validate if option is option that we tried to validate
@ -345,17 +339,14 @@ def manager_callback(callback: Callable,
if self_calc: if self_calc:
config_bag.unrestraint() config_bag.unrestraint()
config_bag.remove_validation() config_bag.remove_validation()
root_option_bag = OptionBag(config_bag.context.get_description(), # root = config_bag.context.get_root(config_bag)
None,
config_bag,
)
try: 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(), opt.impl_getpath(),
index_, index_,
validate_properties=not self_calc, validate_properties=not self_calc,
properties=properties, properties=properties,
) )
except PropertiesOptionError as err: except PropertiesOptionError as err:
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation # raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
if param.notraisepropertyerror or param.raisepropertyerror: if param.notraisepropertyerror or param.raisepropertyerror:
@ -373,30 +364,36 @@ def manager_callback(callback: Callable,
) )
display_name = option.impl_get_display_name() display_name = option.impl_get_display_name()
raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err raise ConfigError(_(f'unable to get value for calculating "{display_name}", {err}')) from err
if len(options_bag) > 1: return subconfig
parent_option_bag = options_bag[-2]
else: def get_common_path(path1, path2):
parent_option_bag = None common_path = commonprefix([path1, path2])
return parent_option_bag, options_bag[-1] 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): if isinstance(param, ParamValue):
return param.value return param.value
if isinstance(param, ParamInformation): if isinstance(param, ParamInformation):
if isinstance(param, ParamSelfInformation): if isinstance(param, ParamSelfInformation):
option_bag = OptionBag(option, isubconfig = subconfig
index,
config_bag,
)
elif param.option: elif param.option:
option_bag = OptionBag(param.option, isubconfig = get_option_bag(config_bag,
None, param.option,
config_bag, param,
) None,
False,
#properties=properties,
)
else: else:
option_bag = None isubconfig = None
try: try:
return config_bag.context.get_values().get_information(option_bag, return config_bag.context.get_values().get_information(isubconfig,
param.information_name, param.information_name,
param.default_value, param.default_value,
) )
@ -409,13 +406,12 @@ def manager_callback(callback: Callable,
if isinstance(param, ParamSuffix): if isinstance(param, ParamSuffix):
if not option.issubdyn(): 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')) raise ConfigError(_('option "{display_name}" is not in a dynoptiondescription'))
return option.get_suffixes()[-1] return subconfig.suffixes[-1]
if isinstance(param, ParamSelfOption): if isinstance(param, ParamSelfOption):
value = calc_self(param, value = calc_self(param,
option,
index, index,
orig_value, orig_value,
config_bag, config_bag,
@ -429,52 +425,31 @@ def manager_callback(callback: Callable,
if isinstance(param, ParamOption): if isinstance(param, ParamOption):
callbk_option = param.option callbk_option = param.option
callbk_options = None callbk_options = None
subconfigs = None
if callbk_option.issubdyn(): if callbk_option.issubdyn():
found = False found = False
if isinstance(param, ParamDynOption): if isinstance(param, ParamDynOption):
od_path = param.dynoptiondescription.impl_getpath() # SUBDYN INSIDE CURRENT != SUBDYN OUTSIDE ?
if "." in od_path: callbk_option = callbk_option.to_sub_dyoption(param.suffixes)
rootpath = od_path.rsplit('.', 1)[0] + '.' found = True
else: else:
rootpath = '' search_option = param.option
full_path = rootpath + param.subpath current_option_path = option.impl_getpath()
root_option_bag = OptionBag(config_bag.context.get_description(), search_option_path = search_option.impl_getpath()
None, common_path = get_common_path(current_option_path, search_option_path)
config_bag, if common_path:
) parent_number = current_option_path[len(common_path) + 2:].count('.')
try: if parent_number:
soptions_bag = config_bag.context.get_sub_option_bag(root_option_bag, raise Exception('pfff')
full_path, subconfig = subconfig.parent.get_child(search_option,
#FIXME index? None,
index=None, True,
validate_properties=True, )
properties=None, else:
) raise Exception('pfff')
except AttributeError as err: subconfigs = [subconfig]
raise ConfigError(_(f'option "{option.impl_get_display_name()}" is not in a dynoptiondescription: {err}'))
callbk_option = soptions_bag[-1].option
found = True 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())
found = True
if not found: if not found:
callbk_options = [] callbk_options = []
for doption_bag in callbk_option.getsubdyn().get_sub_children(callbk_option, for doption_bag in callbk_option.getsubdyn().get_sub_children(callbk_option,
@ -482,29 +457,40 @@ def manager_callback(callback: Callable,
index=None, index=None,
): ):
callbk_options.append(doption_bag.option) callbk_options.append(doption_bag.option)
if callbk_options is None: if index is not None and callbk_option.impl_get_leadership() and \
callbk_options = [callbk_option] callbk_option.impl_get_leadership().in_same_leadership(option):
if not callbk_option.impl_is_follower():
# leader
index_ = None
with_index = True
else:
# follower
index_ = index
with_index = False
else:
index_ = None
with_index = False
if subconfigs is None:
subconfigs = [get_option_bag(config_bag,
callbk_option,
param,
index_,
False,
#properties=properties,
)
]
# callbk_options = [callbk_option]
values = None values = None
else: else:
values = [] values = []
for callbk_option in callbk_options: #FIXME
if index is not None and callbk_option.impl_get_leadership() and \ values = None
callbk_option.impl_get_leadership().in_same_leadership(option): # for callbk_option in callbk_options:
if not callbk_option.impl_is_follower(): for subconfig in subconfigs:
# leader callbk_option = subconfig.option
index_ = None
with_index = True
else:
# follower
index_ = index
with_index = False
else:
index_ = None
with_index = False
value = get_value(config_bag, value = get_value(config_bag,
callbk_option, subconfig,
param, param,
index_,
False, False,
) )
if with_index: if with_index:
@ -519,7 +505,7 @@ def manager_callback(callback: Callable,
'value': value} 'value': value}
def carry_out_calculation(option, def carry_out_calculation(subconfig: 'SubConfig',
callback: Callable, callback: Callable,
callback_params: Optional[Params], callback_params: Optional[Params],
index: Optional[int], 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 - tuple with option and boolean's force_permissive (True when don't raise
if PropertiesOptionError) if PropertiesOptionError)
Values could have multiple values only when key is ''.""" Values could have multiple values only when key is ''."""
option = subconfig.option
if not option.impl_is_optiondescription() and option.impl_is_follower() and index is None: if not option.impl_is_optiondescription() and option.impl_is_follower() and index is None:
raise Exception('follower must have index in carry_out_calculation!') raise Exception('follower must have index in carry_out_calculation!')
def fake_items(iterator): def fake_items(iterator):
@ -556,7 +543,7 @@ def carry_out_calculation(option,
try: try:
value = manager_callback(callback, value = manager_callback(callback,
param, param,
option, subconfig,
index, index,
orig_value, orig_value,
config_bag, config_bag,

View file

@ -26,24 +26,24 @@ class Cache:
def __init__(self): def __init__(self):
self._cache = {} self._cache = {}
def _get_path_index(self, option_bag): def _get_path_index(self, subconfig):
if option_bag is None: if subconfig is None:
path = None path = None
index = None index = None
else: else:
path = option_bag.path path = subconfig.path
index = option_bag.index index = subconfig.index
return path, index return path, index
def getcache(self, def getcache(self,
option_bag, subconfig,
type_, type_,
expiration=True, expiration=True,
): ):
"""get the cache value fot a specified path """get the cache value fot a specified path
""" """
no_cache = False, None, False 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]: if path not in self._cache or index not in self._cache[path]:
return no_cache return no_cache
value, timestamp, validated = self._cache[path][index] value, timestamp, validated = self._cache[path][index]
@ -52,26 +52,26 @@ class Cache:
props = value props = value
self_props = {} self_props = {}
else: else:
props = option_bag.config_bag.properties props = subconfig.config_bag.properties
if type_ == 'self_props': if type_ == 'self_props':
# cached value is self_props # cached value is self_props
self_props = value self_props = value
else: else:
self_props = option_bag.properties self_props = subconfig.properties
if 'cache' in props or \ if 'cache' in props or \
'cache' in self_props: 'cache' in self_props:
if expiration and timestamp and \ if expiration and timestamp and \
('expire' in props or \ ('expire' in props or \
'expire' in self_props): 'expire' in self_props):
ntime = int(time()) ntime = int(time())
if timestamp + option_bag.config_bag.expiration_time >= ntime: if timestamp + subconfig.config_bag.expiration_time >= ntime:
return True, value, validated return True, value, validated
else: else:
return True, value, validated return True, value, validated
return no_cache return no_cache
def setcache(self, def setcache(self,
option_bag, subconfig,
val, val,
type_='values', type_='values',
validated=True, validated=True,
@ -80,13 +80,13 @@ class Cache:
if follower, add index if follower, add index
""" """
if type_ == 'values': if type_ == 'values':
if 'cache' not in option_bag.config_bag.properties and \ if 'cache' not in subconfig.config_bag.properties and \
'cache' not in option_bag.properties: 'cache' not in subconfig.properties:
return 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: 'cache' not in val:
return 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) self._cache.setdefault(path, {})[index] = (val, int(time()), validated)
def delcache(self, path): 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): class PropertiesOptionError(AttributeError):
"attempt to access to an option with a property that is not allowed" "attempt to access to an option with a property that is not allowed"
def __init__(self, def __init__(self,
option_bag, subconfig,
proptype, proptype,
settings, settings,
opt_type=None, opt_type=None,
@ -66,13 +66,12 @@ class PropertiesOptionError(AttributeError):
self._name = name self._name = name
self._orig_opt = orig_opt self._orig_opt = orig_opt
else: else:
if option_bag.option.impl_is_optiondescription(): if subconfig.option.impl_is_optiondescription():
self._opt_type = 'optiondescription' self._opt_type = 'optiondescription'
else: else:
self._opt_type = 'option' 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._orig_opt = None
self._option_bag = option_bag
self.proptype = proptype self.proptype = proptype
self.help_properties = help_properties self.help_properties = help_properties
self._settings = settings self._settings = settings

View file

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

View file

@ -22,7 +22,7 @@
""" """
from typing import Any from typing import Any
from ..setting import undefined, OptionBag from ..setting import undefined
from ..i18n import _ from ..i18n import _
from .option import Option from .option import Option
from ..autolib import Calculation from ..autolib import Calculation
@ -57,12 +57,12 @@ class ChoiceOption(Option):
**kwargs) **kwargs)
def impl_get_values(self, def impl_get_values(self,
option_bag: OptionBag, subconfig: "SubConfig",
): ):
"""get values allowed by option """get values allowed by option
""" """
if isinstance(self._choice_values, Calculation): 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): if values is not undefined and not isinstance(values, list):
raise ConfigError(_('the calculated values "{0}" for "{1}" is not a list' raise ConfigError(_('the calculated values "{0}" for "{1}" is not a list'
'').format(values, self.impl_getname())) '').format(values, self.impl_getname()))
@ -78,12 +78,12 @@ class ChoiceOption(Option):
def validate_with_option(self, def validate_with_option(self,
value: Any, value: Any,
option_bag: OptionBag, subconfig: "SubConfig",
loaded: bool, loaded: bool,
) -> None: ) -> None:
if loaded and isinstance(self._choice_values, Calculation): if loaded and isinstance(self._choice_values, Calculation):
return return
values = self.impl_get_values(option_bag) values = self.impl_get_values(subconfig)
self.validate_values(value, values) self.validate_values(value, values)
def validate_values(self, def validate_values(self,

View file

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

View file

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

View file

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

View file

@ -25,9 +25,9 @@ from typing import Optional, Iterator, Union, List
from ..i18n import _ from ..i18n import _
from ..setting import ConfigBag, OptionBag, groups, undefined, owners, Undefined from ..setting import ConfigBag, groups, undefined, owners, Undefined
from .baseoption import BaseOption from .baseoption import BaseOption
from .syndynoptiondescription import SubDynOptionDescription, SynDynOptionDescription # from .syndynoption import SubDynOptionDescription, SynDynOptionDescription
from ..error import ConfigError, ConflictError from ..error import ConfigError, ConflictError
@ -71,9 +71,7 @@ class CacheOptionDescription(BaseOption):
# cache already set # cache already set
raise ConfigError(_('option description seems to be part of an other ' raise ConfigError(_('option description seems to be part of an other '
'config')) 'config'))
for option in self.get_children(config_bag=undefined, # pylint: disable=no-member for option in self.get_children():
dyn=False,
):
if __debug__: if __debug__:
cache_option.append(option) cache_option.append(option)
sub_currpath = currpath + [option.impl_getname()] 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._cache_dependencies_information = dependencies_information # pylint: disable=attribute-defined-outside-init
self._path = None # pylint: disable=attribute-defined-outside-init,no-member self._path = None # pylint: disable=attribute-defined-outside-init,no-member
self._set_readonly() self._set_readonly()
#
def impl_build_force_store_values(self, # def impl_build_force_store_values(self,
config_bag: ConfigBag, # config_bag: ConfigBag,
) -> None: # ) -> None:
"""set value to force_store_values option # """set value to force_store_values option
""" # """
# pylint: disable=too-many-branches # # pylint: disable=too-many-branches
def do_option_bags(option): # def do_option_bags(option):
if option.issubdyn(): # if option.issubdyn():
dynopt = option.getsubdyn() # dynopt = option.getsubdyn()
yield from dynopt.get_sub_children(option, # yield from dynopt.get_sub_children(option,
config_bag, # config_bag,
index=None, # index=None,
) # )
else: # else:
yield OptionBag(option, # yield OptionBag(option,
None, # None,
config_bag, # config_bag,
properties=None, # properties=None,
) # )
if 'force_store_value' not in config_bag.properties: # if 'force_store_value' not in config_bag.properties:
return # return
values = config_bag.context.get_values() # values = config_bag.context.get_values()
for option in self._cache_force_store_values: # for option in self._cache_force_store_values:
if option.impl_is_follower(): # if option.impl_is_follower():
leader = option.impl_get_leadership().get_leader() # leader = option.impl_get_leadership().get_leader()
for leader_option_bag in do_option_bags(leader): # for leader_option_bag in do_option_bags(leader):
leader_option_bag.properties = frozenset() # leader_option_bag.properties = frozenset()
follower_len = len(values.get_value(leader_option_bag)[0]) # follower_len = len(values.get_value(leader_option_bag)[0])
if option.issubdyn(): # if option.issubdyn():
doption = option.to_dynoption(leader_option_bag.option.rootpath, # doption = option.to_dynoption(leader_option_bag.option.rootpath,
leader_option_bag.option.get_suffixes(), # leader_option_bag.option.get_current_suffixes(),
) # )
else: # else:
doption = option # doption = option
subpath = doption.impl_getpath() # subpath = doption.impl_getpath()
for index in range(follower_len): # for index in range(follower_len):
option_bag = OptionBag(doption, # option_bag = OptionBag(doption,
index, # index,
config_bag, # config_bag,
properties=frozenset(), # properties=frozenset(),
) # )
if values.hasvalue(subpath, index=index): # if values.hasvalue(subpath, index=index):
continue # continue
value = values.get_value(option_bag)[0] # value = values.get_value(option_bag)[0]
if value is None: # if value is None:
continue # continue
values.set_storage_value(subpath, # values.set_storage_value(subpath,
index, # index,
value, # value,
owners.forced, # owners.forced,
) # )
else: # else:
for option_bag in do_option_bags(option): # for option_bag in do_option_bags(option):
option_bag.properties = frozenset() # option_bag.properties = frozenset()
value = values.get_value(option_bag)[0] # value = values.get_value(option_bag)[0]
if value is None: # if value is None:
continue # continue
if values.hasvalue(option_bag.path): # if values.hasvalue(option_bag.path):
continue # continue
values.set_storage_value(option_bag.path, # values.set_storage_value(option_bag.path,
None, # None,
value, # value,
owners.forced, # owners.forced,
) # )
class OptionDescriptionWalk(CacheOptionDescription): class OptionDescriptionWalk(CacheOptionDescription):
@ -179,6 +177,14 @@ class OptionDescriptionWalk(CacheOptionDescription):
""" """
__slots__ = ('_children',) __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, def get_child_not_dynamic(self,
name, name,
allow_dynoption, allow_dynoption,
@ -194,9 +200,11 @@ class OptionDescriptionWalk(CacheOptionDescription):
def get_child(self, def get_child(self,
name: str, name: str,
config_bag: ConfigBag, config_bag: ConfigBag,
parent: 'SubConfig',
*, *,
with_suffix: bool=False,
allow_dynoption: bool=False, allow_dynoption: bool=False,
) -> Union[BaseOption, SynDynOptionDescription]: ) -> Union[BaseOption]:
"""get a child """get a child
""" """
# if not dyn # if not dyn
@ -209,12 +217,12 @@ class OptionDescriptionWalk(CacheOptionDescription):
for child in self._children[1]: # pylint: disable=no-member for child in self._children[1]: # pylint: disable=no-member
if not child.impl_is_dynoptiondescription(): if not child.impl_is_dynoptiondescription():
continue continue
for suffix in child.get_suffixes(config_bag): for suffix in child.get_suffixes(parent):
if name != child.impl_getname(suffix): if name != child.impl_getname(suffix):
continue continue
return child.to_dynoption(self.impl_getpath(), if not with_suffix:
[suffix], return child
) return suffix, child
if self.impl_get_group_type() == groups.root: # pylint: disable=no-member if self.impl_get_group_type() == groups.root: # pylint: disable=no-member
raise AttributeError(_(f'unknown option "{name}" ' raise AttributeError(_(f'unknown option "{name}" '
'in root optiondescription' 'in root optiondescription'
@ -223,52 +231,18 @@ class OptionDescriptionWalk(CacheOptionDescription):
f'in optiondescription "{self.impl_get_display_name()}"' f'in optiondescription "{self.impl_get_display_name()}"'
)) ))
def get_children(self, def get_children(self) -> List[BaseOption]:
config_bag: Union[ConfigBag, Undefined],
*,
dyn: bool=True,
#path: Optional[str]=None,
dynoption=None,
) -> Union[BaseOption, SynDynOptionDescription]:
"""get children """get children
""" """
for child in self._children[1]: return self._children[1]
if dyn and child.impl_is_dynoptiondescription(): # for child in self._children[1]:
yield from self.get_suffixed_children(dynoption, # if config_bag is not undefined and child.impl_is_dynoptiondescription():
[], # yield from self.get_suffixed_children([],
config_bag, # config_bag,
child, # child,
) # )
else: # else:
yield child # 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],
)
def get_children_recursively(self, def get_children_recursively(self,
bytype: Optional[BaseOption], bytype: Optional[BaseOption],
@ -277,12 +251,12 @@ class OptionDescriptionWalk(CacheOptionDescription):
self_opt: BaseOption=None, self_opt: BaseOption=None,
*, *,
option_suffixes: Optional[list]=None option_suffixes: Optional[list]=None
) -> Iterator[Union[BaseOption, SynDynOptionDescription]]: ) -> Iterator[Union[BaseOption]]:
"""get children recursively """get children recursively
""" """
if self_opt is None: if self_opt is None:
self_opt = self self_opt = self
for option in self_opt.get_children(config_bag): for option in self_opt.get_children():
if option.impl_is_optiondescription(): if option.impl_is_optiondescription():
for subopt in option.get_children_recursively(bytype, for subopt in option.get_children_recursively(bytype,
byname, byname,
@ -391,22 +365,22 @@ class OptionDescription(OptionDescriptionWalk):
"""get the group type of option description """get the group type of option description
""" """
return self._group_type return self._group_type
#
def to_dynoption(self, # def to_dynoption(self,
rootpath: str, # rootpath: str,
suffixes: Optional[list], # suffixes: Optional[list],
#ori_dyn, # #ori_dyn,
) -> Union[SubDynOptionDescription, SynDynOptionDescription]: # ) -> Union[SubDynOptionDescription]:
"""get syn dyn option description # """get syn dyn option description
""" # """
if self.impl_is_dynoptiondescription(): # if self.impl_is_dynoptiondescription():
obj = SynDynOptionDescription # obj = SynDynOptionDescription
else: # else:
obj = SubDynOptionDescription # obj = SubDynOptionDescription
return obj(self, # return obj(self,
rootpath, # rootpath,
suffixes, # suffixes,
) # )
def impl_is_dynsymlinkoption(self) -> bool: def impl_is_dynsymlinkoption(self) -> bool:
"""option is not a dyn symlink option """option is not a dyn symlink option

View file

@ -1,5 +1,5 @@
# -*- coding: utf-8 -*- # -*- 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 # 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 # 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 """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 .baseoption import BaseOption
from ..i18n import _
from ..setting import ConfigBag, undefined
class SynDynOption: NAME_REGEXP = re.compile(r'^[a-zA-Z\d\-_]*$')
"""SynDynOption is an Option include un DynOptionDescription with specified prefix
"""
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', __slots__ = ('rootpath',
'opt', 'opt',
'suffixes', '_current_suffixes',
'__weakref__') '__weakref__')
def __init__(self, def __init__(self,
@ -39,28 +116,28 @@ class SynDynOption:
) -> None: ) -> None:
self.opt = opt self.opt = opt
self.rootpath = rootpath self.rootpath = rootpath
self.suffixes = suffixes self._current_suffixes = suffixes
def __getattr__(self, def __getattr__(self,
name: str) -> Any: name: str,
) -> Any:
# if not in SynDynOptionDescription, get value in self.opt
return getattr(self.opt, return getattr(self.opt,
name, name,
) )
def impl_getname(self) -> str:
"""get option name
"""
return self.opt.impl_getname()
def impl_get_display_name(self) -> str: def impl_get_display_name(self) -> str:
"""get option display name
"""
return self.opt.impl_get_display_name(self) return self.opt.impl_get_display_name(self)
def get_suffixes(self) -> str: def get_current_suffixes(self) -> str:
"""get suffix """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: def impl_getpath(self) -> str:
"""get path """get path
@ -70,10 +147,109 @@ class SynDynOption:
path = f'{self.rootpath}.{path}' path = f'{self.rootpath}.{path}'
return 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 def impl_get_leadership(self): # pylint: disable=inconsistent-return-statements
"""is it a leadership? """is it a leadership?
@ -82,5 +258,94 @@ class SynDynOption:
if leadership: if leadership:
rootpath = self.rootpath.rsplit('.', 1)[0] rootpath = self.rootpath.rsplit('.', 1)[0]
return leadership.to_dynoption(rootpath, 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() undefined = Undefined()
#
#
class OptionBag: #class OptionBag:
"""Object to store information for an option # """Object to store information for an option
""" # """
__slots__ = ('option', # current option # __slots__ = ('option', # current option
'path', # 'path',
'index', # 'index',
'config_bag', # 'config_bag',
'ori_option', # original option (for example useful for symlinkoption) # 'ori_option', # original option (for example useful for symlinkoption)
'properties', # properties of current option # 'properties', # properties of current option
'apply_requires', # apply requires or not for this option # 'apply_requires', # apply requires or not for this option
) # 'suffixes',
# )
# pylint: disable=too-many-arguments #
def __init__(self, # # pylint: disable=too-many-arguments
option, # def __init__(self,
index, # option,
config_bag, # index,
path=None, # config_bag,
properties=undefined, # *,
ori_option=None, # path=None,
apply_requires=True, # properties=undefined,
): # parent: 'SubConfig'=None,
self.index = index # ori_option=None,
self.config_bag = config_bag # apply_requires=True,
self.option = option # suffixes=None
if ori_option is not None: # ):
self.ori_option = ori_option # self.index = index
if config_bag is undefined: # self.config_bag = config_bag
self.path = path # self.option = option
elif path: # if ori_option is not None:
self.path = path # self.ori_option = ori_option
elif option: # if config_bag is undefined:
self.path = option.impl_getpath() # self.path = path
context = config_bag.context # elif option:
if self.path is None: # if properties is not undefined:
self.properties = None # self.properties = properties
elif properties is undefined: # self.suffixes = suffixes
settings = context.get_settings() #
try: # def __getattr__(self, key):
self.properties = settings.getproperties(self, # if key == 'ori_option':
apply_requires=apply_requires, # return self.option
) # if key == 'apply_requires':
except ConfigError: # return True
self.properties = None # return None
if properties is not undefined: #
self.properties = properties # def copy(self):
# """copy OptionBag
def __getattr__(self, key): # """
if key == 'ori_option': # option_bag = OptionBag(None,
return self.option # None,
if key == 'apply_requires': # None,
return True # )
return None # for key in self.__slots__:
# setattr(option_bag, key, getattr(self, key))
def copy(self): # return option_bag
"""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: class ConfigBag:
@ -453,7 +444,8 @@ class Settings:
return self._properties[path][index] return self._properties[path][index]
def getproperties(self, def getproperties(self,
option_bag, subconfig: 'SubConfig',
*,
apply_requires=True, apply_requires=True,
uncalculated=False, uncalculated=False,
help_property=False, help_property=False,
@ -462,12 +454,12 @@ class Settings:
"""get properties """get properties
""" """
# pylint: disable=too-many-branches # pylint: disable=too-many-branches
option = option_bag.option option = subconfig.option
if option.impl_is_symlinkoption(): if option.impl_is_symlinkoption():
option = option.impl_getopt() option = option.impl_getopt()
if apply_requires and not uncalculated and not help_property: if apply_requires and not uncalculated and not help_property:
cache = option_bag.config_bag.context.properties_cache cache = subconfig.config_bag.context.properties_cache
is_cached, props, validated = cache.getcache(option_bag, # pylint: disable=unused-variable is_cached, props, validated = cache.getcache(subconfig, # pylint: disable=unused-variable
'self_props', 'self_props',
) )
else: else:
@ -475,14 +467,14 @@ class Settings:
if not is_cached: if not is_cached:
props = set() props = set()
# if index, get option's properties (without index) too # 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, None,
option.impl_getproperties(), option.impl_getproperties(),
) )
if option_bag.index is not None: if subconfig.index is not None:
p_props = chain(p_props, p_props = chain(p_props,
self.get_stored_properties(option_bag.path, self.get_stored_properties(subconfig.path,
option_bag.index, subconfig.index,
option.impl_getproperties(), option.impl_getproperties(),
) )
) )
@ -495,11 +487,11 @@ class Settings:
elif apply_requires: elif apply_requires:
try: try:
if not help_property: if not help_property:
new_prop = prop.execute(option_bag, new_prop = prop.execute(subconfig,
for_settings=True, for_settings=True,
) )
else: else:
new_prop = prop.help(option_bag, new_prop = prop.help(subconfig,
for_settings=True, for_settings=True,
) )
if isinstance(new_prop, str): if isinstance(new_prop, str):
@ -513,18 +505,18 @@ class Settings:
if (not help_property and not isinstance(new_prop, str)) or \ if (not help_property and not isinstance(new_prop, str)) or \
(help_property and not isinstance(new_prop, tuple)): (help_property and not isinstance(new_prop, tuple)):
raise ValueError(_('invalid property type {type(new_prop)} for ' raise ValueError(_('invalid property type {type(new_prop)} for '
'{option_bag.option.impl_getname()} with ' '{subconfig.option.impl_getname()} with '
'{prop.function.__name__} function')) '{prop.function.__name__} function'))
if not option.impl_is_optiondescription() and \ if not option.impl_is_optiondescription() and \
option.impl_is_leader() and \ option.impl_is_leader() and \
new_prop not in ALLOWED_LEADER_PROPERTIES: new_prop not in ALLOWED_LEADER_PROPERTIES:
raise LeadershipError(_('leader cannot have "{new_prop}" property')) raise LeadershipError(_('leader cannot have "{new_prop}" property'))
props.add(new_prop) props.add(new_prop)
props -= self.getpermissives(option_bag) props -= self.getpermissives(subconfig)
if not uncalculated and apply_requires and \ 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: not help_property and transitive_raise:
cache.setcache(option_bag, cache.setcache(subconfig,
props, props,
type_='properties', type_='properties',
) )
@ -546,21 +538,21 @@ class Settings:
return ret return ret
def getpermissives(self, def getpermissives(self,
option_bag, subconfig: "SubConfig",
): ):
"""get permissive """get permissive
""" """
if option_bag is None: if subconfig is None:
path = None path = None
index = None index = None
else: else:
opt = option_bag.option opt = subconfig.option
if opt.impl_is_symlinkoption(): if opt.impl_is_symlinkoption():
opt = opt.impl_getopt() opt = opt.impl_getopt()
path = opt.impl_getpath() path = opt.impl_getpath()
else: else:
path = option_bag.path path = subconfig.path
index = option_bag.index index = subconfig.index
permissives = self._getpermissives(path, permissives = self._getpermissives(path,
None, None,
) )
@ -578,13 +570,13 @@ class Settings:
context.reset_cache(None) context.reset_cache(None)
def setproperties(self, def setproperties(self,
option_bag, subconfig,
properties, properties,
): ):
"""save properties for specified path """save properties for specified path
(never save properties if same has option properties) (never save properties if same has option properties)
""" """
opt = option_bag.option opt = subconfig.option
if not opt.impl_is_optiondescription() and opt.impl_is_leader(): if not opt.impl_is_optiondescription() and opt.impl_is_leader():
not_allowed_properties = properties - ALLOWED_LEADER_PROPERTIES not_allowed_properties = properties - ALLOWED_LEADER_PROPERTIES
if not_allowed_properties: if not_allowed_properties:
@ -595,10 +587,10 @@ class Settings:
raise LeadershipError(_('a leader ({opt.impl_get_display_name()}) cannot have ' raise LeadershipError(_('a leader ({opt.impl_get_display_name()}) cannot have '
'"force_default_on_freeze" or ' '"force_default_on_freeze" or '
'"force_metaconfig_on_freeze" property without "frozen"')) '"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 # values too because of follower values could have a PropertiesOptionError has value
option_bag.config_bag.context.reset_cache(option_bag) subconfig.config_bag.context.reset_cache(subconfig)
option_bag.properties = properties subconfig.properties = properties
def set_context_permissives(self, def set_context_permissives(self,
permissives, permissives,
@ -610,7 +602,7 @@ class Settings:
) )
def setpermissives(self, def setpermissives(self,
option_bag, subconfig,
permissives, permissives,
): ):
""" """
@ -624,9 +616,9 @@ class Settings:
""" """
if not isinstance(permissives, frozenset): if not isinstance(permissives, frozenset):
raise TypeError(_('permissive must be a frozenset')) raise TypeError(_('permissive must be a frozenset'))
if option_bag is not None: if subconfig is not None:
path = option_bag.path path = subconfig.path
index = option_bag.index index = subconfig.index
else: else:
path = None path = None
index = None index = None
@ -635,165 +627,166 @@ class Settings:
raise ConfigError(_('cannot add those permissives: {0}').format( raise ConfigError(_('cannot add those permissives: {0}').format(
' '.join(forbidden_permissives))) ' '.join(forbidden_permissives)))
self._permissives.setdefault(path, {})[index] = permissives self._permissives.setdefault(path, {})[index] = permissives
if option_bag is not None: if subconfig is not None:
option_bag.config_bag.context.reset_cache(option_bag) subconfig.config_bag.context.reset_cache(subconfig)
#____________________________________________________________ #____________________________________________________________
# reset methods # reset methods
def _get_path_index_config_option(self, def _get_path_index_config_option(self,
bag: Union[OptionBag, ConfigBag], bag: Union['SubConfig', ConfigBag],
msg: str, msg: str,
): ):
if isinstance(bag, ConfigBag): if isinstance(bag, ConfigBag):
path = None path = None
index = None index = None
config_bag = bag config_bag = bag
option_bag = None subconfig= None
else: else:
assert not bag.option.impl_is_symlinkoption(), \ assert not bag.option.impl_is_symlinkoption(), \
_(msg).format(bag.option.impl_get_display_name()) _(msg).format(bag.option.impl_get_display_name())
path = bag.path path = bag.path
index = bag.index index = bag.index
config_bag = bag.config_bag config_bag = bag.config_bag
option_bag = bag subconfig = bag
return path, index, config_bag, option_bag return path, index, config_bag, subconfig
def reset(self, def reset(self,
bag: Union[OptionBag, ConfigBag], bag: Union['SubConfig', ConfigBag],
): ):
"""reset property """reset property
""" """
path, index, config_bag, option_bag = \ path, index, config_bag, subconfig = \
self._get_path_index_config_option(bag, self._get_path_index_config_option(bag,
"can't reset properties to " "can't reset properties to "
"the symlinkoption \"{}\"", "the symlinkoption \"{}\"",
) )
if path in self._properties and index in self._properties[path]: if path in self._properties and index in self._properties[path]:
del self._properties[path][index] del self._properties[path][index]
config_bag.context.reset_cache(option_bag) config_bag.context.reset_cache(subconfig)
def reset_permissives(self, def reset_permissives(self,
bag: Union[OptionBag, ConfigBag], bag: Union['SubConfig', ConfigBag],
): ):
"""reset permission """reset permission
""" """
path, index, config_bag, option_bag = \ path, index, config_bag, subconfig = \
self._get_path_index_config_option(bag, self._get_path_index_config_option(bag,
"can't reset permissives to " "can't reset permissives to "
"the symlinkoption \"{}\"", "the symlinkoption \"{}\"",
) )
if path in self._permissives and index in self._permissives[path]: if path in self._permissives and index in self._permissives[path]:
del self._permissives[path][index] del self._permissives[path][index]
config_bag.context.reset_cache(option_bag) config_bag.context.reset_cache(subconfig)
#____________________________________________________________ #____________________________________________________________
# validate properties # validate properties
def calc_raises_properties(self, def calc_raises_properties(self,
option_bag, subconfig,
apply_requires=True, apply_requires=True,
uncalculated=False, uncalculated=False,
transitive_raise=True, transitive_raise=True,
): ):
"""raise if needed """raise if needed
""" """
if not uncalculated and apply_requires and option_bag.properties is not None: if not uncalculated and apply_requires and subconfig.properties is not None:
option_properties = option_bag.properties option_properties = subconfig.properties
else: else:
option_properties = self.getproperties(option_bag, option_properties = self.getproperties(subconfig,
apply_requires=apply_requires, apply_requires=apply_requires,
uncalculated=uncalculated, uncalculated=uncalculated,
transitive_raise=transitive_raise, transitive_raise=transitive_raise,
) )
return self._calc_raises_properties(option_bag, return self._calc_raises_properties(subconfig,
option_properties, option_properties,
) )
def _calc_raises_properties(self, def _calc_raises_properties(self,
option_bag, subconfig,
option_properties, option_properties,
): ):
raises_properties = option_bag.config_bag.properties - SPECIAL_PROPERTIES raises_properties = subconfig.config_bag.properties - SPECIAL_PROPERTIES
# remove global permissive properties # remove global permissive properties
if raises_properties and 'permissive' in raises_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 properties = option_properties & raises_properties
# at this point it should not remain any property for the option # at this point it should not remain any property for the option
return properties return properties
def validate_properties(self, def validate_properties(self,
option_bag, subconfig,
*,
need_help=True, need_help=True,
): ):
"""check properties """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 not config_properties or config_properties == frozenset(['cache']):
# if no global property # if no global property
return return
for transitive_raise in [False, True]: for transitive_raise in [False, True]:
properties = self.calc_raises_properties(option_bag, properties = self.calc_raises_properties(subconfig,
transitive_raise=transitive_raise, transitive_raise=transitive_raise,
) )
if properties != frozenset(): if properties != frozenset():
if need_help: if need_help:
help_properties = dict(self.getproperties(option_bag, help_properties = dict(self.getproperties(subconfig,
help_property=True, help_property=True,
transitive_raise=transitive_raise, transitive_raise=transitive_raise,
)) ))
calc_properties = [] calc_properties = []
for property_ in self._calc_raises_properties(option_bag, for property_ in self._calc_raises_properties(subconfig,
set(help_properties.keys()), set(help_properties.keys()),
): ):
calc_properties.append(help_properties[property_]) calc_properties.append(help_properties[property_])
calc_properties = frozenset(calc_properties) calc_properties = frozenset(calc_properties)
else: else:
calc_properties = properties calc_properties = properties
raise PropertiesOptionError(option_bag, raise PropertiesOptionError(subconfig,
properties, properties,
self, self,
help_properties=calc_properties, help_properties=calc_properties,
) )
def validate_mandatory(self, def validate_mandatory(self,
subconfig,
value, value,
option_bag,
): ):
"""verify if option is mandatory without value """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 return
values = option_bag.config_bag.context.get_values() values = subconfig.config_bag.context.get_values()
if not ('permissive' in option_bag.config_bag.properties and if not ('permissive' in subconfig.config_bag.properties and
'mandatory' in option_bag.config_bag.permissives) and \ 'mandatory' in subconfig.config_bag.permissives) and \
'mandatory' in option_bag.properties and values.isempty(option_bag, 'mandatory' in subconfig.properties and values.isempty(subconfig,
value, value,
False, False,
): ):
raise PropertiesOptionError(option_bag, raise PropertiesOptionError(subconfig,
['mandatory'], ['mandatory'],
self, self,
) )
if 'empty' in option_bag.properties and values.isempty(option_bag, if 'empty' in subconfig.properties and values.isempty(subconfig,
value, value,
True, True,
): ):
raise PropertiesOptionError(option_bag, raise PropertiesOptionError(subconfig,
['empty'], ['empty'],
self, self,
) )
def validate_frozen(self, def validate_frozen(self,
option_bag, subconfig,
): ):
"""verify if option is frozen """verify if option is frozen
""" """
if option_bag.config_bag.properties and \ if subconfig.config_bag.properties and \
('everything_frozen' in option_bag.config_bag.properties or ('everything_frozen' in subconfig.config_bag.properties or
('frozen' in option_bag.config_bag.properties and \ ('frozen' in subconfig.config_bag.properties and \
'frozen' in option_bag.properties)) and \ 'frozen' in subconfig.properties)) and \
not (('permissive' in option_bag.config_bag.properties) and not (('permissive' in subconfig.config_bag.properties) and
'frozen' in option_bag.config_bag.permissives): 'frozen' in subconfig.config_bag.permissives):
raise PropertiesOptionError(option_bag, raise PropertiesOptionError(subconfig,
['frozen'], ['frozen'],
self, self,
) )

View file

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

View file

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