Compare commits

..

1 commit

Author SHA1 Message Date
a05d4e17a3 remote storage, so session and async too 2023-04-17 19:48:38 +02:00
32 changed files with 2398 additions and 2412 deletions

View file

@ -856,31 +856,31 @@ def autocheck_reset_value_permissive(cfg, mcfg, pathread, pathwrite, confread, c
_autocheck_default_value(cfg, pathread, confread, **kwargs) _autocheck_default_value(cfg, pathread, confread, **kwargs)
if confread != confwrite: if confread != confwrite:
_autocheck_default_value(cfg, pathwrite, confwrite, **kwargs) _autocheck_default_value(cfg, pathwrite, confwrite, **kwargs)
#FIXME
#FIXME
#FIXME@autocheck @autocheck
#FIXMEdef autocheck_display(cfg, mcfg, pathread, pathwrite, confread, confwrite, **kwargs): def autocheck_display(cfg, mcfg, pathread, pathwrite, confread, confwrite, **kwargs):
#FIXME """re set value """re set value
#FIXME """ """
#FIXME if kwargs['callback']: if kwargs['callback']:
#FIXME return return
#FIXME make_dict = kwargs['make_dict'] make_dict = kwargs['make_dict']
#FIXME make_dict_value = kwargs['make_dict_value'] make_dict_value = kwargs['make_dict_value']
#FIXME if confread is not None: if confread is not None:
#FIXME cfg_ = cfg.config(confread) cfg_ = cfg.config(confread)
#FIXME else: else:
#FIXME cfg_ = cfg cfg_ = cfg
#FIXME if confwrite is not None: if confwrite is not None:
#FIXME cfg2_ = cfg.config(confwrite) cfg2_ = cfg.config(confwrite)
#FIXME else: else:
#FIXME cfg2_ = cfg cfg2_ = cfg
#FIXME assert cfg_.value.dict() == make_dict assert cfg_.value.dict() == make_dict
#FIXME if confread != confwrite: if confread != confwrite:
#FIXME assert(cfg2_.value.dict()) == make_dict assert(cfg2_.value.dict()) == make_dict
#FIXME _set_value(cfg, pathwrite, confwrite, **kwargs) _set_value(cfg, pathwrite, confwrite, **kwargs)
#FIXME assert cfg_.value.dict() == make_dict_value assert cfg_.value.dict() == make_dict_value
#FIXME if confread != confwrite: if confread != confwrite:
#FIXME assert(cfg2_.value.dict()) == make_dict_value assert(cfg2_.value.dict()) == make_dict_value
@autocheck @autocheck

View file

@ -38,7 +38,7 @@ def test_cache():
od1 = make_description() od1 = make_description()
cfg = Config(od1) cfg = Config(od1)
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._impl_properties_cache
cfg.option('u1').value.get() cfg.option('u1').value.get()
assert 'u1' in values.get_cached() assert 'u1' in values.get_cached()
assert 'u1' in settings.get_cached() assert 'u1' in settings.get_cached()
@ -94,7 +94,7 @@ def test_cache_reset():
od1 = make_description() od1 = make_description()
cfg = Config(od1) cfg = Config(od1)
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._impl_properties_cache
#when change a value #when change a value
cfg.option('u1').value.get() cfg.option('u1').value.get()
cfg.option('u2').value.get() cfg.option('u2').value.get()
@ -156,7 +156,7 @@ def test_cache_reset_multi():
od1 = make_description() od1 = make_description()
cfg = Config(od1) cfg = Config(od1)
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._impl_properties_cache
cfg.option('u1').value.get() cfg.option('u1').value.get()
cfg.option('u3').value.get() cfg.option('u3').value.get()
assert 'u1' in values.get_cached() assert 'u1' in values.get_cached()
@ -209,7 +209,7 @@ def test_reset_cache():
od1 = make_description() od1 = make_description()
cfg = Config(od1) cfg = Config(od1)
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._impl_properties_cache
cfg.option('u1').value.get() cfg.option('u1').value.get()
assert 'u1' in values.get_cached() assert 'u1' in values.get_cached()
assert 'u1' in settings.get_cached() assert 'u1' in settings.get_cached()
@ -234,7 +234,7 @@ def test_cache_not_cache():
od1 = make_description() od1 = make_description()
cfg = Config(od1) cfg = Config(od1)
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._impl_properties_cache
cfg.property.remove('cache') cfg.property.remove('cache')
cfg.option('u1').value.get() cfg.option('u1').value.get()
assert 'u1' not in values.get_cached() assert 'u1' not in values.get_cached()
@ -250,7 +250,7 @@ def test_cache_leadership():
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
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._impl_properties_cache
assert values.get_cached() == {} assert values.get_cached() == {}
#assert settings.get_cached() == {} #assert settings.get_cached() == {}
# #
@ -311,7 +311,7 @@ def test_cache_callback():
cfg.property.read_write() cfg.property.read_write()
cfg.value.dict() cfg.value.dict()
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._impl_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)},
@ -386,11 +386,11 @@ def test_cache_leader_and_followers():
#None because no value #None because no value
idx_val2 = None idx_val2 = None
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._impl_properties_cache
compare(settings.get_cached(), {None: {None: (global_props, None)}, compare(settings.get_cached(), {None: {None: (global_props, None)},
'val1': {None: (val1_props, None)}, 'val1': {None: (val1_props, None)},
'val1.val1': {None: (val1_val1_props, None)}, 'val1.val1': {None: (val1_val1_props, None)},
}) 'val1.val2': {idx_val2: (val1_val2_props, None)}})
# len is 0 so don't get any value # len is 0 so don't get any value
compare(values.get_cached(), {'val1.val1': {None: ([], None)}}) compare(values.get_cached(), {'val1.val1': {None: ([], None)}})
# #
@ -437,11 +437,11 @@ def test_cache_leader_callback():
val1_val1_props = frozenset(val1_val1_props) val1_val1_props = frozenset(val1_val1_props)
val1_val2_props = frozenset(val1_val2_props) val1_val2_props = frozenset(val1_val2_props)
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._impl_properties_cache
compare(settings.get_cached(), {None: {None: (global_props, None)}, compare(settings.get_cached(), {None: {None: (global_props, None)},
'val1': {None: (val1_props, None)}, 'val1': {None: (val1_props, None)},
'val1.val1': {None: (val1_val1_props, None)}, 'val1.val1': {None: (val1_val1_props, None)},
}) 'val1.val2': {None: (val1_val2_props, None)}})
compare(values.get_cached(), {'val1.val1': {None: ([], None)}}) compare(values.get_cached(), {'val1.val1': {None: ([], None)}})
cfg.option('val1.val1').value.set([undefined]) cfg.option('val1.val1').value.set([undefined])
compare(settings.get_cached(), {None: {None: (set(global_props), None)}, compare(settings.get_cached(), {None: {None: (set(global_props), None)},
@ -465,7 +465,7 @@ def test_cache_requires():
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
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._impl_properties_cache
assert values.get_cached() == {} assert values.get_cached() == {}
assert cfg.option('ip_address_service').value.get() == None assert cfg.option('ip_address_service').value.get() == None
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)}, compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},
@ -518,7 +518,7 @@ def test_cache_global_properties():
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
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._impl_properties_cache
assert values.get_cached() == {} assert values.get_cached() == {}
assert cfg.option('ip_address_service').value.get() == None assert cfg.option('ip_address_service').value.get() == None
compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)}, compare(settings.get_cached(), {None: {None: (set(['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']), None)},

View file

@ -10,6 +10,7 @@ from .config import config_type, get_config, value_list, global_owner
import pytest import pytest
from tiramisu import Config from tiramisu import Config
from tiramisu.config import SubConfig
from tiramisu.i18n import _ from tiramisu.i18n import _
from tiramisu import Config, IntOption, FloatOption, ChoiceOption, \ from tiramisu import Config, IntOption, FloatOption, ChoiceOption, \
BoolOption, StrOption, SymLinkOption, OptionDescription, undefined BoolOption, StrOption, SymLinkOption, OptionDescription, undefined

View file

@ -82,6 +82,8 @@ def test_make_dict(config_type):
cfg.option('s1.a').value.set(True) cfg.option('s1.a').value.set(True)
d = cfg.value.dict() d = cfg.value.dict()
assert d == {"s1.a": True, "int": 43} assert d == {"s1.a": True, "int": 43}
d2 = cfg.value.dict(flatten=True)
assert d2 == {'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 cfg.forcepermissive.value.dict() == {"s1.a": True, "s1.b": False, "int": 43}
# assert not list_sessions() # assert not list_sessions()
@ -98,7 +100,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 cfg.option('s1').value.dict() == {'a': False}
def test_make_dict_not_value(config_type): def test_make_dict_not_value(config_type):
@ -167,7 +169,13 @@ def test_make_dict_fullpath(config_type):
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 cfg.value.dict() == {"opt.s1.a": False, "opt.int": 42, "introot": 42}
assert cfg.option('opt').value.dict() == {"opt.s1.a": False, "opt.int": 42} if config_type == 'tiramisu':
# FIXME
assert cfg.option('opt').value.dict() == {"s1.a": False, "int": 42}
assert cfg.value.dict(fullpath=True) == {"opt.s1.a": False, "opt.int": 42, "introot": 42}
if config_type == 'tiramisu':
# FIXME
assert cfg.option('opt').value.dict(fullpath=True) == {"opt.s1.a": False, "opt.int": 42}
# assert not list_sessions() # assert not list_sessions()

View file

@ -17,7 +17,7 @@ def test_deref_value():
b = BoolOption('b', '') b = BoolOption('b', '')
o = OptionDescription('od', '', [b]) o = OptionDescription('od', '', [b])
cfg = Config(o) cfg = Config(o)
w = weakref.ref(cfg._config_bag.context.get_values()) w = weakref.ref(cfg._config_bag.context.cfgimpl_get_values())
del cfg del cfg
assert w() is None assert w() is None
@ -26,7 +26,7 @@ def test_deref_setting():
b = BoolOption('b', '') b = BoolOption('b', '')
o = OptionDescription('od', '', [b]) o = OptionDescription('od', '', [b])
cfg = Config(o) cfg = Config(o)
w = weakref.ref(cfg._config_bag.context.get_settings()) w = weakref.ref(cfg._config_bag.context.cfgimpl_get_settings())
del cfg del cfg
assert w() is None assert w() is None

View file

@ -406,6 +406,7 @@ def test_mandatory_dyndescription():
cfg.property.read_only() cfg.property.read_only()
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.option('od.dodval1.stval1').value.get() cfg.option('od.dodval1.stval1').value.get()
assert list(cfg.value.mandatory()) == ['od.dodval1.stval1', 'od.dodval2.stval2']
# assert not list_sessions() # assert not list_sessions()
@ -581,6 +582,7 @@ def test_mandatory_dyndescription_context():
cfg.property.read_only() cfg.property.read_only()
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.option('od.dodval1.stval1').value.get() cfg.option('od.dodval1.stval1').value.get()
assert list(cfg.value.mandatory()) == ['od.dodval1.stval1', 'od.dodval2.stval2']
# assert not list_sessions() # assert not list_sessions()
@ -950,6 +952,7 @@ def test_makedict_dyndescription_context():
cfg = Config(od2) cfg = Config(od2)
cfg.option('od.dodval1.stval1').value.set('yes') cfg.option('od.dodval1.stval1').value.set('yes')
assert cfg.value.dict() == {'od.val1': ['val1', 'val2'], 'od.dodval1.stval1': 'yes', 'od.dodval2.stval2': None} assert cfg.value.dict() == {'od.val1': ['val1', 'val2'], 'od.dodval1.stval1': 'yes', 'od.dodval2.stval2': None}
assert cfg.value.dict(flatten=True) == {'val1': ['val1', 'val2'], 'stval1': 'yes', 'stval2': None}
# assert not list_sessions() # assert not list_sessions()
@ -1099,14 +1102,14 @@ def test_leadership_dyndescription():
cfg = Config(od1) cfg = Config(od1)
owner = cfg.owner.get() owner = cfg.owner.get()
# #
assert cfg.value.dict() == {'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []} assert cfg.value.dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []}
assert cfg.option('od.stval1.st1val1.st1val1').value.get() == [] assert cfg.option('od.stval1.st1val1.st1val1').value.get() == []
assert cfg.option('od.stval2.st1val2.st1val2').value.get() == [] assert cfg.option('od.stval2.st1val2.st1val2').value.get() == []
assert cfg.option('od.stval1.st1val1.st1val1').owner.isdefault() assert cfg.option('od.stval1.st1val1.st1val1').owner.isdefault()
assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault() assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault()
# #
cfg.option('od.stval1.st1val1.st1val1').value.set(['yes']) cfg.option('od.stval1.st1val1.st1val1').value.set(['yes'])
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'yes', 'od.stval1.st1val1.st2val1': None}], 'od.stval2.st1val2.st1val2': []} assert cfg.value.dict() == {'od.stval1.st1val1.st2val1': [None], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes']}
assert cfg.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] assert cfg.option('od.stval1.st1val1.st1val1').value.get() == ['yes']
assert cfg.option('od.stval1.st1val1.st2val1', 0).value.get() == None assert cfg.option('od.stval1.st1val1.st2val1', 0).value.get() == None
assert cfg.option('od.stval2.st1val2.st1val2').value.get() == [] assert cfg.option('od.stval2.st1val2.st1val2').value.get() == []
@ -1164,20 +1167,20 @@ def test_leadership_dyndescription_force_store_value_leader():
assert cfg.option('od.stval1.st1val1.st2val1', 1).owner.isdefault() == True assert cfg.option('od.stval1.st1val1.st2val1', 1).owner.isdefault() == True
assert cfg.option('od.stval2.st1val2.st2val2', 0).owner.isdefault() == True assert cfg.option('od.stval2.st1val2.st2val2', 0).owner.isdefault() == True
assert cfg.option('od.stval2.st1val2.st2val2', 1).owner.isdefault() == True assert cfg.option('od.stval2.st1val2.st2val2', 1).owner.isdefault() == True
assert cfg.value.dict() == {'od.val1': ['val1', 'val2'], 'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'val1', 'od.stval1.st1val1.st2val1': 'val1'}, {'od.stval1.st1val1.st1val1': 'val2', 'od.stval1.st1val1.st2val1': 'val2'}], 'od.stval2.st1val2.st1val2': [{'od.stval2.st1val2.st1val2': 'val1', 'od.stval2.st1val2.st2val2': 'val1'}, {'od.stval2.st1val2.st1val2': 'val2', 'od.stval2.st1val2.st2val2': 'val2'}]} assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': ['val1', 'val2'], 'od.stval1.st1val1.st2val1': ['val1', 'val2'], 'od.stval2.st1val2.st1val2': ['val1', 'val2'], 'od.stval2.st1val2.st2val2': ['val1', 'val2'], 'od.val1': ['val1', 'val2']}
# #
cfg.option('od.val1').value.set(['val1', 'val2', 'val3']) cfg.option('od.val1').value.set(['val1', 'val2', 'val3'])
assert cfg.option('od.stval3.st1val3.st1val3').owner.isdefault() == False assert cfg.option('od.stval3.st1val3.st1val3').owner.isdefault() == False
assert cfg.option('od.stval3.st1val3.st2val3', 0).owner.isdefault() == True assert cfg.option('od.stval3.st1val3.st2val3', 0).owner.isdefault() == True
assert cfg.option('od.stval3.st1val3.st2val3', 1).owner.isdefault() == True assert cfg.option('od.stval3.st1val3.st2val3', 1).owner.isdefault() == True
assert cfg.value.dict() == {'od.val1': ['val1', 'val2', 'val3'], 'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'val1', 'od.stval1.st1val1.st2val1': 'val1'}, {'od.stval1.st1val1.st1val1': 'val2', 'od.stval1.st1val1.st2val1': 'val2'}], 'od.stval2.st1val2.st1val2': [{'od.stval2.st1val2.st1val2': 'val1', 'od.stval2.st1val2.st2val2': 'val1'}, {'od.stval2.st1val2.st1val2': 'val2', 'od.stval2.st1val2.st2val2': 'val2'}], 'od.stval3.st1val3.st1val3': [{'od.stval3.st1val3.st1val3': 'val1', 'od.stval3.st1val3.st2val3': 'val1'}, {'od.stval3.st1val3.st1val3': 'val2', 'od.stval3.st1val3.st2val3': 'val2'}]} assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': ['val1', 'val2'], 'od.stval1.st1val1.st2val1': ['val1', 'val2'], 'od.stval2.st1val2.st1val2': ['val1', 'val2'], 'od.stval2.st1val2.st2val2': ['val1', 'val2'], 'od.stval3.st1val3.st1val3': ['val1', 'val2'], 'od.stval3.st1val3.st2val3': ['val1', 'val2'], 'od.val1': ['val1', 'val2', 'val3']}
# #
cfg.option('od.stval3.st1val3.st1val3').value.set(['val1', 'val2', 'val3']) cfg.option('od.stval3.st1val3.st1val3').value.set(['val1', 'val2', 'val3'])
assert cfg.option('od.stval3.st1val3.st1val3').owner.isdefault() == False assert cfg.option('od.stval3.st1val3.st1val3').owner.isdefault() == False
assert cfg.option('od.stval3.st1val3.st2val3', 0).owner.isdefault() == True assert cfg.option('od.stval3.st1val3.st2val3', 0).owner.isdefault() == True
assert cfg.option('od.stval3.st1val3.st2val3', 1).owner.isdefault() == True assert cfg.option('od.stval3.st1val3.st2val3', 1).owner.isdefault() == True
assert cfg.option('od.stval3.st1val3.st2val3', 2).owner.isdefault() == True assert cfg.option('od.stval3.st1val3.st2val3', 2).owner.isdefault() == True
assert cfg.value.dict() == {'od.val1': ['val1', 'val2', 'val3'], 'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'val1', 'od.stval1.st1val1.st2val1': 'val1'}, {'od.stval1.st1val1.st1val1': 'val2', 'od.stval1.st1val1.st2val1': 'val2'}], 'od.stval2.st1val2.st1val2': [{'od.stval2.st1val2.st1val2': 'val1', 'od.stval2.st1val2.st2val2': 'val1'}, {'od.stval2.st1val2.st1val2': 'val2', 'od.stval2.st1val2.st2val2': 'val2'}], 'od.stval3.st1val3.st1val3': [{'od.stval3.st1val3.st1val3': 'val1', 'od.stval3.st1val3.st2val3': 'val1'}, {'od.stval3.st1val3.st1val3': 'val2', 'od.stval3.st1val3.st2val3': 'val2'}, {'od.stval3.st1val3.st1val3': 'val3', 'od.stval3.st1val3.st2val3': 'val3'}]} assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': ['val1', 'val2'], 'od.stval1.st1val1.st2val1': ['val1', 'val2'], 'od.stval2.st1val2.st1val2': ['val1', 'val2'], 'od.stval2.st1val2.st2val2': ['val1', 'val2'], 'od.stval3.st1val3.st1val3': ['val1', 'val2', 'val3'], 'od.stval3.st1val3.st2val3': ['val1', 'val2', 'val3'], 'od.val1': ['val1', 'val2', 'val3']}
# assert not list_sessions() # assert not list_sessions()
@ -1197,20 +1200,20 @@ def test_leadership_dyndescription_force_store_value():
assert cfg.option('od.stval1.st1val1.st2val1', 1).owner.isdefault() == False assert cfg.option('od.stval1.st1val1.st2val1', 1).owner.isdefault() == False
assert cfg.option('od.stval2.st1val2.st2val2', 0).owner.isdefault() == False assert cfg.option('od.stval2.st1val2.st2val2', 0).owner.isdefault() == False
assert cfg.option('od.stval2.st1val2.st2val2', 1).owner.isdefault() == False assert cfg.option('od.stval2.st1val2.st2val2', 1).owner.isdefault() == False
assert cfg.value.dict() == {'od.val1': ['val1', 'val2'], 'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'val1', 'od.stval1.st1val1.st2val1': 'val1'}, {'od.stval1.st1val1.st1val1': 'val2', 'od.stval1.st1val1.st2val1': 'val2'}], 'od.stval2.st1val2.st1val2': [{'od.stval2.st1val2.st1val2': 'val1', 'od.stval2.st1val2.st2val2': 'val1'}, {'od.stval2.st1val2.st1val2': 'val2', 'od.stval2.st1val2.st2val2': 'val2'}]} assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': ['val1', 'val2'], 'od.stval1.st1val1.st2val1': ['val1', 'val2'], 'od.stval2.st1val2.st1val2': ['val1', 'val2'], 'od.stval2.st1val2.st2val2': ['val1', 'val2'], 'od.val1': ['val1', 'val2']}
# #
cfg.option('od.val1').value.set(['val1', 'val2', 'val3']) cfg.option('od.val1').value.set(['val1', 'val2', 'val3'])
assert cfg.option('od.stval3.st1val3.st1val3').owner.isdefault() == True assert cfg.option('od.stval3.st1val3.st1val3').owner.isdefault() == True
assert cfg.option('od.stval3.st1val3.st2val3', 0).owner.isdefault() == False assert cfg.option('od.stval3.st1val3.st2val3', 0).owner.isdefault() == False
assert cfg.option('od.stval3.st1val3.st2val3', 1).owner.isdefault() == False assert cfg.option('od.stval3.st1val3.st2val3', 1).owner.isdefault() == False
assert cfg.value.dict() == {'od.val1': ['val1', 'val2', 'val3'], 'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'val1', 'od.stval1.st1val1.st2val1': 'val1'}, {'od.stval1.st1val1.st1val1': 'val2', 'od.stval1.st1val1.st2val1': 'val2'}], 'od.stval2.st1val2.st1val2': [{'od.stval2.st1val2.st1val2': 'val1', 'od.stval2.st1val2.st2val2': 'val1'}, {'od.stval2.st1val2.st1val2': 'val2', 'od.stval2.st1val2.st2val2': 'val2'}], 'od.stval3.st1val3.st1val3': [{'od.stval3.st1val3.st1val3': 'val1', 'od.stval3.st1val3.st2val3': 'val1'}, {'od.stval3.st1val3.st1val3': 'val2', 'od.stval3.st1val3.st2val3': 'val2'}]} assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': ['val1', 'val2'], 'od.stval1.st1val1.st2val1': ['val1', 'val2'], 'od.stval2.st1val2.st1val2': ['val1', 'val2'], 'od.stval2.st1val2.st2val2': ['val1', 'val2'], 'od.stval3.st1val3.st1val3': ['val1', 'val2'], 'od.stval3.st1val3.st2val3': ['val1', 'val2'], 'od.val1': ['val1', 'val2', 'val3']}
# #
cfg.option('od.stval3.st1val3.st1val3').value.set(['val1', 'val2', 'val3']) cfg.option('od.stval3.st1val3.st1val3').value.set(['val1', 'val2', 'val3'])
assert cfg.option('od.stval3.st1val3.st1val3').owner.isdefault() == False assert cfg.option('od.stval3.st1val3.st1val3').owner.isdefault() == False
assert cfg.option('od.stval3.st1val3.st2val3', 0).owner.isdefault() == False assert cfg.option('od.stval3.st1val3.st2val3', 0).owner.isdefault() == False
assert cfg.option('od.stval3.st1val3.st2val3', 1).owner.isdefault() == False assert cfg.option('od.stval3.st1val3.st2val3', 1).owner.isdefault() == False
assert cfg.option('od.stval3.st1val3.st2val3', 2).owner.isdefault() == False assert cfg.option('od.stval3.st1val3.st2val3', 2).owner.isdefault() == False
assert cfg.value.dict() == {'od.val1': ['val1', 'val2', 'val3'], 'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'val1', 'od.stval1.st1val1.st2val1': 'val1'}, {'od.stval1.st1val1.st1val1': 'val2', 'od.stval1.st1val1.st2val1': 'val2'}], 'od.stval2.st1val2.st1val2': [{'od.stval2.st1val2.st1val2': 'val1', 'od.stval2.st1val2.st2val2': 'val1'}, {'od.stval2.st1val2.st1val2': 'val2', 'od.stval2.st1val2.st2val2': 'val2'}], 'od.stval3.st1val3.st1val3': [{'od.stval3.st1val3.st1val3': 'val1', 'od.stval3.st1val3.st2val3': 'val1'}, {'od.stval3.st1val3.st1val3': 'val2', 'od.stval3.st1val3.st2val3': 'val2'}, {'od.stval3.st1val3.st1val3': 'val3', 'od.stval3.st1val3.st2val3': 'val3'}]} assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': ['val1', 'val2'], 'od.stval1.st1val1.st2val1': ['val1', 'val2'], 'od.stval2.st1val2.st1val2': ['val1', 'val2'], 'od.stval2.st1val2.st2val2': ['val1', 'val2'], 'od.stval3.st1val3.st1val3': ['val1', 'val2', 'val3'], 'od.stval3.st1val3.st2val3': ['val1', 'val2', 'val3'], 'od.val1': ['val1', 'val2', 'val3']}
# assert not list_sessions() # assert not list_sessions()
@ -1250,14 +1253,14 @@ def test_leadership_dyndescription_param():
od1 = OptionDescription('od', '', [od]) od1 = OptionDescription('od', '', [od])
cfg = Config(od1) cfg = Config(od1)
owner = cfg.owner.get() owner = cfg.owner.get()
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [], 'od.stval2.st1val2.st1val2': [], 'od.odval1.val1': ['val1', 'val2']} assert cfg.value.dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': [], 'od.odval1.val1': ['val1', 'val2']}
assert cfg.option('od.stval1.st1val1.st1val1').value.get() == [] assert cfg.option('od.stval1.st1val1.st1val1').value.get() == []
assert cfg.option('od.stval2.st1val2.st1val2').value.get() == [] assert cfg.option('od.stval2.st1val2.st1val2').value.get() == []
assert cfg.option('od.stval1.st1val1.st1val1').owner.get() == owners.default assert cfg.option('od.stval1.st1val1.st1val1').owner.get() == owners.default
assert cfg.option('od.stval2.st1val2.st1val2').owner.get() == owners.default assert cfg.option('od.stval2.st1val2.st1val2').owner.get() == owners.default
# #
cfg.option('od.stval1.st1val1.st1val1').value.set(['yes']) cfg.option('od.stval1.st1val1.st1val1').value.set(['yes'])
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'yes', 'od.stval1.st1val1.st2val1': None}], 'od.stval2.st1val2.st1val2': [], 'od.odval1.val1': ['val1', 'val2']} assert cfg.value.dict() == {'od.stval1.st1val1.st2val1': [None], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes'], 'od.odval1.val1': ['val1', 'val2']}
assert cfg.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] assert cfg.option('od.stval1.st1val1.st1val1').value.get() == ['yes']
assert cfg.option('od.stval1.st1val1.st2val1', 0).value.get() == None assert cfg.option('od.stval1.st1val1.st2val1', 0).value.get() == None
assert cfg.option('od.stval2.st1val2.st1val2').value.get() == [] assert cfg.option('od.stval2.st1val2.st1val2').value.get() == []
@ -1330,14 +1333,14 @@ def _test_leadership(cfg):
cfg.option('od.val1.val1').value.set(['val1', 'val2']) cfg.option('od.val1.val1').value.set(['val1', 'val2'])
cfg.option('od.val1.val2', 0).value.set('val1') cfg.option('od.val1.val2', 0).value.set('val1')
cfg.option('od.val1.val2', 1).value.set('val2') cfg.option('od.val1.val2', 1).value.set('val2')
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [], 'od.stval2.st1val2.st1val2': [], 'od.val1.val1': [{'od.val1.val1': 'val1', 'od.val1.val2': 'val1'}, {'od.val1.val1': 'val2', 'od.val1.val2': 'val2'}]} assert cfg.value.dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': [], 'od.val1.val1': ['val1', 'val2'], 'od.val1.val2': ['val1', 'val2']}
assert cfg.option('od.stval1.st1val1.st1val1').value.get() == [] assert cfg.option('od.stval1.st1val1.st1val1').value.get() == []
assert cfg.option('od.stval2.st1val2.st1val2').value.get() == [] assert cfg.option('od.stval2.st1val2.st1val2').value.get() == []
assert cfg.option('od.stval1.st1val1.st1val1').owner.get() == owners.default assert cfg.option('od.stval1.st1val1.st1val1').owner.get() == owners.default
assert cfg.option('od.stval2.st1val2.st1val2').owner.get() == owners.default assert cfg.option('od.stval2.st1val2.st1val2').owner.get() == owners.default
# #
cfg.option('od.stval1.st1val1.st1val1').value.set(['yes']) cfg.option('od.stval1.st1val1.st1val1').value.set(['yes'])
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'yes', 'od.stval1.st1val1.st2val1': None}], 'od.stval2.st1val2.st1val2': [], 'od.val1.val1': [{'od.val1.val1': 'val1', 'od.val1.val2': 'val1'}, {'od.val1.val1': 'val2', 'od.val1.val2': 'val2'}]} assert cfg.value.dict() == {'od.stval1.st1val1.st2val1': [None], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes'], 'od.val1.val1': ['val1', 'val2'], 'od.val1.val2': ['val1', 'val2']}
assert cfg.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] assert cfg.option('od.stval1.st1val1.st1val1').value.get() == ['yes']
assert cfg.option('od.stval1.st1val1.st2val1', 0).value.get() == None assert cfg.option('od.stval1.st1val1.st2val1', 0).value.get() == None
assert cfg.option('od.stval2.st1val2.st1val2').value.get() == [] assert cfg.option('od.stval2.st1val2.st1val2').value.get() == []
@ -1501,14 +1504,14 @@ def test_leadership_callback_dyndescription():
od2 = OptionDescription('od', '', [od1]) od2 = OptionDescription('od', '', [od1])
cfg = Config(od2) cfg = Config(od2)
owner = cfg.owner.get() owner = cfg.owner.get()
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [], 'od.stval2.st1val2.st1val2': []} assert cfg.value.dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []}
assert cfg.option('od.stval1.st1val1.st1val1').value.get() ==[] assert cfg.option('od.stval1.st1val1.st1val1').value.get() ==[]
assert cfg.option('od.stval2.st1val2.st1val2').value.get() == [] assert cfg.option('od.stval2.st1val2.st1val2').value.get() == []
assert cfg.option('od.stval1.st1val1.st1val1').owner.isdefault() assert cfg.option('od.stval1.st1val1.st1val1').owner.isdefault()
assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault() assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault()
# #
cfg.option('od.stval1.st1val1.st1val1').value.set(['yes']) cfg.option('od.stval1.st1val1.st1val1').value.set(['yes'])
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'yes', 'od.stval1.st1val1.st2val1': 'yes'}], 'od.stval2.st1val2.st1val2': []} assert cfg.value.dict() == {'od.stval1.st1val1.st2val1': ['yes'], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes']}
assert cfg.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] assert cfg.option('od.stval1.st1val1.st1val1').value.get() == ['yes']
assert cfg.option('od.stval1.st1val1.st2val1', 0).value.get() == 'yes' assert cfg.option('od.stval1.st1val1.st2val1', 0).value.get() == 'yes'
assert cfg.option('od.stval2.st1val2.st1val2').value.get() == [] assert cfg.option('od.stval2.st1val2.st1val2').value.get() == []
@ -1596,21 +1599,36 @@ def test_leadership_callback_samegroup_dyndescription():
od2 = OptionDescription('od', '', [od1]) od2 = OptionDescription('od', '', [od1])
cfg = Config(od2) cfg = Config(od2)
owner = cfg.owner.get() owner = cfg.owner.get()
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [], 'od.stval2.st1val2.st1val2': []} assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [],
'od.stval1.st1val1.st2val1': [],
'od.stval1.st1val1.st3val1': [],
'od.stval2.st1val2.st1val2': [],
'od.stval2.st1val2.st2val2': [],
'od.stval2.st1val2.st3val2': []}
assert cfg.option('od.stval1.st1val1.st1val1').value.get() == [] assert cfg.option('od.stval1.st1val1.st1val1').value.get() == []
assert cfg.option('od.stval2.st1val2.st1val2').value.get() == [] assert cfg.option('od.stval2.st1val2.st1val2').value.get() == []
assert cfg.option('od.stval1.st1val1.st1val1').owner.isdefault() assert cfg.option('od.stval1.st1val1.st1val1').owner.isdefault()
assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault() assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault()
# #
cfg.option('od.stval1.st1val1.st1val1').value.set(['yes']) cfg.option('od.stval1.st1val1.st1val1').value.set(['yes'])
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'yes', 'od.stval1.st1val1.st2val1': None, 'od.stval1.st1val1.st3val1': None}], 'od.stval2.st1val2.st1val2': []} assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': ['yes'],
'od.stval1.st1val1.st2val1': [None],
'od.stval1.st1val1.st3val1': [None],
'od.stval2.st1val2.st1val2': [],
'od.stval2.st1val2.st2val2': [],
'od.stval2.st1val2.st3val2': []}
assert cfg.option('od.stval1.st1val1.st1val1').owner.get() == owner assert cfg.option('od.stval1.st1val1.st1val1').owner.get() == owner
assert cfg.option('od.stval1.st1val1.st2val1', 0).owner.isdefault() assert cfg.option('od.stval1.st1val1.st2val1', 0).owner.isdefault()
assert cfg.option('od.stval1.st1val1.st3val1', 0).owner.isdefault() assert cfg.option('od.stval1.st1val1.st3val1', 0).owner.isdefault()
assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault() assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault()
# #
cfg.option('od.stval1.st1val1.st2val1', 0).value.set('yes') cfg.option('od.stval1.st1val1.st2val1', 0).value.set('yes')
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'yes', 'od.stval1.st1val1.st2val1': 'yes', 'od.stval1.st1val1.st3val1': 'yes'}], 'od.stval2.st1val2.st1val2': []} assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': ['yes'],
'od.stval1.st1val1.st2val1': ['yes'],
'od.stval1.st1val1.st3val1': ['yes'],
'od.stval2.st1val2.st1val2': [],
'od.stval2.st1val2.st2val2': [],
'od.stval2.st1val2.st3val2': []}
assert cfg.option('od.stval1.st1val1.st1val1').owner.get() == owner assert cfg.option('od.stval1.st1val1.st1val1').owner.get() == owner
assert cfg.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner assert cfg.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner
assert cfg.option('od.stval1.st1val1.st3val1', 0).owner.isdefault() assert cfg.option('od.stval1.st1val1.st3val1', 0).owner.isdefault()
@ -1694,14 +1712,14 @@ def test_leadership_dyndescription_convert():
cfg = Config(od1) cfg = Config(od1)
owner = cfg.owner.get() owner = cfg.owner.get()
# #
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [], 'od.stval2.st1val2.st1val2': []} assert cfg.value.dict() == {'od.stval1.st1val1.st2val1': [], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': []}
assert cfg.option('od.stval1.st1val1.st1val1').value.get() == [] assert cfg.option('od.stval1.st1val1.st1val1').value.get() == []
assert cfg.option('od.stval2.st1val2.st1val2').value.get() == [] assert cfg.option('od.stval2.st1val2.st1val2').value.get() == []
assert cfg.option('od.stval1.st1val1.st1val1').owner.isdefault() assert cfg.option('od.stval1.st1val1.st1val1').owner.isdefault()
assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault() assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault()
# #
cfg.option('od.stval1.st1val1.st1val1').value.set(['yes']) cfg.option('od.stval1.st1val1.st1val1').value.set(['yes'])
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'yes', 'od.stval1.st1val1.st2val1': None}], 'od.stval2.st1val2.st1val2': []} assert cfg.value.dict() == {'od.stval1.st1val1.st2val1': [None], 'od.stval2.st1val2.st2val2': [], 'od.stval2.st1val2.st1val2': [], 'od.stval1.st1val1.st1val1': ['yes']}
assert cfg.option('od.stval1.st1val1.st1val1').value.get() == ['yes'] assert cfg.option('od.stval1.st1val1.st1val1').value.get() == ['yes']
assert cfg.option('od.stval1.st1val1.st2val1', 0).value.get() == None assert cfg.option('od.stval1.st1val1.st2val1', 0).value.get() == None
assert cfg.option('od.stval2.st1val2.st1val2').value.get() == [] assert cfg.option('od.stval2.st1val2.st1val2').value.get() == []
@ -1753,21 +1771,36 @@ def test_leadership_callback_samegroup_dyndescription_convert():
od2 = OptionDescription('od', '', [od1]) od2 = OptionDescription('od', '', [od1])
cfg = Config(od2) cfg = Config(od2)
owner = cfg.owner.get() owner = cfg.owner.get()
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [], 'od.stval2.st1val2.st1val2': []} assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [],
'od.stval1.st1val1.st2val1': [],
'od.stval1.st1val1.st3val1': [],
'od.stval2.st1val2.st1val2': [],
'od.stval2.st1val2.st2val2': [],
'od.stval2.st1val2.st3val2': []}
assert cfg.option('od.stval1.st1val1.st1val1').value.get() == [] assert cfg.option('od.stval1.st1val1.st1val1').value.get() == []
assert cfg.option('od.stval2.st1val2.st1val2').value.get() == [] assert cfg.option('od.stval2.st1val2.st1val2').value.get() == []
assert cfg.option('od.stval1.st1val1.st1val1').owner.isdefault() assert cfg.option('od.stval1.st1val1.st1val1').owner.isdefault()
assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault() assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault()
# #
cfg.option('od.stval1.st1val1.st1val1').value.set(['yes']) cfg.option('od.stval1.st1val1.st1val1').value.set(['yes'])
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'yes', 'od.stval1.st1val1.st2val1': None, 'od.stval1.st1val1.st3val1': None}], 'od.stval2.st1val2.st1val2': []} assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': ['yes'],
'od.stval1.st1val1.st2val1': [None],
'od.stval1.st1val1.st3val1': [None],
'od.stval2.st1val2.st1val2': [],
'od.stval2.st1val2.st2val2': [],
'od.stval2.st1val2.st3val2': []}
assert cfg.option('od.stval1.st1val1.st1val1').owner.get() == owner assert cfg.option('od.stval1.st1val1.st1val1').owner.get() == owner
assert cfg.option('od.stval1.st1val1.st2val1', 0).owner.isdefault() assert cfg.option('od.stval1.st1val1.st2val1', 0).owner.isdefault()
assert cfg.option('od.stval1.st1val1.st3val1', 0).owner.isdefault() assert cfg.option('od.stval1.st1val1.st3val1', 0).owner.isdefault()
assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault() assert cfg.option('od.stval2.st1val2.st1val2').owner.isdefault()
# #
cfg.option('od.stval1.st1val1.st2val1', 0).value.set('yes') cfg.option('od.stval1.st1val1.st2val1', 0).value.set('yes')
assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': [{'od.stval1.st1val1.st1val1': 'yes', 'od.stval1.st1val1.st2val1': 'yes', 'od.stval1.st1val1.st3val1': 'yes'}], 'od.stval2.st1val2.st1val2': []} assert cfg.value.dict() == {'od.stval1.st1val1.st1val1': ['yes'],
'od.stval1.st1val1.st2val1': ['yes'],
'od.stval1.st1val1.st3val1': ['yes'],
'od.stval2.st1val2.st1val2': [],
'od.stval2.st1val2.st2val2': [],
'od.stval2.st1val2.st3val2': []}
assert cfg.option('od.stval1.st1val1.st1val1').owner.get() == owner assert cfg.option('od.stval1.st1val1.st1val1').owner.get() == owner
assert cfg.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner assert cfg.option('od.stval1.st1val1.st2val1', 0).owner.get() == owner
assert cfg.option('od.stval1.st1val1.st3val1', 0).owner.isdefault() assert cfg.option('od.stval1.st1val1.st3val1', 0).owner.isdefault()
@ -1791,8 +1824,8 @@ def test_dyn_with_leader_hidden_in_config():
cfg.option('leaderval1.ip_admin_eth0val1.ip_admin_eth0val1').value.get() cfg.option('leaderval1.ip_admin_eth0val1.ip_admin_eth0val1').value.get()
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 0).value.get() cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 0).value.get()
cfg.value.dict() == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': [{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.1'}], cfg.value.dict(leader_to_list=True) == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': [{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.1'}],
'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': [{'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': '192.168.1.1'}]} 'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': [{'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': '192.168.1.1'}]}
# assert not list_sessions() # assert not list_sessions()
@ -1825,7 +1858,12 @@ def test_dyn_leadership_requires():
assert cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.get() is None assert cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.get() is None
cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.set('255.255.255.255') cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.set('255.255.255.255')
assert cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.get() == '255.255.255.255' assert cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.get() == '255.255.255.255'
ret = cfg.value.dict() assert cfg.value.dict() == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': ['192.168.1.2', '192.168.1.2'],
'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': [None, '255.255.255.255'],
'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': [],
'leaderval2.ip_admin_eth0val2.netmask_admin_eth0val2': []}
ret = cfg.value.dict(leader_to_list=True)
assert ret == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': [{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.2', 'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': None}, assert ret == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': [{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.2', 'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': None},
{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.2', 'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': '255.255.255.255'}], {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.2', 'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': '255.255.255.255'}],
'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': []} 'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': []}
@ -1835,8 +1873,24 @@ def test_dyn_leadership_requires():
assert cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 0).value.get() is None assert cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 0).value.get() is None
with pytest.raises(PropertiesOptionError): with pytest.raises(PropertiesOptionError):
cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.get() cfg.option('leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 1).value.get()
assert cfg.value.dict() == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': [{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.2', 'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': None}, {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.1'}], 'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': []} ret = cfg.value.dict()
assert set(ret.keys()) == set(['leaderval1.ip_admin_eth0val1.ip_admin_eth0val1', 'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1', 'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2', 'leaderval2.ip_admin_eth0val2.netmask_admin_eth0val2'])
assert ret['leaderval1.ip_admin_eth0val1.ip_admin_eth0val1'] == ['192.168.1.2', '192.168.1.1']
assert len(ret['leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1']) == 2
assert ret['leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1'][0] is None
assert isinstance(ret['leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1'][1], PropertiesOptionError)
del ret['leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1'][1]
del ret['leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1'][0]
del ret['leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1']
assert cfg.value.dict(leader_to_list=True) == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': [{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.2',
'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': None},
{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.1'}],
'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': []}
# #
assert cfg.value.dict(leader_to_list=True) == {'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': [{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.2',
'leaderval1.ip_admin_eth0val1.netmask_admin_eth0val1': None},
{'leaderval1.ip_admin_eth0val1.ip_admin_eth0val1': '192.168.1.1'}],
'leaderval2.ip_admin_eth0val2.ip_admin_eth0val2': []}
# assert not list_sessions() # assert not list_sessions()

View file

@ -62,7 +62,17 @@ def test_base_config(config_type):
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} result = {'general.numero_etab': None, 'general.nombre_interfaces': 1,
'general.serveur_ntp': [], 'interface1.ip_admin_eth0.ip_admin_eth0': None,
'general.mode_conteneur_actif': False, 'general.time_zone': 'Paris',
'interface1.ip_admin_eth0.netmask_admin_eth0': None, 'general.nom_machine':
'eoleng', 'general.activer_proxy_client': False}
assert cfg.option('creole').value.dict() == result
result = {'serveur_ntp': [], 'mode_conteneur_actif': False,
'ip_admin_eth0': None, 'time_zone': 'Paris', 'numero_etab': None,
'netmask_admin_eth0': None, 'nom_machine': 'eoleng', 'activer_proxy_client':
False, 'nombre_interfaces': 1}
assert cfg.option('creole').value.dict(flatten=True) == result
if config_type == 'tiramisu-api': if config_type == 'tiramisu-api':
cfg.send() cfg.send()
# assert not list_sessions() # assert not list_sessions()
@ -84,13 +94,11 @@ def test_iter_on_groups():
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.option.name() for res in result] group_names = [res.option.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',
@ -117,7 +125,7 @@ def test_list_recursive():
'netmask_admin_eth0'] 'netmask_admin_eth0']
result = list(cfg.option.list(recursive=True, type='optiondescription')) result = list(cfg.option.list(recursive=True, type='optiondescription'))
group_names = [res.option.name() for res in result] group_names = [res.option.name() for res in result]
assert group_names == ['creole', 'general', 'interface1', 'ip_admin_eth0'] assert group_names == ['general', 'ip_admin_eth0', 'interface1', 'creole']
# assert not list_sessions() # assert not list_sessions()
@ -177,8 +185,12 @@ def test_iter_not_group():
od1 = OptionDescription("name", "descr", []) od1 = OptionDescription("name", "descr", [])
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
with pytest.raises(AssertionError): try:
print(list(cfg.option.list(type='optiondescription', group_type='family'))) list(cfg.option.list(type='optiondescription', group_type='family'))
except AssertionError:
pass
else:
raise Exception('must raise')
# assert not list_sessions() # assert not list_sessions()
@ -245,7 +257,8 @@ 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 cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [], 'ip_admin_eth0.netmask_admin_eth0': []}
assert cfg.value.dict(leader_to_list=True) == {'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
@ -255,7 +268,8 @@ 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 cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['ip1', 'ip2'], 'ip_admin_eth0.netmask_admin_eth0': [None, None]}
assert cfg.value.dict(leader_to_list=True) == {'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()
@ -278,7 +292,8 @@ 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 cfg.value.dict() == {'other.ip_admin_eth0': [], 'other.netmask_admin_eth0': []}
assert cfg.value.dict(leader_to_list=True) == {'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
@ -288,7 +303,8 @@ 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 cfg.value.dict() == {'other.ip_admin_eth0': ['ip1', 'ip2'], 'other.netmask_admin_eth0': [None, None]}
assert cfg.value.dict(leader_to_list=True) == {'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()
@ -328,11 +344,13 @@ def test_groups_with_leader_default_value_2(config_type):
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'netmask1' assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'netmask1'
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.default() == 'netmask1' assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.default() == 'netmask1'
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.default() == 'netmask1' assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.default() == 'netmask1'
assert cfg.option('ip_admin_eth0.netmask_admin_eth0').value.default() == ['netmask1', 'netmask1']
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('netmask2') cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.set('netmask2')
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == 'netmask1' assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == 'netmask1'
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'netmask2' assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == 'netmask2'
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.default() == 'netmask1' assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.default() == 'netmask1'
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.default() == 'netmask1' assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.default() == 'netmask1'
assert cfg.option('ip_admin_eth0.netmask_admin_eth0').value.default() == ['netmask1', 'netmask1']
if config_type == 'tiramisu-api': if config_type == 'tiramisu-api':
cfg.send() cfg.send()
# assert not list_sessions() # assert not list_sessions()
@ -354,6 +372,7 @@ def test_groups_with_leader_hidden_in_config():
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 cfg.value.dict() == {}
assert cfg.value.dict(leader_to_list=True) == {}
# assert not list_sessions() # assert not list_sessions()

View file

@ -5,9 +5,9 @@ do_autopath()
import pytest import pytest
from tiramisu import Config from tiramisu import Config
from tiramisu import IntOption, StrOption, OptionDescription, DynOptionDescription, \ from tiramisu import IntOption, StrOption, OptionDescription, \
SymLinkOption, Leadership, undefined, Calculation, Params, \ SymLinkOption, Leadership, undefined, Calculation, Params, \
ParamOption, ParamValue, ParamIndex, calc_value ParamOption, ParamValue, calc_value
from tiramisu.error import PropertiesOptionError, ConfigError from tiramisu.error import PropertiesOptionError, ConfigError
from tiramisu.setting import groups from tiramisu.setting import groups
@ -36,14 +36,14 @@ def return_value(value):
def make_description2(): def make_description2():
stroption = StrOption('str', 'str', default="abc", stroption = StrOption('str', 'Test string option', default="abc",
properties=('mandatory', )) properties=('mandatory', ))
stroption1 = StrOption('str1', 'str1', stroption1 = StrOption('str1', 'Test string option',
properties=('mandatory', )) properties=('mandatory', ))
stroption2 = SymLinkOption('unicode2', stroption1) stroption2 = SymLinkOption('unicode2', stroption1)
stroption3 = StrOption('str3', 'str3', multi=True, stroption3 = StrOption('str3', 'Test string option', multi=True,
properties=('mandatory', )) properties=('mandatory', ))
unicode1 = StrOption('unicode1', 'unicode1', Calculation(return_value, Params(ParamOption(stroption))), properties=('mandatory',)) unicode1 = StrOption('unicode1', 'Test string option', Calculation(return_value, Params(ParamOption(stroption))), properties=('mandatory',))
descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3, unicode1]) descr = OptionDescription('tiram', '', [stroption, stroption1, stroption2, stroption3, unicode1])
return descr return descr
@ -319,18 +319,6 @@ def test_mandatory_unicode():
# assert not list_sessions() # assert not list_sessions()
def compare(ret, expected):
assert(len(ret) == len(expected))
for index, opt in enumerate(ret):
exp = expected[index]
if isinstance(exp, list):
assert opt.option.path() == exp[0]
assert opt.option.index() == exp[1]
else:
assert opt.option.path() == exp
assert opt.option.index() == None
def test_mandatory_warnings_ro(): def test_mandatory_warnings_ro():
od1 = make_description() od1 = make_description()
cfg = Config(od1) cfg = Config(od1)
@ -342,11 +330,11 @@ def test_mandatory_warnings_ro():
except PropertiesOptionError as err: except PropertiesOptionError as err:
prop = err.proptype prop = err.proptype
assert 'mandatory' in prop assert 'mandatory' in prop
compare(cfg.value.mandatory(), ['str', 'str1', 'unicode2', 'str3']) assert list(cfg.value.mandatory()) == ['str', 'str1', 'unicode2', 'str3']
cfg.property.read_write() cfg.property.read_write()
cfg.option('str').value.set('a') cfg.option('str').value.set('a')
cfg.property.read_only() cfg.property.read_only()
compare(cfg.value.mandatory(), ['str1', 'unicode2', 'str3']) assert list(cfg.value.mandatory()) == ['str1', 'unicode2', 'str3']
# assert not list_sessions() # assert not list_sessions()
@ -356,9 +344,9 @@ def test_mandatory_warnings_rw():
cfg.option('str').value.set('') cfg.option('str').value.set('')
cfg.property.read_write() cfg.property.read_write()
cfg.option('str').value.get() cfg.option('str').value.get()
compare(cfg.value.mandatory(), ['str', 'str1', 'unicode2', 'str3']) assert list(cfg.value.mandatory()) == ['str', 'str1', 'unicode2', 'str3']
cfg.option('str').value.set('a') cfg.option('str').value.set('a')
compare(cfg.value.mandatory(), ['str1', 'unicode2', 'str3']) assert list(cfg.value.mandatory()) == ['str1', 'unicode2', 'str3']
# assert not list_sessions() # assert not list_sessions()
@ -368,9 +356,9 @@ def test_mandatory_warnings_disabled():
cfg.option('str').value.set('') cfg.option('str').value.set('')
cfg.property.read_write() cfg.property.read_write()
cfg.option('str').value.get() cfg.option('str').value.get()
compare(cfg.value.mandatory(), ['str', 'str1', 'unicode2', 'str3']) assert set(cfg.value.mandatory()) == {'str', 'str1', 'unicode2', 'str3'}
cfg.option('str').property.add('disabled') cfg.option('str').property.add('disabled')
compare(cfg.value.mandatory(), ['str1', 'unicode2', 'str3']) assert set(cfg.value.mandatory()) == {'str1', 'unicode2', 'str3'}
# assert not list_sessions() # assert not list_sessions()
@ -381,9 +369,9 @@ def test_mandatory_warnings_hidden():
cfg.property.read_write() cfg.property.read_write()
cfg.permissive.add('hidden') cfg.permissive.add('hidden')
cfg.option('str').value.get() cfg.option('str').value.get()
compare(cfg.value.mandatory(), ['str', 'str1', 'unicode2', 'str3']) assert set(cfg.value.mandatory()) == {'str', 'str1', 'unicode2', 'str3'}
cfg.option('str').property.add('hidden') cfg.option('str').property.add('hidden')
compare(cfg.value.mandatory(), ['str', 'str1', 'unicode2', 'str3']) assert set(cfg.value.mandatory()) == {'str', 'str1', 'unicode2', 'str3'}
# assert not list_sessions() # assert not list_sessions()
@ -393,10 +381,10 @@ def test_mandatory_warnings_frozen():
cfg.option('str').value.set('') cfg.option('str').value.set('')
cfg.property.read_write() cfg.property.read_write()
cfg.option('str').value.get() cfg.option('str').value.get()
compare(cfg.value.mandatory(), ['str', 'str1', 'unicode2', 'str3']) assert set(cfg.value.mandatory()) == {'str', 'str1', 'unicode2', 'str3'}
cfg.option('str').property.add('frozen') cfg.option('str').property.add('frozen')
cfg.property.read_only() cfg.property.read_only()
compare(cfg.value.mandatory(), ['str', 'str1', 'unicode2', 'str3']) assert set(cfg.value.mandatory()) == {'str', 'str1', 'unicode2', 'str3'}
# assert not list_sessions() # assert not list_sessions()
@ -441,7 +429,7 @@ def test_mandatory_warnings_leader():
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0]) interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
od1 = OptionDescription('o', '', [interface1]) od1 = OptionDescription('o', '', [interface1])
cfg = Config(od1) cfg = Config(od1)
compare(cfg.value.mandatory(), ['ip_admin_eth0.ip_admin_eth0']) assert list(cfg.value.mandatory()) == ['ip_admin_eth0.ip_admin_eth0']
# assert not list_sessions() # assert not list_sessions()
@ -504,17 +492,17 @@ def test_mandatory_warnings_leader_empty():
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set([undefined]) cfg.option('ip_admin_eth0.ip_admin_eth0').value.set([undefined])
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [None] assert cfg.option('ip_admin_eth0.ip_admin_eth0').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', 0).value.get() == None
compare(cfg.value.mandatory(), ['ip_admin_eth0.ip_admin_eth0']) assert list(cfg.value.mandatory()) == ['ip_admin_eth0.ip_admin_eth0']
cfg.option('ip_admin_eth0.ip_admin_eth0').value.reset() cfg.option('ip_admin_eth0.ip_admin_eth0').value.reset()
# #
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['']) cfg.option('ip_admin_eth0.ip_admin_eth0').value.set([''])
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [''] assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ['']
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
compare(cfg.value.mandatory(), ['ip_admin_eth0.ip_admin_eth0']) assert list(cfg.value.mandatory()) == ['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'])
compare(cfg.value.mandatory(), []) assert list(cfg.value.mandatory()) == []
# assert not list_sessions() # assert not list_sessions()
@ -527,7 +515,8 @@ 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 cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [],
'ip_admin_eth0.netmask_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'])
@ -548,7 +537,8 @@ 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 cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['ip'],
'ip_admin_eth0.netmask_admin_eth0': ['ip']}
# assert not list_sessions() # assert not list_sessions()
@ -563,9 +553,9 @@ def test_mandatory_warnings_follower():
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == [] assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == []
# #
cfg.property.read_write() cfg.property.read_write()
compare(cfg.value.mandatory(), []) assert list(cfg.value.mandatory()) == []
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['ip']) cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['ip'])
compare(cfg.value.mandatory(), [['ip_admin_eth0.netmask_admin_eth0', 0]]) assert list(cfg.value.mandatory()) == ['ip_admin_eth0.netmask_admin_eth0']
# assert not list_sessions() # assert not list_sessions()
@ -575,10 +565,10 @@ def test_mandatory_warnings_symlink():
cfg.option('str').value.set('') cfg.option('str').value.set('')
cfg.property.read_write() cfg.property.read_write()
cfg.option('str').value.get() cfg.option('str').value.get()
compare(cfg.value.mandatory(), ['str', 'str1', 'str3']) assert list(cfg.value.mandatory()) == ['str', 'str1', 'str3']
cfg.option('str').property.add('frozen') cfg.option('str').property.add('frozen')
cfg.property.read_only() cfg.property.read_only()
compare(cfg.value.mandatory(), ['str', 'str1', 'str3']) assert list(cfg.value.mandatory()) == ['str', 'str1', 'str3']
# assert not list_sessions() # assert not list_sessions()
@ -587,7 +577,7 @@ def test_mandatory_warnings_validate_empty():
cfg = Config(od1) cfg = Config(od1)
cfg.option('str').value.set('') cfg.option('str').value.set('')
cfg.property.read_only() cfg.property.read_only()
compare(cfg.value.mandatory(), ['str', 'str1', 'str3', 'unicode1']) assert list(cfg.value.mandatory()) == ['str', 'str1', 'str3']
# assert not list_sessions() # assert not list_sessions()
@ -609,12 +599,12 @@ def test_mandatory_warnings_requires():
cfg.option('str').value.set('') cfg.option('str').value.set('')
cfg.property.read_write() cfg.property.read_write()
cfg.option('str').value.get() cfg.option('str').value.get()
compare(cfg.value.mandatory(), ['str', 'str1', 'unicode2']) assert list(cfg.value.mandatory()) == ['str', 'str1', 'unicode2']
cfg.property.read_only() cfg.property.read_only()
compare(cfg.value.mandatory(), ['str', 'str1', 'unicode2']) assert list(cfg.value.mandatory()) == ['str', 'str1', 'unicode2']
cfg.property.read_write() cfg.property.read_write()
cfg.option('str').value.set('yes') cfg.option('str').value.set('yes')
compare(cfg.value.mandatory(), ['str1', 'unicode2', 'str3']) assert list(cfg.value.mandatory()) == ['str1', 'unicode2', 'str3']
# assert not list_sessions() # assert not list_sessions()
@ -634,9 +624,9 @@ def test_mandatory_warnings_requires_leadership():
cfg = Config(od1) cfg = Config(od1)
cfg.option('str').value.set('') cfg.option('str').value.set('')
cfg.option('leader.str1').value.set(['str']) cfg.option('leader.str1').value.set(['str'])
compare(cfg.value.mandatory(), ['str']) assert list(cfg.value.mandatory()) == ['str']
cfg.option('str').value.set('yes') cfg.option('str').value.set('yes')
compare(cfg.value.mandatory(), [['leader.str2', 0]]) assert list(cfg.value.mandatory()) == ['leader.str2']
# assert not list_sessions() # assert not list_sessions()
@ -654,21 +644,9 @@ def test_mandatory_warnings_requires_leadership_follower():
od1 = OptionDescription('tiram', '', [leadership]) od1 = OptionDescription('tiram', '', [leadership])
cfg = Config(od1) cfg = Config(od1)
cfg.option('leader.str').value.set(['str']) cfg.option('leader.str').value.set(['str'])
compare(cfg.value.mandatory(), []) assert list(cfg.value.mandatory()) == []
cfg.option('leader.str1', 0).value.set('yes') cfg.option('leader.str1', 0).value.set('yes')
compare(cfg.value.mandatory(), [['leader.str2', 0]]) assert list(cfg.value.mandatory()) == ['leader.str2']
cfg.option('leader.str2', 0).value.set('yes')
compare(cfg.value.mandatory(), [])
#
cfg.option('leader.str').value.set(['str', 'str1'])
compare(cfg.value.mandatory(), [])
cfg.option('leader.str1', 1).value.set('yes')
compare(cfg.value.mandatory(), [['leader.str2', 1]])
cfg.option('leader.str2', 1).value.set('yes')
compare(cfg.value.mandatory(), [])
cfg.option('leader.str2', 0).value.reset()
cfg.option('leader.str2', 1).value.reset()
compare(cfg.value.mandatory(), [['leader.str2', 0], ['leader.str2', 1]])
# assert not list_sessions() # assert not list_sessions()
@ -677,49 +655,7 @@ def test_mandatory_od_disabled():
od1 = OptionDescription('od', '', [descr]) od1 = OptionDescription('od', '', [descr])
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_only() cfg.property.read_only()
compare(cfg.value.mandatory(), ['tiram.str1', 'tiram.unicode2', 'tiram.str3']) assert list(cfg.value.mandatory()) == ['tiram.str1', 'tiram.unicode2', 'tiram.str3']
cfg.option('tiram').property.add('disabled') cfg.option('tiram').property.add('disabled')
compare(cfg.value.mandatory(), []) assert list(cfg.value.mandatory()) == []
# assert not list_sessions()
def return_list(val=None, suffix=None):
if val:
return val
else:
return ['val1', 'val2']
def test_mandatory_dyndescription():
st = StrOption('st', '', properties=('mandatory',))
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list))
od = OptionDescription('od', '', [dod])
od2 = OptionDescription('od', '', [od])
cfg = Config(od2)
cfg.property.read_only()
compare(cfg.value.mandatory(), ['od.dodval1.stval1', 'od.dodval2.stval2'])
def test_mandatory_dyndescription_context():
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
st = StrOption('st', '', properties=('mandatory',))
dod = DynOptionDescription('dod', '', [st], suffixes=Calculation(return_list, Params(ParamOption(val1))))
od = OptionDescription('od', '', [dod, val1])
od2 = OptionDescription('od', '', [od])
cfg = Config(od2)
cfg.property.read_only()
compare(cfg.value.mandatory(), ['od.dodval1.stval1', 'od.dodval2.stval2'])
def test_mandatory_callback_leader_and_followers_leader():
val1 = StrOption('val1', "", multi=True, properties=('mandatory', 'empty'))
val2 = StrOption('val2', "", multi=True, default_multi='val2', properties=('expert',))
val3 = StrOption('val3', "", Calculation(calc_value, Params(ParamOption(val2), {'index': ParamIndex()})), multi=True)
val4 = StrOption('val4', "", Calculation(calc_value, Params(ParamOption(val3), {'index': ParamIndex()})), multi=True)
interface1 = Leadership('val1', '', [val1, val2, val3, val4])
od1 = OptionDescription('rootconfig', '', [interface1])
cfg = Config(od1)
cfg.property.read_write()
# FIXME cfg = get_config(cfg, config_type)
compare(cfg.value.mandatory(), ['val1.val1'])
# assert not list_sessions() # assert not list_sessions()

View file

@ -88,7 +88,7 @@ def test_none():
assert meta.option('od1.i3').value.get() is conf1.option('od1.i3').value.get() is conf2.option('od1.i3').value.get() is None assert meta.option('od1.i3').value.get() is conf1.option('od1.i3').value.get() is conf2.option('od1.i3').value.get() is None
assert meta.option('od1.i3').owner.get() is conf1.option('od1.i3').owner.get() is conf2.option('od1.i3').owner.get() is owners.default assert meta.option('od1.i3').owner.get() is conf1.option('od1.i3').owner.get() is conf2.option('od1.i3').owner.get() is owners.default
# #
assert meta.option('od1.i3').value.set(3) == [] meta.option('od1.i3').value.set(3)
assert meta.option('od1.i3').value.get() == conf1.option('od1.i3').value.get() == conf2.option('od1.i3').value.get() == 3 assert meta.option('od1.i3').value.get() == conf1.option('od1.i3').value.get() == conf2.option('od1.i3').value.get() == 3
assert meta.option('od1.i3').owner.get() is conf1.option('od1.i3').owner.get() is conf2.option('od1.i3').owner.get() is owners.meta1 assert meta.option('od1.i3').owner.get() is conf1.option('od1.i3').owner.get() is conf2.option('od1.i3').owner.get() is owners.meta1
# #
@ -870,7 +870,7 @@ def test_meta_properties_requires_mandatory():
meta.option('ip_gw').value.set('1.1.1.2') meta.option('ip_gw').value.set('1.1.1.2')
conf1.option('eth0_method').value.set('dhcp') conf1.option('eth0_method').value.set('dhcp')
conf1.property.read_only() conf1.property.read_only()
assert conf1.value.dict() == {'ip_gw': '1.1.1.2', 'probes': True, 'eth0_method': 'dhcp', 'ip_address': '1.1.1.1', 'ip_eth0': '1.1.1.1'} assert conf1.value.dict(fullpath=True) == {'probes': True, 'eth0_method': 'dhcp', 'ip_address': '1.1.1.1', 'ip_eth0': '1.1.1.1', 'ip_gw': '1.1.1.2'}
def test_meta_callback(): def test_meta_callback():
@ -909,51 +909,51 @@ def test_meta_callback_follower():
conf1 = Config(maconfig, name='conf1') conf1 = Config(maconfig, name='conf1')
meta = MetaConfig([conf1]) meta = MetaConfig([conf1])
meta.property.read_write() meta.property.read_write()
assert conf1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val', 'val1.val3': 'val'}]} assert conf1.value.dict() == {'val1.val2': ['val'], 'val1.val1': ['val'], 'val1.val3': ['val'], 'val': 'val'}
# #
conf1.option('val').value.set('val1') conf1.option('val').value.set('val1')
assert conf1.value.dict() == {'val': 'val1', 'val1.val1': [{'val1.val1': 'val1', 'val1.val2': 'val1', 'val1.val3': 'val1'}]} assert conf1.value.dict() == {'val1.val2': ['val1'], 'val1.val1': ['val1'], 'val1.val3': ['val1'], 'val': 'val1'}
# #
conf1.option('val').value.reset() conf1.option('val').value.reset()
meta.option('val').value.set('val1') meta.option('val').value.set('val1')
assert conf1.value.dict() == {'val': 'val1', 'val1.val1': [{'val1.val1': 'val1', 'val1.val2': 'val1', 'val1.val3': 'val1'}]} assert conf1.value.dict() == {'val1.val2': ['val1'], 'val1.val1': ['val1'], 'val1.val3': ['val1'], 'val': 'val1'}
# #
meta.option('val').value.reset() meta.option('val').value.reset()
conf1.option('val1.val2', 0).value.set('val2') conf1.option('val1.val2', 0).value.set('val2')
assert conf1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val2', 'val1.val3': 'val'}]} assert conf1.value.dict() == {'val1.val2': ['val2'], 'val1.val1': ['val'], 'val1.val3': ['val'], 'val': 'val'}
# #
conf1.option('val1.val2', 0).value.reset() conf1.option('val1.val2', 0).value.reset()
assert conf1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val', 'val1.val3': 'val'}]} assert conf1.value.dict() == {'val1.val2': ['val'], 'val1.val1': ['val'], 'val1.val3': ['val'], 'val': 'val'}
# #
meta.option('val1.val2', 0).value.set('val2') meta.option('val1.val2', 0).value.set('val2')
assert conf1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val2', 'val1.val3': 'val'}]} assert conf1.value.dict() == {'val1.val2': ['val2'], 'val1.val1': ['val'], 'val1.val3': ['val'], 'val': 'val'}
# #
meta.option('val1.val1').value.set(['val']) meta.option('val1.val1').value.set(['val'])
assert conf1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val2', 'val1.val3': 'val'}]} assert conf1.value.dict() == {'val1.val2': ['val2'], 'val1.val1': ['val'], 'val1.val3': ['val'], 'val': 'val'}
# #
conf1.option('val1.val3', 0).value.set('val6') conf1.option('val1.val3', 0).value.set('val6')
assert conf1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val2', 'val1.val3': 'val6'}]} assert conf1.value.dict() == {'val1.val2': ['val2'], 'val1.val1': ['val'], 'val1.val3': ['val6'], 'val': 'val'}
# #
meta.option('val1.val2', 0).value.reset() meta.option('val1.val2', 0).value.reset()
conf1.option('val1.val3', 0).value.reset() conf1.option('val1.val3', 0).value.reset()
conf1.option('val1.val1').value.set(['val3']) conf1.option('val1.val1').value.set(['val3'])
assert conf1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val3', 'val1.val2': 'val3', 'val1.val3': 'val3'}]} assert conf1.value.dict() == {'val1.val2': ['val3'], 'val1.val1': ['val3'], 'val1.val3': ['val3'], 'val': 'val'}
# #
conf1.option('val1.val1').value.reset() conf1.option('val1.val1').value.reset()
assert conf1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val', 'val1.val3': 'val'}]} assert conf1.value.dict() == {'val1.val2': ['val'], 'val1.val1': ['val'], 'val1.val3': ['val'], 'val': 'val'}
# #
meta.option('val1.val1').value.set(['val3']) meta.option('val1.val1').value.set(['val3'])
assert conf1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val3', 'val1.val2': 'val3', 'val1.val3': 'val3'}]} assert conf1.value.dict() == {'val1.val2': ['val3'], 'val1.val1': ['val3'], 'val1.val3': ['val3'], 'val': 'val'}
# #
conf1.option('val1.val2', 0).value.set('val2') conf1.option('val1.val2', 0).value.set('val2')
assert conf1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val3', 'val1.val2': 'val2', 'val1.val3': 'val3'}]} assert conf1.value.dict() == {'val1.val2': ['val2'], 'val1.val1': ['val3'], 'val1.val3': ['val3'], 'val': 'val'}
# #
meta.option('val1.val1').value.set(['val3', 'rah']) meta.option('val1.val1').value.set(['val3', 'rah'])
assert conf1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val3', 'val1.val2': 'val2', 'val1.val3': 'val3'}, {'val1.val1': 'rah', 'val1.val2': 'rah', 'val1.val3': 'rah'}]} assert conf1.value.dict() == {'val1.val2': ['val2', 'rah'], 'val1.val1': ['val3', 'rah'], 'val1.val3': ['val3', 'rah'], 'val': 'val'}
# #
meta.option('val1.val1').value.pop(1) meta.option('val1.val1').value.pop(1)
meta.option('val1.val1').value.set(['val4']) meta.option('val1.val1').value.set(['val4'])
assert conf1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val4', 'val1.val2': 'val2', 'val1.val3': 'val4'}]} assert conf1.value.dict() == {'val1.val2': ['val2'], 'val1.val1': ['val4'], 'val1.val3': ['val4'], 'val': 'val'}
def test_meta_reset(): def test_meta_reset():

View file

@ -709,51 +709,51 @@ def test_mix_callback_follower():
mix = MixConfig(maconfig, [cfg]) mix = MixConfig(maconfig, [cfg])
mix.property.read_write() mix.property.read_write()
newcfg1 = mix.config('cfg1') newcfg1 = mix.config('cfg1')
assert newcfg1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val', 'val1.val3': 'val'}]} assert newcfg1.value.dict() == {'val1.val2': ['val'], 'val1.val1': ['val'], 'val1.val3': ['val'], 'val': 'val'}
# #
newcfg1.option('val').value.set('val1') newcfg1.option('val').value.set('val1')
assert newcfg1.value.dict() == {'val': 'val1', 'val1.val1': [{'val1.val1': 'val1', 'val1.val2': 'val1', 'val1.val3': 'val1'}]} assert newcfg1.value.dict() == {'val1.val2': ['val1'], 'val1.val1': ['val1'], 'val1.val3': ['val1'], 'val': 'val1'}
# #
newcfg1.option('val').value.reset() newcfg1.option('val').value.reset()
mix.option('val').value.set('val1') mix.option('val').value.set('val1')
assert newcfg1.value.dict() == {'val': 'val1', 'val1.val1': [{'val1.val1': 'val1', 'val1.val2': 'val1', 'val1.val3': 'val1'}]} assert newcfg1.value.dict() == {'val1.val2': ['val1'], 'val1.val1': ['val1'], 'val1.val3': ['val1'], 'val': 'val1'}
# #
mix.option('val').value.reset() mix.option('val').value.reset()
newcfg1.option('val1.val2', 0).value.set('val2') newcfg1.option('val1.val2', 0).value.set('val2')
assert newcfg1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val2', 'val1.val3': 'val'}]} assert newcfg1.value.dict() == {'val1.val2': ['val2'], 'val1.val1': ['val'], 'val1.val3': ['val'], 'val': 'val'}
# #
newcfg1.option('val1.val2', 0).value.reset() newcfg1.option('val1.val2', 0).value.reset()
assert newcfg1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val', 'val1.val3': 'val'}]} assert newcfg1.value.dict() == {'val1.val2': ['val'], 'val1.val1': ['val'], 'val1.val3': ['val'], 'val': 'val'}
# #
mix.option('val1.val2', 0).value.set('val2') mix.option('val1.val2', 0).value.set('val2')
assert newcfg1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val2', 'val1.val3': 'val'}]} assert newcfg1.value.dict() == {'val1.val2': ['val2'], 'val1.val1': ['val'], 'val1.val3': ['val'], 'val': 'val'}
# #
mix.option('val1.val1').value.set(['val']) mix.option('val1.val1').value.set(['val'])
assert newcfg1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val2', 'val1.val3': 'val'}]} assert newcfg1.value.dict() == {'val1.val2': ['val2'], 'val1.val1': ['val'], 'val1.val3': ['val'], 'val': 'val'}
# #
newcfg1.option('val1.val3', 0).value.set('val6') newcfg1.option('val1.val3', 0).value.set('val6')
assert newcfg1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val2', 'val1.val3': 'val6'}]} assert newcfg1.value.dict() == {'val1.val2': ['val2'], 'val1.val1': ['val'], 'val1.val3': ['val6'], 'val': 'val'}
# #
mix.option('val1.val2', 0).value.reset() mix.option('val1.val2', 0).value.reset()
newcfg1.option('val1.val3', 0).value.reset() newcfg1.option('val1.val3', 0).value.reset()
newcfg1.option('val1.val1').value.set(['val3']) newcfg1.option('val1.val1').value.set(['val3'])
assert newcfg1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val3', 'val1.val2': 'val3', 'val1.val3': 'val3'}]} assert newcfg1.value.dict() == {'val1.val2': ['val3'], 'val1.val1': ['val3'], 'val1.val3': ['val3'], 'val': 'val'}
# #
newcfg1.option('val1.val1').value.reset() newcfg1.option('val1.val1').value.reset()
assert newcfg1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val', 'val1.val2': 'val', 'val1.val3': 'val'}]} assert newcfg1.value.dict() == {'val1.val2': ['val'], 'val1.val1': ['val'], 'val1.val3': ['val'], 'val': 'val'}
# #
mix.option('val1.val1').value.set(['val3']) mix.option('val1.val1').value.set(['val3'])
assert newcfg1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val3', 'val1.val2': 'val3', 'val1.val3': 'val3'}]} assert newcfg1.value.dict() == {'val1.val2': ['val3'], 'val1.val1': ['val3'], 'val1.val3': ['val3'], 'val': 'val'}
# #
newcfg1.option('val1.val2', 0).value.set('val2') newcfg1.option('val1.val2', 0).value.set('val2')
assert newcfg1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val3', 'val1.val2': 'val2', 'val1.val3': 'val3'}]} assert newcfg1.value.dict() == {'val1.val2': ['val2'], 'val1.val1': ['val3'], 'val1.val3': ['val3'], 'val': 'val'}
# #
mix.option('val1.val1').value.set(['val3', 'rah']) mix.option('val1.val1').value.set(['val3', 'rah'])
assert newcfg1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val3', 'val1.val2': 'val2', 'val1.val3': 'val3'}, {'val1.val1': 'rah', 'val1.val2': 'rah', 'val1.val3': 'rah'}]} assert newcfg1.value.dict() == {'val1.val2': ['val2', 'rah'], 'val1.val1': ['val3', 'rah'], 'val1.val3': ['val3', 'rah'], 'val': 'val'}
# #
mix.option('val1.val1').value.pop(1) mix.option('val1.val1').value.pop(1)
mix.option('val1.val1').value.set(['val4']) mix.option('val1.val1').value.set(['val4'])
assert newcfg1.value.dict() == {'val': 'val', 'val1.val1': [{'val1.val1': 'val4', 'val1.val2': 'val2', 'val1.val3': 'val4'}]} assert newcfg1.value.dict() == {'val1.val2': ['val2'], 'val1.val1': ['val4'], 'val1.val3': ['val4'], 'val': 'val'}
def test_meta_reset(): def test_meta_reset():

View file

@ -776,6 +776,20 @@ def test_callback_leader_and_followers_leader_mandatory4(config_type):
# assert not list_sessions() # assert not list_sessions()
def test_callback_leader_and_followers_leader3():
val1 = StrOption('val1', "", multi=True, properties=('mandatory', 'empty'))
val2 = StrOption('val2', "", multi=True, default_multi='val2', properties=('expert',))
val3 = StrOption('val3', "", Calculation(calc_value, Params(ParamOption(val2), {'index': ParamIndex()})), multi=True)
val4 = StrOption('val4', "", Calculation(calc_value, Params(ParamOption(val3), {'index': ParamIndex()})), multi=True)
interface1 = Leadership('val1', '', [val1, val2, val3, val4])
od1 = OptionDescription('rootconfig', '', [interface1])
cfg = Config(od1)
cfg.property.read_write()
# FIXME cfg = get_config(cfg, config_type)
assert list(cfg.value.mandatory()) == ['val1.val1']
# assert not list_sessions()
def test_callback_leader_and_followers_leader4(): def test_callback_leader_and_followers_leader4():
val1 = StrOption('val1', "", ['val1'], multi=True, properties=('mandatory',)) val1 = StrOption('val1', "", ['val1'], multi=True, properties=('mandatory',))
val2 = StrOption('val2', "", multi=True, default_multi='val2', properties=('expert', 'mandatory')) val2 = StrOption('val2', "", multi=True, default_multi='val2', properties=('expert', 'mandatory'))
@ -982,7 +996,7 @@ def test_callback_leader_and_followers_leader_callback_disabled():
with pytest.raises(ConfigError): with pytest.raises(ConfigError):
cfg.option('val1.val1').value.get() cfg.option('val1.val1').value.get()
with pytest.raises(ConfigError): with pytest.raises(ConfigError):
cfg.option('val1.val2', 0).value.get() cfg.option('val1.val2').value.get()
cfg.property.remove('disabled') cfg.property.remove('disabled')
cfg.option('val1.val1').value.set([]) cfg.option('val1.val1').value.set([])
cfg.property.add('disabled') cfg.property.add('disabled')

View file

@ -219,7 +219,7 @@ def test_setowner_symlinkoption(config_type):
assert not cfg.option('tiramisu.symdummy').owner.isdefault() assert not cfg.option('tiramisu.symdummy').owner.isdefault()
if config_type == 'tiramisu-api': if config_type == 'tiramisu-api':
cfg.send() cfg.send()
with pytest.raises(APIError): with pytest.raises(ConfigError):
cfg_ori.option('tiramisu.symdummy').owner.set('user') cfg_ori.option('tiramisu.symdummy').owner.set('user')
# assert not list_sessions() # assert not list_sessions()

View file

@ -709,7 +709,7 @@ def test_pprint():
kwargs={'condition': ParamOption(intoption, todict=True), kwargs={'condition': ParamOption(intoption, todict=True),
'expected': ParamValue(1)}), 'expected': ParamValue(1)}),
calc_value_property_help) calc_value_property_help)
descr2 = OptionDescription("options", "options", [val2], properties=(hidden_property,)) descr2 = OptionDescription("options", "", [val2], properties=(hidden_property,))
#descr2 = OptionDescription("options", "", [val2], requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}]) #descr2 = OptionDescription("options", "", [val2], requires=[{'option': intoption, 'expected': 1, 'action': 'hidden'}])
hidden_property = Calculation(calc_value, hidden_property = Calculation(calc_value,
@ -721,7 +721,7 @@ def test_pprint():
val3 = StrOption('val3', "", properties=(hidden_property,)) val3 = StrOption('val3', "", properties=(hidden_property,))
#val3 = StrOption('val3', "", requires=[{'option': stroption, 'expected': '2', 'action': 'hidden', 'inverse': True}]) #val3 = StrOption('val3', "", requires=[{'option': stroption, 'expected': '2', 'action': 'hidden', 'inverse': True}])
od1 = OptionDescription("options", "root option", [s, s2, s3, intoption, stroption, descr2, val3]) od1 = OptionDescription("options", "", [s, s2, s3, intoption, stroption, descr2, val3])
cfg = Config(od1) cfg = Config(od1)
cfg.property.read_write() cfg.property.read_write()
cfg.option('int').value.set(1) cfg.option('int').value.set(1)

View file

@ -1106,21 +1106,41 @@ 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 cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['192.168.1.2', '192.168.1.2'],
{'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': [None, '255.255.255.255']}
assert cfg.value.dict(leader_to_list=True) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2', 'ip_admin_eth0.netmask_admin_eth0': None},
{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2', 'ip_admin_eth0.netmask_admin_eth0': '255.255.255.255'}]}
# #
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.1']) 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', ret = cfg.value.dict()
'ip_admin_eth0.netmask_admin_eth0': None}, assert set(ret.keys()) == set(['ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
{'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]} assert ret['ip_admin_eth0.ip_admin_eth0'] == ['192.168.1.2', '192.168.1.1']
assert len(ret['ip_admin_eth0.netmask_admin_eth0']) == 2
assert ret['ip_admin_eth0.netmask_admin_eth0'][0] is None
assert isinstance(ret['ip_admin_eth0.netmask_admin_eth0'][1], PropertiesOptionError)
del ret['ip_admin_eth0.netmask_admin_eth0'][1]
del ret['ip_admin_eth0.netmask_admin_eth0'][0]
del ret['ip_admin_eth0.netmask_admin_eth0']
assert cfg.value.dict(leader_to_list=True) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2',
'ip_admin_eth0.netmask_admin_eth0': None},
{'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]}
# #
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set('255.255.255.255') 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', ret = cfg.value.dict()
'ip_admin_eth0.netmask_admin_eth0': '255.255.255.255'}, assert set(ret.keys()) == set(['ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
{'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]} assert ret['ip_admin_eth0.ip_admin_eth0'] == ['192.168.1.2', '192.168.1.1']
assert len(ret['ip_admin_eth0.netmask_admin_eth0']) == 2
assert ret['ip_admin_eth0.netmask_admin_eth0'][0] == '255.255.255.255'
assert isinstance(ret['ip_admin_eth0.netmask_admin_eth0'][1], PropertiesOptionError)
del ret['ip_admin_eth0.netmask_admin_eth0'][1]
del ret['ip_admin_eth0.netmask_admin_eth0'][0]
del ret['ip_admin_eth0.netmask_admin_eth0']
assert cfg.value.dict(leader_to_list=True) == {'ip_admin_eth0.ip_admin_eth0': [{'ip_admin_eth0.ip_admin_eth0': '192.168.1.2',
'ip_admin_eth0.netmask_admin_eth0': '255.255.255.255'},
{'ip_admin_eth0.ip_admin_eth0': '192.168.1.1'}]}
# assert not list_sessions() # assert not list_sessions()
@ -1238,7 +1258,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 cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['192.168.1.2', '192.168.1.1'], 'activate': False}
# assert not list_sessions() # assert not list_sessions()
@ -1299,10 +1319,53 @@ 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} dico = cfg.value.dict()
assert dico.keys() == set(['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode2', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicode.unicode6', 'options.unicode.unicode7', 'options.unicodetoto'])
assert dico['options.unicode.unicode'] == ['test', 'trah']
assert dico['options.unicode.unicode1'] == [None, None]
assert dico['options.unicode.unicode2'] == ['test', None]
assert dico['options.unicode.unicode3'][0] is None
assert isinstance(dico['options.unicode.unicode3'][1], PropertiesOptionError)
assert dico['options.unicode.unicode4'][0] is None
assert isinstance(dico['options.unicode.unicode4'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode6'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode6'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode7'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode7'][1], PropertiesOptionError)
assert dico['options.unicodetoto'] is None
del dico['options.unicode.unicode3'][1]
del dico['options.unicode.unicode3']
del dico['options.unicode.unicode4'][1]
del dico['options.unicode.unicode4']
del dico['options.unicode.unicode6'][1]
del dico['options.unicode.unicode6'][0]
del dico['options.unicode.unicode7'][1]
del dico['options.unicode.unicode7'][0]
# #
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'} dico = cfg.value.dict()
assert dico.keys() == set(['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode2', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicode.unicode5', 'options.unicode.unicode6', 'options.unicode.unicode7', 'options.unicodetoto'])
assert dico['options.unicode.unicode'] == ['test', 'trah']
assert dico['options.unicode.unicode1'] == [None, None]
assert dico['options.unicode.unicode2'] == ['test', None]
assert dico['options.unicode.unicode3'][0] is None
assert isinstance(dico['options.unicode.unicode3'][1], PropertiesOptionError)
assert dico['options.unicode.unicode4'][0] is None
assert isinstance(dico['options.unicode.unicode4'][1], PropertiesOptionError)
assert dico['options.unicode.unicode5'] == [None, None]
assert dico['options.unicode.unicode6'][0] is None
assert isinstance(dico['options.unicode.unicode6'][1], PropertiesOptionError)
assert dico['options.unicode.unicode7'][0] is None
assert isinstance(dico['options.unicode.unicode7'][1], PropertiesOptionError)
assert dico['options.unicodetoto'] == 'test'
del dico['options.unicode.unicode3'][1]
del dico['options.unicode.unicode3']
del dico['options.unicode.unicode4'][1]
del dico['options.unicode.unicode4']
del dico['options.unicode.unicode6'][1]
del dico['options.unicode.unicode6'][0]
del dico['options.unicode.unicode7'][1]
del dico['options.unicode.unicode7'][0]
# assert not list_sessions() # assert not list_sessions()
@ -1339,24 +1402,91 @@ 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 cfg.value.dict() == {'options.unicode.unicode': [], 'options.unicode.unicode1': [], 'options.unicode.unicode3': [], 'options.unicode.unicode4': [], 'options.unicodetoto': None}
# #
cfg.option('options.unicodetoto').value.set('test') cfg.option('options.unicodetoto').value.set('test')
assert cfg.value.dict() == {'options.unicode.unicode': [], 'options.unicodetoto': 'test'} assert cfg.value.dict() == {'options.unicode.unicode': [], 'options.unicode.unicode1': [], 'options.unicode.unicode2': [], 'options.unicode.unicode3': [], 'options.unicode.unicode4': [], 'options.unicodetoto': 'test'}
# #
cfg.option('options.unicode.unicode').value.set(['a', 'b', 'c']) 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'} dico = cfg.value.dict()
assert list(dico.keys()) == ['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode2', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicodetoto']
assert dico['options.unicodetoto'] == 'test'
assert dico['options.unicode.unicode'] == ['a', 'b', 'c']
assert dico['options.unicode.unicode1'] == [None, None, None]
assert dico['options.unicode.unicode2'] == [None, None, None]
assert isinstance(dico['options.unicode.unicode3'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode3'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode3'][2], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][2], PropertiesOptionError)
del (dico['options.unicode.unicode3'][2])
del (dico['options.unicode.unicode3'][1])
del (dico['options.unicode.unicode3'][0])
del (dico['options.unicode.unicode4'][2])
del (dico['options.unicode.unicode4'][1])
del (dico['options.unicode.unicode4'][0])
cfg.option('options.unicode.unicode2', 1).value.set('test') cfg.option('options.unicode.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'} dico = cfg.value.dict()
assert list(dico.keys()) == ['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode2', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicodetoto']
assert dico['options.unicodetoto'] == 'test'
assert dico['options.unicode.unicode'] == ['a', 'b', 'c']
assert dico['options.unicode.unicode1'] == [None, None, None]
assert dico['options.unicode.unicode2'] == [None, 'test', None]
assert isinstance(dico['options.unicode.unicode3'][0], PropertiesOptionError)
assert dico['options.unicode.unicode3'][1] == 'test'
assert isinstance(dico['options.unicode.unicode3'][2], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][0], PropertiesOptionError)
assert dico['options.unicode.unicode4'][1] == None
assert isinstance(dico['options.unicode.unicode4'][2], PropertiesOptionError)
del (dico['options.unicode.unicode3'][2])
del (dico['options.unicode.unicode3'][1])
del (dico['options.unicode.unicode3'][0])
del (dico['options.unicode.unicode4'][2])
del (dico['options.unicode.unicode4'][1])
del (dico['options.unicode.unicode4'][0])
# #
cfg.option('options.unicode.unicode2', 1).value.set('rah') 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'} dico = cfg.value.dict()
assert list(dico.keys()) == ['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode2', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicodetoto']
assert dico['options.unicodetoto'] == 'test'
assert dico['options.unicode.unicode'] == ['a', 'b', 'c']
assert dico['options.unicode.unicode1'] == [None, None, None]
assert dico['options.unicode.unicode2'] == [None, 'rah', None]
assert isinstance(dico['options.unicode.unicode3'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode3'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode3'][2], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][2], PropertiesOptionError)
del (dico['options.unicode.unicode3'][2])
del (dico['options.unicode.unicode3'][1])
del (dico['options.unicode.unicode3'][0])
del (dico['options.unicode.unicode4'][2])
del (dico['options.unicode.unicode4'][1])
del (dico['options.unicode.unicode4'][0])
# #
cfg.option('options.unicode.unicode2', 1).value.set('test') cfg.option('options.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'} dico = cfg.value.dict()
assert list(dico.keys()) == ['options.unicode.unicode', 'options.unicode.unicode1', 'options.unicode.unicode3', 'options.unicode.unicode4', 'options.unicodetoto']
assert dico['options.unicodetoto'] == 'rah'
assert dico['options.unicode.unicode'] == ['a', 'b', 'c']
assert dico['options.unicode.unicode1'] == [None, None, None]
assert isinstance(dico['options.unicode.unicode3'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode3'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode3'][2], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][0], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][1], PropertiesOptionError)
assert isinstance(dico['options.unicode.unicode4'][2], PropertiesOptionError)
del (dico['options.unicode.unicode3'][2])
del (dico['options.unicode.unicode3'][1])
del (dico['options.unicode.unicode3'][0])
del (dico['options.unicode.unicode4'][2])
del (dico['options.unicode.unicode4'][1])
del (dico['options.unicode.unicode4'][0])
# assert not list_sessions() # assert not list_sessions()

View file

@ -11,6 +11,7 @@ try:
except: except:
tiramisu_version = 2 tiramisu_version = 2
from tiramisu import Config from tiramisu import Config
from tiramisu.config import SubConfig
from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption,\ from tiramisu.option import ChoiceOption, BoolOption, IntOption, FloatOption,\
StrOption, SymLinkOption, StrOption, IPOption, OptionDescription, \ StrOption, SymLinkOption, StrOption, IPOption, OptionDescription, \
PortOption, NetworkOption, NetmaskOption, DomainnameOption, EmailOption, \ PortOption, NetworkOption, NetmaskOption, DomainnameOption, EmailOption, \
@ -157,11 +158,32 @@ def test_slots_option_readonly():
# assert slots == set(OptionDescription.__slots__) # assert slots == set(OptionDescription.__slots__)
def test_slots_config():
od1 = OptionDescription('a', '', [])
od2 = OptionDescription('a', '', [od1])
cfg = Config(od2)
with pytest.raises(AttributeError):
cfg._config_bag.context.x = 1
with pytest.raises(AttributeError):
cfg._config_bag.context.cfgimpl_x = 1
option_bag = OptionBag()
option_bag.set_option(od2,
'a',
ConfigBag(cfg._config_bag.context, None, None))
sc = cfg._config_bag.context.get_subconfig(option_bag)
assert isinstance(sc, SubConfig)
with pytest.raises(AttributeError):
sc.x = 1
with pytest.raises(AttributeError):
sc.cfgimpl_x = 1
# assert not list_sessions()
def test_slots_setting(): def test_slots_setting():
od1 = OptionDescription('a', '', []) od1 = OptionDescription('a', '', [])
od2 = OptionDescription('a', '', [od1]) od2 = OptionDescription('a', '', [od1])
cfg = Config(od2) cfg = Config(od2)
s = cfg._config_bag.context.get_settings() s = cfg._config_bag.context.cfgimpl_get_settings()
s s
with pytest.raises(AttributeError): with pytest.raises(AttributeError):
s.x = 1 s.x = 1
@ -172,7 +194,7 @@ def test_slots_value():
od1 = OptionDescription('a', '', []) od1 = OptionDescription('a', '', [])
od2 = OptionDescription('a', '', [od1]) od2 = OptionDescription('a', '', [od1])
cfg = Config(od2) cfg = Config(od2)
v = cfg._config_bag.context.get_values() v = cfg._config_bag.context.cfgimpl_get_values()
v v
with pytest.raises(AttributeError): with pytest.raises(AttributeError):
v.x = 1 v.x = 1

View file

@ -43,7 +43,7 @@ def test_symlink_assign_option(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)
with pytest.raises(APIError): with pytest.raises(ConfigError):
cfg.option('c').value.set(True) cfg.option('c').value.set(True)
# assert not list_sessions() # assert not list_sessions()
@ -55,7 +55,7 @@ def test_symlink_del_option(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)
with pytest.raises(APIError): with pytest.raises(ConfigError):
cfg.option('c').value.reset() cfg.option('c').value.reset()
# assert not list_sessions() # assert not list_sessions()
@ -191,7 +191,7 @@ def test_symlink_assign(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)
with pytest.raises(APIError): with pytest.raises(ConfigError):
cfg.option('c').value.set(True) cfg.option('c').value.set(True)
# assert not list_sessions() # assert not list_sessions()
@ -246,9 +246,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 cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [], 'ip_admin_eth0.netmask_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 cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['val1', 'val2'], 'ip_admin_eth0.netmask_admin_eth0': [None, 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(APIError): with pytest.raises(APIError):
cfg.option('leader').value.pop(0) cfg.option('leader').value.pop(0)
@ -263,36 +263,36 @@ def test_symlink_with_follower(config_type):
od1 = OptionDescription('root', '', [interface1, follower]) od1 = OptionDescription('root', '', [interface1, follower])
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': [], 'follower': []} assert cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': [], 'ip_admin_eth0.netmask_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 cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['val1', 'val2'], 'ip_admin_eth0.netmask_admin_eth0': [None, 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'
with pytest.raises(APIError): assert cfg.option('follower', 0).owner.get() == 'default'
assert cfg.option('follower', 0).owner.get() == 'default' assert cfg.option('follower', 1).owner.get() == 'default'
assert cfg.option('follower').owner.get() == 'default' assert cfg.option('follower').owner.get() == ['default', 'default']
# #
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() == None assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).value.get() == None
with pytest.raises(APIError): assert cfg.option('follower', 0).value.get() == None
assert cfg.option('follower', 0).value.get() == None assert cfg.option('follower', 1).value.get() == None
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 cfg.value.dict() == {'ip_admin_eth0.ip_admin_eth0': ['val1', 'val2'], 'ip_admin_eth0.netmask_admin_eth0': [None, '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'
with pytest.raises(APIError): assert cfg.option('follower', 0).value.get() == None
assert cfg.option('follower', 0).value.get() == None assert cfg.option('follower', 1).value.get() == 'val3'
assert cfg.option('follower').value.get() == [None, 'val3'] assert cfg.option('follower').value.get() == [None, 'val3']
# #
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() == 'user' assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).owner.get() == 'user'
with pytest.raises(APIError): assert cfg.option('follower', 0).owner.get() == 'default'
assert cfg.option('follower', 0).owner.get() == 'default' assert cfg.option('follower', 1).owner.get() == 'user'
assert cfg.option('follower').owner.get() == 'user' assert cfg.option('follower').owner.get() == ['default', 'user']
# assert not list_sessions() # assert not list_sessions()

File diff suppressed because it is too large Load diff

View file

@ -176,35 +176,35 @@ class Calculation:
for_settings: bool=False, for_settings: bool=False,
) -> Any: ) -> Any:
return carry_out_calculation(option_bag.option, return carry_out_calculation(option_bag.option,
callback=self.function, callback=self.function,
callback_params=self.params, callback_params=self.params,
index=option_bag.index, index=option_bag.index,
config_bag=option_bag.config_bag, config_bag=option_bag.config_bag,
leadership_must_have_index=leadership_must_have_index, leadership_must_have_index=leadership_must_have_index,
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,
for_settings=for_settings, for_settings=for_settings,
) )
def help(self, def help(self,
option_bag: OptionBag, option_bag: OptionBag,
leadership_must_have_index: bool=False, leadership_must_have_index: bool=False,
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(option_bag,
leadership_must_have_index=leadership_must_have_index, leadership_must_have_index=leadership_must_have_index,
for_settings=for_settings, for_settings=for_settings,
) )
return carry_out_calculation(option_bag.option, return carry_out_calculation(option_bag.option,
callback=self.help_function, callback=self.help_function,
callback_params=self.params, callback_params=self.params,
index=option_bag.index, index=option_bag.index,
config_bag=option_bag.config_bag, config_bag=option_bag.config_bag,
leadership_must_have_index=leadership_must_have_index, leadership_must_have_index=leadership_must_have_index,
for_settings=for_settings, for_settings=for_settings,
) )
def has_index(self, current_option): def has_index(self, current_option):
if hasattr(self, '_has_index'): if hasattr(self, '_has_index'):
@ -223,13 +223,13 @@ class Break(Exception):
def manager_callback(callbk: Param, def manager_callback(callbk: Param,
option, option,
index: Optional[int], index: Optional[int],
orig_value, orig_value,
config_bag: ConfigBag, config_bag: ConfigBag,
leadership_must_have_index: bool, leadership_must_have_index: bool,
for_settings: bool, for_settings: bool,
) -> Any: ) -> Any:
"""replace Param by true value""" """replace Param by true value"""
def calc_index(callbk, index, same_leadership): def calc_index(callbk, index, same_leadership):
if index is not None: if index is not None:
@ -243,12 +243,7 @@ def manager_callback(callbk: Param,
return index return index
return None return None
def calc_self(callbk, def calc_self(callbk, option, index, value, config_bag):
option,
index,
value,
config_bag,
):
# index must be apply only if follower # index must be apply only if follower
is_follower = option.impl_is_follower() is_follower = option.impl_is_follower()
apply_index = calc_index(callbk, index, is_follower) apply_index = calc_index(callbk, index, is_follower)
@ -256,40 +251,11 @@ def manager_callback(callbk: Param,
if config_bag is undefined: if config_bag is undefined:
return undefined return undefined
path = option.impl_getpath() path = option.impl_getpath()
option_bag = OptionBag(option, option_bag = get_option_bag(config_bag,
None, option,
config_bag, apply_index,
properties=None, True)
) new_value = get_value(callbk, option_bag, path)
properties = config_bag.context.get_settings().getproperties(option_bag,
uncalculated=True,
)
parent_option_bag, option_bag = get_option_bag(config_bag,
option,
callbk,
apply_index,
True,
properties=properties,
)
if option.impl_is_follower() and apply_index is None:
new_value = []
for idx in range(config_bag.context.get_length_leadership(parent_option_bag)):
parent_option_bag, option_bag = get_option_bag(config_bag,
option,
callbk,
idx,
True,
properties=properties,
)
new_value.append(get_value(callbk,
option_bag,
path,
))
else:
new_value = get_value(callbk,
option_bag,
path,
)
if apply_index is None and is_follower: if apply_index is None and is_follower:
new_value[index] = value new_value[index] = value
value = new_value value = new_value
@ -298,12 +264,13 @@ def manager_callback(callbk: Param,
return value return value
def get_value(callbk, def get_value(callbk,
option_bag, option_bag,
path, path,
): ):
try: try:
# get value # get value
value = config_bag.context.get_value(option_bag) value = config_bag.context.getattr(path,
option_bag)
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 callbk.notraisepropertyerror or callbk.raisepropertyerror: if callbk.notraisepropertyerror or callbk.raisepropertyerror:
@ -317,18 +284,15 @@ def manager_callback(callbk: Param,
# cannot acces, simulate a propertyerror # cannot acces, simulate a propertyerror
raise PropertiesOptionError(option_bag, raise PropertiesOptionError(option_bag,
['configerror'], ['configerror'],
config_bag.context.get_settings(), config_bag.context.cfgimpl_get_settings(),
) )
raise ConfigError(_(f'unable to get value for calculating "{option_bag.option.impl_get_display_name()}", {err}')) from err raise ConfigError(_(f'unable to get value for calculating "{option_bag.option.impl_get_display_name()}", {err}')) from err
return value return value
def get_option_bag(config_bag, def get_option_bag(config_bag,
opt, opt,
callbk, index_,
index_, self_calc):
self_calc,
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
config_bag = config_bag.copy() config_bag = config_bag.copy()
if for_settings: if for_settings:
@ -336,62 +300,38 @@ def manager_callback(callbk: Param,
config_bag.set_permissive() config_bag.set_permissive()
if not for_settings: if not for_settings:
config_bag.properties -= {'warnings'} config_bag.properties -= {'warnings'}
if self_calc: option_bag = OptionBag()
config_bag.unrestraint() option_bag.set_option(opt,
config_bag.remove_validation() index_,
root_option_bag = OptionBag(config_bag.context.get_description(), config_bag)
None, if not self_calc:
config_bag, option_bag.properties = config_bag.context.cfgimpl_get_settings().getproperties(option_bag)
)
try:
options_bag = config_bag.context.get_sub_option_bag(root_option_bag,
opt.impl_getpath(),
index_,
validate_properties=not self_calc,
properties=properties,
)
except PropertiesOptionError as err:
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
if callbk.notraisepropertyerror or callbk.raisepropertyerror:
raise err from err
raise ConfigError(_('unable to carry out a calculation for "{}"'
', {}').format(option.impl_get_display_name(), err), err) from err
except ValueError as err:
raise ValueError(_('the option "{0}" is used in a calculation but is invalid ({1})').format(option.impl_get_display_name(), err)) from err
except AttributeError as err:
if isinstance(callbk, ParamDynOption) and callbk.optional:
# cannot acces, simulate a propertyerror
raise PropertiesOptionError(options_bag[-1],
['configerror'],
config_bag.context.get_settings(),
)
raise ConfigError(_(f'unable to get value for calculating "{option.impl_get_display_name()}", {err}')) from err
if self_calc:
if len(options_bag) > 1:
parent_option_bag = options_bag[-2]
else:
parent_option_bag = None
return parent_option_bag, options_bag[-1]
else: else:
return options_bag[-1] option_bag.config_bag.unrestraint()
option_bag.config_bag.remove_validation()
# if we are in properties calculation, cannot calculated properties
option_bag.properties = config_bag.context.cfgimpl_get_settings().getproperties(option_bag,
apply_requires=False)
return option_bag
if isinstance(callbk, ParamValue): if isinstance(callbk, ParamValue):
return callbk.value return callbk.value
if isinstance(callbk, ParamInformation): if isinstance(callbk, ParamInformation):
if isinstance(callbk, ParamSelfInformation): if isinstance(callbk, ParamSelfInformation):
option_bag = OptionBag(option, option_bag = OptionBag()
index, option_bag.set_option(option,
config_bag, index,
) config_bag,
)
else: else:
option_bag = None option_bag = None
try: try:
return config_bag.context.impl_get_information(config_bag, return config_bag.context.impl_get_information(config_bag,
option_bag, option_bag,
callbk.information_name, callbk.information_name,
callbk.default_value, callbk.default_value,
) )
except ValueError as err: except ValueError as err:
raise ConfigError(_('option "{}" cannot be calculated: {}').format(option.impl_get_display_name(), raise ConfigError(_('option "{}" cannot be calculated: {}').format(option.impl_get_display_name(),
str(err), str(err),
@ -408,17 +348,11 @@ def manager_callback(callbk: Param,
if isinstance(callbk, ParamSelfOption): if isinstance(callbk, ParamSelfOption):
if leadership_must_have_index and option.impl_is_follower() and index is None: if leadership_must_have_index and option.impl_is_follower() and index is None:
raise Break() raise Break()
value = calc_self(callbk, value = calc_self(callbk, option, index, orig_value, config_bag)
option,
index,
orig_value,
config_bag,
)
if not callbk.todict: if not callbk.todict:
return value return value
return {'name': option.impl_get_display_name(), return {'name': option.impl_get_display_name(),
'value': value, 'value': value}
}
if isinstance(callbk, ParamOption): if isinstance(callbk, ParamOption):
callbk_option = callbk.option callbk_option = callbk.option
@ -431,8 +365,7 @@ def manager_callback(callbk: Param,
suffix = callbk.suffix suffix = callbk.suffix
callbk_option = callbk_option.to_dynoption(rootpath, callbk_option = callbk_option.to_dynoption(rootpath,
suffix, suffix,
subdyn, subdyn)
)
found = True found = True
elif option.impl_is_dynsymlinkoption(): elif option.impl_is_dynsymlinkoption():
rootpath = option.rootpath rootpath = option.rootpath
@ -485,15 +418,13 @@ def manager_callback(callbk: Param,
with_index = False with_index = False
path = callbk_option.impl_getpath() path = callbk_option.impl_getpath()
option_bag = get_option_bag(config_bag, option_bag = get_option_bag(config_bag,
callbk_option, callbk_option,
callbk, index_,
index_, False)
False,
)
value = get_value(callbk, value = get_value(callbk,
option_bag, option_bag,
path, path,
) )
if with_index: if with_index:
value = value[index] value = value[index]
if values is not None: if values is not None:
@ -509,16 +440,16 @@ def manager_callback(callbk: Param,
def carry_out_calculation(option, def carry_out_calculation(option,
callback: Callable, callback: Callable,
callback_params: Optional[Params], callback_params: Optional[Params],
index: Optional[int], index: Optional[int],
config_bag: Optional[ConfigBag], config_bag: Optional[ConfigBag],
orig_value=undefined, orig_value=undefined,
leadership_must_have_index: bool=False, leadership_must_have_index: bool=False,
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,
): ):
"""a function that carries out a calculation for an option's value """a function that carries out a calculation for an option's value
:param option: the option :param option: the option
@ -543,13 +474,13 @@ def carry_out_calculation(option,
for key, callbk in chain(fake_items(callback_params.args), callback_params.kwargs.items()): for key, callbk in chain(fake_items(callback_params.args), callback_params.kwargs.items()):
try: try:
value = manager_callback(callbk, value = manager_callback(callbk,
option, option,
index, index,
orig_value, orig_value,
config_bag, config_bag,
leadership_must_have_index, leadership_must_have_index,
for_settings, for_settings,
) )
if value is undefined: if value is undefined:
return undefined return undefined
if key is None: if key is None:
@ -567,12 +498,11 @@ def carry_out_calculation(option,
except Break: except Break:
continue continue
ret = calculate(option, ret = calculate(option,
callback, callback,
allow_value_error, allow_value_error,
force_value_warning, force_value_warning,
args, args,
kwargs, kwargs)
)
if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \ if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \
option.impl_is_follower() and not option.impl_is_submulti(): option.impl_is_follower() and not option.impl_is_submulti():
if args or kwargs: if args or kwargs:
@ -594,12 +524,12 @@ def carry_out_calculation(option,
def calculate(option, def calculate(option,
callback: Callable, callback: Callable,
allow_value_error: bool, allow_value_error: bool,
force_value_warning: bool, force_value_warning: bool,
args, args,
kwargs, kwargs,
): ):
"""wrapper that launches the 'callback' """wrapper that launches the 'callback'
:param callback: callback function :param callback: callback function

View file

@ -52,8 +52,7 @@ class Cache:
index, index,
props, props,
self_props, self_props,
type_, type_):
):
no_cache = False, None, False no_cache = False, None, False
if 'cache' in props or type_ == 'context_props': if 'cache' in props or type_ == 'context_props':
values = self._cache.get(path) values = self._cache.get(path)

File diff suppressed because it is too large Load diff

View file

@ -128,7 +128,7 @@ class PropertiesOptionError(AttributeError):
# Exceptions for a Config # Exceptions for a Config
class ConfigError(Exception): class ConfigError(Exception):
"""attempt to change an option's owner without a value """attempt to change an option's owner without a value
or in case of `_descr` is None or in case of `_cfgimpl_descr` is None
or if a calculation cannot be carried out""" or if a calculation cannot be carried out"""
def __init__(self, def __init__(self,
exp, exp,

View file

@ -157,9 +157,8 @@ class Base:
return getattr(self, '_properties', frozenset()) return getattr(self, '_properties', frozenset())
def _setsubdyn(self, def _setsubdyn(self,
subdyn, subdyn) -> None:
) -> None: self._subdyn = weakref.ref(subdyn)
self._subdyn = subdyn
def issubdyn(self) -> bool: def issubdyn(self) -> bool:
return getattr(self, '_subdyn', None) is not None return getattr(self, '_subdyn', None) is not None
@ -296,7 +295,7 @@ class BaseOption(Base):
config_bag: 'OptionBag', config_bag: 'OptionBag',
resetted_opts: List[Base]) -> None: resetted_opts: List[Base]) -> None:
context = config_bag.context context = config_bag.context
context.properties_cache.delcache(path) context._impl_properties_cache.delcache(path)
context._impl_permissives_cache.delcache(path) context._impl_permissives_cache.delcache(path)
if not self.impl_is_optiondescription(): if not self.impl_is_optiondescription():
context._impl_values_cache.delcache(path) context._impl_values_cache.delcache(path)

View file

@ -19,7 +19,6 @@
# the whole pypy projet is under MIT licence # the whole pypy projet is under MIT licence
# ____________________________________________________________ # ____________________________________________________________
import re import re
import weakref
from typing import List, Callable, Any from typing import List, Callable, Any
from itertools import chain from itertools import chain
from ..autolib import ParamOption from ..autolib import ParamOption
@ -44,18 +43,24 @@ class DynOptionDescription(OptionDescription):
doc: str, doc: str,
children: List[BaseOption], children: List[BaseOption],
suffixes: Calculation, suffixes: Calculation,
properties=None, properties=None) -> None:
) -> None:
super().__init__(name, super().__init__(name,
doc, doc,
children, children,
properties, properties)
)
# check children + set relation to this dynoptiondescription # check children + set relation to this dynoptiondescription
wself = weakref.ref(self)
for child in children: for child in children:
child._setsubdyn(wself) if isinstance(child, OptionDescription):
if __debug__ and child.impl_get_group_type() != groups.leadership:
raise ConfigError(_('cannot set optiondescription in a '
'dynoptiondescription'))
for chld in child._children[1]:
chld._setsubdyn(self)
if __debug__ and child.impl_is_symlinkoption():
raise ConfigError(_('cannot set symlinkoption in a '
'dynoptiondescription'))
child._setsubdyn(self)
# add suffixes # add suffixes
if __debug__ and not isinstance(suffixes, Calculation): if __debug__ and not isinstance(suffixes, Calculation):
raise ConfigError(_('suffixes in dynoptiondescription has to be a calculation')) raise ConfigError(_('suffixes in dynoptiondescription has to be a calculation'))
@ -79,11 +84,10 @@ class DynOptionDescription(OptionDescription):
def get_suffixes(self, def get_suffixes(self,
config_bag: ConfigBag) -> List[str]: config_bag: ConfigBag) -> List[str]:
option_bag = OptionBag(self, option_bag = OptionBag()
None, option_bag.set_option(self,
config_bag, None,
properties=None, config_bag)
)
values = self._suffixes.execute(option_bag) values = self._suffixes.execute(option_bag)
if values is None: if values is None:
values = [] values = []

View file

@ -96,13 +96,6 @@ class Leadership(OptionDescription):
if prop not in ALLOWED_LEADER_PROPERTIES and not isinstance(prop, Calculation): if prop not in ALLOWED_LEADER_PROPERTIES and not isinstance(prop, Calculation):
raise LeadershipError(_('leader cannot have "{}" property').format(prop)) raise LeadershipError(_('leader cannot have "{}" property').format(prop))
def _setsubdyn(self,
subdyn,
) -> None:
for chld in self._children[1]:
chld._setsubdyn(subdyn)
self._subdyn = subdyn
def is_leader(self, def is_leader(self,
opt: Option) -> bool: opt: Option) -> bool:
leader = self.get_leader() leader = self.get_leader()
@ -127,10 +120,11 @@ class Leadership(OptionDescription):
config_bag = option_bag.config_bag.copy() config_bag = option_bag.config_bag.copy()
config_bag.remove_validation() config_bag.remove_validation()
for follower in self.get_followers(): for follower in self.get_followers():
soption_bag = OptionBag(follower, soption_bag = OptionBag()
None, soption_bag.set_option(follower,
config_bag, None,
) config_bag)
soption_bag.properties = config_bag.context.cfgimpl_get_settings().getproperties(soption_bag)
values.reset(soption_bag) values.reset(soption_bag)
def follower_force_store_value(self, def follower_force_store_value(self,
@ -140,37 +134,37 @@ class Leadership(OptionDescription):
owner, owner,
dyn=None, dyn=None,
) -> None: ) -> None:
settings = option_bag.config_bag.context.get_settings() settings = option_bag.config_bag.context.cfgimpl_get_settings()
if value: if value:
if dyn is None: if dyn is None:
dyn = self dyn = self
for idx, follower in enumerate(dyn.get_children(option_bag.config_bag)): for idx, follower in enumerate(dyn.get_children(option_bag.config_bag)):
foption_bag = OptionBag(follower, foption_bag = OptionBag()
None, foption_bag.set_option(follower,
option_bag.config_bag, None,
) option_bag.config_bag)
if 'force_store_value' in foption_bag.properties: if 'force_store_value' in settings.getproperties(foption_bag):
if idx == 0: if idx == 0:
indexes = [None] indexes = [None]
else: else:
indexes = range(len(value)) indexes = range(len(value))
for index in indexes: for index in indexes:
foption_bag_index = OptionBag(follower, foption_bag = OptionBag()
index, foption_bag.set_option(follower,
option_bag.config_bag, index,
) option_bag.config_bag)
values.set_storage_value(foption_bag_index.path, foption_bag.properties = settings.getproperties(foption_bag)
values.set_storage_value(foption_bag.path,
index, index,
values.getvalue(foption_bag_index), values.getvalue(foption_bag),
owner, owner,
) )
def pop(self, def pop(self,
values: Values, values: Values,
index: int, index: int,
option_bag: OptionBag, option_bag: OptionBag,
followers: Optional[List[Option]]=undefined, followers: Optional[List[Option]]=undefined) -> None:
) -> None:
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()
@ -179,14 +173,14 @@ class Leadership(OptionDescription):
for follower in followers: for follower in followers:
follower_path = follower.impl_getpath() follower_path = follower.impl_getpath()
followerlen = values.get_max_length(follower_path) followerlen = values.get_max_length(follower_path)
soption_bag = OptionBag(follower, soption_bag = OptionBag()
index, soption_bag.set_option(follower,
config_bag, index,
properties=set(), # do not check force_default_on_freeze or force_metaconfig_on_freeze config_bag)
) # do not check force_default_on_freeze or force_metaconfig_on_freeze
soption_bag.properties = set()
is_default = values.is_default_owner(soption_bag, is_default = values.is_default_owner(soption_bag,
validate_meta=False, validate_meta=False)
)
if not is_default and followerlen > index: if not is_default and followerlen > index:
values.resetvalue_index(follower_path, values.resetvalue_index(follower_path,
index, index,
@ -203,22 +197,19 @@ class Leadership(OptionDescription):
def reset_cache(self, def reset_cache(self,
path: str, path: str,
config_bag: 'ConfigBag', config_bag: 'ConfigBag',
resetted_opts: List[Option], resetted_opts: List[Option]) -> None:
) -> None:
self._reset_cache(path, self._reset_cache(path,
self.get_leader(), self.get_leader(),
self.get_followers(), self.get_followers(),
config_bag, config_bag,
resetted_opts, resetted_opts)
)
def _reset_cache(self, def _reset_cache(self,
path: str, path: str,
leader: Option, leader: Option,
followers: List[Option], followers: List[Option],
config_bag: 'ConfigBag', config_bag: 'ConfigBag',
resetted_opts: List[Option], resetted_opts: List[Option]) -> None:
) -> None:
super().reset_cache(path, super().reset_cache(path,
config_bag, config_bag,
resetted_opts) resetted_opts)

View file

@ -121,11 +121,10 @@ 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()
None, option_bag.set_option(self,
undefined, None,
properties=None, undefined)
)
try: try:
self.validate(value) self.validate(value)
self.sync_validate_with_option(value, self.sync_validate_with_option(value,
@ -153,11 +152,10 @@ 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()
None, option_bag.set_option(self,
undefined, None,
properties=None, undefined)
)
self.sync_impl_validate(default, self.sync_impl_validate(default,
option_bag) option_bag)
self.sync_impl_validate(default, self.sync_impl_validate(default,
@ -486,8 +484,8 @@ class Option(BaseOption):
pass pass
def validate_with_option(self, def validate_with_option(self,
value: Any, value: Any,
option_bag: OptionBag) -> None: option_bag: OptionBag) -> None:
pass pass
def second_level_validation(self, def second_level_validation(self,
@ -516,10 +514,10 @@ class Option(BaseOption):
def to_dynoption(self, def to_dynoption(self,
rootpath: str, rootpath: str,
suffix: str, suffix: str,
dyn_parent, ori_dyn,
) -> SynDynOption: ) -> SynDynOption:
return SynDynOption(self, return SynDynOption(self,
rootpath, rootpath,
suffix, suffix,
dyn_parent, ori_dyn,
) )

View file

@ -38,15 +38,15 @@ class CacheOptionDescription(BaseOption):
return self.impl_is_readonly() return self.impl_is_readonly()
def _build_cache(self, def _build_cache(self,
path='', path='',
_consistencies=None, _consistencies=None,
_consistencies_id=0, _consistencies_id=0,
currpath: List[str]=None, currpath: List[str]=None,
cache_option=None, cache_option=None,
force_store_values=None, force_store_values=None,
dependencies_information=None, dependencies_information=None,
display_name=None, display_name=None,
) -> None: ) -> None:
"""validate options and set option has readonly option """validate options and set option has readonly option
""" """
# _consistencies is None only when we start to build cache # _consistencies is None only when we start to build cache
@ -66,21 +66,20 @@ class CacheOptionDescription(BaseOption):
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, for option in self.get_children(config_bag=undefined,
dyn=False): 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()]
subpath = '.'.join(sub_currpath) subpath = '.'.join(sub_currpath)
if isinstance(option, OptionDescription): if isinstance(option, OptionDescription):
option._build_cache(subpath, option._build_cache(subpath,
_consistencies, _consistencies,
_consistencies_id, _consistencies_id,
sub_currpath, sub_currpath,
cache_option, cache_option,
force_store_values, force_store_values,
dependencies_information, dependencies_information,
display_name, display_name)
)
else: else:
for information in option.get_dependencies_information(): for information in option.get_dependencies_information():
dependencies_information.setdefault(information, []).append(option) dependencies_information.setdefault(information, []).append(option)
@ -125,22 +124,21 @@ class CacheOptionDescription(BaseOption):
suffix, suffix,
dynopt, dynopt,
) )
doption_bag = OptionBag(doption, doption_bag = OptionBag()
None, doption_bag.set_option(doption,
config_bag, None,
properties=None, config_bag,
) )
yield doption_bag yield doption_bag
else: else:
option_bag = OptionBag(option, option_bag = OptionBag()
None, option_bag.set_option(option,
config_bag, None,
properties=None, config_bag)
)
yield option_bag yield option_bag
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.cfgimpl_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()
@ -151,7 +149,7 @@ class CacheOptionDescription(BaseOption):
subpath = leader_option_bag.option.rootpath subpath = leader_option_bag.option.rootpath
doption = option.to_dynoption(subpath, doption = option.to_dynoption(subpath,
leader_option_bag.option.impl_getsuffix(), leader_option_bag.option.impl_getsuffix(),
leader_option_bag.option.dyn_parent, leader_option_bag.option.ori_dyn,
) )
else: else:
doption = option doption = option
@ -159,11 +157,12 @@ class CacheOptionDescription(BaseOption):
for index in range(follower_len): for index in range(follower_len):
if values.hasvalue(subpath, index): if values.hasvalue(subpath, index):
continue continue
option_bag = OptionBag(doption, option_bag = OptionBag()
index, option_bag.set_option(doption,
config_bag, index,
properties=frozenset(), config_bag,
) )
option_bag.properties = frozenset()
value = values.getvalue(option_bag) value = values.getvalue(option_bag)
if value is None: if value is None:
continue continue
@ -191,10 +190,10 @@ class OptionDescriptionWalk(CacheOptionDescription):
__slots__ = ('_children',) __slots__ = ('_children',)
def get_child(self, def get_child(self,
name: str, name: str,
config_bag: ConfigBag, config_bag: ConfigBag,
subpath: str, subpath: str,
) -> Union[BaseOption, SynDynOptionDescription]: ) -> Union[BaseOption, SynDynOptionDescription]:
# if not dyn # if not dyn
if name in self._children[0]: if name in self._children[0]:
option = self._children[1][self._children[0].index(name)] option = self._children[1][self._children[0].index(name)]
@ -205,32 +204,29 @@ class OptionDescriptionWalk(CacheOptionDescription):
return option return option
# if dyn # if dyn
for child in self._children[1]: for child in self._children[1]:
if not child.impl_is_dynoptiondescription(): if child.impl_is_dynoptiondescription():
continue cname = child.impl_getname()
cname = child.impl_getname() if name.startswith(cname):
if not name.startswith(cname): for suffix in child.get_suffixes(config_bag):
continue if name == cname + child.convert_suffix_to_path(suffix):
for suffix in child.get_suffixes(config_bag): return child.to_dynoption(subpath,
if name != cname + child.convert_suffix_to_path(suffix): suffix,
continue child)
return child.to_dynoption(subpath,
suffix,
child,
)
if self.impl_get_group_type() == groups.root: if self.impl_get_group_type() == groups.root:
raise AttributeError(_(f'unknown option "{name}" ' raise AttributeError(_(f'unknown option "{name}" '
'in root optiondescription' 'in root optiondescription'
)) ))
raise AttributeError(_(f'unknown option "{name}" ' else:
f'in optiondescription "{self.impl_get_display_name()}"' raise AttributeError(_(f'unknown option "{name}" '
)) f'in optiondescription "{self.impl_get_display_name()}"'
))
def get_children(self, def get_children(self,
config_bag: Union[ConfigBag, Undefined], config_bag: Union[ConfigBag, Undefined],
dyn: bool=True, dyn: bool=True,
) -> Union[BaseOption, SynDynOptionDescription]: ) -> Union[BaseOption, SynDynOptionDescription]:
if not dyn or config_bag is undefined or \ if not dyn or config_bag is undefined or \
config_bag.context.get_description() == self: config_bag.context.cfgimpl_get_description() == self:
subpath = '' subpath = ''
else: else:
subpath = self.impl_getpath() subpath = self.impl_getpath()
@ -246,19 +242,17 @@ class OptionDescriptionWalk(CacheOptionDescription):
return children return children
def get_children_recursively(self, def get_children_recursively(self,
bytype: Optional[BaseOption], bytype: Optional[BaseOption],
byname: Optional[str], byname: Optional[str],
config_bag: ConfigBag, config_bag: ConfigBag,
self_opt: BaseOption=None, self_opt: BaseOption=None) -> Iterator[Union[BaseOption, SynDynOptionDescription]]:
) -> Iterator[Union[BaseOption, SynDynOptionDescription]]:
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(config_bag):
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,
config_bag, config_bag):
):
yield subopt yield subopt
elif (byname is None or option.impl_getname() == byname) and \ elif (byname is None or option.impl_getname() == byname) and \
(bytype is None or isinstance(option, bytype)): (bytype is None or isinstance(option, bytype)):
@ -315,12 +309,6 @@ class OptionDescription(OptionDescriptionWalk):
# the group_type is useful for filtering OptionDescriptions in a config # the group_type is useful for filtering OptionDescriptions in a config
self._group_type = groups.default self._group_type = groups.default
def _setsubdyn(self,
subdyn,
) -> None:
raise ConfigError(_('cannot set optiondescription in a '
'dynoptiondescription'))
def impl_is_optiondescription(self) -> bool: def impl_is_optiondescription(self) -> bool:
return True return True
@ -342,7 +330,7 @@ class OptionDescription(OptionDescriptionWalk):
if self._group_type != groups.default: if self._group_type != groups.default:
raise ValueError(_('cannot change group_type if already set ' raise ValueError(_('cannot change group_type if already set '
'(old {0}, new {1})').format(self._group_type, '(old {0}, new {1})').format(self._group_type,
group_type)) group_type))
if not isinstance(group_type, groups.GroupType): if not isinstance(group_type, groups.GroupType):
raise ValueError(_('group_type: {0}' raise ValueError(_('group_type: {0}'
' not allowed').format(group_type)) ' not allowed').format(group_type))

View file

@ -20,7 +20,6 @@
# ____________________________________________________________ # ____________________________________________________________
from typing import Any from typing import Any
from .baseoption import BaseOption, valid_name from .baseoption import BaseOption, valid_name
from ..error import ConfigError
from ..i18n import _ from ..i18n import _
@ -48,12 +47,6 @@ class SymLinkOption(BaseOption):
) -> Any: ) -> Any:
return getattr(self._opt, name) return getattr(self._opt, name)
def _setsubdyn(self,
subdyn,
) -> None:
raise ConfigError(_('cannot set symlinkoption in a '
'dynoptiondescription'))
def impl_has_dependency(self, def impl_has_dependency(self,
self_is_dep: bool=True) -> bool: self_is_dep: bool=True) -> bool:
"""If self_is_dep is True, it has dependency (self._opt), so return True """If self_is_dep is True, it has dependency (self._opt), so return True

View file

@ -29,25 +29,23 @@ class SynDynOption:
__slots__ = ('rootpath', __slots__ = ('rootpath',
'opt', 'opt',
'suffix', 'suffix',
'dyn_parent', 'ori_dyn',
'__weakref__') '__weakref__')
def __init__(self, def __init__(self,
opt: BaseOption, opt: BaseOption,
rootpath: str, rootpath: str,
suffix: str, suffix: str,
dyn_parent, ori_dyn) -> None:
) -> None:
self.opt = opt self.opt = opt
self.rootpath = rootpath self.rootpath = rootpath
self.suffix = suffix self.suffix = suffix
self.dyn_parent = dyn_parent self.ori_dyn = ori_dyn
def __getattr__(self, def __getattr__(self,
name: str) -> Any: name: str) -> Any:
return getattr(self.opt, return getattr(self.opt,
name, name)
)
def __eq__(self, def __eq__(self,
left: BaseOption) -> bool: left: BaseOption) -> bool:
@ -58,21 +56,18 @@ class SynDynOption:
self.suffix == left.suffix self.suffix == left.suffix
def impl_getname(self) -> str: def impl_getname(self) -> str:
return self.opt.impl_getname() + self.dyn_parent.convert_suffix_to_path(self.suffix) return self.opt.impl_getname() + self.ori_dyn.convert_suffix_to_path(self.suffix)
def impl_get_display_name(self) -> str: def impl_get_display_name(self) -> str:
return self.opt._get_display_name(dyn_name=self.impl_getname(), return self.opt._get_display_name(dyn_name=self.impl_getname(),
suffix=self.dyn_parent.convert_suffix_to_path(self.suffix), suffix=self.ori_dyn.convert_suffix_to_path(self.suffix),
) )
def impl_getsuffix(self) -> str: def impl_getsuffix(self) -> str:
return self.suffix return self.suffix
def impl_getpath(self) -> str: def impl_getpath(self) -> str:
path = self.impl_getname() return self.rootpath + '.' + self.impl_getname()
if self.rootpath:
path = f'{self.rootpath}.{path}'
return path
def impl_is_dynsymlinkoption(self) -> bool: def impl_is_dynsymlinkoption(self) -> bool:
return True return True
@ -83,5 +78,5 @@ class SynDynOption:
rootpath = self.rootpath.rsplit('.', 1)[0] rootpath = self.rootpath.rsplit('.', 1)[0]
return leadership.to_dynoption(rootpath, return leadership.to_dynoption(rootpath,
self.suffix, self.suffix,
self.dyn_parent, self.ori_dyn,
) )

View file

@ -40,6 +40,9 @@ class SynDynOptionDescription:
suffix: str, suffix: str,
ori_dyn) -> None: ori_dyn) -> None:
self.opt = opt self.opt = opt
if rootpath is None:
rootpath = ''
assert isinstance(rootpath, str), 'rootpath must be a string, not {}'.format(type(rootpath))
self.rootpath = rootpath self.rootpath = rootpath
self._suffix = suffix self._suffix = suffix
# For a Leadership inside a DynOptionDescription # For a Leadership inside a DynOptionDescription
@ -57,10 +60,9 @@ class SynDynOptionDescription:
return self.opt return self.opt
def get_child(self, def get_child(self,
name: str, name: str,
config_bag: ConfigBag, config_bag: ConfigBag,
subpath: str, subpath: str) -> BaseOption:
) -> BaseOption:
suffix = self.ori_dyn.convert_suffix_to_path(self._suffix) suffix = self.ori_dyn.convert_suffix_to_path(self._suffix)
if name.endswith(suffix): if name.endswith(suffix):
oname = name[:-len(suffix)] oname = name[:-len(suffix)]
@ -84,9 +86,9 @@ class SynDynOptionDescription:
return True return True
def get_children(self, def get_children(self,
config_bag: ConfigBag, config_bag: ConfigBag,
dyn: bool=True, dyn: bool=True,
): ):
subpath = self.impl_getpath() subpath = self.impl_getpath()
children = [] children = []
for child in self.opt.get_children(config_bag): for child in self.opt.get_children(config_bag):
@ -100,23 +102,21 @@ class SynDynOptionDescription:
return True return True
def get_children_recursively(self, def get_children_recursively(self,
bytype: Optional[BaseOption], bytype: Optional[BaseOption],
byname: Optional[str], byname: Optional[str],
config_bag: ConfigBag, config_bag: ConfigBag,
self_opt: BaseOption=None, self_opt: BaseOption=None) -> BaseOption:
) -> BaseOption:
for option in self.opt.get_children_recursively(bytype, for option in self.opt.get_children_recursively(bytype,
byname, byname,
config_bag, config_bag,
self, self):
):
yield option yield option
def impl_getpath(self) -> str: def impl_getpath(self) -> str:
path = self.impl_getname() rootpath = self.rootpath
if self.rootpath: if rootpath != '':
path = f'{self.rootpath}.{path}' rootpath += '.'
return path return rootpath + self.impl_getname()
def impl_get_display_name(self) -> str: def impl_get_display_name(self) -> str:
return self.opt.impl_get_display_name() + str(self._suffix) return self.opt.impl_get_display_name() + str(self._suffix)
@ -126,52 +126,44 @@ class SynDynLeadership(SynDynOptionDescription):
def get_leader(self) -> SynDynOption: def get_leader(self) -> SynDynOption:
return self.opt.get_leader().to_dynoption(self.impl_getpath(), return self.opt.get_leader().to_dynoption(self.impl_getpath(),
self._suffix, self._suffix,
self.ori_dyn, self.ori_dyn)
)
def get_followers(self) -> Iterator[SynDynOption]: def get_followers(self) -> Iterator[SynDynOption]:
subpath = self.impl_getpath() subpath = self.impl_getpath()
for follower in self.opt.get_followers(): for follower in self.opt.get_followers():
yield follower.to_dynoption(subpath, yield follower.to_dynoption(subpath,
self._suffix, self._suffix,
self.ori_dyn, self.ori_dyn)
)
def reset_cache(self, def reset_cache(self,
path: str, path: str,
config_bag: 'ConfigBag', config_bag: 'ConfigBag',
resetted_opts: List[str], resetted_opts: List[str]) -> None:
) -> None:
leader = self.get_leader() leader = self.get_leader()
followers = self.get_followers() followers = self.get_followers()
self._reset_cache(path, self._reset_cache(path,
leader, leader,
followers, followers,
config_bag, config_bag,
resetted_opts, resetted_opts)
)
def pop(self, def pop(self,
*args, *args,
**kwargs, **kwargs) -> None:
) -> None:
self.opt.pop(*args, self.opt.pop(*args,
followers=self.get_followers(), followers=self.get_followers(),
**kwargs, **kwargs)
)
def follower_force_store_value(self, def follower_force_store_value(self,
values, values,
value, value,
option_bag, option_bag,
owner, owner) -> None:
) -> None:
self.opt.follower_force_store_value(values, self.opt.follower_force_store_value(values,
value, value,
option_bag, option_bag,
owner, owner,
dyn=self, dyn=self)
)
def impl_getsuffix(self) -> str: def impl_getsuffix(self) -> str:
return self._suffix return self._suffix

View file

@ -15,7 +15,6 @@
# You should have received a copy of the GNU Lesser General Public License # You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________ # ____________________________________________________________
from typing import Union
from itertools import chain from itertools import chain
from .error import PropertiesOptionError, ConstError, ConfigError, LeadershipError, display_list from .error import PropertiesOptionError, ConstError, ConfigError, LeadershipError, display_list
from .i18n import _ from .i18n import _
@ -103,35 +102,19 @@ read_write
you can get all variables not disabled and not hidden you can get all variables not disabled and not hidden
you can set all variables not frozen you can set all variables not frozen
""" """
RO_APPEND = frozenset(['frozen', RO_APPEND = frozenset(['frozen', 'disabled', 'validator', 'everything_frozen',
'disabled', 'mandatory', 'empty', 'force_store_value'])
'validator', RO_REMOVE = frozenset(['permissive', 'hidden'])
'everything_frozen', RW_APPEND = frozenset(['frozen', 'disabled', 'validator', 'hidden',
'mandatory', 'force_store_value'])
'empty', RW_REMOVE = frozenset(['permissive', 'everything_frozen', 'mandatory',
'force_store_value', 'empty'])
])
RO_REMOVE = frozenset(['permissive',
'hidden',
])
RW_APPEND = frozenset(['frozen',
'disabled',
'validator',
'hidden',
'force_store_value',
])
RW_REMOVE = frozenset(['permissive',
'everything_frozen',
'mandatory',
'empty',
])
FORBIDDEN_SET_PROPERTIES = frozenset(['force_store_value']) FORBIDDEN_SET_PROPERTIES = frozenset(['force_store_value'])
FORBIDDEN_SET_PERMISSIVES = frozenset(['force_default_on_freeze', FORBIDDEN_SET_PERMISSIVES = frozenset(['force_default_on_freeze',
'force_metaconfig_on_freeze', 'force_metaconfig_on_freeze',
'force_store_value', 'force_store_value'])
])
ALLOWED_LEADER_PROPERTIES = frozenset(['empty', ALLOWED_LEADER_PROPERTIES = frozenset(['empty',
'notempty', 'notempty',
'notunique', 'notunique',
@ -140,23 +123,11 @@ ALLOWED_LEADER_PROPERTIES = frozenset(['empty',
'mandatory', 'mandatory',
'force_default_on_freeze', 'force_default_on_freeze',
'force_metaconfig_on_freeze', 'force_metaconfig_on_freeze',
'frozen', 'frozen'])
])
static_set = frozenset() static_set = frozenset()
# ____________________________________________________________
class Undefined(object):
def __str__(self): # pragma: no cover
return 'Undefined'
__repr__ = __str__
undefined = Undefined()
class OptionBag: class OptionBag:
__slots__ = ('option', # current option __slots__ = ('option', # current option
'path', 'path',
@ -164,42 +135,38 @@ class OptionBag:
'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
'properties_setted',
'apply_requires', # apply requires or not for this option 'apply_requires', # apply requires or not for this option
) )
def __init__(self, def __init__(self):
option, self.option = None
index,
config_bag, def set_option(self,
path=None, option,
properties=undefined, index,
ori_option=None, config_bag):
apply_requires=True,
):
self.index = index
self.config_bag = config_bag
self.option = option
if ori_option is not None:
self.ori_option = ori_option
if config_bag is undefined: if config_bag is undefined:
self.path = path self.path = None
elif path: else:
self.path = path
elif option:
self.path = option.impl_getpath() self.path = option.impl_getpath()
if '.' not in self.path and option == config_bag.context.get_description(): self.index = index
self.properties = None self.option = option
elif properties is undefined: self.config_bag = config_bag
self.properties = config_bag.context.get_settings().getproperties(self, apply_requires=apply_requires)
if properties is not undefined:
self.properties = properties
def __getattr__(self, key): def __getattr__(self, key):
if key == 'ori_option': if key == 'ori_option':
return self.option return self.option
elif key == 'apply_requires': elif key == 'apply_requires':
return True return True
return undefined elif key == 'properties_setted':
return False
raise KeyError('unknown key "{}" for OptionBag'.format(key)) # pragma: no cover
def __setattr__(self, key, val):
super().__setattr__(key, val)
if key == 'properties':
self.properties_setted = True
def __delattr__(self, key): def __delattr__(self, key):
if key in ['properties', 'permissives']: if key in ['properties', 'permissives']:
@ -211,14 +178,10 @@ class OptionBag:
raise KeyError(_('cannot delete key "{}" for OptionBag').format(key)) # pragma: no cover raise KeyError(_('cannot delete key "{}" for OptionBag').format(key)) # pragma: no cover
def copy(self): def copy(self):
option_bag = OptionBag(None, option_bag = OptionBag()
None,
None,
)
for key in self.__slots__: for key in self.__slots__:
if not hasattr(self, key): if hasattr(self, key):
continue setattr(option_bag, key, getattr(self, key))
setattr(option_bag, key, getattr(self, key))
return option_bag return option_bag
@ -285,15 +248,13 @@ class _NameSpace(object):
def __setattr__(self, def __setattr__(self,
name, name,
value, value):
):
if name in self.__dict__: if name in self.__dict__:
raise ConstError(_("can't rebind {0}").format(name)) raise ConstError(_("can't rebind {0}").format(name))
self.__dict__[name] = value self.__dict__[name] = value
def __delattr__(self, def __delattr__(self,
name, name):
):
raise ConstError(_("can't unbind {0}").format(name)) raise ConstError(_("can't unbind {0}").format(name))
@ -327,7 +288,7 @@ class GroupModule(_NameSpace):
class OwnerModule(_NameSpace): class OwnerModule(_NameSpace):
"""emulates a module to manage unique owner names. """emulates a module to manage unique owner names.
owners are living in `Config._value_owners` owners are living in `Config._cfgimpl_value_owners`
""" """
class Owner(str): class Owner(str):
"""allowed owner names """allowed owner names
@ -381,6 +342,17 @@ owners.forced = owners.Owner('forced')
forbidden_owners = (owners.default, owners.forced) forbidden_owners = (owners.default, owners.forced)
# ____________________________________________________________
class Undefined(object):
def __str__(self): # pragma: no cover
return 'Undefined'
__repr__ = __str__
undefined = Undefined()
# ____________________________________________________________ # ____________________________________________________________
class Settings(object): class Settings(object):
"``config.Config()``'s configuration options settings" "``config.Config()``'s configuration options settings"
@ -415,15 +387,14 @@ class Settings(object):
# get properties and permissive methods # get properties and permissive methods
def get_context_properties(self, def get_context_properties(self,
cache, cache,
): ):
is_cached, props, validated = cache.getcache(None, is_cached, props, validated = cache.getcache(None,
None, None,
None, None,
{}, {},
{}, {},
'context_props', 'context_props')
)
if not is_cached: if not is_cached:
props = self._properties.get(None, {}).get(None, self.default_properties) props = self._properties.get(None, {}).get(None, self.default_properties)
cache.setcache(None, cache.setcache(None,
@ -446,11 +417,10 @@ class Settings(object):
return ret return ret
def getproperties(self, def getproperties(self,
option_bag, option_bag,
apply_requires=True, apply_requires=True,
uncalculated=False, uncalculated=False,
help_property=False, help_property=False):
):
""" """
""" """
option = option_bag.option option = option_bag.option
@ -460,14 +430,13 @@ class Settings(object):
path = option.impl_getpath() path = option.impl_getpath()
index = option_bag.index index = option_bag.index
if apply_requires and not uncalculated and not help_property: if apply_requires and not uncalculated and not help_property:
cache = config_bag.context.properties_cache cache = config_bag.context._impl_properties_cache
is_cached, props, validated = cache.getcache(path, is_cached, props, validated = cache.getcache(path,
config_bag.expiration_time, config_bag.expiration_time,
index, index,
config_bag.properties, config_bag.properties,
{}, {},
'self_props', 'self_props')
)
else: else:
is_cached = False is_cached = False
if not is_cached: if not is_cached:
@ -490,14 +459,14 @@ class Settings(object):
elif apply_requires: elif apply_requires:
if not help_property: if not help_property:
new_prop = prop.execute(option_bag, new_prop = prop.execute(option_bag,
leadership_must_have_index=True, leadership_must_have_index=True,
for_settings=True, for_settings=True,
) )
else: else:
new_prop = prop.help(option_bag, new_prop = prop.help(option_bag,
leadership_must_have_index=True, leadership_must_have_index=True,
for_settings=True, for_settings=True,
) )
if isinstance(new_prop, str): if isinstance(new_prop, str):
new_prop = (new_prop, new_prop) new_prop = (new_prop, new_prop)
if new_prop is None: if new_prop is None:
@ -552,8 +521,8 @@ class Settings(object):
return ret return ret
def getpermissives(self, def getpermissives(self,
option_bag, option_bag,
): ):
if option_bag is None: if option_bag is None:
path = None path = None
index = None index = None
@ -577,12 +546,13 @@ class Settings(object):
# set methods # set methods
def set_context_properties(self, properties, context): def set_context_properties(self, properties, context):
self._properties.setdefault(None, {})[None] = properties self._properties.setdefault(None, {})[None] = properties
context.reset_cache(None) context.cfgimpl_reset_cache(None)
def setproperties(self, def setproperties(self,
option_bag, path,
properties, properties,
): option_bag,
context):
"""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)
""" """
@ -602,22 +572,22 @@ class Settings(object):
raise LeadershipError(_('a leader ({0}) cannot have ' raise LeadershipError(_('a leader ({0}) cannot have '
'"force_default_on_freeze" or "force_metaconfig_on_freeze" property without "frozen"' '"force_default_on_freeze" or "force_metaconfig_on_freeze" property without "frozen"'
'').format(opt.impl_get_display_name())) '').format(opt.impl_get_display_name()))
self._properties.setdefault(option_bag.path, {})[option_bag.index] = properties self._properties.setdefault(path, {})[option_bag.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) context.cfgimpl_reset_cache(option_bag)
option_bag.properties = properties option_bag.properties = properties
def set_context_permissives(self, def set_context_permissives(self,
permissives, permissives,
): ):
self.setpermissives(None, self.setpermissives(None,
permissives, permissives,
) )
def setpermissives(self, def setpermissives(self,
option_bag, option_bag,
permissives, permissives,
): ):
""" """
enables us to put the permissives in the storage enables us to put the permissives in the storage
@ -645,66 +615,59 @@ class Settings(object):
' '.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 option_bag is not None:
option_bag.config_bag.context.reset_cache(option_bag) option_bag.config_bag.context.cfgimpl_reset_cache(option_bag)
#____________________________________________________________ #____________________________________________________________
# reset methods # reset methods
def _get_path_index_config_option(self,
bag: Union[OptionBag, ConfigBag],
msg: str,
):
if isinstance(bag, ConfigBag):
path = None
index = None
config_bag = bag
option_bag = None
else:
assert not bag.option.impl_is_symlinkoption(), \
_(msg).format(bag.option.impl_get_display_name())
path = bag.path
index = bag.index
config_bag = bag.config_bag
option_bag = bag
return path, index, config_bag, option_bag
def reset(self, def reset(self,
bag: Union[OptionBag, ConfigBag], option_bag,
): config_bag):
path, index, config_bag, option_bag = \ if option_bag is None:
self._get_path_index_config_option(bag, opt = None
"can't reset properties to " path = None
"the symlinkoption \"{}\"", index = None
) else:
opt = option_bag.option
assert not opt.impl_is_symlinkoption(), _("can't reset properties to "
"the symlinkoption \"{}\""
"").format(opt.impl_get_display_name())
path = option_bag.path
index = option_bag.index
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.cfgimpl_reset_cache(option_bag)
def reset_permissives(self, def reset_permissives(self,
bag: Union[OptionBag, ConfigBag], option_bag,
): config_bag):
path, index, config_bag, option_bag = \ if option_bag is None:
self._get_path_index_config_option(bag, opt = None
"can't reset permissives to " path = None
"the symlinkoption \"{}\"", index = None
) else:
opt = option_bag.option
assert not opt.impl_is_symlinkoption(), _("can't reset permissives to "
"the symlinkoption \"{}\""
"").format(opt.impl_get_display_name())
index = option_bag.index
path = option_bag.path
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.cfgimpl_reset_cache(option_bag)
#____________________________________________________________ #____________________________________________________________
# validate properties # validate properties
def calc_raises_properties(self, def calc_raises_properties(self,
option_bag, option_bag,
apply_requires=True, apply_requires=True,
uncalculated=False, uncalculated=False):
): if not uncalculated and apply_requires and option_bag.properties_setted:
if not uncalculated and apply_requires:
option_properties = option_bag.properties option_properties = option_bag.properties
else: else:
option_properties = self.getproperties(option_bag, option_properties = self.getproperties(option_bag,
apply_requires=apply_requires, apply_requires=apply_requires,
uncalculated=uncalculated, uncalculated=uncalculated)
)
return self._calc_raises_properties(option_bag.config_bag.properties, return self._calc_raises_properties(option_bag.config_bag.properties,
option_bag.config_bag.permissives, option_bag.config_bag.permissives,
option_properties) option_properties)
@ -722,9 +685,8 @@ class Settings(object):
return properties return properties
def validate_properties(self, def validate_properties(self,
option_bag, option_bag,
need_help=True, need_help=True):
):
config_properties = option_bag.config_bag.properties config_properties = option_bag.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
@ -733,13 +695,11 @@ class Settings(object):
if properties != frozenset(): if properties != frozenset():
if need_help: if need_help:
help_properties = dict(self.getproperties(option_bag, help_properties = dict(self.getproperties(option_bag,
help_property=True, help_property=True))
))
calc_properties = [] calc_properties = []
for property_ in self._calc_raises_properties(option_bag.config_bag.properties, for property_ in self._calc_raises_properties(option_bag.config_bag.properties,
option_bag.config_bag.permissives, option_bag.config_bag.permissives,
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:
@ -751,10 +711,9 @@ class Settings(object):
def validate_mandatory(self, def validate_mandatory(self,
value, value,
option_bag, option_bag):
):
if 'mandatory' in option_bag.config_bag.properties: if 'mandatory' in option_bag.config_bag.properties:
values = option_bag.config_bag.context.get_values() values = option_bag.config_bag.context.cfgimpl_get_values()
if option_bag.option.impl_is_follower(): if option_bag.option.impl_is_follower():
force_allow_empty_list = True force_allow_empty_list = True
else: else:
@ -762,23 +721,19 @@ class Settings(object):
if not ('permissive' in option_bag.config_bag.properties and if not ('permissive' in option_bag.config_bag.properties and
'mandatory' in option_bag.config_bag.permissives) and \ 'mandatory' in option_bag.config_bag.permissives) and \
'mandatory' in option_bag.properties and values.isempty(option_bag.option, 'mandatory' in option_bag.properties and values.isempty(option_bag.option,
value, value,
force_allow_empty_list=force_allow_empty_list, force_allow_empty_list=force_allow_empty_list,
index=option_bag.index, index=option_bag.index):
):
raise PropertiesOptionError(option_bag, raise PropertiesOptionError(option_bag,
['mandatory'], ['mandatory'],
self, self)
)
if 'empty' in option_bag.properties and values.isempty(option_bag.option, if 'empty' in option_bag.properties and values.isempty(option_bag.option,
value, value,
force_allow_empty_list=True, force_allow_empty_list=True,
index=option_bag.index, index=option_bag.index):
):
raise PropertiesOptionError(option_bag, raise PropertiesOptionError(option_bag,
['empty'], ['empty'],
self, self)
)
def validate_frozen(self, def validate_frozen(self,
option_bag): option_bag):
@ -795,10 +750,9 @@ class Settings(object):
# read only/read write # read only/read write
def _read(self, def _read(self,
remove, remove,
append, append,
config_bag, config_bag):
):
props = self._properties.get(None, {}).get(None, self.default_properties) props = self._properties.get(None, {}).get(None, self.default_properties)
modified = False modified = False
if remove & props: if remove & props:
@ -809,23 +763,19 @@ class Settings(object):
modified = True modified = True
if modified: if modified:
self.set_context_properties(frozenset(props), self.set_context_properties(frozenset(props),
config_bag.context, config_bag.context,
) )
def read_only(self, def read_only(self,
config_bag, config_bag):
):
"convenience method to freeze, hide and disable" "convenience method to freeze, hide and disable"
self._read(self.ro_remove, self._read(self.ro_remove,
self.ro_append, self.ro_append,
config_bag, config_bag)
)
def read_write(self, def read_write(self,
config_bag, config_bag):
):
"convenience method to freeze, hide and disable" "convenience method to freeze, hide and disable"
self._read(self.rw_remove, self._read(self.rw_remove,
self.rw_append, self.rw_append,
config_bag, config_bag)
)

View file

@ -152,11 +152,10 @@ class Requires(object):
self.tiramisu_web.set_remotable(leader.option.path(), form, leader) self.tiramisu_web.set_remotable(leader.option.path(), form, leader)
def manage_requires(self, def manage_requires(self,
childapi, childapi,
path, path,
form, form,
current_action, current_action):
):
for requires in childapi.option.properties(uncalculated=True): for requires in childapi.option.properties(uncalculated=True):
if not isinstance(requires, str): if not isinstance(requires, str):
option = requires.params.kwargs['condition'].option option = requires.params.kwargs['condition'].option
@ -366,15 +365,14 @@ class TiramisuDict:
form.setdefault(leader.option.path(), {})['remote'] = True form.setdefault(leader.option.path(), {})['remote'] = True
def walk(self, def walk(self,
root, root,
subchildapi, subchildapi,
schema, schema,
model, model,
form, form,
order, order,
updates_status, updates_status,
init=False, init=False):
):
error = None error = None
if init: if init:
if form is not None: if form is not None:
@ -400,26 +398,22 @@ class TiramisuDict:
props_no_requires = set(childapi.option.properties()) props_no_requires = set(childapi.option.properties())
if form is not None: if form is not None:
self.requires.add(path, self.requires.add(path,
childapi, childapi,
form, form)
)
self.consistencies.add(path, self.consistencies.add(path,
childapi, childapi,
form, form)
)
self.callbacks.add(path, self.callbacks.add(path,
childapi, childapi,
schema, schema,
'force_store_value' in props_no_requires, 'force_store_value' in props_no_requires)
)
childapi_option = childapi.option childapi_option = childapi.option
if model is not None and childapi.option.isoptiondescription() or not childapi_option.issymlinkoption(): if model is not None and childapi.option.isoptiondescription() or not childapi_option.issymlinkoption():
self.gen_model(model, self.gen_model(model,
childapi, childapi,
path, path,
leader_len, leader_len,
updates_status, updates_status)
)
if order is not None: if order is not None:
order.append(path) order.append(path)
if childapi.option.isoptiondescription(): if childapi.option.isoptiondescription():
@ -435,13 +429,12 @@ class TiramisuDict:
else: else:
subschema = schema subschema = schema
self.walk(path, self.walk(path,
childapi, childapi,
subschema, subschema,
model, model,
form, form,
order, order,
updates_status, updates_status)
)
else: else:
child = childapi_option.get() child = childapi_option.get()
childtype = child.__class__.__name__ childtype = child.__class__.__name__
@ -468,24 +461,22 @@ class TiramisuDict:
if schema is not None: if schema is not None:
self.gen_schema(schema, self.gen_schema(schema,
childapi, childapi,
childapi_option, childapi_option,
path, path,
props_no_requires, props_no_requires,
value, value,
defaultmulti, defaultmulti,
is_multi, is_multi,
web_type, web_type,
form, form)
)
if form is not None: if form is not None:
self.gen_form(form, self.gen_form(form,
web_type, web_type,
path, path,
child, child,
childapi_option, childapi_option,
childtype, childtype)
)
if schema is not None: if schema is not None:
if web_type != 'symlink': if web_type != 'symlink':
schema[path]['title'] = childapi_option.description() schema[path]['title'] = childapi_option.description()
@ -511,17 +502,16 @@ class TiramisuDict:
def gen_schema(self, def gen_schema(self,
schema, schema,
childapi, childapi,
childapi_option, childapi_option,
path, path,
props_no_requires, props_no_requires,
value, value,
defaultmulti, defaultmulti,
is_multi, is_multi,
web_type, web_type,
form, form):
):
schema[path] = {'type': web_type} schema[path] = {'type': web_type}
if childapi_option.issymlinkoption(): if childapi_option.issymlinkoption():
sym_option = childapi_option.get() sym_option = childapi_option.get()
@ -555,11 +545,10 @@ class TiramisuDict:
def get_enum(self, def get_enum(self,
childapi, childapi,
is_multi, is_multi,
path, path,
props_no_requires, props_no_requires):
):
values = childapi.value.list() values = childapi.value.list()
empty_is_required = not childapi.option.isfollower() and is_multi empty_is_required = not childapi.option.isfollower() and is_multi
if '' not in values and ((empty_is_required and not 'empty' in props_no_requires) or \ if '' not in values and ((empty_is_required and not 'empty' in props_no_requires) or \
@ -568,13 +557,12 @@ class TiramisuDict:
return values return values
def gen_form(self, def gen_form(self,
form, form,
web_type, web_type,
path, path,
child, child,
childapi_option, childapi_option,
childtype, childtype):
):
obj_form = {} obj_form = {}
if path in form: if path in form:
obj_form.update(form[path]) obj_form.update(form[path])
@ -613,14 +601,13 @@ class TiramisuDict:
form[path] = obj_form form[path] = obj_form
def calc_raises_properties(self, def calc_raises_properties(self,
obj, obj,
childapi, childapi):
): old_properties = childapi._option_bag.config_bag.properties
old_properties = childapi._config_bag.properties config = childapi._option_bag.config_bag.context
config = childapi._config_bag.context settings = config.cfgimpl_get_settings()
settings = config.get_settings() childapi._option_bag.config_bag.properties = self.config.property.get(default=True) # settings.get_context_properties(config._impl_properties_cache)
childapi._config_bag.properties = self.config.property.get(default=True) # settings.get_context_properties(config._impl_properties_cache) childapi._option_bag.config_bag.properties -= {'permissive'}
childapi._config_bag.properties -= {'permissive'}
properties = childapi.property.get(only_raises=True, properties = childapi.property.get(only_raises=True,
uncalculated=True) uncalculated=True)
properties -= childapi.permissive.get() properties -= childapi.permissive.get()
@ -631,13 +618,12 @@ class TiramisuDict:
properties -= self.config.permissive.get() properties -= self.config.permissive.get()
if properties: if properties:
obj['hidden'] = True obj['hidden'] = True
childapi._config_bag.properties = old_properties childapi._option_bag.config_bag.properties = old_properties
def _gen_model_properties(self, def _gen_model_properties(self,
childapi, childapi,
path, path,
index, index):
):
isfollower = childapi.option.isfollower() isfollower = childapi.option.isfollower()
props = set(childapi.property.get()) props = set(childapi.property.get())
obj = self.gen_properties(props, obj = self.gen_properties(props,
@ -681,12 +667,11 @@ class TiramisuDict:
return obj return obj
def gen_model(self, def gen_model(self,
model, model,
childapi, childapi,
path, path,
leader_len, leader_len,
updates_status, updates_status):
):
if childapi.option.isoptiondescription(): if childapi.option.isoptiondescription():
props = set(childapi.property.get()) props = set(childapi.property.get())
obj = {} obj = {}
@ -701,31 +686,27 @@ class TiramisuDict:
pass pass
else: else:
obj = self._gen_model_properties(childapi, obj = self._gen_model_properties(childapi,
path, path,
None, None)
)
if childapi.option.isfollower(): if childapi.option.isfollower():
for index in range(leader_len): for index in range(leader_len):
follower_childapi = self.config.unrestraint.option(path, index) follower_childapi = self.config.unrestraint.option(path, index)
sobj = self._gen_model_properties(follower_childapi, sobj = self._gen_model_properties(follower_childapi,
path, path,
index, index)
)
self._get_model_value(follower_childapi, self._get_model_value(follower_childapi,
path, path,
sobj, sobj,
index, index,
updates_status, updates_status)
)
if sobj: if sobj:
model.setdefault(path, {})[str(index)] = sobj model.setdefault(path, {})[str(index)] = sobj
else: else:
self._get_model_value(childapi, self._get_model_value(childapi,
path, path,
obj, obj,
None, None,
updates_status, updates_status)
)
if obj: if obj:
if not childapi.option.isoptiondescription() and childapi.option.isfollower(): if not childapi.option.isoptiondescription() and childapi.option.isfollower():
model.setdefault(path, {})['null'] = obj model.setdefault(path, {})['null'] = obj
@ -733,12 +714,11 @@ class TiramisuDict:
model[path] = obj model[path] = obj
def _get_model_value(self, def _get_model_value(self,
childapi, childapi,
path, path,
obj, obj,
index, index,
updates_status, updates_status):
):
if path in updates_status and index in updates_status[path]: if path in updates_status and index in updates_status[path]:
value = childapi.value.get() value = childapi.value.get()
self._get_value_with_exception(obj, self._get_value_with_exception(obj,
@ -759,7 +739,7 @@ class TiramisuDict:
value = self.config.unrestraint.option(path, index=index).value.get() value = self.config.unrestraint.option(path, index=index).value.get()
except PropertiesOptionError as err: except PropertiesOptionError as err:
config_bag = self.config._config_bag config_bag = self.config._config_bag
settings = config_bag.context.get_settings() settings = config_bag.context.cfgimpl_get_settings()
if settings._calc_raises_properties(config_bag.properties, if settings._calc_raises_properties(config_bag.properties,
config_bag.permissives, config_bag.permissives,
set(err.proptype)): set(err.proptype)):
@ -855,10 +835,9 @@ class TiramisuDict:
childapi.value.set(multi) childapi.value.set(multi)
def apply_updates(self, def apply_updates(self,
oripath, oripath,
updates, updates,
model_ori, model_ori):
):
updates_status = {} updates_status = {}
for update in updates: for update in updates:
path = update['name'] path = update['name']
@ -873,15 +852,13 @@ class TiramisuDict:
try: try:
if update['action'] == 'modify': if update['action'] == 'modify':
self.mod_value(childapi, self.mod_value(childapi,
path, path,
index, index,
update.get('value', undefined), update.get('value', undefined))
)
elif update['action'] == 'delete': elif update['action'] == 'delete':
self.del_value(childapi, self.del_value(childapi,
path, path,
index, index)
)
elif update['action'] == 'add': elif update['action'] == 'add':
if childapi_option.ismulti(): if childapi_option.ismulti():
self.add_value(childapi, path, update['value']) self.add_value(childapi, path, update['value'])
@ -896,22 +873,19 @@ class TiramisuDict:
return updates_status return updates_status
def set_updates(self, def set_updates(self,
body, body):
):
root_path = self.root root_path = self.root
updates = body.get('updates', []) updates = body.get('updates', [])
updates_status = self.apply_updates(root_path, updates_status = self.apply_updates(root_path,
updates, updates,
body.get('model'), body.get('model'))
)
if 'model' in body: if 'model' in body:
order = [] order = []
old_model = body['model'] old_model = body['model']
new_model = self.todict(order=order, new_model = self.todict(order=order,
build_schema=False, build_schema=False,
build_form=False, build_form=False,
updates_status=updates_status, updates_status=updates_status)
)
values = {'updates': list_keys(old_model, new_model['model'], order, updates_status), values = {'updates': list_keys(old_model, new_model['model'], order, updates_status),
'model': new_model['model']} 'model': new_model['model']}
else: else:
@ -919,13 +893,12 @@ class TiramisuDict:
return values return values
def todict(self, def todict(self,
custom_form=[], custom_form=[],
build_schema=True, build_schema=True,
build_model=True, build_model=True,
build_form=True, build_form=True,
order=None, order=None,
updates_status={}, updates_status={}):
):
rootpath = self.root rootpath = self.root
if build_schema: if build_schema:
schema = {} schema = {}
@ -941,14 +914,13 @@ class TiramisuDict:
else: else:
form = None form = None
self.walk(rootpath, self.walk(rootpath,
None, None,
schema, schema,
model, model,
form, form,
order, order,
updates_status, updates_status,
init=True, init=True)
)
if build_form: if build_form:
for form_ in custom_form: for form_ in custom_form:
if 'key' in form_: if 'key' in form_:

View file

@ -101,9 +101,9 @@ class Values:
def force_to_metaconfig(self, option_bag): def force_to_metaconfig(self, option_bag):
# force_metaconfig_on_freeze in config => to metaconfig # force_metaconfig_on_freeze in config => to metaconfig
# force_metaconfig_on_freeze in option + config is kernelconfig => to metaconfig # force_metaconfig_on_freeze in option + config is kernelconfig => to metaconfig
settings = option_bag.config_bag.context.get_settings() settings = option_bag.config_bag.context.cfgimpl_get_settings()
if 'force_metaconfig_on_freeze' in option_bag.properties: if 'force_metaconfig_on_freeze' in option_bag.properties:
settings = option_bag.config_bag.context.get_settings() settings = option_bag.config_bag.context.cfgimpl_get_settings()
if 'force_metaconfig_on_freeze' in option_bag.option.impl_getproperties() and \ if 'force_metaconfig_on_freeze' in option_bag.option.impl_getproperties() and \
not settings._properties.get(option_bag.path, {}).get(None, frozenset()): not settings._properties.get(option_bag.path, {}).get(None, frozenset()):
# if force_metaconfig_on_freeze is only in option (not in config) # if force_metaconfig_on_freeze is only in option (not in config)
@ -113,9 +113,8 @@ class Values:
return False return False
def _do_value_list(self, def _do_value_list(self,
value: Any, value: Any,
option_bag: OptionBag, option_bag: OptionBag):
):
ret = [] ret = []
for val in value: for val in value:
if isinstance(val, (list, tuple)): if isinstance(val, (list, tuple)):
@ -127,8 +126,8 @@ class Values:
return ret return ret
def getvalue(self, def getvalue(self,
option_bag, option_bag,
): ):
"""actually retrieves the value """actually retrieves the value
:param path: the path of the `Option` :param path: the path of the `Option`
@ -181,7 +180,7 @@ class Values:
moption_bag = self._get_modified_parent(option_bag) moption_bag = self._get_modified_parent(option_bag)
if moption_bag is not None: if moption_bag 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 moption_bag.config_bag.context.cfgimpl_get_values().get_cached_value(moption_bag)
# now try to get default value: # now try to get default value:
value = self.calc_value(option_bag, value = self.calc_value(option_bag,
@ -227,7 +226,7 @@ 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) option_bag.config_bag.context.cfgimpl_reset_cache(option_bag)
# and manage force_store_value # and manage force_store_value
self._set_force_value_suffix(option_bag) self._set_force_value_suffix(option_bag)
@ -247,10 +246,10 @@ class Values:
#______________________________________________________________________ #______________________________________________________________________
# set value # set value
def set_value(self, def setvalue(self,
option_bag, value,
value, option_bag,
): ):
context = option_bag.config_bag.context context = option_bag.config_bag.context
owner = self.get_context_owner() owner = self.get_context_owner()
if 'validator' in option_bag.config_bag.properties: if 'validator' in option_bag.config_bag.properties:
@ -283,36 +282,30 @@ class Values:
def setvalue_validation(self, def setvalue_validation(self,
value, value,
option_bag, option_bag):
): settings = option_bag.config_bag.context.cfgimpl_get_settings()
settings = option_bag.config_bag.context.get_settings()
# First validate properties with this value # First validate properties with this value
opt = option_bag.option opt = option_bag.option
settings.validate_frozen(option_bag) settings.validate_frozen(option_bag)
val = self.calc_value(option_bag, val = self.calc_value(option_bag, value, False)
value,
False,)
settings.validate_mandatory(val, settings.validate_mandatory(val,
option_bag, option_bag)
)
# Value must be valid for option # Value must be valid for option
opt.impl_validate(val, opt.impl_validate(val,
option_bag, option_bag,
check_error=True, check_error=True)
)
if 'warnings' in option_bag.config_bag.properties: if 'warnings' in option_bag.config_bag.properties:
# No error found so emit warnings # No error found so emit warnings
opt.impl_validate(value, opt.impl_validate(value,
option_bag, option_bag,
check_error=False, check_error=False)
)
def _setvalue(self, def _setvalue(self,
option_bag: OptionBag, option_bag: OptionBag,
value: Any, value: Any,
owner: str, owner: str,
) -> None: ) -> None:
option_bag.config_bag.context.reset_cache(option_bag) option_bag.config_bag.context.cfgimpl_reset_cache(option_bag)
self.set_storage_value(option_bag.path, self.set_storage_value(option_bag.path,
option_bag.index, option_bag.index,
value, value,
@ -350,7 +343,7 @@ class Values:
if not force_store_options: if not force_store_options:
continue continue
rootpath = option.impl_getpath() rootpath = option.impl_getpath()
settings = option_bag.config_bag.context.get_settings() settings = option_bag.config_bag.context.cfgimpl_get_settings()
for suffix in option.get_suffixes(option_bag.config_bag): for suffix in option.get_suffixes(option_bag.config_bag):
for coption in force_store_options: for coption in force_store_options:
subpaths = [rootpath] + coption.impl_getpath()[len(rootpath) + 1:].split('.')[:-1] subpaths = [rootpath] + coption.impl_getpath()[len(rootpath) + 1:].split('.')[:-1]
@ -362,24 +355,26 @@ class Values:
) )
if coption.impl_is_follower(): if coption.impl_is_follower():
leader = coption.impl_get_leadership().get_leader() leader = coption.impl_get_leadership().get_leader()
loption_bag = OptionBag(leader, loption_bag = OptionBag()
None, loption_bag.set_option(leader,
option_bag.config_bag, None,
properties=frozenset(), option_bag.config_bag,
) )
loption_bag.properties = frozenset()
indexes = range(len(self.getvalue(loption_bag))) indexes = range(len(self.getvalue(loption_bag)))
else: else:
indexes = [None] indexes = [None]
for index in indexes: for index in indexes:
coption_bag = OptionBag(doption, coption_bag = OptionBag()
index, coption_bag.set_option(doption,
option_bag.config_bag, index,
) option_bag.config_bag,
)
coption_bag.properties = settings.getproperties(coption_bag)
self._values.setdefault(coption_bag.path, {})[index] = [self.getvalue(coption_bag), owners.forced] self._values.setdefault(coption_bag.path, {})[index] = [self.getvalue(coption_bag), owners.forced]
def _get_modified_parent(self, def _get_modified_parent(self,
option_bag: OptionBag, option_bag: OptionBag) -> Optional[OptionBag]:
) -> Optional[OptionBag]:
""" 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
@ -398,14 +393,13 @@ class Values:
# 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
doption_bag.properties = doption_bag.config_bag.context.get_settings().getproperties(doption_bag) doption_bag.properties = doption_bag.config_bag.context.cfgimpl_get_settings().getproperties(doption_bag)
if not self.force_to_metaconfig(doption_bag): if not self.force_to_metaconfig(doption_bag):
doption_bag.properties = ori_properties - {'force_metaconfig_on_freeze'} doption_bag.properties = ori_properties - {'force_metaconfig_on_freeze'}
else: else:
doption_bag.properties = ori_properties doption_bag.properties = ori_properties
parent_owner = parent.get_values().getowner(doption_bag, parent_owner = parent.cfgimpl_get_values().getowner(doption_bag,
only_default=True, only_default=True)
)
if parent_owner != owners.default: if parent_owner != owners.default:
return doption_bag return doption_bag
@ -439,8 +433,7 @@ class Values:
def getowner(self, def getowner(self,
option_bag, option_bag,
validate_meta=True, validate_meta=True,
only_default=False, only_default=False):
):
""" """
retrieves the option's owner retrieves the option's owner
@ -456,7 +449,7 @@ class Values:
opt = opt.impl_getopt() opt = opt.impl_getopt()
option_bag.option = opt option_bag.option = opt
option_bag.path = opt.impl_getpath() option_bag.path = opt.impl_getpath()
settings = context.get_settings() settings = context.cfgimpl_get_settings()
settings.validate_properties(option_bag) settings.validate_properties(option_bag)
if 'frozen' in option_bag.properties and \ if 'frozen' in option_bag.properties and \
'force_default_on_freeze' in option_bag.properties: 'force_default_on_freeze' in option_bag.properties:
@ -473,17 +466,16 @@ class Values:
'frozen' in option_bag.properties and 'force_metaconfig_on_freeze' in option_bag.properties): 'frozen' in option_bag.properties and 'force_metaconfig_on_freeze' in option_bag.properties):
moption_bag = self._get_modified_parent(option_bag) moption_bag = self._get_modified_parent(option_bag)
if moption_bag is not None: if moption_bag is not None:
owner = moption_bag.config_bag.context.get_values().getowner(moption_bag, owner = moption_bag.config_bag.context.cfgimpl_get_values().getowner(moption_bag,
only_default=only_default, only_default=only_default)
)
elif 'force_metaconfig_on_freeze' in option_bag.properties: elif 'force_metaconfig_on_freeze' in option_bag.properties:
return owners.default return owners.default
return owner return owner
def set_owner(self, def setowner(self,
option_bag, owner,
owner, option_bag,
): ):
""" """
sets a owner to an option sets a owner to an option
@ -500,7 +492,7 @@ class Values:
if not self.hasvalue(option_bag.path, option_bag.index): if not self.hasvalue(option_bag.path, option_bag.index):
raise ConfigError(_('no value for {0} cannot change owner to {1}' raise ConfigError(_('no value for {0} cannot change owner to {1}'
'').format(option_bag.path, owner)) '').format(option_bag.path, owner))
option_bag.config_bag.context.get_settings().validate_frozen(option_bag) option_bag.config_bag.context.cfgimpl_get_settings().validate_frozen(option_bag)
self._values[option_bag.path][option_bag.index][1] = owner self._values[option_bag.path][option_bag.index][1] = owner
#______________________________________________________________________ #______________________________________________________________________
# reset # reset
@ -518,7 +510,7 @@ class Values:
config_bag.context = fake_context config_bag.context = fake_context
soption_bag = option_bag.copy() soption_bag = option_bag.copy()
soption_bag.config_bag = config_bag soption_bag.config_bag = config_bag
fake_value = fake_context.get_values() fake_value = fake_context.cfgimpl_get_values()
fake_value.reset(soption_bag) fake_value.reset(soption_bag)
soption_bag.config_bag.properties = option_bag.config_bag.properties soption_bag.config_bag.properties = option_bag.config_bag.properties
value = fake_value.getdefaultvalue(soption_bag) value = fake_value.getdefaultvalue(soption_bag)
@ -541,7 +533,7 @@ class Values:
value = None value = None
if option_bag.path in self._values: if option_bag.path in self._values:
del self._values[option_bag.path] del self._values[option_bag.path]
context.reset_cache(option_bag) context.cfgimpl_reset_cache(option_bag)
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.getdefaultvalue(option_bag) value = self.getdefaultvalue(option_bag)
@ -564,7 +556,7 @@ class Values:
setting_properties = option_bag.config_bag.properties setting_properties = option_bag.config_bag.properties
if 'validator' in setting_properties: if 'validator' in setting_properties:
fake_context = context._gen_fake_values() fake_context = context._gen_fake_values()
fake_value = fake_context.get_values() fake_value = fake_context.cfgimpl_get_values()
config_bag = option_bag.config_bag.copy() config_bag = option_bag.config_bag.copy()
config_bag.remove_validation() config_bag.remove_validation()
config_bag.context = fake_context config_bag.context = fake_context
@ -585,7 +577,7 @@ class Values:
self.resetvalue_index(option_bag.path, self.resetvalue_index(option_bag.path,
option_bag.index, option_bag.index,
) )
context.reset_cache(option_bag) context.cfgimpl_reset_cache(option_bag)
def resetvalue_index(self, def resetvalue_index(self,
path, path,
@ -595,10 +587,9 @@ class Values:
del self._values[path][index] del self._values[path][index]
def reset_leadership(self, def reset_leadership(self,
option_bag: OptionBag, index,
leadership_option_bag: OptionBag, option_bag,
index: int, subconfig):
):
current_value = self.get_cached_value(option_bag) current_value = self.get_cached_value(option_bag)
length = len(current_value) length = len(current_value)
if index >= length: if index >= length:
@ -607,13 +598,12 @@ class Values:
length, length,
option_bag.option.impl_get_display_name())) option_bag.option.impl_get_display_name()))
current_value.pop(index) current_value.pop(index)
leadership_option_bag.option.pop(self, subconfig.cfgimpl_get_description().pop(self,
index, index,
option_bag, option_bag)
) self.setvalue(current_value,
self.set_value(option_bag, option_bag,
current_value, )
)
#______________________________________________________________________ #______________________________________________________________________
# information # information
@ -636,7 +626,7 @@ class Values:
self._informations.setdefault(path, {})[key] = value self._informations.setdefault(path, {})[key] = value
if path is not None: if path is not None:
for option in option_bag.option.get_dependencies_information(itself=True): for option in option_bag.option.get_dependencies_information(itself=True):
config_bag.context.reset_cache(option_bag) config_bag.context.cfgimpl_reset_cache(option_bag)
def get_information(self, def get_information(self,
config_bag, config_bag,
@ -676,6 +666,95 @@ class Values:
): ):
return list(self._informations.get(path, {}).keys()) return list(self._informations.get(path, {}).keys())
#______________________________________________________________________
# mandatory warnings
def _mandatory_warnings(self,
context,
config_bag,
description,
currpath,
subconfig,
od_config_bag):
settings = context.cfgimpl_get_settings()
for option in description.get_children(config_bag):
name = option.impl_getname()
if option.impl_is_optiondescription():
try:
option_bag = OptionBag()
option_bag.set_option(option,
None,
od_config_bag)
option_bag.properties = settings.getproperties(option_bag)
subsubconfig = subconfig.get_subconfig(option_bag)
except PropertiesOptionError as err:
pass
else:
for option in self._mandatory_warnings(context,
config_bag,
option,
currpath + [name],
subsubconfig,
od_config_bag):
yield option
elif not option.impl_is_symlinkoption():
# don't verifying symlink
try:
if not option.impl_is_follower():
option_bag = OptionBag()
option_bag.set_option(option,
None,
config_bag)
option_bag.properties = settings.getproperties(option_bag)
if 'mandatory' in option_bag.properties or 'empty' in option_bag.properties:
subconfig.getattr(name,
option_bag)
else:
for index in range(subconfig.cfgimpl_get_length()):
option_bag = OptionBag()
option_bag.set_option(option,
index,
config_bag)
option_bag.properties = settings.getproperties(option_bag)
if 'mandatory' in option_bag.properties or 'empty' in option_bag.properties:
subconfig.getattr(name,
option_bag)
except PropertiesOptionError as err:
if err.proptype in (['mandatory'], ['empty']):
yield option.impl_getpath()
except ConfigError:
pass
def mandatory_warnings(self,
config_bag):
"""convenience function to trace Options that are mandatory and
where no value has been set
:returns: generator of mandatory Option's path
"""
context = config_bag.context
# copy
od_setting_properties = config_bag.properties - {'mandatory', 'empty'}
setting_properties = set(config_bag.properties) - {'warnings'}
setting_properties.update(['mandatory', 'empty'])
nconfig_bag = ConfigBag(context=config_bag.context,
properties=frozenset(setting_properties),
permissives=config_bag.permissives)
nconfig_bag.set_permissive()
od_config_bag = ConfigBag(context=nconfig_bag.context,
properties=frozenset(od_setting_properties),
permissives=nconfig_bag.permissives)
od_config_bag.set_permissive()
descr = context.cfgimpl_get_description()
for option in self._mandatory_warnings(context,
nconfig_bag,
descr,
[],
context,
od_config_bag):
yield option
#____________________________________________________________ #____________________________________________________________
# default owner methods # default owner methods
def set_context_owner(self, owner): def set_context_owner(self, owner):