Compare commits
No commits in common. "5.2.0a27" and "main" have entirely different histories.
68 changed files with 4388 additions and 6173 deletions
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -4,7 +4,7 @@ requires = ["flit_core >=3.8.0,<4"]
|
||||||
|
|
||||||
[project]
|
[project]
|
||||||
name = "tiramisu"
|
name = "tiramisu"
|
||||||
version = "5.2.0a27"
|
version = "5.1.0"
|
||||||
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
|
authors = [{name = "Emmanuel Garette", email = "gnunux@gnunux.info"}]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
description = "an options controller tool"
|
description = "an options controller tool"
|
||||||
|
|
@ -18,8 +18,6 @@ classifiers = [
|
||||||
"Programming Language :: Python :: 3.10",
|
"Programming Language :: Python :: 3.10",
|
||||||
"Programming Language :: Python :: 3.11",
|
"Programming Language :: Python :: 3.11",
|
||||||
"Programming Language :: Python :: 3.12",
|
"Programming Language :: Python :: 3.12",
|
||||||
"Programming Language :: Python :: 3.13",
|
|
||||||
"Programming Language :: Python :: 3.14",
|
|
||||||
"Programming Language :: Python :: 3",
|
"Programming Language :: Python :: 3",
|
||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
"Natural Language :: English",
|
"Natural Language :: English",
|
||||||
|
|
@ -35,9 +33,5 @@ name = "cz_conventional_commits"
|
||||||
tag_format = "$version"
|
tag_format = "$version"
|
||||||
version_scheme = "pep440"
|
version_scheme = "pep440"
|
||||||
version_provider = "pep621"
|
version_provider = "pep621"
|
||||||
version_files = [
|
|
||||||
"tiramisu/__version__.py",
|
|
||||||
"pyproject.toml:version"
|
|
||||||
]
|
|
||||||
#update_changelog_on_bump = true
|
#update_changelog_on_bump = true
|
||||||
changelog_merge_prerelease = true
|
changelog_merge_prerelease = true
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
# from json import dumps, loads
|
# from json import dumps, loads
|
||||||
|
import asyncio
|
||||||
from os import environ
|
from os import environ
|
||||||
try:
|
try:
|
||||||
from tiramisu_api import Config
|
from tiramisu_api import Config
|
||||||
|
|
@ -62,14 +63,3 @@ def parse_od_get(dico):
|
||||||
else:
|
else:
|
||||||
ret[k.path()] = v
|
ret[k.path()] = v
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
def get_dependencies(option):
|
|
||||||
ret = []
|
|
||||||
for a in option.dependencies():
|
|
||||||
if a.isoptiondescription():
|
|
||||||
ret.append((a.path(), None))
|
|
||||||
else:
|
|
||||||
ret.append((a.path(), a.index()))
|
|
||||||
ret.sort()
|
|
||||||
return ret
|
|
||||||
|
|
|
||||||
|
|
@ -69,11 +69,11 @@ def test_cache_importation_property():
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.option('u2').property.add('prop')
|
cfg.option('u2').property.add('prop')
|
||||||
export = cfg.property.exportation()
|
export = cfg.property.exportation()
|
||||||
assert cfg.option('u2').property.get() == {'validator', 'prop'}
|
assert cfg.option('u2').property.get() == {'prop'}
|
||||||
cfg.option('u2').property.add('prop2')
|
cfg.option('u2').property.add('prop2')
|
||||||
assert cfg.option('u2').property.get() == {'validator', 'prop', 'prop2'}
|
assert cfg.option('u2').property.get() == {'prop', 'prop2'}
|
||||||
cfg.property.importation(export)
|
cfg.property.importation(export)
|
||||||
assert cfg.option('u2').property.get() == {'validator', 'prop'}
|
assert cfg.option('u2').property.get() == {'prop'}
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
@ -366,8 +366,8 @@ def test_cache_leader_and_followers():
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
global_props = ['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']
|
global_props = ['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']
|
||||||
val1_props = []
|
val1_props = []
|
||||||
val1_val1_props = ['empty', 'unique', 'validator']
|
val1_val1_props = ['empty', 'unique']
|
||||||
val1_val2_props = ['validator']
|
val1_val2_props = []
|
||||||
global_props = frozenset(global_props)
|
global_props = frozenset(global_props)
|
||||||
val1_props = frozenset(val1_props)
|
val1_props = frozenset(val1_props)
|
||||||
val1_val1_props = frozenset(val1_val1_props)
|
val1_val1_props = frozenset(val1_val1_props)
|
||||||
|
|
@ -384,7 +384,7 @@ def test_cache_leader_and_followers():
|
||||||
#
|
#
|
||||||
cfg.option('val1.val1').value.set([None])
|
cfg.option('val1.val1').value.set([None])
|
||||||
val_val2_props = {idx_val2: (val1_val2_props, None), None: (set(), None)}
|
val_val2_props = {idx_val2: (val1_val2_props, None), None: (set(), None)}
|
||||||
compare(settings.get_cached(), {'val1.val1': {None: ({'validator', 'empty', 'unique'}, None, True)}})
|
compare(settings.get_cached(), {'val1.val1': {None: ({'empty', 'unique'}, None, True)}})
|
||||||
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
|
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
#has value
|
#has value
|
||||||
|
|
@ -416,8 +416,8 @@ def test_cache_leader_callback():
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
global_props = ['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']
|
global_props = ['cache', 'disabled', 'frozen', 'hidden', 'validator', 'warnings', 'force_store_value']
|
||||||
val1_props = []
|
val1_props = []
|
||||||
val1_val1_props = ['empty', 'unique', 'validator']
|
val1_val1_props = ['empty', 'unique']
|
||||||
val1_val2_props = ['validator']
|
val1_val2_props = []
|
||||||
global_props = frozenset(global_props)
|
global_props = frozenset(global_props)
|
||||||
val1_props = frozenset(val1_props)
|
val1_props = frozenset(val1_props)
|
||||||
val1_val1_props = frozenset(val1_val1_props)
|
val1_val1_props = frozenset(val1_val1_props)
|
||||||
|
|
@ -429,7 +429,7 @@ def test_cache_leader_callback():
|
||||||
})
|
})
|
||||||
compare(values.get_cached(), {'val1.val1': {None: ([], None)}})
|
compare(values.get_cached(), {'val1.val1': {None: ([], None)}})
|
||||||
cfg.option('val1.val1').value.set([None])
|
cfg.option('val1.val1').value.set([None])
|
||||||
compare(settings.get_cached(), {'val1.val1': {None: ({'unique', 'empty', 'validator'}, None, True)}})
|
compare(settings.get_cached(), {'val1.val1': {None: ({'unique', 'empty'}, None, True)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
|
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
|
|
@ -451,24 +451,24 @@ def test_cache_requires():
|
||||||
settings = cfg._config_bag.context.properties_cache
|
settings = cfg._config_bag.context.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(), {'activate_service': {None: ({'validator'}, None)},
|
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: ({"validator"}, None)}})
|
'ip_address_service': {None: (set([]), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
|
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
|
||||||
'activate_service': {None: (True, None)}})
|
'activate_service': {None: (True, None)}})
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
compare(settings.get_cached(), {'activate_service': {None: ({"validator"}, None)},
|
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: ({"validator"}, None)}})
|
'ip_address_service': {None: (set([]), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
|
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
|
||||||
'activate_service': {None: (True, None)}})
|
'activate_service': {None: (True, None)}})
|
||||||
cfg.option('ip_address_service').value.set('1.1.1.1')
|
cfg.option('ip_address_service').value.set('1.1.1.1')
|
||||||
compare(settings.get_cached(), {'activate_service': {None: ({"validator"}, None)}})
|
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'activate_service': {None: (True, None)}, 'ip_address_service': {None: ('1.1.1.1', None, True)}})
|
compare(values.get_cached(), {'activate_service': {None: (True, None)}, 'ip_address_service': {None: ('1.1.1.1', None, True)}})
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
compare(settings.get_cached(), {'activate_service': {None: ({"validator"}, None)},
|
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: ({"validator"}, None)}})
|
'ip_address_service': {None: (set([]), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'ip_address_service': {None: ('1.1.1.1', None)},
|
compare(values.get_cached(), {'ip_address_service': {None: ('1.1.1.1', None)},
|
||||||
'activate_service': {None: (True, None)}})
|
'activate_service': {None: (True, None)}})
|
||||||
|
|
@ -477,8 +477,8 @@ def test_cache_requires():
|
||||||
|
|
||||||
compare(values.get_cached(), {'activate_service': {None: (False, None)}})
|
compare(values.get_cached(), {'activate_service': {None: (False, None)}})
|
||||||
cfg.value.get()
|
cfg.value.get()
|
||||||
compare(settings.get_cached(), {'activate_service': {None: ({"validator"}, None)},
|
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: ({'disabled', "validator"}, None)}})
|
'ip_address_service': {None: (set(['disabled']), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'activate_service': {None: (False, None)}})
|
compare(values.get_cached(), {'activate_service': {None: (False, None)}})
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
@ -499,19 +499,19 @@ def test_cache_global_properties():
|
||||||
settings = cfg._config_bag.context.properties_cache
|
settings = cfg._config_bag.context.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(), {'activate_service': {None: ({"validator"}, None)},
|
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: ({"validator"}, None)}})
|
'ip_address_service': {None: (set([]), None)}})
|
||||||
|
|
||||||
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
|
compare(values.get_cached(), {'ip_address_service': {None: (None, None)},
|
||||||
'activate_service': {None: (True, None)}})
|
'activate_service': {None: (True, None)}})
|
||||||
cfg.property.remove('disabled')
|
cfg.property.remove('disabled')
|
||||||
assert cfg.option('ip_address_service').value.get() == None
|
assert cfg.option('ip_address_service').value.get() == None
|
||||||
compare(settings.get_cached(), {'activate_service': {None: ({"validator"}, None)},
|
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: ({"validator"}, None)}})
|
'ip_address_service': {None: (set([]), None)}})
|
||||||
cfg.property.add('test')
|
cfg.property.add('test')
|
||||||
assert cfg.option('ip_address_service').value.get() == None
|
assert cfg.option('ip_address_service').value.get() == None
|
||||||
compare(settings.get_cached(), {'activate_service': {None: ({"validator"}, None)},
|
compare(settings.get_cached(), {'activate_service': {None: (set([]), None)},
|
||||||
'ip_address_service': {None: ({"validator"}, None)}})
|
'ip_address_service': {None: (set([]), None)}})
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -162,10 +162,6 @@ def test_choiceoption_calc_opt_function(config_type):
|
||||||
cfg = get_config(cfg, config_type)
|
cfg = get_config(cfg, config_type)
|
||||||
assert cfg.option('choice').owner.isdefault()
|
assert cfg.option('choice').owner.isdefault()
|
||||||
#
|
#
|
||||||
dep = cfg.option('str').dependencies()
|
|
||||||
assert len(dep) == 1
|
|
||||||
assert dep[0].path() == 'choice'
|
|
||||||
#
|
|
||||||
cfg.option('choice').value.set('val1')
|
cfg.option('choice').value.set('val1')
|
||||||
assert cfg.option('choice').owner.get() == owner
|
assert cfg.option('choice').owner.get() == owner
|
||||||
#
|
#
|
||||||
|
|
@ -191,6 +187,7 @@ def test_choiceoption_calc_opt_function_propertyerror():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
#def test_choiceoption_calc_opt_multi_function(config_type):
|
||||||
def test_choiceoption_calc_opt_multi_function():
|
def test_choiceoption_calc_opt_multi_function():
|
||||||
# FIXME
|
# FIXME
|
||||||
config_type = 'tiramisu'
|
config_type = 'tiramisu'
|
||||||
|
|
|
||||||
|
|
@ -332,7 +332,7 @@ def test_duplicated_option():
|
||||||
g1
|
g1
|
||||||
#in same OptionDescription
|
#in same OptionDescription
|
||||||
with pytest.raises(ConflictError):
|
with pytest.raises(ConflictError):
|
||||||
OptionDescription('od', '', [g1, g1])
|
d1 = OptionDescription('od', '', [g1, g1])
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -346,28 +346,6 @@ def test_duplicated_option_diff_od():
|
||||||
Config(d2)
|
Config(d2)
|
||||||
|
|
||||||
|
|
||||||
def test_duplicated_option_diff_od_2():
|
|
||||||
g1 = IntOption('g1', '', 1)
|
|
||||||
d1 = OptionDescription('od1', '', [g1])
|
|
||||||
#in different OptionDescription
|
|
||||||
d2 = OptionDescription('od2', '', [d1, g1])
|
|
||||||
d2
|
|
||||||
with pytest.raises(ConflictError):
|
|
||||||
Config(d2)
|
|
||||||
|
|
||||||
|
|
||||||
def test_duplicated_option_diff_od_3():
|
|
||||||
g1 = IntOption('g1', '', 1)
|
|
||||||
d1 = OptionDescription('od1', '', [g1])
|
|
||||||
d3 = OptionDescription('od3', '', [g1])
|
|
||||||
#in different OptionDescription
|
|
||||||
d2 = OptionDescription('od2', '', [d1, d3])
|
|
||||||
d4 = OptionDescription('od4', '', [d2])
|
|
||||||
d4
|
|
||||||
with pytest.raises(ConflictError):
|
|
||||||
Config(d4)
|
|
||||||
|
|
||||||
|
|
||||||
def test_cannot_assign_value_to_option_description():
|
def test_cannot_assign_value_to_option_description():
|
||||||
od1 = make_description()
|
od1 = make_description()
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
|
|
@ -402,12 +380,12 @@ def test_prefix_error():
|
||||||
try:
|
try:
|
||||||
cfg.option('test1').value.set('yes')
|
cfg.option('test1').value.set('yes')
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
assert str(err) == _('"{0}" is an invalid {1} for "{2}", it\'s not an integer').format('yes', _('integer'), 'test1')
|
assert str(err) == _('"{0}" is an invalid {1} for "{2}"').format('yes', _('integer'), 'test1')
|
||||||
try:
|
try:
|
||||||
cfg.option('test1').value.set('yes')
|
cfg.option('test1').value.set('yes')
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
err.prefix = ''
|
err.prefix = ''
|
||||||
assert str(err) == _('it\'s not an integer')
|
assert str(err) == _('invalid value')
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,12 @@ from tiramisu.error import PropertiesOptionError, ValueWarning, ConfigError
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
|
|
||||||
|
#def teardown_function(function):
|
||||||
|
# # test_od_not_list emit a warnings because of doesn't create a Config
|
||||||
|
# with warnings.catch_warnings(record=True) as w:
|
||||||
|
# assert list_sessions() == [], 'session list is not empty when leaving "{}"'.format(function.__name__)
|
||||||
|
|
||||||
|
|
||||||
def make_description():
|
def make_description():
|
||||||
gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
|
gcoption = ChoiceOption('name', 'GC name', ('ref', 'framework'), 'ref')
|
||||||
gcdummy = BoolOption('dummy', 'dummy', default=False)
|
gcdummy = BoolOption('dummy', 'dummy', default=False)
|
||||||
|
|
@ -346,8 +352,6 @@ def test_invalid_option():
|
||||||
PortOption('a', '', allow_zero=False, allow_wellknown=False, allow_registred=False, allow_private=False)
|
PortOption('a', '', allow_zero=False, allow_wellknown=False, allow_registred=False, allow_private=False)
|
||||||
with raises(ValueError):
|
with raises(ValueError):
|
||||||
PortOption('a', '', 'tcp:80')
|
PortOption('a', '', 'tcp:80')
|
||||||
with raises(ValueError):
|
|
||||||
PortOption('a', '', '')
|
|
||||||
NetworkOption('a', '')
|
NetworkOption('a', '')
|
||||||
with raises(ValueError):
|
with raises(ValueError):
|
||||||
NetworkOption('a', '', 'string')
|
NetworkOption('a', '', 'string')
|
||||||
|
|
@ -419,7 +423,7 @@ def test_config_reset():
|
||||||
cfg.owner.set('test')
|
cfg.owner.set('test')
|
||||||
assert cfg.owner.get() == 'test'
|
assert cfg.owner.get() == 'test'
|
||||||
assert not cfg.option('gc.gc2.bool').value.get()
|
assert not cfg.option('gc.gc2.bool').value.get()
|
||||||
assert cfg.option('boolop').property.get() == frozenset(["validator"])
|
assert not cfg.option('boolop').property.get()
|
||||||
assert not cfg.option('boolop').permissive.get()
|
assert not cfg.option('boolop').permissive.get()
|
||||||
assert not cfg.option('wantref').information.get('info', None)
|
assert not cfg.option('wantref').information.get('info', None)
|
||||||
#
|
#
|
||||||
|
|
@ -436,7 +440,7 @@ def test_config_reset():
|
||||||
cfg.config.reset()
|
cfg.config.reset()
|
||||||
assert cfg.owner.get() == 'test'
|
assert cfg.owner.get() == 'test'
|
||||||
assert not cfg.option('gc.gc2.bool').value.get()
|
assert not cfg.option('gc.gc2.bool').value.get()
|
||||||
assert cfg.option('boolop').property.get() == {"validator"}
|
assert not cfg.option('boolop').property.get()
|
||||||
assert not cfg.option('float').permissive.get()
|
assert not cfg.option('float').permissive.get()
|
||||||
assert not cfg.option('wantref').information.get('info', None)
|
assert not cfg.option('wantref').information.get('info', None)
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
|
||||||
|
|
@ -275,9 +275,3 @@ def test_url(config_type):
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('u').value.set('https://FOO.COM:8443')
|
cfg.option('u').value.set('https://FOO.COM:8443')
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_domainname_existence():
|
|
||||||
DomainnameOption('d', '', 'google.fr', test_existence=True)
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
DomainnameOption('d', '', 'ljijouuuehyfr.com', test_existence=True)
|
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,6 @@ def test_ip(config_type):
|
||||||
cfg.option('a').value.set('192.168.1.0')
|
cfg.option('a').value.set('192.168.1.0')
|
||||||
cfg.option('a').value.set('88.88.88.88')
|
cfg.option('a').value.set('88.88.88.88')
|
||||||
cfg.option('a').value.set('0.0.0.0')
|
cfg.option('a').value.set('0.0.0.0')
|
||||||
cfg.option('a').value.set('2001:db8::1')
|
|
||||||
if config_type != 'tiramisu-api':
|
if config_type != 'tiramisu-api':
|
||||||
# FIXME
|
# FIXME
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
|
|
@ -149,7 +148,8 @@ def test_network_cidr(config_type):
|
||||||
cfg.option('a').value.set('192.168.1.1')
|
cfg.option('a').value.set('192.168.1.1')
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('a').value.set('192.168.1.1/24')
|
cfg.option('a').value.set('192.168.1.1/24')
|
||||||
cfg.option('a').value.set('2001:db00::0/24')
|
with pytest.raises(ValueError):
|
||||||
|
cfg.option('a').value.set('2001:db00::0/24')
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -197,7 +197,8 @@ def test_broadcast(config_type):
|
||||||
cfg.option('a').value.set(1)
|
cfg.option('a').value.set(1)
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
cfg.option('a').value.set(2)
|
cfg.option('a').value.set(2)
|
||||||
cfg.option('a').value.set('2001:db8::1')
|
with pytest.raises(ValueError):
|
||||||
|
cfg.option('a').value.set('2001:db8::1')
|
||||||
cfg.option('a').value.set('0.0.0.0')
|
cfg.option('a').value.set('0.0.0.0')
|
||||||
cfg.option('a').value.set('255.255.255.0')
|
cfg.option('a').value.set('255.255.255.0')
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
|
||||||
|
|
@ -80,15 +80,15 @@ def test_copy_force_store_value():
|
||||||
assert conf.value.exportation() == {'creole.general.wantref': {None: [True, 'user']}}
|
assert conf.value.exportation() == {'creole.general.wantref': {None: [True, 'user']}}
|
||||||
assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
assert conf2.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_copy_force_store_value_metaconfig():
|
#def test_copy_force_store_value_metaconfig():
|
||||||
od1 = make_description()
|
# od1 = make_description()
|
||||||
meta = MetaConfig([], optiondescription=od1)
|
# meta = MetaConfig([], optiondescription=od1)
|
||||||
conf = meta.config.new()
|
# conf = meta.config.new()
|
||||||
assert meta.property.get() == conf.property.get()
|
# assert meta.property.get() == conf.property.get()
|
||||||
assert meta.permissive.get() == conf.permissive.get()
|
# assert meta.permissive.get() == conf.permissive.get()
|
||||||
conf.property.read_write()
|
# conf.property.read_write()
|
||||||
assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
# assert conf.value.exportation() == {'creole.general.wantref': {None: [False, 'forced']}}
|
||||||
assert meta.value.exportation() == {}
|
# assert meta.value.exportation() == {}
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
# coding: utf-8
|
# coding: utf-8
|
||||||
from .autopath import do_autopath
|
from .autopath import do_autopath
|
||||||
do_autopath()
|
do_autopath()
|
||||||
from .config import parse_od_get, get_dependencies
|
from .config import parse_od_get
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
from tiramisu.setting import groups, owners
|
from tiramisu.setting import groups, owners
|
||||||
|
|
@ -13,7 +13,7 @@ from tiramisu import BoolOption, StrOption, ChoiceOption, IPOption, \
|
||||||
Config, \
|
Config, \
|
||||||
Params, ParamOption, ParamValue, ParamIdentifier, ParamSelfOption, ParamDynOption, ParamIndex, ParamSelfInformation, ParamInformation, \
|
Params, ParamOption, ParamValue, ParamIdentifier, ParamSelfOption, ParamDynOption, ParamIndex, ParamSelfInformation, ParamInformation, \
|
||||||
Calculation, calc_value
|
Calculation, calc_value
|
||||||
from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError, ValueOptionError, AttributeOptionError
|
from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError, ValueOptionError
|
||||||
|
|
||||||
|
|
||||||
def display_name(kls, subconfig, with_quote=False) -> str:
|
def display_name(kls, subconfig, with_quote=False) -> str:
|
||||||
|
|
@ -28,8 +28,6 @@ def display_name(kls, subconfig, with_quote=False) -> str:
|
||||||
class ConvertDynOptionDescription(DynOptionDescription):
|
class ConvertDynOptionDescription(DynOptionDescription):
|
||||||
def convert_identifier_to_path(self, identifier):
|
def convert_identifier_to_path(self, identifier):
|
||||||
# remove dot with is illegal
|
# remove dot with is illegal
|
||||||
if not identifier:
|
|
||||||
return identifier
|
|
||||||
return identifier.replace('.', '')
|
return identifier.replace('.', '')
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -39,18 +37,6 @@ def return_true(value, param=None, identifier=None):
|
||||||
raise ValueError('no value')
|
raise ValueError('no value')
|
||||||
|
|
||||||
|
|
||||||
def return_no_dyn(value):
|
|
||||||
if value in [['val', 'val'], ['yes', 'yes']]:
|
|
||||||
return
|
|
||||||
raise ValueError('no value')
|
|
||||||
|
|
||||||
|
|
||||||
def return_no_dyn_properties(value, identifier):
|
|
||||||
idx = int(identifier)
|
|
||||||
if idx and not value[idx - 1]:
|
|
||||||
return 'disabled'
|
|
||||||
|
|
||||||
|
|
||||||
def return_dynval(value='val', identifier=None):
|
def return_dynval(value='val', identifier=None):
|
||||||
return value
|
return value
|
||||||
|
|
||||||
|
|
@ -314,37 +300,23 @@ def test_prop_dyndescription():
|
||||||
od = OptionDescription('od', '', [dod])
|
od = OptionDescription('od', '', [dod])
|
||||||
od2 = OptionDescription('od', '', [od])
|
od2 = OptionDescription('od', '', [od])
|
||||||
cfg = Config(od2)
|
cfg = Config(od2)
|
||||||
assert set(cfg.option('od.dodval1.st').property.get()) == {'test', "validator"}
|
assert set(cfg.option('od.dodval1.st').property.get()) == set(['test'])
|
||||||
assert set(cfg.option('od.dodval2.st').property.get()) == {'test', "validator"}
|
assert set(cfg.option('od.dodval2.st').property.get()) == set(['test'])
|
||||||
cfg.option('od.dodval2.st').property.add('test2')
|
cfg.option('od.dodval2.st').property.add('test2')
|
||||||
assert set(cfg.option('od.dodval1.st').property.get()) == {'test', "validator"}
|
assert set(cfg.option('od.dodval1.st').property.get()) == set(['test'])
|
||||||
assert set(cfg.option('od.dodval2.st').property.get()) == {'test', 'test2', "validator"}
|
assert set(cfg.option('od.dodval2.st').property.get()) == set(['test', 'test2'])
|
||||||
#
|
#
|
||||||
assert set(cfg.option('od.dodval1').property.get()) == set()
|
assert set(cfg.option('od.dodval1').property.get()) == set([])
|
||||||
assert set(cfg.option('od.dodval2').property.get()) == set()
|
assert set(cfg.option('od.dodval2').property.get()) == set([])
|
||||||
cfg.option('od.dodval1').property.add('test1')
|
cfg.option('od.dodval1').property.add('test1')
|
||||||
assert set(cfg.option('od.dodval1').property.get()) == {'test1'}
|
assert set(cfg.option('od.dodval1').property.get()) == set(['test1'])
|
||||||
assert set(cfg.option('od.dodval2').property.get()) == set()
|
assert set(cfg.option('od.dodval2').property.get()) == set([])
|
||||||
cfg.option('od.dodval1').property.remove('test1')
|
cfg.option('od.dodval1').property.remove('test1')
|
||||||
assert set(cfg.option('od.dodval1').property.get()) == set()
|
assert set(cfg.option('od.dodval1').property.get()) == set([])
|
||||||
assert set(cfg.option('od.dodval2').property.get()) == set()
|
assert set(cfg.option('od.dodval2').property.get()) == set([])
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_prop_dyndescription_uncalculated():
|
|
||||||
st = StrOption('st', '', properties=('test',))
|
|
||||||
od = OptionDescription('od', '', [st], properties=('test_od',))
|
|
||||||
dod = DynOptionDescription('dod', '', [od], identifiers=Calculation(return_list))
|
|
||||||
od2 = OptionDescription('od', '', [dod])
|
|
||||||
cfg = Config(od2)
|
|
||||||
assert set(cfg.option('dod.od').property.get(uncalculated=True)) == {'test_od'}
|
|
||||||
assert set(cfg.option('dod.od.st').property.get(uncalculated=True)) == {'test', 'validator'}
|
|
||||||
with pytest.raises(AttributeOptionError):
|
|
||||||
set(cfg.option('dod.od').property.get())
|
|
||||||
with pytest.raises(AttributeOptionError):
|
|
||||||
set(cfg.option('dod.od.st').property.get())
|
|
||||||
|
|
||||||
|
|
||||||
def test_prop_dyndescription_force_store_value():
|
def test_prop_dyndescription_force_store_value():
|
||||||
st = StrOption('st', '', properties=('force_store_value',))
|
st = StrOption('st', '', properties=('force_store_value',))
|
||||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||||
|
|
@ -356,17 +328,6 @@ def test_prop_dyndescription_force_store_value():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_prop_dyndescription_force_store_value_disabled():
|
|
||||||
st = StrOption('st', '', properties=('force_store_value', 'disabled'))
|
|
||||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
|
||||||
od = OptionDescription('od', '', [dod])
|
|
||||||
od2 = OptionDescription('od', '', [od])
|
|
||||||
cfg = Config(od2)
|
|
||||||
cfg.property.read_write()
|
|
||||||
assert parse_od_get(cfg.value.get()) == {}
|
|
||||||
# assert not list_sessions()
|
|
||||||
|
|
||||||
|
|
||||||
def test_prop_dyndescription_force_store_value_calculation_prefix():
|
def test_prop_dyndescription_force_store_value_calculation_prefix():
|
||||||
lst = StrOption('lst', '', ['val1', 'val2'], multi=True)
|
lst = StrOption('lst', '', ['val1', 'val2'], multi=True)
|
||||||
st = StrOption('st', '', Calculation(return_list, Params(ParamIdentifier())) , properties=('force_store_value',))
|
st = StrOption('st', '', Calculation(return_list, Params(ParamIdentifier())) , properties=('force_store_value',))
|
||||||
|
|
@ -375,7 +336,6 @@ def test_prop_dyndescription_force_store_value_calculation_prefix():
|
||||||
od2 = OptionDescription('od', '', [od])
|
od2 = OptionDescription('od', '', [od])
|
||||||
cfg = Config(od2)
|
cfg = Config(od2)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
assert get_dependencies(cfg.option('od.lst')) == [('od.dodval1', None), ('od.dodval2', None)]
|
|
||||||
assert cfg.option('od.dodval1.st').owner.isdefault() == False
|
assert cfg.option('od.dodval1.st').owner.isdefault() == False
|
||||||
assert cfg.option('od.dodval2.st').owner.isdefault() == False
|
assert cfg.option('od.dodval2.st').owner.isdefault() == False
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.lst': ['val1', 'val2'], 'od.dodval1.st': 'val1', 'od.dodval2.st': 'val2'}
|
assert parse_od_get(cfg.value.get()) == {'od.lst': ['val1', 'val2'], 'od.dodval1.st': 'val1', 'od.dodval2.st': 'val2'}
|
||||||
|
|
@ -434,8 +394,6 @@ def test_callback_dyndescription_outside1():
|
||||||
od = OptionDescription('od', '', [dod, out])
|
od = OptionDescription('od', '', [dod, out])
|
||||||
od2 = OptionDescription('od', '', [od, lst])
|
od2 = OptionDescription('od', '', [od, lst])
|
||||||
cfg = Config(od2)
|
cfg = Config(od2)
|
||||||
#
|
|
||||||
assert get_dependencies(cfg.option('od.dodval1.st')) == [('od.out', None)]
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.dodval1.st': 'val', 'od.dodval2.st': 'val', 'od.out': 'val', 'lst': ['val1', 'val2']}
|
assert parse_od_get(cfg.value.get()) == {'od.dodval1.st': 'val', 'od.dodval2.st': 'val', 'od.out': 'val', 'lst': ['val1', 'val2']}
|
||||||
cfg.option('od.dodval1.st').value.set('val1')
|
cfg.option('od.dodval1.st').value.set('val1')
|
||||||
cfg.option('od.dodval2.st').value.set('val2')
|
cfg.option('od.dodval2.st').value.set('val2')
|
||||||
|
|
@ -459,8 +417,6 @@ def test_callback_dyndescription_outside2():
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.dodval1.st': None, 'od.dodval2.st': None, 'od.out': None, 'lst': ['val1', 'val2']}
|
assert parse_od_get(cfg.value.get()) == {'od.dodval1.st': None, 'od.dodval2.st': None, 'od.out': None, 'lst': ['val1', 'val2']}
|
||||||
cfg.option('od.out').value.set('val1')
|
cfg.option('od.out').value.set('val1')
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.dodval1.st': 'val1', 'od.dodval2.st': 'val1', 'od.out': 'val1', 'lst': ['val1', 'val2']}
|
assert parse_od_get(cfg.value.get()) == {'od.dodval1.st': 'val1', 'od.dodval2.st': 'val1', 'od.out': 'val1', 'lst': ['val1', 'val2']}
|
||||||
#
|
|
||||||
assert get_dependencies(cfg.option('od.out')) == [('od.dodval1.st', None), ('od.dodval2.st', None)]
|
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -476,77 +432,6 @@ def test_callback_dyndescription_outside3():
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.out': 'val1', 'lst': ['val1', 'val2']}
|
assert parse_od_get(cfg.value.get()) == {'od.out': 'val1', 'lst': ['val1', 'val2']}
|
||||||
|
|
||||||
|
|
||||||
def test_callback_dyndescription_outside_optional():
|
|
||||||
lst = StrOption('lst', '', ['val'], multi=True)
|
|
||||||
st = StrOption('st', '', 'val')
|
|
||||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(lst))))
|
|
||||||
out = StrOption('out', '', Calculation(calc_value, Params(ParamDynOption(st, ['unknown_val'], optional=True))))
|
|
||||||
od = OptionDescription('od', '', [dod, out])
|
|
||||||
od2 = OptionDescription('od', '', [od, lst])
|
|
||||||
cfg = Config(od2)
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.dodval.st': 'val', 'od.out': None, 'lst': ['val']}
|
|
||||||
cfg.option('lst').value.set(['val', 'unknown_val'])
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.dodval.st': 'val', 'od.dodunknown_val.st': 'val', 'od.out': 'val', 'lst': ['val', 'unknown_val']}
|
|
||||||
# assert not list_sessions()
|
|
||||||
|
|
||||||
|
|
||||||
def test_dyndescription_subdyn():
|
|
||||||
lst = StrOption('lst', '', ['val1', 'val2'], multi=True)
|
|
||||||
st = StrOption('st', '', 'val1')
|
|
||||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
|
||||||
out = StrOption('out', '', Calculation(return_dynval, Params(ParamDynOption(st, ['val1', None]))), multi=True, properties=('notunique',))
|
|
||||||
dod2 = DynOptionDescription('dod2', '', [dod, out], identifiers=Calculation(return_list))
|
|
||||||
od = OptionDescription('od', '', [dod2])
|
|
||||||
od2 = OptionDescription('od', '', [od, lst])
|
|
||||||
cfg = Config(od2)
|
|
||||||
cfg.property.read_write()
|
|
||||||
assert cfg.option('od.dod2val1.dodval1.st').value.get() == 'val1'
|
|
||||||
with pytest.raises(AttributeOptionError):
|
|
||||||
cfg.option('od.dod2.dodval1.st').value.get()
|
|
||||||
with pytest.raises(AttributeOptionError):
|
|
||||||
cfg.option('od.dod2val1.dod.st').value.get()
|
|
||||||
assert set(cfg.option('od.dod2val1.dodval1.st').property.get()) == {'validator'}
|
|
||||||
assert set(cfg.option('od.dod2val1.dodval1.st').property.get(uncalculated=True)) == {'validator'}
|
|
||||||
assert set(cfg.option('od.dod2.dod.st').property.get(uncalculated=True)) == {'validator'}
|
|
||||||
with pytest.raises(AttributeOptionError):
|
|
||||||
cfg.option('od.dod2.dodval1.st').property.get(uncalculated=True)
|
|
||||||
assert cfg.option('od.dod2val1.dod.st').property.get(uncalculated=True) == {'validator'}
|
|
||||||
#
|
|
||||||
with pytest.raises(AttributeOptionError):
|
|
||||||
cfg.option('od.dod2.dod.st').name()
|
|
||||||
with pytest.raises(AttributeOptionError):
|
|
||||||
cfg.option('od.dod2val1.dod.st').name()
|
|
||||||
assert cfg.option('od.dod2.dod.st').name(uncalculated=True) == 'st'
|
|
||||||
cfg.option('od.dod2val1.dod.st').name(uncalculated=True)
|
|
||||||
#
|
|
||||||
with pytest.raises(AttributeOptionError):
|
|
||||||
cfg.option('od.dod2.dod.st').path()
|
|
||||||
with pytest.raises(AttributeOptionError):
|
|
||||||
cfg.option('od.dod2val1.dod.st').path()
|
|
||||||
assert cfg.option('od.dod2.dod.st').path(uncalculated=True) == 'od.dod2.dod.st'
|
|
||||||
assert cfg.option('od.dod2val1.dod.st').path(uncalculated=True) == 'od.dod2.dod.st'
|
|
||||||
#
|
|
||||||
assert cfg.option('od.dod2.dod.st').isoptiondescription() is False
|
|
||||||
assert cfg.option('od.dod2val1.dodval1.st').isoptiondescription() is False
|
|
||||||
assert cfg.option('od.dod2.dod').isoptiondescription() is True
|
|
||||||
assert cfg.option('od.dod2val1.dodval1').isoptiondescription() is True
|
|
||||||
assert cfg.option('od.dod2.dod').isleadership() is False
|
|
||||||
assert cfg.option('od.dod2val1.dodval1').isleadership() is False
|
|
||||||
#
|
|
||||||
assert cfg.option('od.dod2.dod.st').type() == "string"
|
|
||||||
assert cfg.option('od.dod2val1.dodval1.st').type() == "string"
|
|
||||||
assert cfg.option('od.dod2.dod').type() == "optiondescription"
|
|
||||||
assert cfg.option('od.dod2val1.dodval1').type() == "optiondescription"
|
|
||||||
assert cfg.option('od.dod2.dod').group_type() == "default"
|
|
||||||
assert cfg.option('od.dod2val1.dodval1').group_type() == "default"
|
|
||||||
#
|
|
||||||
with pytest.raises(AttributeOptionError):
|
|
||||||
cfg.option('od.dod2.dod').identifiers()
|
|
||||||
assert cfg.option('od.dod2.dod').identifiers(only_self=True) == ['val1', 'val2']
|
|
||||||
assert cfg.option('od.dod2val1.dodval1').identifiers() == ['val1', 'val1']
|
|
||||||
assert cfg.option('od.dod2val1.dodval1').identifiers(only_self=True) == ['val1', 'val2']
|
|
||||||
|
|
||||||
|
|
||||||
def test_callback_dyndescription_subdyn():
|
def test_callback_dyndescription_subdyn():
|
||||||
lst = StrOption('lst', '', ['val1', 'val2'], multi=True)
|
lst = StrOption('lst', '', ['val1', 'val2'], multi=True)
|
||||||
st = StrOption('st', '', 'val1')
|
st = StrOption('st', '', 'val1')
|
||||||
|
|
@ -558,10 +443,6 @@ def test_callback_dyndescription_subdyn():
|
||||||
cfg = Config(od2)
|
cfg = Config(od2)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.dod2val1.dodval1.st': 'val1', 'od.dod2val1.dodval2.st': 'val1', 'od.dod2val1.out': ['val1', 'val1'], 'od.dod2val2.dodval1.st': 'val1', 'od.dod2val2.dodval2.st': 'val1', 'od.dod2val2.out': ['val1', 'val1'], 'lst': ['val1', 'val2']}
|
assert parse_od_get(cfg.value.get()) == {'od.dod2val1.dodval1.st': 'val1', 'od.dod2val1.dodval2.st': 'val1', 'od.dod2val1.out': ['val1', 'val1'], 'od.dod2val2.dodval1.st': 'val1', 'od.dod2val2.dodval2.st': 'val1', 'od.dod2val2.out': ['val1', 'val1'], 'lst': ['val1', 'val2']}
|
||||||
cfg.option('lst').value.set(["val1", "val3"])
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.dod2val1.dodval1.st': 'val1', 'od.dod2val1.dodval3.st': 'val1', 'od.dod2val1.out': ['val1', 'val1'], 'od.dod2val3.dodval1.st': 'val1', 'od.dod2val3.dodval3.st': 'val1', 'od.dod2val3.out': ['val1', 'val1'], 'lst': ['val1', 'val3']}
|
|
||||||
cfg.option('lst').value.set(["val1", "val3", None])
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.dod2val1.dodval1.st': 'val1', 'od.dod2val1.dodval3.st': 'val1', 'od.dod2val1.out': ['val1', 'val1'], 'od.dod2val3.dodval1.st': 'val1', 'od.dod2val3.dodval3.st': 'val1', 'od.dod2val3.out': ['val1', 'val1'], 'lst': ['val1', 'val3', None]}
|
|
||||||
|
|
||||||
|
|
||||||
def test_callback_list_dyndescription():
|
def test_callback_list_dyndescription():
|
||||||
|
|
@ -721,14 +602,14 @@ def test_prop_dyndescription_context():
|
||||||
od = OptionDescription('od', '', [dod, val1])
|
od = OptionDescription('od', '', [dod, val1])
|
||||||
od2 = OptionDescription('od', '', [od])
|
od2 = OptionDescription('od', '', [od])
|
||||||
cfg = Config(od2)
|
cfg = Config(od2)
|
||||||
assert set(cfg.option('od.dodval1.st').property.get()) == {"validator", 'test'}
|
assert set(cfg.option('od.dodval1.st').property.get()) == set(['test'])
|
||||||
assert set(cfg.option('od.dodval2.st').property.get()) == {"validator", 'test'}
|
assert set(cfg.option('od.dodval2.st').property.get()) == set(['test'])
|
||||||
cfg.option('od.dodval2.st').property.add('test2')
|
cfg.option('od.dodval2.st').property.add('test2')
|
||||||
assert set(cfg.option('od.dodval1.st').property.get()) == {"validator", 'test'}
|
assert set(cfg.option('od.dodval1.st').property.get()) == set(['test'])
|
||||||
assert set(cfg.option('od.dodval2.st').property.get()) == {"validator", 'test', 'test2'}
|
assert set(cfg.option('od.dodval2.st').property.get()) == set(['test', 'test2'])
|
||||||
cfg.option('od.dodval1.st').permissive.add('test')
|
cfg.option('od.dodval1.st').permissive.add('test')
|
||||||
assert set(cfg.option('od.dodval1.st').property.get()) == {"validator"}
|
assert set(cfg.option('od.dodval1.st').property.get()) == set([])
|
||||||
assert set(cfg.option('od.dodval2.st').property.get()) == {"validator", 'test', 'test2'}
|
assert set(cfg.option('od.dodval2.st').property.get()) == set(['test', 'test2'])
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1032,22 +913,6 @@ def test_requires_dyndescription_in_dyn():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_requires_dyndescription_in_dyn_hidden():
|
|
||||||
str1 = StrOption('str1', '', "val", properties=('hidden',))
|
|
||||||
st = StrOption('st', '', Calculation(calc_value, Params(ParamOption(str1))))
|
|
||||||
dod = DynOptionDescription('dod', '', [str1, st], identifiers=Calculation(return_list))
|
|
||||||
od = OptionDescription('od', '', [dod])
|
|
||||||
od2 = OptionDescription('od', '', [od])
|
|
||||||
cfg = Config(od2)
|
|
||||||
cfg.property.read_write()
|
|
||||||
|
|
||||||
assert cfg.option('od.dodval1.st').value.get() is 'val'
|
|
||||||
assert cfg.option('od.dodval2.st').value.get() is 'val'
|
|
||||||
#
|
|
||||||
with pytest.raises(PropertiesOptionError):
|
|
||||||
cfg.option('od.dodval1.str1').value.get()
|
|
||||||
|
|
||||||
|
|
||||||
def calc_value_not_same(param, condition, expected, default, identifier):
|
def calc_value_not_same(param, condition, expected, default, identifier):
|
||||||
if identifier == 'val1':
|
if identifier == 'val1':
|
||||||
index = 0
|
index = 0
|
||||||
|
|
@ -1156,43 +1021,6 @@ def test_validator_dyndescription():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_validator_param_self_option():
|
|
||||||
out = StrOption('out', '', 'val')
|
|
||||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
|
||||||
st_in = StrOption('st_in', '', Calculation(return_dynval, Params(ParamOption(out))))
|
|
||||||
st = StrOption('st', '', Calculation(return_dynval, Params(ParamOption(st_in))), validators=[Calculation(return_no_dyn, Params((ParamSelfOption(dynamic=False),)))])
|
|
||||||
dod = DynOptionDescription('dod', '', [st_in, st], identifiers=Calculation(return_list))
|
|
||||||
od = OptionDescription('od', '', [dod, val1, out])
|
|
||||||
od2 = OptionDescription('od', '', [od])
|
|
||||||
cfg = Config(od2)
|
|
||||||
assert cfg.option('od.dodval1.st').value.get() == 'val'
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
cfg.option('od.dodval1.st').value.set('no')
|
|
||||||
cfg.option('od.out').value.set('yes')
|
|
||||||
|
|
||||||
|
|
||||||
def test_properties_param_self_option():
|
|
||||||
out = StrOption('out', '', 'val')
|
|
||||||
val1 = StrOption('val1', '', ["0", "1", "2"], multi=True)
|
|
||||||
disabled_property = Calculation(return_no_dyn_properties, Params((ParamSelfOption(dynamic=False), ParamIdentifier())))
|
|
||||||
st = StrOption('st', '', None, properties=(disabled_property,))
|
|
||||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
|
||||||
od = OptionDescription('od', '', [dod, val1, out])
|
|
||||||
od2 = OptionDescription('od', '', [od])
|
|
||||||
cfg = Config(od2)
|
|
||||||
cfg.property.read_write()
|
|
||||||
assert cfg.option('od.dod0.st').value.get() is None
|
|
||||||
with pytest.raises(PropertiesOptionError):
|
|
||||||
cfg.option('od.dod1.st').value.get()
|
|
||||||
with pytest.raises(PropertiesOptionError):
|
|
||||||
cfg.option('od.dod2.st').value.get()
|
|
||||||
cfg.option('od.dod0.st').value.set('val')
|
|
||||||
assert cfg.option('od.dod0.st').value.get() == 'val'
|
|
||||||
assert cfg.option('od.dod1.st').value.get() is None
|
|
||||||
with pytest.raises(PropertiesOptionError):
|
|
||||||
cfg.option('od.dod2.st').value.get()
|
|
||||||
|
|
||||||
|
|
||||||
def test_makedict_dyndescription_context():
|
def test_makedict_dyndescription_context():
|
||||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||||
st = StrOption('st', '')
|
st = StrOption('st', '')
|
||||||
|
|
@ -1349,8 +1177,6 @@ def test_leadership_dyndescription():
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
owner = cfg.owner.get()
|
owner = cfg.owner.get()
|
||||||
#
|
#
|
||||||
assert get_dependencies(cfg.option('od.stval1.st1.st2')) == [('od.stval1.st1', None)]
|
|
||||||
assert get_dependencies(cfg.option('od.stval2.st1.st2')) == [('od.stval2.st1', None)]
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.stval2.st1.st1': [], 'od.stval1.st1.st1': []}
|
assert parse_od_get(cfg.value.get()) == {'od.stval2.st1.st1': [], 'od.stval1.st1.st1': []}
|
||||||
assert cfg.option('od.stval1.st1.st1').value.get() == []
|
assert cfg.option('od.stval1.st1.st1').value.get() == []
|
||||||
assert cfg.option('od.stval2.st1.st1').value.get() == []
|
assert cfg.option('od.stval2.st1.st1').value.get() == []
|
||||||
|
|
@ -1410,9 +1236,6 @@ def test_leadership_dyndescription_force_store_value_leader():
|
||||||
od1 = OptionDescription('od', '', [od])
|
od1 = OptionDescription('od', '', [od])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
#
|
|
||||||
assert get_dependencies(cfg.option('od.stval1.st1.st2')) == [('od.stval1.st1', None)]
|
|
||||||
assert get_dependencies(cfg.option('od.stval2.st1.st2')) == [('od.stval2.st1', None)]
|
|
||||||
assert cfg.option('od.stval1.st1.st1').owner.isdefault() == False
|
assert cfg.option('od.stval1.st1.st1').owner.isdefault() == False
|
||||||
assert cfg.option('od.stval2.st1.st1').owner.isdefault() == False
|
assert cfg.option('od.stval2.st1.st1').owner.isdefault() == False
|
||||||
assert cfg.option('od.stval1.st1.st2', 0).owner.isdefault() == True
|
assert cfg.option('od.stval1.st1.st2', 0).owner.isdefault() == True
|
||||||
|
|
@ -1873,6 +1696,16 @@ def test_leadership_callback_samegroup_dyndescription():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
def test_invalid_conflict_dyndescription():
|
||||||
|
st = StrOption('st', '')
|
||||||
|
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||||
|
dodinvalid = StrOption('dodinvalid', '')
|
||||||
|
dod, dodinvalid
|
||||||
|
with pytest.raises(ConflictError):
|
||||||
|
OptionDescription('od', '', [dod, dodinvalid])
|
||||||
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_leadership_default_multi_dyndescription4():
|
def test_leadership_default_multi_dyndescription4():
|
||||||
st1 = StrOption('st1', "", multi=True)
|
st1 = StrOption('st1', "", multi=True)
|
||||||
st2 = StrOption('st2', "", multi=True, default_multi='no')
|
st2 = StrOption('st2', "", multi=True, default_multi='no')
|
||||||
|
|
@ -2218,10 +2051,6 @@ def test_leadership_dyndescription_convert():
|
||||||
assert cfg.option('od.stval2.st1.st1').value.get() == []
|
assert cfg.option('od.stval2.st1.st1').value.get() == []
|
||||||
assert cfg.option('od.stval1.st1.st1').owner.isdefault()
|
assert cfg.option('od.stval1.st1.st1').owner.isdefault()
|
||||||
assert cfg.option('od.stval2.st1.st1').owner.isdefault()
|
assert cfg.option('od.stval2.st1.st1').owner.isdefault()
|
||||||
assert cfg.option('od.stval2.st1.st1').identifiers() == ["val.2"]
|
|
||||||
assert cfg.option('od.stval2.st1.st1').identifiers(convert=True) == ["val2"]
|
|
||||||
assert cfg.option('od.stval2').identifiers(only_self=True) == ["val.1", "val.2"]
|
|
||||||
assert cfg.option('od.stval2').identifiers(only_self=True, convert=True) == ["val1", "val2"]
|
|
||||||
#
|
#
|
||||||
cfg.option('od.stval1.st1.st1').value.set(['yes'])
|
cfg.option('od.stval1.st1.st1').value.set(['yes'])
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.stval1.st1.st1': [{'od.stval1.st1.st1': 'yes', 'od.stval1.st1.st2': None}], 'od.stval2.st1.st1': []}
|
assert parse_od_get(cfg.value.get()) == {'od.stval1.st1.st1': [{'od.stval1.st1.st1': 'yes', 'od.stval1.st1.st2': None}], 'od.stval2.st1.st1': []}
|
||||||
|
|
@ -2266,23 +2095,6 @@ def test_leadership_dyndescription_convert():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_leadership_dyndescription_convert_2():
|
|
||||||
identifier = StrOption("identifier", "", ['val.1', 'val.2', None], multi=True)
|
|
||||||
st1 = StrOption('st1', "", multi=True)
|
|
||||||
st2 = StrOption('st2', "", multi=True)
|
|
||||||
stm = Leadership('st1', '', [st1, st2])
|
|
||||||
st = ConvertDynOptionDescription('st', '', [stm], identifiers=Calculation(calc_value, Params((ParamOption(identifier),))))
|
|
||||||
od = OptionDescription('od', '', [st])
|
|
||||||
od1 = OptionDescription('od', '', [od, identifier])
|
|
||||||
cfg = Config(od1)
|
|
||||||
owner = cfg.owner.get()
|
|
||||||
#
|
|
||||||
assert cfg.option('od.stval2.st1.st1').identifiers() == ["val.2"]
|
|
||||||
assert cfg.option('od.stval2.st1.st1').identifiers(convert=True) == ["val2"]
|
|
||||||
assert cfg.option('od.stval2').identifiers(only_self=True) == ["val.1", "val.2"]
|
|
||||||
assert cfg.option('od.stval2').identifiers(only_self=True, convert=True) == ["val1", "val2"]
|
|
||||||
|
|
||||||
|
|
||||||
def test_leadership_callback_samegroup_dyndescription_convert():
|
def test_leadership_callback_samegroup_dyndescription_convert():
|
||||||
st1 = StrOption('st1', "", multi=True)
|
st1 = StrOption('st1', "", multi=True)
|
||||||
st2 = StrOption('st2', "", multi=True)
|
st2 = StrOption('st2', "", multi=True)
|
||||||
|
|
@ -3047,137 +2859,3 @@ def test_callback_list_dyndescription_information_not_list():
|
||||||
cfg.information.set('identifier', 'ival3')
|
cfg.information.set('identifier', 'ival3')
|
||||||
assert cfg.option('od.dodival3.st').value.get() == ['ival3', 'val2']
|
assert cfg.option('od.dodival3.st').value.get() == ['ival3', 'val2']
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_dynoption_not_duplicate():
|
|
||||||
st = StrOption('st', '')
|
|
||||||
st2 = StrOption('st', '')
|
|
||||||
dod = DynOptionDescription('od_', '', [st], identifiers=["val1"])
|
|
||||||
dod2 = DynOptionDescription('od_', '', [st2], identifiers=["val2"])
|
|
||||||
od = OptionDescription('od', '', [dod, dod2])
|
|
||||||
od2 = OptionDescription('od', '', [od])
|
|
||||||
cfg = Config(od2)
|
|
||||||
assert parse_od_get(cfg.value.get()) == {
|
|
||||||
'od.od_val1.st': None,
|
|
||||||
'od.od_val2.st': None,
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
def test_dynoption_duplicate_1():
|
|
||||||
st = StrOption('st', '', "val1")
|
|
||||||
od = OptionDescription('od_val', '', [st])
|
|
||||||
st2 = StrOption('st', '', "val2")
|
|
||||||
dod = DynOptionDescription('od_', '', [st2], identifiers=["val"])
|
|
||||||
od1 = OptionDescription('od', '', [od, dod])
|
|
||||||
od2 = OptionDescription('od', '', [od1])
|
|
||||||
cfg = Config(od2)
|
|
||||||
with pytest.raises(ConflictError):
|
|
||||||
cfg.value.get()
|
|
||||||
with pytest.raises(ConflictError):
|
|
||||||
cfg.option('od.od_val').value.get()
|
|
||||||
|
|
||||||
|
|
||||||
def test_dynoption_duplicate_2():
|
|
||||||
st2 = StrOption('st', '', "val2")
|
|
||||||
dod = DynOptionDescription('od_', '', [st2], identifiers=["val"])
|
|
||||||
st = StrOption('st', '', "val1")
|
|
||||||
od = OptionDescription('od_val', '', [st])
|
|
||||||
od1 = OptionDescription('od', '', [dod, od])
|
|
||||||
od2 = OptionDescription('od', '', [od1])
|
|
||||||
cfg = Config(od2)
|
|
||||||
with pytest.raises(ConflictError):
|
|
||||||
cfg.value.get()
|
|
||||||
with pytest.raises(ConflictError):
|
|
||||||
cfg.option('od.od_val').value.get()
|
|
||||||
|
|
||||||
|
|
||||||
def test_dynoption_duplicate_3():
|
|
||||||
st = StrOption('od_val', '')
|
|
||||||
st2 = StrOption('st', '', "val2")
|
|
||||||
dod = DynOptionDescription('od_', '', [st2], identifiers=["val"])
|
|
||||||
od1 = OptionDescription('od', '', [dod, st])
|
|
||||||
od2 = OptionDescription('od', '', [od1])
|
|
||||||
cfg = Config(od2)
|
|
||||||
with pytest.raises(ConflictError):
|
|
||||||
cfg.value.get()
|
|
||||||
with pytest.raises(ConflictError):
|
|
||||||
cfg.option('od.od_val').value.get()
|
|
||||||
|
|
||||||
|
|
||||||
def test_dynoption_duplicate_4():
|
|
||||||
st = StrOption('st', '')
|
|
||||||
st2 = StrOption('st', '')
|
|
||||||
dod = DynOptionDescription('od_', '', [st], identifiers=["val"])
|
|
||||||
dod2 = DynOptionDescription('od_', '', [st2], identifiers=["val"])
|
|
||||||
od = OptionDescription('od', '', [dod, dod2])
|
|
||||||
od2 = OptionDescription('od', '', [od])
|
|
||||||
cfg = Config(od2)
|
|
||||||
with pytest.raises(ConflictError):
|
|
||||||
cfg.value.get()
|
|
||||||
with pytest.raises(ConflictError):
|
|
||||||
cfg.option('od.od_val').value.get()
|
|
||||||
|
|
||||||
|
|
||||||
def test_dynoption_duplicate_5():
|
|
||||||
st = StrOption('st', '')
|
|
||||||
st2 = StrOption('st', '')
|
|
||||||
dod = DynOptionDescription('od_', '', [st], identifiers=["val"])
|
|
||||||
dod2 = DynOptionDescription('od', '', [st2], identifiers=["_val"])
|
|
||||||
od = OptionDescription('od', '', [dod, dod2])
|
|
||||||
od2 = OptionDescription('od', '', [od])
|
|
||||||
cfg = Config(od2)
|
|
||||||
with pytest.raises(ConflictError):
|
|
||||||
cfg.value.get()
|
|
||||||
with pytest.raises(ConflictError):
|
|
||||||
cfg.option('od.od_val').value.get()
|
|
||||||
|
|
||||||
|
|
||||||
def test_dyn_disabled():
|
|
||||||
var1 = StrOption("var1", "var1", default=["val1", "val2"], multi=True)
|
|
||||||
var = StrOption("var", "var", properties=frozenset({"disabled"}))
|
|
||||||
dyn = DynOptionDescription("dyn", "dyn", identifiers=Calculation(calc_value, Params((ParamOption(var1)))), children=[var])
|
|
||||||
var2 = StrOption(name="var2", doc="A variable calculated", default=Calculation(calc_value, Params((ParamDynOption(var, ["val1"])))))
|
|
||||||
od = OptionDescription('od', '', [var1, dyn, var2])
|
|
||||||
cfg = Config(od)
|
|
||||||
cfg.property.read_write()
|
|
||||||
with pytest.raises(ConfigError):
|
|
||||||
cfg.value.get()
|
|
||||||
|
|
||||||
|
|
||||||
def test_dyn_param_calculation():
|
|
||||||
var1 = StrOption("var1", "var1", default=["val1", "val2"], multi=True)
|
|
||||||
var = StrOption("var", "var", default=Calculation(calc_value, Params(ParamIdentifier())))
|
|
||||||
dyn = DynOptionDescription("dyn", "dyn", identifiers=Calculation(calc_value, Params((ParamOption(var1)))), children=[var])
|
|
||||||
var2 = StrOption(name="var2", doc="A variable calculated", default=Calculation(calc_value, Params((ParamDynOption(var, Calculation(calc_value, Params(ParamValue(["val1"]))))))))
|
|
||||||
od = OptionDescription('od', '', [var1, dyn, var2])
|
|
||||||
cfg = Config(od)
|
|
||||||
cfg.property.read_write()
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'var1': ['val1', 'val2'], 'dynval1.var': 'val1', 'dynval2.var': 'val2', 'var2': 'val1'}
|
|
||||||
|
|
||||||
|
|
||||||
def test_dyn_param_calculation_var():
|
|
||||||
identifier_var = StrOption("identifier_var", "identifier_var", default=["val1"], multi=True)
|
|
||||||
var1 = StrOption("var1", "var1", default=["val1", "val2"], multi=True)
|
|
||||||
var = StrOption("var", "var", default=Calculation(calc_value, Params(ParamIdentifier())))
|
|
||||||
dyn = DynOptionDescription("dyn", "dyn", identifiers=Calculation(calc_value, Params((ParamOption(var1)))), children=[var])
|
|
||||||
var2 = StrOption(name="var2", doc="A variable calculated", default=Calculation(calc_value, Params((ParamDynOption(var, Calculation(calc_value, Params(ParamOption(identifier_var))))))))
|
|
||||||
od = OptionDescription('od', '', [identifier_var, var1, dyn, var2])
|
|
||||||
cfg = Config(od)
|
|
||||||
cfg.property.read_write()
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'identifier_var': ['val1'], 'var1': ['val1', 'val2'], 'dynval1.var': 'val1', 'dynval2.var': 'val2', 'var2': 'val1'}
|
|
||||||
cfg.option('identifier_var').value.set(['val2'])
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'identifier_var': ['val2'], 'var1': ['val1', 'val2'], 'dynval1.var': 'val1', 'dynval2.var': 'val2', 'var2': 'val2'}
|
|
||||||
|
|
||||||
|
|
||||||
def test_dyn_param_calculation_var_not_multi():
|
|
||||||
identifier_var = StrOption("identifier_var", "identifier_var", default="val1")
|
|
||||||
var1 = StrOption("var1", "var1", default=["val1", "val2"], multi=True)
|
|
||||||
var = StrOption("var", "var", default=Calculation(calc_value, Params(ParamIdentifier())))
|
|
||||||
dyn = DynOptionDescription("dyn", "dyn", identifiers=Calculation(calc_value, Params((ParamOption(var1)))), children=[var])
|
|
||||||
var2 = StrOption(name="var2", doc="A variable calculated", default=Calculation(calc_value, Params((ParamDynOption(var, Calculation(calc_value, Params(ParamOption(identifier_var))))))))
|
|
||||||
od = OptionDescription('od', '', [identifier_var, var1, dyn, var2])
|
|
||||||
cfg = Config(od)
|
|
||||||
cfg.property.read_write()
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'identifier_var': 'val1', 'var1': ['val1', 'val2'], 'dynval1.var': 'val1', 'dynval2.var': 'val2', 'var2': 'val1'}
|
|
||||||
cfg.option('identifier_var').value.set('val2')
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'identifier_var': 'val2', 'var1': ['val1', 'val2'], 'dynval1.var': 'val1', 'dynval2.var': 'val2', 'var2': 'val2'}
|
|
||||||
|
|
|
||||||
|
|
@ -165,15 +165,15 @@ def test_force_store_value():
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
compare(cfg.value.exportation(), {})
|
compare(cfg.value.exportation(), {})
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
compare(cfg.value.exportation(), {'wantref3': {None: [[False], 'forced']}})
|
compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
|
||||||
cfg.option('bool').value.set(False)
|
cfg.option('bool').value.set(False)
|
||||||
cfg.option('wantref').value.set(True)
|
cfg.option('wantref').value.set(True)
|
||||||
cfg.option('bool').value.reset()
|
cfg.option('bool').value.reset()
|
||||||
compare(cfg.value.exportation(), {'wantref': {None: [True, 'user']}, 'wantref3': {None: [[False], 'forced']}})
|
compare(cfg.value.exportation(), {'wantref': {None: [True, 'user']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
|
||||||
cfg.option('bool').value.set(False)
|
cfg.option('bool').value.set(False)
|
||||||
cfg.option('wantref').value.reset()
|
cfg.option('wantref').value.reset()
|
||||||
cfg.option('bool').value.reset()
|
cfg.option('bool').value.reset()
|
||||||
compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
|
compare(cfg.value.exportation(), {'wantref': {None: [False, 'forced']}, 'wantref2': {None: [False, 'forced']}, 'wantref3': {None: [[False], 'forced']}})
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import pytest
|
||||||
|
|
||||||
from tiramisu.setting import groups, owners
|
from tiramisu.setting import groups, owners
|
||||||
from tiramisu import ChoiceOption, BoolOption, IntOption, IPOption, NetworkOption, NetmaskOption, \
|
from tiramisu import ChoiceOption, BoolOption, IntOption, IPOption, NetworkOption, NetmaskOption, \
|
||||||
StrOption, OptionDescription, Leadership, Config, Calculation, ParamValue, ParamOption, calc_value, Params, submulti
|
StrOption, OptionDescription, Leadership, Config, Calculation, ParamValue, calc_value, Params
|
||||||
from tiramisu.error import LeadershipError, PropertiesOptionError, ConfigError
|
from tiramisu.error import LeadershipError, PropertiesOptionError, ConfigError
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -200,24 +200,6 @@ def test_groups_is_leader(config_type):
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_leader_follower_index():
|
|
||||||
ip = StrOption('ip', "", ['val1', 'val2'], multi=True)
|
|
||||||
netmask = StrOption('netmask', "", multi=True, default_multi='value')
|
|
||||||
interface1 = Leadership('leadership', '', [ip, netmask])
|
|
||||||
od1 = OptionDescription('od', '', [interface1])
|
|
||||||
cfg = Config(od1)
|
|
||||||
assert cfg.option('leadership.ip').value.get() == ['val1', 'val2']
|
|
||||||
with pytest.raises(ConfigError):
|
|
||||||
cfg.option('leadership.ip').index(0)
|
|
||||||
follower = cfg.option('leadership.netmask')
|
|
||||||
with pytest.raises(ConfigError):
|
|
||||||
follower.value.get()
|
|
||||||
assert follower.index(0).value.get() == 'value'
|
|
||||||
assert follower.index(0).index(None).index() is None
|
|
||||||
with pytest.raises(ConfigError):
|
|
||||||
follower.index(0).index(None).value.get()
|
|
||||||
|
|
||||||
|
|
||||||
def test_leader_list(config_type):
|
def test_leader_list(config_type):
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", ['val1'], multi=True)
|
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", ['val1'], multi=True)
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, default_multi='value')
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, default_multi='value')
|
||||||
|
|
@ -410,9 +392,6 @@ def test_groups_with_leader_hidden_in_config():
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
|
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
|
||||||
with pytest.raises(PropertiesOptionError):
|
with pytest.raises(PropertiesOptionError):
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()
|
||||||
cfg.forcepermissive.option('ip_admin_eth0.netmask_admin_eth0').index(0).value.get()
|
|
||||||
with pytest.raises(PropertiesOptionError):
|
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0').index(0).value.get()
|
|
||||||
assert parse_od_get(cfg.value.get()) == {}
|
assert parse_od_get(cfg.value.get()) == {}
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
@ -809,19 +788,6 @@ def test_values_with_leader_and_followers_leader_pop():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_values_with_leader_and_followers_leader_pop_default_value():
|
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", default=["192.168.230.145", "192.168.230.146"], multi=True, properties=('notunique',))
|
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", default_multi="255.255.255.0", multi=True)
|
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
|
||||||
od1 = OptionDescription('toto', '', [interface1])
|
|
||||||
cfg = Config(od1)
|
|
||||||
cfg.property.read_write()
|
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.pop(0)
|
|
||||||
compare(cfg.value.exportation(), {'ip_admin_eth0.ip_admin_eth0': {None: [['192.168.230.146'], 'user']}})
|
|
||||||
assert cfg.option('ip_admin_eth0.ip_admin_eth0').value.get() == ["192.168.230.146"]
|
|
||||||
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get() == '255.255.255.0'
|
|
||||||
|
|
||||||
|
|
||||||
def test_follower_unique():
|
def test_follower_unique():
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('unique',))
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('unique',))
|
||||||
|
|
@ -830,7 +796,7 @@ def test_follower_unique():
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145", "192.168.230.146"])
|
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(["192.168.230.145", "192.168.230.146"])
|
||||||
# unique property is removed for a follower
|
# unique property is removed for a follower
|
||||||
assert cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).property.get() == {"validator"}
|
assert not cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).property.get()
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1076,7 +1042,7 @@ def test_follower_force_store_value_reset():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_follower_properties():
|
#def test_follower_properties():
|
||||||
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
|
||||||
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('aproperty',))
|
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=True, properties=('aproperty',))
|
||||||
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
interface1 = Leadership('ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
|
||||||
|
|
@ -1094,10 +1060,6 @@ def test_follower_properties():
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0').property.add('newproperty1')
|
cfg.option('ip_admin_eth0.netmask_admin_eth0').property.add('newproperty1')
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).property.get() == ('aproperty', 'newproperty', 'newproperty1')
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).property.get() == ('aproperty', 'newproperty', 'newproperty1')
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).property.get() == ('aproperty', 'newproperty1')
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 1).property.get() == ('aproperty', 'newproperty1')
|
||||||
#
|
|
||||||
with pytest.raises(ConfigError):
|
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0').property.get()
|
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0').property.get(uncalculated=True) == ('aproperty', 'newproperty1')
|
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1131,37 +1093,3 @@ def test_leader_forbidden_properties_callback(config_type):
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
with pytest.raises(LeadershipError):
|
with pytest.raises(LeadershipError):
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
|
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
|
||||||
|
|
||||||
|
|
||||||
def test_follower_value_not_list():
|
|
||||||
ip_admin_eth0 = IPOption('ip_admin_eth0', "ip réseau autorisé", multi=True, default=['1.1.1.1'])
|
|
||||||
netmask_admin_eth0 = NetmaskOption('netmask_admin_eth0', "masque du sous-réseau", default_multi='255.255.255.0', multi=True, properties=('force_store_value',))
|
|
||||||
interface0 = Leadership('interface0', '', [ip_admin_eth0, netmask_admin_eth0])
|
|
||||||
od1 = OptionDescription('od', '', [interface0])
|
|
||||||
od2 = OptionDescription('root', '', [od1])
|
|
||||||
cfg = Config(od2)
|
|
||||||
cfg.property.read_write()
|
|
||||||
with pytest.raises(ValueError):
|
|
||||||
cfg.option('od.interface0.ip_admin_eth0').value.set(None)
|
|
||||||
|
|
||||||
|
|
||||||
def test_default_calc():
|
|
||||||
var1 = StrOption('var1', "", multi=True, default=['leader1', 'leader2'], properties=frozenset({"mandatory",}))
|
|
||||||
var2 = StrOption('var2', "", default_multi=[Calculation(calc_value, Params((ParamOption(var1))))], multi=submulti, properties=frozenset({"mandatory",}))
|
|
||||||
leader = Leadership('interface0', '', [var1, var2])
|
|
||||||
od1 = OptionDescription('od', '', [leader])
|
|
||||||
od2 = OptionDescription('root', '', [od1])
|
|
||||||
cfg = Config(od2)
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.interface0.var1': [{'od.interface0.var1': 'leader1', 'od.interface0.var2': ['leader1']}, {'od.interface0.var1': 'leader2', 'od.interface0.var2': ['leader2']}]}
|
|
||||||
|
|
||||||
|
|
||||||
def test_default_set_calc():
|
|
||||||
var1 = StrOption('var1', "", multi=True, properties=frozenset({"mandatory", "novalidator", "force_store_value"}))
|
|
||||||
var2 = StrOption('var2', "", default_multi=[Calculation(calc_value, Params((ParamOption(var1))))], multi=submulti, properties=frozenset({"mandatory",}))
|
|
||||||
leader = Leadership('interface0', '', [var1, var2])
|
|
||||||
od1 = OptionDescription('od', '', [leader])
|
|
||||||
od2 = OptionDescription('root', '', [od1])
|
|
||||||
cfg = Config(od2)
|
|
||||||
cfg.property.read_write()
|
|
||||||
cfg.option('od.interface0.var1').value.set(Calculation(calc_value, Params(ParamValue(['leader1', 'leader2']))))
|
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.interface0.var1': [{'od.interface0.var1': 'leader1', 'od.interface0.var2': ['leader1']}, {'od.interface0.var1': 'leader2', 'od.interface0.var2': ['leader2']}]}
|
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,8 @@ from tiramisu.error import PropertiesOptionError, ConfigError
|
||||||
from tiramisu.setting import groups
|
from tiramisu.setting import groups
|
||||||
|
|
||||||
|
|
||||||
|
#def teardown_function(function):
|
||||||
|
# assert list_sessions() == [], 'session list is not empty when leaving "{}"'.format(function.__name__)
|
||||||
def is_mandatory(variable):
|
def is_mandatory(variable):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
@ -208,9 +210,7 @@ def test_mandatory_multi_none():
|
||||||
cfg.option('str3').value.get()
|
cfg.option('str3').value.get()
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
prop = err.proptype
|
prop = err.proptype
|
||||||
assert 'empty' in prop
|
assert 'mandatory' in prop
|
||||||
assert cfg.option("str3").value.mandatory()
|
|
||||||
assert cfg.option("str3").value.mandatory(return_type=True) == "empty"
|
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
cfg.option('str3').value.set(['yes', None])
|
cfg.option('str3').value.set(['yes', None])
|
||||||
assert cfg.option('str3').owner.get() == 'user'
|
assert cfg.option('str3').owner.get() == 'user'
|
||||||
|
|
@ -220,7 +220,7 @@ def test_mandatory_multi_none():
|
||||||
cfg.option('str3').value.get()
|
cfg.option('str3').value.get()
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
prop = err.proptype
|
prop = err.proptype
|
||||||
assert 'empty' in prop
|
assert 'mandatory' in prop
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -246,7 +246,7 @@ def test_mandatory_multi_empty():
|
||||||
cfg.option('str3').value.get()
|
cfg.option('str3').value.get()
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
prop = err.proptype
|
prop = err.proptype
|
||||||
assert 'empty' in prop
|
assert 'mandatory' in prop
|
||||||
#
|
#
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
cfg.option('str3').value.set(['yes', ''])
|
cfg.option('str3').value.set(['yes', ''])
|
||||||
|
|
@ -257,7 +257,7 @@ def test_mandatory_multi_empty():
|
||||||
cfg.option('str3').value.get()
|
cfg.option('str3').value.get()
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
prop = err.proptype
|
prop = err.proptype
|
||||||
assert 'empty' in prop
|
assert 'mandatory' in prop
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -334,26 +334,10 @@ def test_mandatory_warnings_ro():
|
||||||
prop = err.proptype
|
prop = err.proptype
|
||||||
assert 'mandatory' in prop
|
assert 'mandatory' in prop
|
||||||
compare(cfg.value.mandatory(), ['str', 'str1', 'unicode2', 'str3'])
|
compare(cfg.value.mandatory(), ['str', 'str1', 'unicode2', 'str3'])
|
||||||
assert cfg.option('str').value.mandatory()
|
|
||||||
assert cfg.option('str1').value.mandatory()
|
|
||||||
assert cfg.option('unicode2').value.mandatory()
|
|
||||||
assert cfg.option('str3').value.mandatory()
|
|
||||||
assert cfg.option('str').value.mandatory(return_type=True) == 'mandatory'
|
|
||||||
assert cfg.option('str1').value.mandatory(return_type=True) == 'mandatory'
|
|
||||||
assert cfg.option('unicode2').value.mandatory(return_type=True) == 'mandatory'
|
|
||||||
assert cfg.option('str3').value.mandatory(return_type=True) == 'mandatory'
|
|
||||||
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'])
|
compare(cfg.value.mandatory(), ['str1', 'unicode2', 'str3'])
|
||||||
assert not cfg.option('str').value.mandatory()
|
|
||||||
assert cfg.option('str1').value.mandatory()
|
|
||||||
assert cfg.option('unicode2').value.mandatory()
|
|
||||||
assert cfg.option('str3').value.mandatory()
|
|
||||||
assert cfg.option('str').value.mandatory(return_type=True) is False
|
|
||||||
assert cfg.option('str1').value.mandatory(return_type=True) == 'mandatory'
|
|
||||||
assert cfg.option('unicode2').value.mandatory(return_type=True) == 'mandatory'
|
|
||||||
assert cfg.option('str3').value.mandatory(return_type=True) == 'mandatory'
|
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -704,25 +688,25 @@ def return_list(val=None, identifier=None):
|
||||||
return ['val1', 'val2']
|
return ['val1', 'val2']
|
||||||
|
|
||||||
|
|
||||||
def test_mandatory_dyndescription():
|
#def test_mandatory_dyndescription():
|
||||||
st = StrOption('st', '', properties=('mandatory',))
|
# st = StrOption('st', '', properties=('mandatory',))
|
||||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
# dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list))
|
||||||
od = OptionDescription('od', '', [dod])
|
# od = OptionDescription('od', '', [dod])
|
||||||
od2 = OptionDescription('od', '', [od])
|
# od2 = OptionDescription('od', '', [od])
|
||||||
cfg = Config(od2)
|
# cfg = Config(od2)
|
||||||
cfg.property.read_only()
|
# cfg.property.read_only()
|
||||||
compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
|
# compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_mandatory_dyndescription_context():
|
#def test_mandatory_dyndescription_context():
|
||||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
# val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||||
st = StrOption('st', '', properties=('mandatory',))
|
# st = StrOption('st', '', properties=('mandatory',))
|
||||||
dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
# dod = DynOptionDescription('dod', '', [st], identifiers=Calculation(return_list, Params(ParamOption(val1))))
|
||||||
od = OptionDescription('od', '', [dod, val1])
|
# od = OptionDescription('od', '', [dod, val1])
|
||||||
od2 = OptionDescription('od', '', [od])
|
# od2 = OptionDescription('od', '', [od])
|
||||||
cfg = Config(od2)
|
# cfg = Config(od2)
|
||||||
cfg.property.read_only()
|
# cfg.property.read_only()
|
||||||
compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
|
# compare(cfg.value.mandatory(), ['od.dodval1.st', 'od.dodval2.st'])
|
||||||
|
|
||||||
|
|
||||||
def test_mandatory_callback_leader_and_followers_leader():
|
def test_mandatory_callback_leader_and_followers_leader():
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
|
@ -15,76 +15,76 @@ def make_metaconfig():
|
||||||
return MetaConfig([], optiondescription=od2, name='metacfg1')
|
return MetaConfig([], optiondescription=od2, name='metacfg1')
|
||||||
|
|
||||||
|
|
||||||
def test_multi_parents_path():
|
#def test_multi_parents_path():
|
||||||
"""
|
# """
|
||||||
metacfg1 (1) ---
|
# metacfg1 (1) ---
|
||||||
| -- cfg1
|
# | -- cfg1
|
||||||
metacfg2 (2) ---
|
# metacfg2 (2) ---
|
||||||
"""
|
# """
|
||||||
metacfg1 = make_metaconfig()
|
# metacfg1 = make_metaconfig()
|
||||||
cfg1 = metacfg1.config.new(type='config', name="cfg1")
|
# cfg1 = metacfg1.config.new(type='config', name="cfg1")
|
||||||
metacfg2 = MetaConfig([cfg1], name='metacfg2')
|
# metacfg2 = MetaConfig([cfg1], name='metacfg2')
|
||||||
#
|
# #
|
||||||
assert metacfg1.config.path() == 'metacfg1'
|
# assert metacfg1.config.path() == 'metacfg1'
|
||||||
assert metacfg2.config.path() == 'metacfg2'
|
# assert metacfg2.config.path() == 'metacfg2'
|
||||||
assert cfg1.config.path() == 'metacfg2.metacfg1.cfg1'
|
# assert cfg1.config.path() == 'metacfg2.metacfg1.cfg1'
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_multi_parents_path_same():
|
#def test_multi_parents_path_same():
|
||||||
"""
|
# """
|
||||||
--- metacfg2 (1) ---
|
# --- metacfg2 (1) ---
|
||||||
metacfg1 --| | -- cfg1
|
# metacfg1 --| | -- cfg1
|
||||||
--- metacfg3 (2) ---
|
# --- metacfg3 (2) ---
|
||||||
"""
|
# """
|
||||||
metacfg1 = make_metaconfig()
|
# metacfg1 = make_metaconfig()
|
||||||
metacfg2 = metacfg1.config.new(type='metaconfig', name="metacfg2")
|
# metacfg2 = metacfg1.config.new(type='metaconfig', name="metacfg2")
|
||||||
metacfg3 = metacfg1.config.new(type='metaconfig', name="metacfg3")
|
# metacfg3 = metacfg1.config.new(type='metaconfig', name="metacfg3")
|
||||||
cfg1 = metacfg2.config.new(type='config', name="cfg1")
|
# cfg1 = metacfg2.config.new(type='config', name="cfg1")
|
||||||
metacfg3.config.add(cfg1)
|
# metacfg3.config.add(cfg1)
|
||||||
#
|
# #
|
||||||
assert metacfg2.config.path() == 'metacfg1.metacfg2'
|
# assert metacfg2.config.path() == 'metacfg1.metacfg2'
|
||||||
assert metacfg3.config.path() == 'metacfg1.metacfg3'
|
# assert metacfg3.config.path() == 'metacfg1.metacfg3'
|
||||||
assert cfg1.config.path() == 'metacfg1.metacfg3.metacfg1.metacfg2.cfg1'
|
# assert cfg1.config.path() == 'metacfg1.metacfg3.metacfg1.metacfg2.cfg1'
|
||||||
metacfg1.option('od1.i1').value.set(1)
|
# metacfg1.option('od1.i1').value.set(1)
|
||||||
metacfg3.option('od1.i1').value.set(2)
|
# metacfg3.option('od1.i1').value.set(2)
|
||||||
assert cfg1.option('od1.i1').value.get() == 1
|
# assert cfg1.option('od1.i1').value.get() == 1
|
||||||
orideep = cfg1.config.deepcopy(metaconfig_prefix="test_", name='test_cfg1')
|
# orideep = cfg1.config.deepcopy(metaconfig_prefix="test_", name='test_cfg1')
|
||||||
deep = orideep
|
# deep = orideep
|
||||||
while True:
|
# while True:
|
||||||
try:
|
# try:
|
||||||
children = list(deep.config.list())
|
# children = list(deep.config.list())
|
||||||
except:
|
# except:
|
||||||
break
|
# break
|
||||||
assert len(children) < 2
|
# assert len(children) < 2
|
||||||
deep = children[0]
|
# deep = children[0]
|
||||||
assert deep.config.path() == 'test_metacfg3.test_metacfg1.test_metacfg2.test_cfg1'
|
# assert deep.config.path() == 'test_metacfg3.test_metacfg1.test_metacfg2.test_cfg1'
|
||||||
assert cfg1.option('od1.i1').value.get() == 1
|
# assert cfg1.option('od1.i1').value.get() == 1
|
||||||
|
#
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_multi_parents_value():
|
#def test_multi_parents_value():
|
||||||
metacfg1 = make_metaconfig()
|
# metacfg1 = make_metaconfig()
|
||||||
cfg1 = metacfg1.config.new(type='config', name="cfg1")
|
# cfg1 = metacfg1.config.new(type='config', name="cfg1")
|
||||||
metacfg2 = MetaConfig([cfg1], name='metacfg2')
|
# metacfg2 = MetaConfig([cfg1], name='metacfg2')
|
||||||
#
|
# #
|
||||||
assert cfg1.option('od1.i1').value.get() == None
|
# assert cfg1.option('od1.i1').value.get() == None
|
||||||
assert cfg1.option('od1.i2').value.get() == 1
|
# assert cfg1.option('od1.i2').value.get() == 1
|
||||||
assert cfg1.option('od1.i3').value.get() == None
|
# assert cfg1.option('od1.i3').value.get() == None
|
||||||
#
|
# #
|
||||||
assert metacfg1.option('od1.i1').value.get() == None
|
# assert metacfg1.option('od1.i1').value.get() == None
|
||||||
assert metacfg1.option('od1.i2').value.get() == 1
|
# assert metacfg1.option('od1.i2').value.get() == 1
|
||||||
assert metacfg1.option('od1.i3').value.get() == None
|
# assert metacfg1.option('od1.i3').value.get() == None
|
||||||
#
|
# #
|
||||||
assert metacfg2.option('od1.i1').value.get() == None
|
# assert metacfg2.option('od1.i1').value.get() == None
|
||||||
assert metacfg2.option('od1.i2').value.get() == 1
|
# assert metacfg2.option('od1.i2').value.get() == 1
|
||||||
assert metacfg2.option('od1.i3').value.get() == None
|
# assert metacfg2.option('od1.i3').value.get() == None
|
||||||
#
|
# #
|
||||||
metacfg1.option('od1.i3').value.set(3)
|
# metacfg1.option('od1.i3').value.set(3)
|
||||||
assert metacfg1.option('od1.i3').value.get() == 3
|
# assert metacfg1.option('od1.i3').value.get() == 3
|
||||||
assert cfg1.option('od1.i3').value.get() == 3
|
# assert cfg1.option('od1.i3').value.get() == 3
|
||||||
assert metacfg2.option('od1.i2').value.get() == 1
|
# assert metacfg2.option('od1.i2').value.get() == 1
|
||||||
#
|
# #
|
||||||
metacfg2.option('od1.i2').value.set(4)
|
# metacfg2.option('od1.i2').value.set(4)
|
||||||
assert metacfg2.option('od1.i2').value.get() == 4
|
# assert metacfg2.option('od1.i2').value.get() == 4
|
||||||
assert metacfg1.option('od1.i2').value.get() == 1
|
# assert metacfg1.option('od1.i2').value.get() == 1
|
||||||
assert cfg1.option('od1.i2').value.get() == 4
|
# assert cfg1.option('od1.i2').value.get() == 4
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \
|
||||||
valid_ip_netmask, ParamSelfOption, ParamInformation, ParamSelfInformation
|
valid_ip_netmask, ParamSelfOption, ParamInformation, ParamSelfInformation
|
||||||
from tiramisu.error import PropertiesOptionError, ConflictError, LeadershipError, ConfigError
|
from tiramisu.error import PropertiesOptionError, ConflictError, LeadershipError, ConfigError
|
||||||
from tiramisu.i18n import _
|
from tiramisu.i18n import _
|
||||||
from .config import config_type, get_config, parse_od_get, get_dependencies
|
from .config import config_type, get_config, parse_od_get
|
||||||
|
|
||||||
|
|
||||||
def return_val():
|
def return_val():
|
||||||
|
|
@ -693,7 +693,6 @@ def test_callback_leader_and_followers_leader(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 [(a.path(), a.index()) for a in cfg.option('val1').dependencies()] == [('val2.val2', None)]
|
|
||||||
assert cfg.option('val1').value.get() == ['val']
|
assert cfg.option('val1').value.get() == ['val']
|
||||||
assert cfg.option('val2.val2').value.get() == ['val']
|
assert cfg.option('val2.val2').value.get() == ['val']
|
||||||
#
|
#
|
||||||
|
|
@ -784,29 +783,10 @@ def test_callback_leader_and_followers_leader2(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 get_dependencies(cfg.option('val1.val2')) == [('val1', None)]
|
|
||||||
assert get_dependencies(cfg.option('val1.val3')) == [('val1', None)] #, ('val2.val2', 0)]
|
|
||||||
assert get_dependencies(cfg.option('val1.val4')) == [('val1', None)] #, ('val2.val3', 0)]
|
|
||||||
#
|
|
||||||
cfg.option('val1.val1').value.set(['val'])
|
cfg.option('val1.val1').value.set(['val'])
|
||||||
assert get_dependencies(cfg.option('val1.val2')) == [('val1', None), ('val1.val3', 0)]
|
|
||||||
assert get_dependencies(cfg.option('val1.val2', 0)) == [('val1', None), ('val1.val3', 0)]
|
|
||||||
assert get_dependencies(cfg.option('val1.val3')) == [('val1', None), ('val1.val4', 0)]
|
|
||||||
assert get_dependencies(cfg.option('val1.val3', 0)) == [('val1', None), ('val1.val4', 0)]
|
|
||||||
assert get_dependencies(cfg.option('val1.val4')) == [('val1', None)]
|
|
||||||
|
|
||||||
assert cfg.option('val1.val4', 0).value.get() == 'val2'
|
assert cfg.option('val1.val4', 0).value.get() == 'val2'
|
||||||
assert cfg.option('val1.val3', 0).value.get() == 'val2'
|
assert cfg.option('val1.val3', 0).value.get() == 'val2'
|
||||||
assert cfg.option('val1.val2', 0).value.get() == 'val2'
|
assert cfg.option('val1.val2', 0).value.get() == 'val2'
|
||||||
#
|
|
||||||
cfg.option('val1.val1').value.set(['val1', 'val2'])
|
|
||||||
assert get_dependencies(cfg.option('val1.val2')) == [('val1', None), ('val1.val3', 0), ('val1.val3', 1)]
|
|
||||||
assert get_dependencies(cfg.option('val1.val2', 0)) == [('val1', None), ('val1.val3', 0)]
|
|
||||||
assert get_dependencies(cfg.option('val1.val2', 1)) == [('val1', None), ('val1.val3', 1)]
|
|
||||||
assert get_dependencies(cfg.option('val1.val3')) == [('val1', None), ('val1.val4', 0), ('val1.val4', 1)]
|
|
||||||
assert get_dependencies(cfg.option('val1.val3', 0)) == [('val1', None), ('val1.val4', 0)]
|
|
||||||
assert get_dependencies(cfg.option('val1.val3', 1)) == [('val1', None), ('val1.val4', 1)]
|
|
||||||
assert get_dependencies(cfg.option('val1.val4')) == [('val1', None)]
|
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -965,7 +945,7 @@ def test_consistency_leader_and_followers_leader_mandatory_transitive():
|
||||||
try:
|
try:
|
||||||
cfg.option('val1.val2', 0).value.get()
|
cfg.option('val1.val2', 0).value.get()
|
||||||
except PropertiesOptionError as error:
|
except PropertiesOptionError as error:
|
||||||
assert str(error) == str(_('cannot access to {0} {1} at index "{2}" because has {3} {4}').format('option', '"val2"', 0, _('property'), '"disabled"'))
|
assert str(error) == str(_('cannot access to {0} {1} because has {2} {3}').format('option', '"val2"', _('property'), '"disabled"'))
|
||||||
else:
|
else:
|
||||||
raise Exception('must raises')
|
raise Exception('must raises')
|
||||||
assert list(cfg.value.mandatory()) == []
|
assert list(cfg.value.mandatory()) == []
|
||||||
|
|
@ -1519,7 +1499,6 @@ def test_leadership_callback_description(config_type):
|
||||||
cfg.option('od.st.st1.st2', 0).value.set('yes')
|
cfg.option('od.st.st1.st2', 0).value.set('yes')
|
||||||
assert cfg.option('od.st.st1.st1').owner.get() == owner
|
assert cfg.option('od.st.st1.st1').owner.get() == owner
|
||||||
assert cfg.option('od.st.st1.st2', 0).owner.get() == owner
|
assert cfg.option('od.st.st1.st2', 0).owner.get() == owner
|
||||||
assert get_dependencies(cfg.option('od.st.st1.st2')) == [('od.st.st1', None)]
|
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1536,8 +1515,6 @@ def test_leadership_callback_outside(config_type):
|
||||||
owner = cfg.owner.get()
|
owner = cfg.owner.get()
|
||||||
cfg.option('od.st.st1.st1').value.set(['yes'])
|
cfg.option('od.st.st1.st1').value.set(['yes'])
|
||||||
assert parse_od_get(cfg.value.get()) == {'od.st.st1.st1': [{'od.st.st1.st1': 'yes', 'od.st.st1.st2': 'val2'}], 'od.st.st3': ['val2']}
|
assert parse_od_get(cfg.value.get()) == {'od.st.st1.st1': [{'od.st.st1.st1': 'yes', 'od.st.st1.st2': 'val2'}], 'od.st.st3': ['val2']}
|
||||||
assert get_dependencies(cfg.option('od.st.st1.st2')) == [('od.st.st1', None), ('od.st.st3', None,)]
|
|
||||||
|
|
||||||
## assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,8 +154,8 @@ def test_force_default_on_freeze_multi():
|
||||||
# with pytest.raises(ConfigError):
|
# with pytest.raises(ConfigError):
|
||||||
# Config(od1)
|
# Config(od1)
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
#
|
|
||||||
#
|
|
||||||
#def test_force_metaconfig_on_freeze_leader():
|
#def test_force_metaconfig_on_freeze_leader():
|
||||||
# dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('force_metaconfig_on_freeze',))
|
# dummy1 = BoolOption('dummy1', 'Test int option', multi=True, properties=('force_metaconfig_on_freeze',))
|
||||||
# dummy2 = BoolOption('dummy2', 'Test string option', multi=True)
|
# dummy2 = BoolOption('dummy2', 'Test string option', multi=True)
|
||||||
|
|
|
||||||
|
|
@ -64,16 +64,15 @@ def test_hidden_owner():
|
||||||
od1 = OptionDescription('tiramisu', '', [gcdummy])
|
od1 = OptionDescription('tiramisu', '', [gcdummy])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
with pytest.raises(PropertiesOptionError):
|
#with pytest.raises(PropertiesOptionError):
|
||||||
cfg.option('dummy').value.get()
|
# cfg.forcepermissive.option('dummy').owner.get()
|
||||||
with pytest.raises(PropertiesOptionError):
|
#with pytest.raises(PropertiesOptionError):
|
||||||
cfg.option('dummy').owner.isdefault()
|
# cfg.option('dummy').owner.isdefault()
|
||||||
|
#with pytest.raises(PropertiesOptionError):
|
||||||
|
# cfg.forcepermissive.option('dummy').owner.isdefault()
|
||||||
cfg.permissive.add('hidden')
|
cfg.permissive.add('hidden')
|
||||||
cfg.forcepermissive.option('dummy').value.get()
|
cfg.forcepermissive.option('dummy').value.get()
|
||||||
cfg.forcepermissive.option('dummy').owner.isdefault()
|
cfg.forcepermissive.option('dummy').owner.isdefault()
|
||||||
option = cfg.option("dummy")
|
|
||||||
option.forcepermissive.value.get()
|
|
||||||
option.forcepermissive.owner.isdefault()
|
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -202,10 +202,10 @@ def test_property_get_unique_empty():
|
||||||
od1 = OptionDescription("options", "", [s, s2, s3, s4])
|
od1 = OptionDescription("options", "", [s, s2, s3, s4])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
assert cfg.option('string').property.get() == {"validator", 'empty', 'unique'}
|
assert cfg.option('string').property.get() == {'empty', 'unique'}
|
||||||
assert cfg.option('string2').property.get() == {"validator", 'empty', 'notunique'}
|
assert cfg.option('string2').property.get() == {'empty', 'notunique'}
|
||||||
assert cfg.option('string3').property.get() == {"validator", 'unique', 'notempty'}
|
assert cfg.option('string3').property.get() == {'unique', 'notempty'}
|
||||||
assert cfg.option('string4').property.get() == {"validator", 'notunique', 'notempty'}
|
assert cfg.option('string4').property.get() == {'notunique', 'notempty'}
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -220,7 +220,7 @@ def test_property_only_raises():
|
||||||
od1 = OptionDescription("options", "", [s, intoption, stroption])
|
od1 = OptionDescription("options", "", [s, intoption, stroption])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
assert cfg.option('str').property.get() == {'empty', 'unique', 'validator'}
|
assert cfg.option('str').property.get() == {'empty', 'unique'}
|
||||||
assert cfg.option('str').property.get(only_raises=True) == set()
|
assert cfg.option('str').property.get(only_raises=True) == set()
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
@ -569,23 +569,23 @@ def test_access_by_get_whith_hide():
|
||||||
def test_append_properties():
|
def test_append_properties():
|
||||||
od1 = make_description()
|
od1 = make_description()
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
assert cfg.option('gc.dummy').property.get() == {"validator"}
|
assert cfg.option('gc.dummy').property.get() == set()
|
||||||
cfg.option('gc.dummy').property.add('test')
|
cfg.option('gc.dummy').property.add('test')
|
||||||
assert cfg.option('gc.dummy').property.get() == {'test', "validator"}
|
assert cfg.option('gc.dummy').property.get() == {'test'}
|
||||||
with pytest.raises(ConfigError):
|
with pytest.raises(ConfigError):
|
||||||
cfg.option('gc.dummy').property.add('force_store_value')
|
cfg.option('gc.dummy').property.add('force_store_value')
|
||||||
assert cfg.option('gc.dummy').property.get() == {'test', "validator"}
|
assert cfg.option('gc.dummy').property.get() == {'test'}
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_reset_properties():
|
def test_reset_properties():
|
||||||
od1 = make_description()
|
od1 = make_description()
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
assert cfg.option('gc.dummy').property.get() == {"validator"}
|
assert cfg.option('gc.dummy').property.get() == set()
|
||||||
cfg.option('gc.dummy').property.add('frozen')
|
cfg.option('gc.dummy').property.add('frozen')
|
||||||
assert cfg.option('gc.dummy').property.get() == {"validator", 'frozen'}
|
assert cfg.option('gc.dummy').property.get() == {'frozen'}
|
||||||
cfg.option('gc.dummy').property.reset()
|
cfg.option('gc.dummy').property.reset()
|
||||||
assert cfg.option('gc.dummy').property.get() == {"validator"}
|
assert cfg.option('gc.dummy').property.get() == set()
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -594,7 +594,7 @@ def test_properties_cached():
|
||||||
od1 = OptionDescription("opt", "", [OptionDescription("sub", "", [b1])])
|
od1 = OptionDescription("opt", "", [OptionDescription("sub", "", [b1])])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
assert cfg.option('sub.b1').property.get() == {'test', "validator"}
|
assert cfg.option('sub.b1').property.get() == {'test'}
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -603,9 +603,9 @@ def test_append_properties_force_store_value():
|
||||||
gcgroup = OptionDescription('gc', '', [gcdummy])
|
gcgroup = OptionDescription('gc', '', [gcdummy])
|
||||||
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
assert cfg.option('gc.dummy').property.get() == {'force_store_value', "validator"}
|
assert cfg.option('gc.dummy').property.get() == {'force_store_value'}
|
||||||
cfg.option('gc.dummy').property.add('test')
|
cfg.option('gc.dummy').property.add('test')
|
||||||
assert cfg.option('gc.dummy').property.get() == {'force_store_value', 'test', "validator"}
|
assert cfg.option('gc.dummy').property.get() == {'force_store_value', 'test'}
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -818,27 +818,27 @@ def test_reset_properties_force_store_value():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_importation_force_store_value():
|
#def test_importation_force_store_value():
|
||||||
gcdummy = BoolOption('dummy', 'dummy', default=False,
|
# gcdummy = BoolOption('dummy', 'dummy', default=False,
|
||||||
properties=('force_store_value',))
|
# properties=('force_store_value',))
|
||||||
gcgroup = OptionDescription('gc', '', [gcdummy])
|
# gcgroup = OptionDescription('gc', '', [gcdummy])
|
||||||
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
# od1 = OptionDescription('tiramisu', '', [gcgroup])
|
||||||
config1 = Config(od1)
|
# config1 = Config(od1)
|
||||||
assert config1.value.exportation() == {}
|
# assert config1.value.exportation() == {}
|
||||||
config1.property.add('frozen')
|
# config1.property.add('frozen')
|
||||||
assert config1.value.exportation() == {}
|
# assert config1.value.exportation() == {}
|
||||||
config1.property.add('force_store_value')
|
# config1.property.add('force_store_value')
|
||||||
assert config1.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
|
# assert config1.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
|
||||||
exportation = config1.property.exportation()
|
# exportation = config1.property.exportation()
|
||||||
config2 = Config(od1)
|
# config2 = Config(od1)
|
||||||
assert config2.value.exportation() == {}
|
# assert config2.value.exportation() == {}
|
||||||
config2.property.importation(exportation)
|
# config2.property.importation(exportation)
|
||||||
assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
|
# assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
|
||||||
config2.property.importation(exportation)
|
# config2.property.importation(exportation)
|
||||||
assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
|
# assert config2.value.exportation() == {'gc.dummy': {None: [False, 'forced']}}
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_set_modified_value():
|
def test_set_modified_value():
|
||||||
gcdummy = BoolOption('dummy', 'dummy', default=False, properties=('force_store_value',))
|
gcdummy = BoolOption('dummy', 'dummy', default=False, properties=('force_store_value',))
|
||||||
gcgroup = OptionDescription('gc', '', [gcdummy])
|
gcgroup = OptionDescription('gc', '', [gcdummy])
|
||||||
|
|
@ -920,57 +920,18 @@ def test_set_modified_value():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_none_is_not_modified():
|
#def test_none_is_not_modified():
|
||||||
gcdummy = StrOption('dummy', 'dummy', properties=('force_store_value',))
|
# gcdummy = StrOption('dummy', 'dummy', properties=('force_store_value',))
|
||||||
gcdummy1 = StrOption('dummy1', 'dummy1', default="str", properties=('force_store_value',))
|
# gcdummy1 = StrOption('dummy1', 'dummy1', default="str", properties=('force_store_value',))
|
||||||
gcgroup = OptionDescription('gc', '', [gcdummy, gcdummy1])
|
# gcgroup = OptionDescription('gc', '', [gcdummy, gcdummy1])
|
||||||
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
# od1 = OptionDescription('tiramisu', '', [gcgroup])
|
||||||
cfg = Config(od1)
|
# cfg = Config(od1)
|
||||||
assert cfg.value.exportation() == {}
|
# assert cfg.value.exportation() == {}
|
||||||
cfg.property.read_write()
|
# cfg.property.read_write()
|
||||||
assert cfg.value.exportation() == {'gc.dummy1': {None: ['str', 'forced']}}
|
# assert cfg.value.exportation() == {'gc.dummy1': {None: ['str', 'forced']}}
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_force_store_value_disabled_value():
|
|
||||||
gcdummy = StrOption('dummy', 'dummy', properties=('force_store_value',))
|
|
||||||
gcdummy1 = StrOption('dummy1', 'dummy1', default="str", properties=('force_store_value', 'disabled'))
|
|
||||||
gcgroup = OptionDescription('gc', '', [gcdummy, gcdummy1])
|
|
||||||
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
|
||||||
cfg = Config(od1)
|
|
||||||
cfg.property.read_write()
|
|
||||||
assert cfg.value.exportation() == {}
|
|
||||||
cfg.option('gc.dummy1').permissive.add('disabled')
|
|
||||||
assert cfg.option('gc.dummy1').value.get() == 'str'
|
|
||||||
# do not export
|
|
||||||
assert cfg._config_bag.context.get_values()._values == {None: {None: [None, 'user']},'gc.dummy1': {None: ['str', 'forced']}}
|
|
||||||
|
|
||||||
|
|
||||||
def test_force_store_value_disabled_owner():
|
|
||||||
gcdummy = StrOption('dummy', 'dummy', properties=('force_store_value',))
|
|
||||||
gcdummy1 = StrOption('dummy1', 'dummy1', default="str", properties=('force_store_value', 'disabled'))
|
|
||||||
gcgroup = OptionDescription('gc', '', [gcdummy, gcdummy1])
|
|
||||||
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
|
||||||
cfg = Config(od1)
|
|
||||||
cfg.property.read_write()
|
|
||||||
assert cfg.value.exportation() == {}
|
|
||||||
cfg.option('gc.dummy1').permissive.add('disabled')
|
|
||||||
assert cfg.option('gc.dummy1').owner.get() == owners.forced
|
|
||||||
assert cfg.value.exportation() == {'gc.dummy1': {None: ['str', 'forced']}}
|
|
||||||
|
|
||||||
|
|
||||||
def test_force_store_value_disabled_exportation():
|
|
||||||
gcdummy = StrOption('dummy', 'dummy', properties=('force_store_value',))
|
|
||||||
gcdummy1 = StrOption('dummy1', 'dummy1', default="str", properties=('force_store_value', 'disabled'))
|
|
||||||
gcgroup = OptionDescription('gc', '', [gcdummy, gcdummy1])
|
|
||||||
od1 = OptionDescription('tiramisu', '', [gcgroup])
|
|
||||||
cfg = Config(od1)
|
|
||||||
cfg.property.read_write()
|
|
||||||
assert cfg.value.exportation() == {}
|
|
||||||
cfg.option('gc.dummy1').permissive.add('disabled')
|
|
||||||
assert cfg.value.exportation() == {'gc.dummy1': {None: ['str', 'forced']}}
|
|
||||||
|
|
||||||
|
|
||||||
def test_pprint():
|
def test_pprint():
|
||||||
msg_error = _("cannot access to {0} {1} because has {2} {3}")
|
msg_error = _("cannot access to {0} {1} because has {2} {3}")
|
||||||
msg_is_not = _('the value of "{0}" is not {1}')
|
msg_is_not = _('the value of "{0}" is not {1}')
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ import pytest
|
||||||
|
|
||||||
from tiramisu import BoolOption, StrOption, IPOption, NetmaskOption, NetworkOption, BroadcastOption, \
|
from tiramisu import BoolOption, StrOption, IPOption, NetmaskOption, NetworkOption, BroadcastOption, \
|
||||||
IntOption, OptionDescription, Leadership, Config, Params, ParamValue, ParamOption, \
|
IntOption, OptionDescription, Leadership, Config, Params, ParamValue, ParamOption, \
|
||||||
ParamSelfOption, ParamIndex, ParamInformation, ParamSelfInformation, Calculation, \
|
ParamSelfOption, ParamIndex, ParamInformation, ParamSelfInformation, ParamSelfOption, Calculation, \
|
||||||
valid_ip_netmask, valid_network_netmask, \
|
valid_ip_netmask, valid_network_netmask, \
|
||||||
valid_in_network, valid_broadcast, valid_not_equal
|
valid_in_network, valid_broadcast, valid_not_equal
|
||||||
from tiramisu.setting import groups
|
from tiramisu.setting import groups
|
||||||
|
|
@ -34,7 +34,7 @@ def return_val(value, param=None):
|
||||||
|
|
||||||
|
|
||||||
def return_if_val(value):
|
def return_if_val(value):
|
||||||
if value not in ['val', 'val_not_raise']:
|
if value != 'val':
|
||||||
raise ValueError('test error')
|
raise ValueError('test error')
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -121,34 +121,6 @@ def test_validator(config_type):
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_validator_no_validation(config_type):
|
|
||||||
opt1 = StrOption('opt1', '', validators=[Calculation(return_true, Params(ParamSelfOption()))], default='val', properties=frozenset(['novalidator']))
|
|
||||||
opt2 = StrOption('opt2', '', validators=[Calculation(return_false, Params(ParamSelfOption()))], properties=frozenset(['novalidator']))
|
|
||||||
od1 = OptionDescription('root', '', [opt1, opt2])
|
|
||||||
cfg_ori = Config(od1)
|
|
||||||
cfg = get_config(cfg_ori, config_type)
|
|
||||||
assert cfg.option('opt1').value.get() == 'val'
|
|
||||||
assert cfg.option('opt2').value.valid() is True
|
|
||||||
cfg.option('opt2').value.set('val')
|
|
||||||
|
|
||||||
|
|
||||||
def test_validator_no_validation2(config_type):
|
|
||||||
opt1 = StrOption('opt1', '', properties=frozenset(['novalidator']))
|
|
||||||
od1 = OptionDescription('root', '', [opt1])
|
|
||||||
cfg_ori = Config(od1)
|
|
||||||
cfg = get_config(cfg_ori, config_type)
|
|
||||||
cfg.option('opt1').value.set(1)
|
|
||||||
assert cfg.option('opt1').value.get() == 1
|
|
||||||
|
|
||||||
|
|
||||||
def test_validator_no_validation3(config_type):
|
|
||||||
opt1 = StrOption('opt1', '', 1, properties=frozenset(['novalidator']))
|
|
||||||
od1 = OptionDescription('root', '', [opt1])
|
|
||||||
cfg_ori = Config(od1)
|
|
||||||
cfg = get_config(cfg_ori, config_type)
|
|
||||||
assert cfg.option('opt1').value.get() == 1
|
|
||||||
|
|
||||||
|
|
||||||
def test_validator_not_valid(config_type):
|
def test_validator_not_valid(config_type):
|
||||||
with pytest.raises(ValueError):
|
with pytest.raises(ValueError):
|
||||||
StrOption('not_a_list', '', validators=Calculation(return_true, Params(ParamSelfOption())), default='val')
|
StrOption('not_a_list', '', validators=Calculation(return_true, Params(ParamSelfOption())), default='val')
|
||||||
|
|
@ -341,13 +313,6 @@ def test_validator_multi(config_type):
|
||||||
with warnings.catch_warnings(record=True) as w:
|
with warnings.catch_warnings(record=True) as w:
|
||||||
cfg.option('opt1').value.set(['val', 'val1'])
|
cfg.option('opt1').value.set(['val', 'val1'])
|
||||||
assert len(w) == 1
|
assert len(w) == 1
|
||||||
with warnings.catch_warnings(record=True) as w:
|
|
||||||
cfg.option('opt1').value.set(['val1', 'val2'])
|
|
||||||
assert len(w) == 2
|
|
||||||
with warnings.catch_warnings(record=True) as w:
|
|
||||||
# same value twice
|
|
||||||
cfg.option('opt1').value.set(['val', 'val', 'val_not_raise'])
|
|
||||||
assert len(w) == 2
|
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -22,16 +22,7 @@ def test_forcepermissive_and_unrestraint(config_type):
|
||||||
cfg_ori.property.read_write()
|
cfg_ori.property.read_write()
|
||||||
cfg = get_config(cfg_ori, config_type)
|
cfg = get_config(cfg_ori, config_type)
|
||||||
with pytest.raises(ConfigError):
|
with pytest.raises(ConfigError):
|
||||||
cfg_ori.unrestraint.forcepermissive
|
cfg_ori.forcepermissive.add('disabled')
|
||||||
|
|
||||||
|
|
||||||
def test_unrestraint_and_unrestraint(config_type):
|
|
||||||
od1 = make_description()
|
|
||||||
cfg_ori = Config(od1)
|
|
||||||
cfg_ori.property.read_write()
|
|
||||||
cfg_ori.property.read_write()
|
|
||||||
cfg = get_config(cfg_ori, config_type)
|
|
||||||
cfg_ori.unrestraint.unrestraint
|
|
||||||
|
|
||||||
|
|
||||||
def test_permissive(config_type):
|
def test_permissive(config_type):
|
||||||
|
|
|
||||||
|
|
@ -426,9 +426,9 @@ def test_requires_transitive_unrestraint(config_type):
|
||||||
#
|
#
|
||||||
if config_type == 'tiramisu-api':
|
if config_type == 'tiramisu-api':
|
||||||
cfg.send()
|
cfg.send()
|
||||||
assert cfg_ori.option('activate_service_web').property.get() == {'disabled', "validator"}
|
assert cfg_ori.option('activate_service_web').property.get() == {'disabled'}
|
||||||
# FIXME assert cfg_ori.unrestraint.option('ip_address_service_web').property.get() == {'disabled'}
|
# FIXME assert cfg_ori.unrestraint.option('ip_address_service_web').property.get() == {'disabled'}
|
||||||
assert cfg_ori.option('ip_address_service_web').property.get() == {'disabled', "validator"}
|
assert cfg_ori.option('ip_address_service_web').property.get() == {'disabled'}
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -146,8 +146,8 @@ def test_slots_option_readonly():
|
||||||
with pytest.raises(AttributeError):
|
with pytest.raises(AttributeError):
|
||||||
q._requires = 'q'
|
q._requires = 'q'
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
#
|
|
||||||
#
|
|
||||||
#def test_slots_description():
|
#def test_slots_description():
|
||||||
# # __slots__ for OptionDescription should be complete for __getattr__
|
# # __slots__ for OptionDescription should be complete for __getattr__
|
||||||
# slots = set()
|
# slots = set()
|
||||||
|
|
|
||||||
|
|
@ -8,7 +8,7 @@ import warnings
|
||||||
from tiramisu.setting import groups, owners
|
from tiramisu.setting import groups, owners
|
||||||
from tiramisu import StrOption, IntOption, OptionDescription, submulti, Leadership, Config, \
|
from tiramisu import StrOption, IntOption, OptionDescription, submulti, Leadership, Config, \
|
||||||
MetaConfig, Params, ParamOption, Calculation
|
MetaConfig, Params, ParamOption, Calculation
|
||||||
from tiramisu.error import LeadershipError, PropertiesOptionError, ValueOptionError
|
from tiramisu.error import LeadershipError, PropertiesOptionError
|
||||||
|
|
||||||
|
|
||||||
def return_val(val=None):
|
def return_val(val=None):
|
||||||
|
|
@ -317,8 +317,10 @@ def test_values_with_leader_and_followers_submulti_mandatory():
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()
|
||||||
#
|
#
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
with pytest.raises(ValueOptionError):
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(["255.255.255.0", '', "255.255.255.0"])
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(["255.255.255.0", "255.255.255.0"])
|
cfg.property.read_only()
|
||||||
|
with pytest.raises(PropertiesOptionError):
|
||||||
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.get()
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -380,6 +382,7 @@ def test_values_with_leader_and_followers_follower_submulti():
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0'])
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0'])
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145'])
|
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145'])
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0'])
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0'])
|
||||||
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0', '255.255.255.0'])
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.reset()
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.reset()
|
||||||
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0'])
|
cfg.option('ip_admin_eth0.netmask_admin_eth0', 0).value.set(['255.255.255.0'])
|
||||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145', '192.168.230.145'])
|
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.230.145', '192.168.230.145'])
|
||||||
|
|
@ -498,7 +501,7 @@ def test_callback_submulti():
|
||||||
|
|
||||||
def test_callback_submulti_follower():
|
def test_callback_submulti_follower():
|
||||||
multi = StrOption('multi', '', multi=True)
|
multi = StrOption('multi', '', multi=True)
|
||||||
multi2 = StrOption('multi2', '', Calculation(return_list), multi=submulti, properties=('notunique',))
|
multi2 = StrOption('multi2', '', Calculation(return_list), multi=submulti)
|
||||||
od = Leadership('multi', '', [multi, multi2])
|
od = Leadership('multi', '', [multi, multi2])
|
||||||
od1 = OptionDescription('multi', '', [od])
|
od1 = OptionDescription('multi', '', [od])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
|
|
@ -525,43 +528,43 @@ def test_submulti_unique():
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
||||||
def test_multi_submulti_meta():
|
#def test_multi_submulti_meta():
|
||||||
multi = StrOption('multi', '', multi=submulti)
|
# multi = StrOption('multi', '', multi=submulti)
|
||||||
od1 = OptionDescription('od', '', [multi])
|
# od1 = OptionDescription('od', '', [multi])
|
||||||
cfg = Config(od1, name='cfg')
|
# cfg = Config(od1, name='cfg')
|
||||||
cfg.property.read_write()
|
# cfg.property.read_write()
|
||||||
cfg2 = Config(od1, name="cfg2")
|
# cfg2 = Config(od1)
|
||||||
cfg2.property.read_write()
|
# cfg2.property.read_write()
|
||||||
meta = MetaConfig([cfg, cfg2])
|
# meta = MetaConfig([cfg, cfg2])
|
||||||
meta.property.read_write()
|
# meta.property.read_write()
|
||||||
meta.option('multi').value.set([['val']])
|
# meta.option('multi').value.set([['val']])
|
||||||
assert meta.option('multi').value.get() == [['val']]
|
# assert meta.option('multi').value.get() == [['val']]
|
||||||
newcfg = meta.config('cfg')
|
# newcfg = meta.config('cfg')
|
||||||
newcfg.option('multi').value.set([['val', None]])
|
# newcfg.option('multi').value.set([['val', None]])
|
||||||
assert cfg.option('multi').value.get() == [['val', None]]
|
# assert cfg.option('multi').value.get() == [['val', None]]
|
||||||
newcfg = meta.config('cfg')
|
# newcfg = meta.config('cfg')
|
||||||
assert newcfg.option('multi').value.get() == [['val', None]]
|
# assert newcfg.option('multi').value.get() == [['val', None]]
|
||||||
assert meta.option('multi').value.get() == [['val']]
|
# assert meta.option('multi').value.get() == [['val']]
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
#
|
||||||
|
#
|
||||||
def test_multi_submulti_meta_no_cache():
|
#def test_multi_submulti_meta_no_cache():
|
||||||
multi = StrOption('multi', '', multi=submulti)
|
# multi = StrOption('multi', '', multi=submulti)
|
||||||
multi = StrOption('multi', '', multi=submulti)
|
# multi = StrOption('multi', '', multi=submulti)
|
||||||
od1 = OptionDescription('od', '', [multi])
|
# od1 = OptionDescription('od', '', [multi])
|
||||||
cfg = Config(od1, name='cfg')
|
# cfg = Config(od1, name='cfg')
|
||||||
cfg.property.read_write()
|
# cfg.property.read_write()
|
||||||
cfg2 = Config(od1, name="cfg2")
|
# cfg2 = Config(od1)
|
||||||
cfg.property.read_write()
|
# cfg.property.read_write()
|
||||||
meta = MetaConfig([cfg, cfg2])
|
# meta = MetaConfig([cfg, cfg2])
|
||||||
meta.property.read_write()
|
# meta.property.read_write()
|
||||||
meta.property.remove('cache')
|
# meta.property.remove('cache')
|
||||||
meta.option('multi').value.set([['val']])
|
# meta.option('multi').value.set([['val']])
|
||||||
assert meta.option('multi').value.get() == [['val']]
|
# assert meta.option('multi').value.get() == [['val']]
|
||||||
newcfg = meta.config('cfg')
|
# newcfg = meta.config('cfg')
|
||||||
newcfg.option('multi').value.set([['val', None]])
|
# newcfg.option('multi').value.set([['val', None]])
|
||||||
assert cfg.option('multi').value.get() == [['val', None]]
|
# assert cfg.option('multi').value.get() == [['val', None]]
|
||||||
newcfg = meta.config('cfg')
|
# newcfg = meta.config('cfg')
|
||||||
assert newcfg.option('multi').value.get() == [['val', None]]
|
# assert newcfg.option('multi').value.get() == [['val', None]]
|
||||||
assert meta.option('multi').value.get() == [['val']]
|
# assert meta.option('multi').value.get() == [['val']]
|
||||||
# assert not list_sessions()
|
## assert not list_sessions()
|
||||||
|
|
|
||||||
|
|
@ -28,8 +28,6 @@ def test_symlink_option(config_type):
|
||||||
assert cfg.option('c').issymlinkoption()
|
assert cfg.option('c').issymlinkoption()
|
||||||
assert cfg.option('s1.b').type() == 'boolean'
|
assert cfg.option('s1.b').type() == 'boolean'
|
||||||
assert cfg.option('c').type() == 'boolean'
|
assert cfg.option('c').type() == 'boolean'
|
||||||
assert cfg.option('s1.b').type(only_self=True) == 'boolean'
|
|
||||||
assert cfg.option('c').type(only_self=True) == 'symlink'
|
|
||||||
assert cfg.option('s1.b').value.get() is False
|
assert cfg.option('s1.b').value.get() is False
|
||||||
cfg.option("s1.b").value.set(True)
|
cfg.option("s1.b").value.set(True)
|
||||||
cfg.option("s1.b").value.set(False)
|
cfg.option("s1.b").value.set(False)
|
||||||
|
|
@ -159,7 +157,7 @@ def test_symlink_getproperties():
|
||||||
od1 = OptionDescription('opt', '', [boolopt, linkopt])
|
od1 = OptionDescription('opt', '', [boolopt, linkopt])
|
||||||
cfg = Config(od1)
|
cfg = Config(od1)
|
||||||
cfg.property.read_write()
|
cfg.property.read_write()
|
||||||
assert boolopt.impl_getproperties() == linkopt.impl_getproperties() == {'test', "validator"}
|
assert boolopt.impl_getproperties() == linkopt.impl_getproperties() == {'test'}
|
||||||
# assert boolopt.impl_has_callback() == linkopt.impl_has_callback() == False
|
# assert boolopt.impl_has_callback() == linkopt.impl_has_callback() == False
|
||||||
# assert not list_sessions()
|
# assert not list_sessions()
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (C) 2012-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -42,7 +42,6 @@ from .error import ConfigError
|
||||||
from .api import Config, MetaConfig, GroupConfig, MixConfig
|
from .api import Config, MetaConfig, GroupConfig, MixConfig
|
||||||
from .option import __all__ as all_options
|
from .option import __all__ as all_options
|
||||||
from .setting import owners, groups, undefined
|
from .setting import owners, groups, undefined
|
||||||
from .__version__ import __version__
|
|
||||||
|
|
||||||
|
|
||||||
allfuncs = [
|
allfuncs = [
|
||||||
|
|
@ -77,3 +76,4 @@ allfuncs.extend(all_options)
|
||||||
del all_options
|
del all_options
|
||||||
__all__ = tuple(allfuncs)
|
__all__ = tuple(allfuncs)
|
||||||
del allfuncs
|
del allfuncs
|
||||||
|
__version__ = "4.1.0"
|
||||||
|
|
|
||||||
|
|
@ -1 +0,0 @@
|
||||||
__version__ = "5.2.0a27"
|
|
||||||
564
tiramisu/api.py
564
tiramisu/api.py
File diff suppressed because it is too large
Load diff
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (C) 2012-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -22,15 +22,7 @@ from typing import Any, Optional, Union, Callable, Dict, List
|
||||||
from itertools import chain
|
from itertools import chain
|
||||||
import weakref
|
import weakref
|
||||||
|
|
||||||
from .error import (
|
from .error import PropertiesOptionError, ConfigError, LeadershipError, ValueWarning
|
||||||
PropertiesOptionError,
|
|
||||||
ConfigError,
|
|
||||||
LeadershipError,
|
|
||||||
ValueWarning,
|
|
||||||
CancelParam,
|
|
||||||
display_list,
|
|
||||||
errors,
|
|
||||||
)
|
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
from .setting import undefined, ConfigBag
|
from .setting import undefined, ConfigBag
|
||||||
from .function import FUNCTION_WAITING_FOR_DICT, FUNCTION_WAITING_FOR_ERROR
|
from .function import FUNCTION_WAITING_FOR_DICT, FUNCTION_WAITING_FOR_ERROR
|
||||||
|
|
@ -57,7 +49,6 @@ def get_calculated_value(
|
||||||
has_calculation = True
|
has_calculation = True
|
||||||
elif isinstance(value, list):
|
elif isinstance(value, list):
|
||||||
# if value is a list, do subcalculation
|
# if value is a list, do subcalculation
|
||||||
value = value.copy()
|
|
||||||
for idx, val in enumerate(value):
|
for idx, val in enumerate(value):
|
||||||
value[idx], _has_calculation = get_calculated_value(
|
value[idx], _has_calculation = get_calculated_value(
|
||||||
subconfig,
|
subconfig,
|
||||||
|
|
@ -155,36 +146,28 @@ class ParamDynOption(ParamOption):
|
||||||
notraisepropertyerror,
|
notraisepropertyerror,
|
||||||
raisepropertyerror,
|
raisepropertyerror,
|
||||||
)
|
)
|
||||||
if not isinstance(identifiers, (list, Calculation)):
|
if not isinstance(identifiers, list):
|
||||||
raise Exception(
|
raise Exception(
|
||||||
_("identifiers in ParamDynOption must be a list or a calculation, not {0}").format(
|
f"identifiers in ParamDynOption must be a list, not {identifiers}"
|
||||||
identifiers
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
if not isinstance(optional, bool):
|
if not isinstance(optional, bool):
|
||||||
raise Exception(
|
raise Exception(
|
||||||
_("optional in ParamDynOption must be a boolean, not {0}").format(
|
f"optional in ParamDynOption must be a boolean, not {optional}"
|
||||||
optional
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
if isinstance(identifiers, Calculation):
|
|
||||||
option.value_dependency(identifiers, type_="identifier")
|
|
||||||
self.identifiers = identifiers
|
self.identifiers = identifiers
|
||||||
self.optional = optional
|
self.optional = optional
|
||||||
|
|
||||||
|
|
||||||
class ParamSelfOption(Param):
|
class ParamSelfOption(Param):
|
||||||
__slots__ = ("whole", "dynamic")
|
__slots__ = "whole"
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
whole: bool = undefined,
|
whole: bool = undefined,
|
||||||
dynamic: bool = True,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
"""whole: send all value for a multi, not only indexed value"""
|
"""whole: send all value for a multi, not only indexed value"""
|
||||||
if whole is not undefined:
|
if whole is not undefined:
|
||||||
self.whole = whole
|
self.whole = whole
|
||||||
self.dynamic = dynamic
|
|
||||||
|
|
||||||
|
|
||||||
class ParamValue(Param):
|
class ParamValue(Param):
|
||||||
|
|
@ -220,11 +203,9 @@ class ParamInformation(Param):
|
||||||
|
|
||||||
def set_option(self, option: "Option" = None) -> None:
|
def set_option(self, option: "Option" = None) -> None:
|
||||||
if not hasattr(self, "self_option"):
|
if not hasattr(self, "self_option"):
|
||||||
raise ConfigError(
|
raise ConfigError("cannot add option in information after creating config")
|
||||||
_("cannot add option in information after creating config")
|
|
||||||
)
|
|
||||||
if self.option:
|
if self.option:
|
||||||
raise ConfigError(_("cannot redefine option in information"))
|
raise ConfigError("cannot redefine option in information")
|
||||||
if not option.impl_is_optiondescription():
|
if not option.impl_is_optiondescription():
|
||||||
if option.impl_is_symlinkoption():
|
if option.impl_is_symlinkoption():
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
|
@ -464,7 +445,14 @@ def manager_callback(
|
||||||
or param.raisepropertyerror
|
or param.raisepropertyerror
|
||||||
):
|
):
|
||||||
raise err from err
|
raise err from err
|
||||||
raise ConfigError(str(err), subconfig=subconfig) from err
|
display_name = subconfig.option.impl_get_display_name(
|
||||||
|
subconfig, with_quote=True
|
||||||
|
)
|
||||||
|
raise ConfigError(
|
||||||
|
_("unable to carry out a calculation for {}, {}").format(
|
||||||
|
display_name, err
|
||||||
|
)
|
||||||
|
) from err
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
display_name = subconfig.option.impl_get_display_name(
|
display_name = subconfig.option.impl_get_display_name(
|
||||||
subconfig, with_quote=True
|
subconfig, with_quote=True
|
||||||
|
|
@ -476,15 +464,20 @@ def manager_callback(
|
||||||
) from err
|
) from err
|
||||||
except AttributeError as err:
|
except AttributeError as err:
|
||||||
if isinstance(param, ParamDynOption) and param.optional:
|
if isinstance(param, ParamDynOption) and param.optional:
|
||||||
# cannot access, simulate a propertyerror
|
# cannot acces, simulate a propertyerror
|
||||||
raise PropertiesOptionError(
|
raise PropertiesOptionError(
|
||||||
subconfig,
|
subconfig,
|
||||||
["configerror"],
|
["configerror"],
|
||||||
config_bag.context.get_settings(),
|
config_bag.context.get_settings(),
|
||||||
)
|
)
|
||||||
errors.raise_carry_out_calculation_error(
|
display_name = subconfig.option.impl_get_display_name(
|
||||||
subconfig, _("unable to get value for calculating {0}, {1}"), err
|
subconfig, with_quote=True
|
||||||
)
|
)
|
||||||
|
raise ConfigError(
|
||||||
|
_("unable to get value for calculating {0}, {1}").format(
|
||||||
|
display_name, err
|
||||||
|
)
|
||||||
|
) from err
|
||||||
return value
|
return value
|
||||||
|
|
||||||
def get_option_bag(
|
def get_option_bag(
|
||||||
|
|
@ -511,18 +504,17 @@ def manager_callback(
|
||||||
index_,
|
index_,
|
||||||
validate_properties=not self_calc,
|
validate_properties=not self_calc,
|
||||||
properties=properties,
|
properties=properties,
|
||||||
valid_conflict=False,
|
|
||||||
)
|
)
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
|
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
|
||||||
if param.notraisepropertyerror or param.raisepropertyerror:
|
if param.notraisepropertyerror or param.raisepropertyerror:
|
||||||
raise err from err
|
raise err from err
|
||||||
errors.raise_carry_out_calculation_error(
|
display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
||||||
subconfig,
|
raise ConfigError(
|
||||||
_("unable to carry out a calculation for {0}, {1}"),
|
_("unable to carry out a calculation for {}, {}").format(
|
||||||
err,
|
display_name, err
|
||||||
option=option,
|
)
|
||||||
)
|
) from err
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
|
|
@ -532,18 +524,18 @@ def manager_callback(
|
||||||
) from err
|
) from err
|
||||||
except AttributeError as err:
|
except AttributeError as err:
|
||||||
if isinstance(param, ParamDynOption) and param.optional:
|
if isinstance(param, ParamDynOption) and param.optional:
|
||||||
# cannot access, simulate a propertyerror
|
# cannot acces, simulate a propertyerror
|
||||||
raise PropertiesOptionError(
|
raise PropertiesOptionError(
|
||||||
param,
|
param,
|
||||||
["configerror"],
|
["configerror"],
|
||||||
config_bag.context.get_settings(),
|
config_bag.context.get_settings(),
|
||||||
)
|
)
|
||||||
errors.raise_carry_out_calculation_error(
|
display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
||||||
subconfig,
|
raise ConfigError(
|
||||||
_("unable to get value for calculating {0}, {1}"),
|
_("unable to get value for calculating {0}, {1}").format(
|
||||||
err,
|
display_name, err
|
||||||
option=option,
|
)
|
||||||
)
|
) from err
|
||||||
return subsubconfig
|
return subsubconfig
|
||||||
|
|
||||||
if isinstance(param, ParamValue):
|
if isinstance(param, ParamValue):
|
||||||
|
|
@ -560,15 +552,14 @@ def manager_callback(
|
||||||
true_path=subconfig.path,
|
true_path=subconfig.path,
|
||||||
)
|
)
|
||||||
if isinstance(isubconfig, list):
|
if isinstance(isubconfig, list):
|
||||||
|
display_name = option.impl_get_display_name(
|
||||||
|
subconfig, with_quote=True
|
||||||
|
)
|
||||||
search_name = search_option.impl_get_display_name(
|
search_name = search_option.impl_get_display_name(
|
||||||
None, with_quote=True
|
None, with_quote=True
|
||||||
)
|
)
|
||||||
errors.raise_carry_out_calculation_error(
|
raise ConfigError(
|
||||||
subconfig,
|
f"cannot find information for {display_name}, {search_name} is a dynamic option"
|
||||||
_("cannot find information for {0}, {1} is a dynamic option"),
|
|
||||||
None,
|
|
||||||
option=option,
|
|
||||||
extra_keys=[search_name],
|
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
isubconfig = get_option_bag(
|
isubconfig = get_option_bag(
|
||||||
|
|
@ -588,12 +579,12 @@ def manager_callback(
|
||||||
param.default_value,
|
param.default_value,
|
||||||
)
|
)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
errors.raise_carry_out_calculation_error(
|
display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
||||||
subconfig,
|
raise ConfigError(
|
||||||
_("unable to get value for calculating {0}, {1}"),
|
_("unable to get value for calculating {0}, {1}").format(
|
||||||
err,
|
display_name, err
|
||||||
option=option,
|
)
|
||||||
)
|
) from err
|
||||||
|
|
||||||
if isinstance(param, ParamIndex):
|
if isinstance(param, ParamIndex):
|
||||||
return index
|
return index
|
||||||
|
|
@ -603,59 +594,29 @@ def manager_callback(
|
||||||
not option.impl_is_optiondescription()
|
not option.impl_is_optiondescription()
|
||||||
or not option.impl_is_dynoptiondescription()
|
or not option.impl_is_dynoptiondescription()
|
||||||
):
|
):
|
||||||
errors.raise_carry_out_calculation_error(
|
display_name = subconfig.option.impl_get_display_name(
|
||||||
subconfig,
|
subconfig, with_quote=True
|
||||||
|
)
|
||||||
|
raise ConfigError(
|
||||||
_(
|
_(
|
||||||
"option {0} is not a dynoptiondescription or in a dynoptiondescription"
|
"option {0} is not a dynoptiondescription or in a dynoptiondescription"
|
||||||
),
|
).format(display_name)
|
||||||
None,
|
|
||||||
option=option,
|
|
||||||
)
|
)
|
||||||
if subconfig.identifiers is None:
|
|
||||||
# if uncalculated
|
|
||||||
return
|
|
||||||
return subconfig.identifiers[param.identifier_index]
|
return subconfig.identifiers[param.identifier_index]
|
||||||
|
|
||||||
if isinstance(param, ParamSelfOption):
|
if isinstance(param, ParamSelfOption):
|
||||||
search_option = subconfig.option
|
value = calc_self(
|
||||||
if subconfig.option.issubdyn() and not param.dynamic:
|
param,
|
||||||
subconfigs = subconfig.parent.parent.get_common_child(
|
index,
|
||||||
search_option,
|
orig_value,
|
||||||
true_path=subconfig.path,
|
config_bag,
|
||||||
validate_properties=False,
|
)
|
||||||
)
|
if callback.__name__ not in FUNCTION_WAITING_FOR_DICT:
|
||||||
values = []
|
return value
|
||||||
properties = config_bag.context.get_settings().getproperties(
|
return {
|
||||||
subconfig,
|
"name": option.impl_get_display_name(subconfig),
|
||||||
uncalculated=True,
|
"value": value,
|
||||||
) - {'validator', 'mandatory', 'empty'}
|
}
|
||||||
for subconfig_ in subconfigs:
|
|
||||||
if subconfig.path == subconfig_.path:
|
|
||||||
values.append(orig_value)
|
|
||||||
else:
|
|
||||||
subconfig_.properties = properties
|
|
||||||
values.append(get_value(
|
|
||||||
config_bag,
|
|
||||||
subconfig_,
|
|
||||||
param,
|
|
||||||
True,
|
|
||||||
))
|
|
||||||
if callback.__name__ not in FUNCTION_WAITING_FOR_DICT:
|
|
||||||
return values
|
|
||||||
return {"name": search_option.impl_get_display_name(subconfig), "value": values}
|
|
||||||
else:
|
|
||||||
value = calc_self(
|
|
||||||
param,
|
|
||||||
index,
|
|
||||||
orig_value,
|
|
||||||
config_bag,
|
|
||||||
)
|
|
||||||
if callback.__name__ not in FUNCTION_WAITING_FOR_DICT:
|
|
||||||
return value
|
|
||||||
return {
|
|
||||||
"name": option.impl_get_display_name(subconfig),
|
|
||||||
"value": value,
|
|
||||||
}
|
|
||||||
|
|
||||||
if isinstance(param, ParamOption):
|
if isinstance(param, ParamOption):
|
||||||
callbk_option = param.option
|
callbk_option = param.option
|
||||||
|
|
@ -677,15 +638,7 @@ def manager_callback(
|
||||||
with_index = False
|
with_index = False
|
||||||
if callbk_option.issubdyn():
|
if callbk_option.issubdyn():
|
||||||
if isinstance(param, ParamDynOption):
|
if isinstance(param, ParamDynOption):
|
||||||
if isinstance(param.identifiers, Calculation):
|
identifiers = param.identifiers.copy()
|
||||||
identifiers = get_calculated_value(
|
|
||||||
subconfig,
|
|
||||||
param.identifiers,
|
|
||||||
)[0]
|
|
||||||
if not isinstance(identifiers, list):
|
|
||||||
identifiers = [identifiers]
|
|
||||||
else:
|
|
||||||
identifiers = param.identifiers.copy()
|
|
||||||
paths = callbk_option.impl_getpath().split(".")
|
paths = callbk_option.impl_getpath().split(".")
|
||||||
parents = [config_bag.context.get_root(config_bag)]
|
parents = [config_bag.context.get_root(config_bag)]
|
||||||
subconfigs_is_a_list = False
|
subconfigs_is_a_list = False
|
||||||
|
|
@ -720,37 +673,7 @@ def manager_callback(
|
||||||
parent,
|
parent,
|
||||||
)
|
)
|
||||||
except AttributeError as err:
|
except AttributeError as err:
|
||||||
if parent.path:
|
raise ConfigError(err) from err
|
||||||
child_path = parent.path + "." + name
|
|
||||||
else:
|
|
||||||
child_path = name
|
|
||||||
if param.optional:
|
|
||||||
raise CancelParam(
|
|
||||||
callbk_option.impl_getpath(), child_path
|
|
||||||
)
|
|
||||||
|
|
||||||
identifiers = doption.get_identifiers(parent)
|
|
||||||
if not identifiers:
|
|
||||||
errors.raise_carry_out_calculation_error(
|
|
||||||
subconfig,
|
|
||||||
_(
|
|
||||||
'cannot calculate arguments for {0}, {1} with identifier "{2}", there is no identifiers'
|
|
||||||
),
|
|
||||||
err,
|
|
||||||
extra_keys=[identifier],
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
identifiers_list = display_list(
|
|
||||||
identifiers, add_quote=True
|
|
||||||
)
|
|
||||||
errors.raise_carry_out_calculation_error(
|
|
||||||
subconfig,
|
|
||||||
_(
|
|
||||||
'cannot calculate arguments for {0}, {1} with identifier "{2}", list of valid identifiers: {3}'
|
|
||||||
),
|
|
||||||
err,
|
|
||||||
extra_keys=[identifier, identifiers_list],
|
|
||||||
)
|
|
||||||
new_parents.append(
|
new_parents.append(
|
||||||
parent.get_child(
|
parent.get_child(
|
||||||
doption,
|
doption,
|
||||||
|
|
@ -761,28 +684,21 @@ def manager_callback(
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
try:
|
new_parents.append(
|
||||||
new_parents.append(
|
parent.get_child(
|
||||||
parent.get_child(
|
doption,
|
||||||
doption,
|
None,
|
||||||
None,
|
True,
|
||||||
True,
|
name=name,
|
||||||
name=name,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
except PropertiesOptionError as err:
|
)
|
||||||
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
|
|
||||||
if (
|
|
||||||
param.notraisepropertyerror
|
|
||||||
or param.raisepropertyerror
|
|
||||||
):
|
|
||||||
raise err from err
|
|
||||||
raise ConfigError(str(err), subconfig=subconfig) from err
|
|
||||||
parents = new_parents
|
parents = new_parents
|
||||||
|
|
||||||
if subconfigs_is_a_list:
|
if subconfigs_is_a_list:
|
||||||
subconfigs = parents
|
subconfigs = parents
|
||||||
else:
|
else:
|
||||||
subconfigs = parents[0]
|
subconfigs = parents[0]
|
||||||
|
|
||||||
else:
|
else:
|
||||||
search_option = param.option
|
search_option = param.option
|
||||||
subconfigs = subconfig.get_common_child(
|
subconfigs = subconfig.get_common_child(
|
||||||
|
|
@ -808,15 +724,13 @@ def manager_callback(
|
||||||
]
|
]
|
||||||
values = None
|
values = None
|
||||||
for subconfig in subconfigs:
|
for subconfig in subconfigs:
|
||||||
if isinstance(subconfig, PropertiesOptionError):
|
callbk_option = subconfig.option
|
||||||
value = subconfig
|
value = get_value(
|
||||||
else:
|
config_bag,
|
||||||
value = get_value(
|
subconfig,
|
||||||
config_bag,
|
param,
|
||||||
subconfig,
|
False,
|
||||||
param,
|
)
|
||||||
False,
|
|
||||||
)
|
|
||||||
if with_index:
|
if with_index:
|
||||||
value = value[index]
|
value = value[index]
|
||||||
if values is not None:
|
if values is not None:
|
||||||
|
|
@ -825,8 +739,6 @@ def manager_callback(
|
||||||
value = values
|
value = values
|
||||||
if callback.__name__ not in FUNCTION_WAITING_FOR_DICT:
|
if callback.__name__ not in FUNCTION_WAITING_FOR_DICT:
|
||||||
return value
|
return value
|
||||||
# FIXME the last one?
|
|
||||||
callbk_option = subconfig.option
|
|
||||||
return {"name": callbk_option.impl_get_display_name(subconfig), "value": value}
|
return {"name": callbk_option.impl_get_display_name(subconfig), "value": value}
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -865,11 +777,8 @@ def carry_out_calculation(
|
||||||
and option.impl_is_follower()
|
and option.impl_is_follower()
|
||||||
and index is None
|
and index is None
|
||||||
):
|
):
|
||||||
errors.raise_carry_out_calculation_error(
|
raise ConfigError(
|
||||||
subconfig,
|
f"the follower {option.impl_get_display_name(subconfig, with_quote=True)} must have index in carry_out_calculation!"
|
||||||
_("the follower {0} must have index in carry_out_calculation!"),
|
|
||||||
None,
|
|
||||||
option=option,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def fake_items(iterator):
|
def fake_items(iterator):
|
||||||
|
|
@ -879,17 +788,6 @@ def carry_out_calculation(
|
||||||
kwargs = {}
|
kwargs = {}
|
||||||
config_bag = config_bag.copy()
|
config_bag = config_bag.copy()
|
||||||
config_bag.set_permissive()
|
config_bag.set_permissive()
|
||||||
subconfig = subconfig.__class__(option=subconfig.option,
|
|
||||||
index=subconfig.index,
|
|
||||||
path=subconfig.path,
|
|
||||||
config_bag=config_bag,
|
|
||||||
parent=subconfig.parent,
|
|
||||||
identifiers=subconfig.identifiers,
|
|
||||||
true_path=subconfig.true_path,
|
|
||||||
properties=subconfig.properties,
|
|
||||||
validate_properties=False,
|
|
||||||
check_dynamic_without_identifiers=False,
|
|
||||||
)
|
|
||||||
if callback_params:
|
if callback_params:
|
||||||
for key, param in chain(
|
for key, param in chain(
|
||||||
fake_items(callback_params.args), callback_params.kwargs.items()
|
fake_items(callback_params.args), callback_params.kwargs.items()
|
||||||
|
|
@ -930,12 +828,6 @@ def carry_out_calculation(
|
||||||
args.append(err)
|
args.append(err)
|
||||||
else:
|
else:
|
||||||
kwargs[key] = err
|
kwargs[key] = err
|
||||||
except CancelParam as err:
|
|
||||||
if callback.__name__ in FUNCTION_WAITING_FOR_ERROR:
|
|
||||||
if key is None:
|
|
||||||
args.append(err)
|
|
||||||
else:
|
|
||||||
kwargs[key] = err
|
|
||||||
ret = calculate(
|
ret = calculate(
|
||||||
subconfig,
|
subconfig,
|
||||||
callback,
|
callback,
|
||||||
|
|
@ -951,14 +843,33 @@ def carry_out_calculation(
|
||||||
and option.impl_is_follower()
|
and option.impl_is_follower()
|
||||||
and not option.impl_is_submulti()
|
and not option.impl_is_submulti()
|
||||||
):
|
):
|
||||||
raise LeadershipError(
|
if args or kwargs:
|
||||||
subconfig,
|
raise LeadershipError(
|
||||||
"leadership-follower-callback-list",
|
_(
|
||||||
callback=callback.__name__,
|
'the "{}" function with positional arguments "{}" '
|
||||||
args=args,
|
'and keyword arguments "{}" must not return '
|
||||||
kwargs=kwargs,
|
'a list ("{}") for the follower option {}'
|
||||||
ret=ret,
|
""
|
||||||
)
|
).format(
|
||||||
|
callback.__name__,
|
||||||
|
args,
|
||||||
|
kwargs,
|
||||||
|
ret,
|
||||||
|
option.impl_get_display_name(subconfig, with_quote=True),
|
||||||
|
)
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
raise LeadershipError(
|
||||||
|
_(
|
||||||
|
'the "{}" function must not return a list ("{}") '
|
||||||
|
"for the follower option {}"
|
||||||
|
""
|
||||||
|
).format(
|
||||||
|
callback.__name__,
|
||||||
|
ret,
|
||||||
|
option.impl_get_display_name(subconfig, with_quote=True),
|
||||||
|
)
|
||||||
|
)
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -982,27 +893,28 @@ def calculate(
|
||||||
except (ValueError, ValueWarning) as err:
|
except (ValueError, ValueWarning) as err:
|
||||||
if allow_value_error:
|
if allow_value_error:
|
||||||
if force_value_warning:
|
if force_value_warning:
|
||||||
raise ValueWarning(msg=str(err))
|
raise ValueWarning(str(err))
|
||||||
raise err from err
|
raise err from err
|
||||||
error = err
|
error = err
|
||||||
except ConfigError as err:
|
except ConfigError as err:
|
||||||
err.subconfig = subconfig
|
|
||||||
raise err from err
|
raise err from err
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
error = err
|
error = err
|
||||||
if args or kwargs:
|
if args or kwargs:
|
||||||
msg = _(
|
msg = _(
|
||||||
'unexpected error "{1}" in function "{2}" with arguments "{3}" and "{4}" '
|
'unexpected error "{0}" in function "{1}" with arguments "{3}" and "{4}" '
|
||||||
"for option {0}"
|
"for option {2}"
|
||||||
)
|
).format(
|
||||||
extra_keys = [
|
str(error),
|
||||||
callback.__name__,
|
callback.__name__,
|
||||||
|
subconfig.option.impl_get_display_name(subconfig, with_quote=True),
|
||||||
args,
|
args,
|
||||||
kwargs,
|
kwargs,
|
||||||
]
|
)
|
||||||
else:
|
else:
|
||||||
msg = _('unexpected error "{1}" in function "{2}" for option {0}')
|
msg = _('unexpected error "{0}" in function "{1}" for option {2}' "").format(
|
||||||
extra_keys = [callback.__name__]
|
str(error),
|
||||||
errors.raise_carry_out_calculation_error(
|
callback.__name__,
|
||||||
subconfig, msg, error, extra_keys=extra_keys
|
subconfig.option.impl_get_display_name(subconfig, with_quote=True),
|
||||||
)
|
)
|
||||||
|
raise ConfigError(msg) from error
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"cache used by storage"
|
"cache used by storage"
|
||||||
# Copyright (C) 2013-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2013-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2012-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -25,13 +25,7 @@ from copy import copy, deepcopy
|
||||||
from typing import Optional, List, Any, Union
|
from typing import Optional, List, Any, Union
|
||||||
from os.path import commonprefix
|
from os.path import commonprefix
|
||||||
|
|
||||||
from .error import (
|
from .error import PropertiesOptionError, ConfigError, ConflictError, LeadershipError
|
||||||
PropertiesOptionError,
|
|
||||||
ConfigError,
|
|
||||||
ConflictError,
|
|
||||||
LeadershipError,
|
|
||||||
AttributeOptionError,
|
|
||||||
)
|
|
||||||
from .option import DynOptionDescription, Leadership, Option
|
from .option import DynOptionDescription, Leadership, Option
|
||||||
from .setting import ConfigBag, Settings, undefined, groups
|
from .setting import ConfigBag, Settings, undefined, groups
|
||||||
from .value import Values, owners
|
from .value import Values, owners
|
||||||
|
|
@ -42,18 +36,12 @@ from . import autolib
|
||||||
|
|
||||||
|
|
||||||
def get_common_path(path1, path2):
|
def get_common_path(path1, path2):
|
||||||
if None in (path1, path2):
|
|
||||||
return None
|
|
||||||
common_path = commonprefix([path1, path2])
|
common_path = commonprefix([path1, path2])
|
||||||
all_paths = [path1, path2]
|
if common_path in [path1, path2]:
|
||||||
if common_path in all_paths:
|
return common_path
|
||||||
# od.st is not the common_path of od.st_in
|
|
||||||
all_paths.remove(common_path)
|
|
||||||
if all_paths[0].startswith(common_path + '.'):
|
|
||||||
return common_path
|
|
||||||
if common_path.endswith("."):
|
if common_path.endswith("."):
|
||||||
return common_path[:-1]
|
return common_path[:-1]
|
||||||
elif "." in common_path:
|
if "." in common_path:
|
||||||
return common_path.rsplit(".", 1)[0]
|
return common_path.rsplit(".", 1)[0]
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
@ -80,7 +68,6 @@ class CCache:
|
||||||
self.reset_one_option_cache(
|
self.reset_one_option_cache(
|
||||||
subconfig,
|
subconfig,
|
||||||
resetted_opts,
|
resetted_opts,
|
||||||
False,
|
|
||||||
)
|
)
|
||||||
subconfig.config_bag.properties = subconfig.config_bag.properties | {
|
subconfig.config_bag.properties = subconfig.config_bag.properties | {
|
||||||
"cache"
|
"cache"
|
||||||
|
|
@ -93,60 +80,53 @@ class CCache:
|
||||||
self,
|
self,
|
||||||
subconfig,
|
subconfig,
|
||||||
resetted_opts,
|
resetted_opts,
|
||||||
is_default,
|
|
||||||
*,
|
|
||||||
force=False,
|
|
||||||
):
|
):
|
||||||
"""reset cache for one option"""
|
"""reset cache for one option"""
|
||||||
if not force and subconfig.path in resetted_opts:
|
if subconfig.path in resetted_opts:
|
||||||
return
|
return
|
||||||
resetted_opts.append(subconfig.path)
|
resetted_opts.append(subconfig.path)
|
||||||
config_bag = subconfig.config_bag
|
config_bag = subconfig.config_bag
|
||||||
if not force:
|
for woption in subconfig.option.get_dependencies(subconfig.option):
|
||||||
# if is_default and config_bag.context.get_owner(subconfig) != owners.default:
|
option = woption()
|
||||||
# return
|
if option.issubdyn():
|
||||||
for is_default, woption in subconfig.option.get_dependencies(subconfig.option):
|
# it's an option in dynoptiondescription, remove cache for all generated option
|
||||||
option = woption()
|
self.reset_cache_dyn_option(
|
||||||
if option.issubdyn():
|
config_bag,
|
||||||
# it's an option in dynoptiondescription, remove cache for all generated option
|
option,
|
||||||
if option.impl_getpath() == subconfig.option.impl_getpath():
|
resetted_opts,
|
||||||
force = True
|
)
|
||||||
subconfig = subconfig.parent.parent
|
elif option.impl_is_dynoptiondescription():
|
||||||
self.reset_cache_dyn_option(
|
self._reset_cache_dyn_optiondescription(
|
||||||
subconfig,
|
option,
|
||||||
option,
|
config_bag,
|
||||||
resetted_opts,
|
resetted_opts,
|
||||||
is_default,
|
)
|
||||||
force,
|
else:
|
||||||
)
|
option_subconfig = self.get_sub_config(
|
||||||
elif option.impl_is_dynoptiondescription():
|
config_bag,
|
||||||
self.reset_cache_dyn_optiondescription(
|
option.impl_getpath(),
|
||||||
option,
|
None,
|
||||||
config_bag,
|
properties=None,
|
||||||
resetted_opts,
|
validate_properties=False,
|
||||||
is_default,
|
)
|
||||||
)
|
self.reset_one_option_cache(
|
||||||
else:
|
option_subconfig,
|
||||||
option_subconfig = self.get_sub_config(
|
resetted_opts,
|
||||||
config_bag,
|
)
|
||||||
option.impl_getpath(),
|
del option
|
||||||
None,
|
|
||||||
properties=None,
|
|
||||||
validate_properties=False,
|
|
||||||
)
|
|
||||||
self.reset_one_option_cache(
|
|
||||||
option_subconfig,
|
|
||||||
resetted_opts,
|
|
||||||
is_default,
|
|
||||||
)
|
|
||||||
del option
|
|
||||||
subconfig.option.reset_cache(
|
subconfig.option.reset_cache(
|
||||||
subconfig.path,
|
subconfig.path,
|
||||||
config_bag,
|
config_bag,
|
||||||
resetted_opts,
|
resetted_opts,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_dynamic_from_dyn_optiondescription(self, config_bag, option):
|
def _reset_cache_dyn_optiondescription(
|
||||||
|
self,
|
||||||
|
option,
|
||||||
|
config_bag,
|
||||||
|
resetted_opts,
|
||||||
|
):
|
||||||
|
# reset cache for all chidren
|
||||||
path = option.impl_getpath()
|
path = option.impl_getpath()
|
||||||
if "." in path:
|
if "." in path:
|
||||||
parent_path = path.rsplit(".", 1)[0]
|
parent_path = path.rsplit(".", 1)[0]
|
||||||
|
|
@ -159,27 +139,13 @@ class CCache:
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
parent_subconfig = self.get_root(config_bag)
|
parent_subconfig = self.get_root(config_bag)
|
||||||
return parent_subconfig.dyn_to_subconfig(
|
for subconfig in parent_subconfig.dyn_to_subconfig(
|
||||||
option,
|
option,
|
||||||
False,
|
False,
|
||||||
)
|
|
||||||
|
|
||||||
def reset_cache_dyn_optiondescription(
|
|
||||||
self,
|
|
||||||
option,
|
|
||||||
config_bag,
|
|
||||||
resetted_opts,
|
|
||||||
is_default,
|
|
||||||
):
|
|
||||||
# reset cache for all chidren
|
|
||||||
for subconfig in self.get_dynamic_from_dyn_optiondescription(
|
|
||||||
config_bag,
|
|
||||||
option,
|
|
||||||
):
|
):
|
||||||
self.reset_one_option_cache(
|
self.reset_one_option_cache(
|
||||||
subconfig,
|
subconfig,
|
||||||
resetted_opts,
|
resetted_opts,
|
||||||
is_default,
|
|
||||||
)
|
)
|
||||||
for walk_subconfig in self.walk(
|
for walk_subconfig in self.walk(
|
||||||
subconfig,
|
subconfig,
|
||||||
|
|
@ -189,27 +155,17 @@ class CCache:
|
||||||
self.reset_one_option_cache(
|
self.reset_one_option_cache(
|
||||||
walk_subconfig,
|
walk_subconfig,
|
||||||
resetted_opts,
|
resetted_opts,
|
||||||
is_default,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_dynamic_from_dyn_option(self, subconfig, option):
|
def reset_cache_dyn_option(
|
||||||
config_bag = subconfig.config_bag
|
self,
|
||||||
sub_paths = option.impl_getpath()
|
config_bag,
|
||||||
if not subconfig.path:
|
option,
|
||||||
current_paths = []
|
resetted_opts,
|
||||||
current_paths_max_index = 0
|
):
|
||||||
else:
|
|
||||||
current_paths = subconfig.path.split(".")
|
|
||||||
current_paths_max_index = len(current_paths) - 1
|
|
||||||
current_subconfigs = []
|
|
||||||
parent = subconfig
|
|
||||||
while True:
|
|
||||||
current_subconfigs.insert(0, parent)
|
|
||||||
parent = parent.parent
|
|
||||||
if not parent or parent.path is None:
|
|
||||||
break
|
|
||||||
currents = [self.get_root(config_bag)]
|
currents = [self.get_root(config_bag)]
|
||||||
for idx, sub_path in enumerate(sub_paths.split(".")):
|
sub_paths = option.impl_getpath()
|
||||||
|
for sub_path in sub_paths.split("."):
|
||||||
new_currents = []
|
new_currents = []
|
||||||
for current in currents:
|
for current in currents:
|
||||||
sub_option = current.option.get_child(
|
sub_option = current.option.get_child(
|
||||||
|
|
@ -219,20 +175,15 @@ class CCache:
|
||||||
allow_dynoption=True,
|
allow_dynoption=True,
|
||||||
)
|
)
|
||||||
if sub_option.impl_is_dynoptiondescription():
|
if sub_option.impl_is_dynoptiondescription():
|
||||||
if (
|
new_currents.extend(
|
||||||
idx <= current_paths_max_index
|
list(
|
||||||
and sub_option == current_subconfigs[idx].option
|
current.dyn_to_subconfig(
|
||||||
):
|
sub_option,
|
||||||
new_currents.append(current_subconfigs[idx])
|
False,
|
||||||
else:
|
|
||||||
new_currents.extend(
|
|
||||||
list(
|
|
||||||
current.dyn_to_subconfig(
|
|
||||||
sub_option,
|
|
||||||
False,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
)
|
||||||
|
|
||||||
else:
|
else:
|
||||||
new_currents.append(
|
new_currents.append(
|
||||||
current.get_child(
|
current.get_child(
|
||||||
|
|
@ -243,22 +194,10 @@ class CCache:
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
currents = new_currents
|
currents = new_currents
|
||||||
return currents
|
for dyn_option_subconfig in currents:
|
||||||
|
|
||||||
def reset_cache_dyn_option(
|
|
||||||
self,
|
|
||||||
subconfig,
|
|
||||||
option,
|
|
||||||
resetted_opts,
|
|
||||||
is_default,
|
|
||||||
force,
|
|
||||||
):
|
|
||||||
for dyn_option_subconfig in self.get_dynamic_from_dyn_option(subconfig, option):
|
|
||||||
self.reset_one_option_cache(
|
self.reset_one_option_cache(
|
||||||
dyn_option_subconfig,
|
dyn_option_subconfig,
|
||||||
resetted_opts,
|
resetted_opts,
|
||||||
is_default,
|
|
||||||
force=force,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -274,7 +213,6 @@ class SubConfig:
|
||||||
"apply_requires",
|
"apply_requires",
|
||||||
"transitive_properties",
|
"transitive_properties",
|
||||||
"is_dynamic",
|
"is_dynamic",
|
||||||
"is_dynamic_without_identifiers",
|
|
||||||
"identifiers",
|
"identifiers",
|
||||||
"_length",
|
"_length",
|
||||||
)
|
)
|
||||||
|
|
@ -289,10 +227,8 @@ class SubConfig:
|
||||||
identifiers: Optional[list[str]],
|
identifiers: Optional[list[str]],
|
||||||
*,
|
*,
|
||||||
true_path: Optional[str] = None,
|
true_path: Optional[str] = None,
|
||||||
# for python 3.9 properties: Union[list[str], undefined] = undefined,
|
properties: Union[list[str], undefined] = undefined,
|
||||||
properties=undefined,
|
|
||||||
validate_properties: bool = True,
|
validate_properties: bool = True,
|
||||||
check_dynamic_without_identifiers: bool = True,
|
|
||||||
) -> None:
|
) -> None:
|
||||||
self.index = index
|
self.index = index
|
||||||
self.identifiers = identifiers
|
self.identifiers = identifiers
|
||||||
|
|
@ -308,26 +244,10 @@ class SubConfig:
|
||||||
)
|
)
|
||||||
self.apply_requires = not is_follower or index is not None
|
self.apply_requires = not is_follower or index is not None
|
||||||
self.true_path = true_path
|
self.true_path = true_path
|
||||||
if self.option.impl_is_dynoptiondescription():
|
if parent and parent.is_dynamic or self.option.impl_is_dynoptiondescription():
|
||||||
self.is_dynamic = True
|
self.is_dynamic = True
|
||||||
self.is_dynamic_without_identifiers = identifiers is None or (
|
|
||||||
parent and identifiers == parent.identifiers
|
|
||||||
)
|
|
||||||
if (
|
|
||||||
check_dynamic_without_identifiers
|
|
||||||
and parent
|
|
||||||
and parent.is_dynamic
|
|
||||||
and parent.is_dynamic_without_identifiers
|
|
||||||
and self.is_dynamic_without_identifiers
|
|
||||||
!= parent.is_dynamic_without_identifiers
|
|
||||||
):
|
|
||||||
raise AttributeOptionError(true_path, "option-dynamic")
|
|
||||||
elif parent:
|
|
||||||
self.is_dynamic = parent.is_dynamic
|
|
||||||
self.is_dynamic_without_identifiers = parent.is_dynamic_without_identifiers
|
|
||||||
else:
|
else:
|
||||||
self.is_dynamic = False
|
self.is_dynamic = False
|
||||||
self.is_dynamic_without_identifiers = False
|
|
||||||
self._properties = properties
|
self._properties = properties
|
||||||
if validate_properties:
|
if validate_properties:
|
||||||
if self.path and self._properties is undefined:
|
if self.path and self._properties is undefined:
|
||||||
|
|
@ -427,55 +347,26 @@ class SubConfig:
|
||||||
validate_properties,
|
validate_properties,
|
||||||
*,
|
*,
|
||||||
uncalculated: bool = False,
|
uncalculated: bool = False,
|
||||||
with_index: bool = True,
|
|
||||||
check_dynamic_without_identifiers: bool = True,
|
|
||||||
):
|
):
|
||||||
if self.option.impl_is_leadership() and not uncalculated and with_index:
|
if self.option.impl_is_leadership() and not uncalculated:
|
||||||
yield from self.get_leadership_children(validate_properties)
|
yield from self.get_leadership_children(validate_properties)
|
||||||
else:
|
else:
|
||||||
children_name = []
|
|
||||||
for child in self.option.get_children():
|
for child in self.option.get_children():
|
||||||
if child.impl_is_dynoptiondescription() and not uncalculated:
|
if child.impl_is_dynoptiondescription() and not uncalculated:
|
||||||
for dyn_child in self.dyn_to_subconfig(
|
yield from self.dyn_to_subconfig(
|
||||||
child,
|
child,
|
||||||
validate_properties,
|
validate_properties,
|
||||||
):
|
)
|
||||||
yield dyn_child
|
|
||||||
if child.could_conflict:
|
|
||||||
name = dyn_child.path
|
|
||||||
if name in children_name:
|
|
||||||
raise ConflictError(
|
|
||||||
_('option name "{0}" is not unique in {1}').format(
|
|
||||||
name,
|
|
||||||
self.option.impl_get_display_name(
|
|
||||||
self, with_quote=True
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
children_name.append(name)
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
yield self.get_child(
|
yield self.get_child(
|
||||||
child,
|
child,
|
||||||
None,
|
None,
|
||||||
validate_properties,
|
validate_properties,
|
||||||
check_dynamic_without_identifiers=check_dynamic_without_identifiers,
|
|
||||||
)
|
)
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
if err.proptype in (["mandatory"], ["empty"]):
|
if err.proptype in (["mandatory"], ["empty"]):
|
||||||
raise err
|
raise err
|
||||||
if child.could_conflict:
|
|
||||||
name = child.impl_getpath()
|
|
||||||
if name in children_name:
|
|
||||||
raise ConflictError(
|
|
||||||
_('option name "{0}" is not unique in {1}').format(
|
|
||||||
name,
|
|
||||||
self.option.impl_get_display_name(
|
|
||||||
self, with_quote=True
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
children_name.append(name)
|
|
||||||
|
|
||||||
def get_child(
|
def get_child(
|
||||||
self,
|
self,
|
||||||
|
|
@ -484,12 +375,12 @@ class SubConfig:
|
||||||
validate_properties: bool,
|
validate_properties: bool,
|
||||||
*,
|
*,
|
||||||
properties=undefined,
|
properties=undefined,
|
||||||
|
allow_dynoption: bool = False,
|
||||||
identifier: Optional[str] = None,
|
identifier: Optional[str] = None,
|
||||||
name: Optional[str] = None,
|
name: Optional[str] = None,
|
||||||
check_index: bool = True,
|
check_index: bool = True,
|
||||||
config_bag: ConfigBag = None,
|
config_bag: ConfigBag = None,
|
||||||
true_path: Optional[str] = None,
|
true_path: Optional[str] = None,
|
||||||
check_dynamic_without_identifiers: bool = True,
|
|
||||||
) -> "SubConfig":
|
) -> "SubConfig":
|
||||||
# pylint: disable=too-many-branches,too-many-locals,too-many-arguments
|
# pylint: disable=too-many-branches,too-many-locals,too-many-arguments
|
||||||
if config_bag is None:
|
if config_bag is None:
|
||||||
|
|
@ -512,21 +403,26 @@ class SubConfig:
|
||||||
option,
|
option,
|
||||||
index,
|
index,
|
||||||
path,
|
path,
|
||||||
config_bag,
|
self.config_bag,
|
||||||
self,
|
self,
|
||||||
identifiers,
|
identifiers,
|
||||||
properties=properties,
|
properties=properties,
|
||||||
validate_properties=validate_properties,
|
validate_properties=validate_properties,
|
||||||
true_path=true_path,
|
true_path=true_path,
|
||||||
check_dynamic_without_identifiers=check_dynamic_without_identifiers,
|
|
||||||
)
|
)
|
||||||
if check_index and index is not None:
|
if check_index and index is not None:
|
||||||
if option.impl_is_optiondescription() or not option.impl_is_follower():
|
if option.impl_is_optiondescription() or not option.impl_is_follower():
|
||||||
raise ConfigError("index must be set only with a follower option", subconfig=subsubconfig,)
|
raise ConfigError("index must be set only with a follower option")
|
||||||
length = self.get_length_leadership()
|
length = self.get_length_leadership()
|
||||||
if index >= length:
|
if index >= length:
|
||||||
raise LeadershipError(
|
raise LeadershipError(
|
||||||
subsubconfig, "leadership-greater", index=index, length=length
|
_(
|
||||||
|
'index "{0}" is greater than the leadership length "{1}" for option {2}'
|
||||||
|
).format(
|
||||||
|
index,
|
||||||
|
length,
|
||||||
|
option.impl_get_display_name(subsubconfig, with_quote=True),
|
||||||
|
)
|
||||||
)
|
)
|
||||||
return subsubconfig
|
return subsubconfig
|
||||||
|
|
||||||
|
|
@ -562,17 +458,14 @@ class SubConfig:
|
||||||
self.identifiers,
|
self.identifiers,
|
||||||
validate_properties=False,
|
validate_properties=False,
|
||||||
)
|
)
|
||||||
#FIXME
|
self._length = len(cconfig_bag.context.get_value(subconfig))
|
||||||
#self._length = len(cconfig_bag.context.get_value(subconfig))
|
return self._length
|
||||||
length = len(cconfig_bag.context.get_value(subconfig))
|
|
||||||
return length
|
|
||||||
|
|
||||||
def get_common_child(
|
def get_common_child(
|
||||||
self,
|
self,
|
||||||
search_option: "BaseOption",
|
search_option: "BaseOption",
|
||||||
true_path: Optional[str] = None,
|
true_path: Optional[str] = None,
|
||||||
validate_properties: bool = True,
|
validate_properties: bool = True,
|
||||||
check_dynamic_without_identifiers: bool = True,
|
|
||||||
):
|
):
|
||||||
current_option_path = self.option.impl_getpath()
|
current_option_path = self.option.impl_getpath()
|
||||||
search_option_path = search_option.impl_getpath()
|
search_option_path = search_option.impl_getpath()
|
||||||
|
|
@ -590,17 +483,10 @@ class SubConfig:
|
||||||
parents = [self.parent]
|
parents = [self.parent]
|
||||||
else:
|
else:
|
||||||
if common_path:
|
if common_path:
|
||||||
|
parent = self.parent
|
||||||
common_parent_number = common_path.count(".") + 1
|
common_parent_number = common_path.count(".") + 1
|
||||||
parent_count = current_option_path.count(".") - common_parent_number
|
for idx in range(current_option_path.count(".") - common_parent_number):
|
||||||
if parent_count >= 0:
|
parent = parent.parent
|
||||||
parent = self.parent
|
|
||||||
for idx in range(parent_count):
|
|
||||||
parent = parent.parent
|
|
||||||
elif parent_count == 0:
|
|
||||||
parent = self.parent
|
|
||||||
else:
|
|
||||||
# so -1
|
|
||||||
parent = self
|
|
||||||
parents = [parent]
|
parents = [parent]
|
||||||
else:
|
else:
|
||||||
common_parent_number = 0
|
common_parent_number = 0
|
||||||
|
|
@ -639,42 +525,22 @@ class SubConfig:
|
||||||
None,
|
None,
|
||||||
validate_properties,
|
validate_properties,
|
||||||
true_path=true_path,
|
true_path=true_path,
|
||||||
check_dynamic_without_identifiers=check_dynamic_without_identifiers,
|
|
||||||
config_bag=config_bag,
|
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
parents = new_parents
|
parents = new_parents
|
||||||
subconfigs = []
|
subconfigs = []
|
||||||
for parent in parents:
|
for parent in parents:
|
||||||
try:
|
subconfigs.append(
|
||||||
ret = parent.get_child(
|
parent.get_child(
|
||||||
search_option,
|
search_option,
|
||||||
index,
|
index,
|
||||||
validate_properties,
|
validate_properties,
|
||||||
check_dynamic_without_identifiers=check_dynamic_without_identifiers,
|
|
||||||
config_bag=config_bag,
|
|
||||||
)
|
)
|
||||||
except PropertiesOptionError as err:
|
)
|
||||||
ret = err
|
|
||||||
subconfigs.append(ret)
|
|
||||||
if subconfigs_is_a_list:
|
if subconfigs_is_a_list:
|
||||||
return subconfigs
|
return subconfigs
|
||||||
return subconfigs[0]
|
return subconfigs[0]
|
||||||
|
|
||||||
def change_context(self, context) -> "SubConfig":
|
|
||||||
config_bag = self.config_bag.copy()
|
|
||||||
config_bag.context = context
|
|
||||||
return SubConfig(
|
|
||||||
self.option,
|
|
||||||
self.index,
|
|
||||||
self.path,
|
|
||||||
config_bag,
|
|
||||||
self.parent,
|
|
||||||
self.identifiers,
|
|
||||||
true_path=self.true_path,
|
|
||||||
validate_properties=False,
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class _Config(CCache):
|
class _Config(CCache):
|
||||||
"""Sub configuration management entry.
|
"""Sub configuration management entry.
|
||||||
|
|
@ -727,8 +593,80 @@ class _Config(CCache):
|
||||||
"""get cache for values"""
|
"""get cache for values"""
|
||||||
return self._impl_values_cache # pylint: disable=no-member
|
return self._impl_values_cache # pylint: disable=no-member
|
||||||
|
|
||||||
# # =============================================================================
|
# =============================================================================
|
||||||
# # WALK
|
# WALK
|
||||||
|
def find(
|
||||||
|
self,
|
||||||
|
option_bag,
|
||||||
|
bytype,
|
||||||
|
byname,
|
||||||
|
byvalue,
|
||||||
|
raise_if_not_found=True,
|
||||||
|
only_path=undefined,
|
||||||
|
only_option=undefined,
|
||||||
|
with_option=False,
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
convenience method for finding an option that lives only in the subtree
|
||||||
|
|
||||||
|
:param first: return only one option if True, a list otherwise
|
||||||
|
:return: find list or an exception if nothing has been found
|
||||||
|
"""
|
||||||
|
|
||||||
|
# pylint: disable=too-many-arguments,too-many-locals
|
||||||
|
def _filter_by_value(soption_bag):
|
||||||
|
value = self.get_value(soption_bag)
|
||||||
|
if isinstance(value, list):
|
||||||
|
return byvalue in value
|
||||||
|
return value == byvalue
|
||||||
|
|
||||||
|
found = False
|
||||||
|
if only_path is not undefined:
|
||||||
|
|
||||||
|
def _fake_iter():
|
||||||
|
yield only_option
|
||||||
|
|
||||||
|
options = _fake_iter()
|
||||||
|
else:
|
||||||
|
options = option_bag.option.get_children_recursively(
|
||||||
|
bytype,
|
||||||
|
byname,
|
||||||
|
option_bag.config_bag,
|
||||||
|
)
|
||||||
|
for option in options:
|
||||||
|
path = option.impl_getpath()
|
||||||
|
soption_bag = OptionBag(
|
||||||
|
option,
|
||||||
|
None,
|
||||||
|
option_bag.config_bag,
|
||||||
|
)
|
||||||
|
if byvalue is not undefined and not _filter_by_value(soption_bag):
|
||||||
|
continue
|
||||||
|
if option_bag.config_bag.properties:
|
||||||
|
# remove option with propertyerror, ...
|
||||||
|
try:
|
||||||
|
self.get_sub_config(
|
||||||
|
option_bag.config_bag, # pylint: disable=no-member
|
||||||
|
path,
|
||||||
|
None,
|
||||||
|
validate_properties=True,
|
||||||
|
)
|
||||||
|
except PropertiesOptionError:
|
||||||
|
continue
|
||||||
|
found = True
|
||||||
|
if not with_option:
|
||||||
|
yield path
|
||||||
|
else:
|
||||||
|
yield path, option
|
||||||
|
self._find_return_results(
|
||||||
|
found,
|
||||||
|
raise_if_not_found,
|
||||||
|
)
|
||||||
|
|
||||||
|
def _find_return_results(self, found, raise_if_not_found):
|
||||||
|
if not found and raise_if_not_found:
|
||||||
|
raise AttributeError(_("no option found in config" " with these criteria"))
|
||||||
|
|
||||||
def walk_valid_value(
|
def walk_valid_value(
|
||||||
self,
|
self,
|
||||||
subconfig,
|
subconfig,
|
||||||
|
|
@ -773,7 +711,6 @@ class _Config(CCache):
|
||||||
properties=undefined,
|
properties=undefined,
|
||||||
true_path: Optional[str] = None,
|
true_path: Optional[str] = None,
|
||||||
allow_dynoption: bool = False,
|
allow_dynoption: bool = False,
|
||||||
valid_conflict: bool = True,
|
|
||||||
):
|
):
|
||||||
subconfig = self.get_root(config_bag)
|
subconfig = self.get_root(config_bag)
|
||||||
if path is None:
|
if path is None:
|
||||||
|
|
@ -806,32 +743,6 @@ class _Config(CCache):
|
||||||
identifier, option = option
|
identifier, option = option
|
||||||
else:
|
else:
|
||||||
identifier = None
|
identifier = None
|
||||||
if valid_conflict and option.could_conflict:
|
|
||||||
for ref in option.could_conflict:
|
|
||||||
child = ref()
|
|
||||||
if child.impl_is_dynoptiondescription():
|
|
||||||
for dyn_child in subconfig.dyn_to_subconfig(
|
|
||||||
child,
|
|
||||||
validate_properties,
|
|
||||||
):
|
|
||||||
if path == dyn_child.path:
|
|
||||||
raise ConflictError(
|
|
||||||
_('option name "{0}" is not unique in {1}').format(
|
|
||||||
name,
|
|
||||||
option.impl_get_display_name(
|
|
||||||
subconfig, with_quote=True
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
elif child.impl_getname() == name:
|
|
||||||
raise ConflictError(
|
|
||||||
_('option name "{0}" is not unique in {1}').format(
|
|
||||||
name,
|
|
||||||
self.option.impl_get_display_name(
|
|
||||||
self, with_quote=True
|
|
||||||
),
|
|
||||||
)
|
|
||||||
)
|
|
||||||
subconfig = subconfig.get_child(
|
subconfig = subconfig.get_child(
|
||||||
option,
|
option,
|
||||||
index_,
|
index_,
|
||||||
|
|
@ -910,15 +821,6 @@ class _Config(CCache):
|
||||||
|
|
||||||
# =============================================================================
|
# =============================================================================
|
||||||
# Manage value
|
# Manage value
|
||||||
def set_value(
|
|
||||||
self,
|
|
||||||
subconfig,
|
|
||||||
value: Any,
|
|
||||||
) -> Any:
|
|
||||||
"""set value"""
|
|
||||||
self.get_settings().validate_properties(subconfig)
|
|
||||||
return self.get_values().set_value(subconfig, value)
|
|
||||||
|
|
||||||
def get_value(
|
def get_value(
|
||||||
self,
|
self,
|
||||||
subconfig,
|
subconfig,
|
||||||
|
|
@ -966,10 +868,9 @@ class _Config(CCache):
|
||||||
subconfig, with_quote=True
|
subconfig, with_quote=True
|
||||||
)
|
)
|
||||||
raise LeadershipError(
|
raise LeadershipError(
|
||||||
subconfig,
|
_(
|
||||||
"leadership-follower-greater",
|
"the follower option {0} has greater length ({1}) than the leader length ({2})"
|
||||||
index=follower_len,
|
).format(option_name, follower_len, length)
|
||||||
length=length,
|
|
||||||
)
|
)
|
||||||
self.get_settings().validate_mandatory(
|
self.get_settings().validate_mandatory(
|
||||||
subconfig,
|
subconfig,
|
||||||
|
|
@ -1038,8 +939,6 @@ class _Config(CCache):
|
||||||
def get_owner(
|
def get_owner(
|
||||||
self,
|
self,
|
||||||
subconfig: "SubConfig",
|
subconfig: "SubConfig",
|
||||||
*,
|
|
||||||
validate_meta=True,
|
|
||||||
):
|
):
|
||||||
"""get owner"""
|
"""get owner"""
|
||||||
subconfigs = self._get(
|
subconfigs = self._get(
|
||||||
|
|
@ -1050,14 +949,13 @@ class _Config(CCache):
|
||||||
for sc in subconfigs:
|
for sc in subconfigs:
|
||||||
owner = self.get_owner(
|
owner = self.get_owner(
|
||||||
sc,
|
sc,
|
||||||
validate_meta=validate_meta,
|
|
||||||
)
|
)
|
||||||
if owner != owners.default:
|
if owner != owners.default:
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
owner = owners.default
|
owner = owners.default
|
||||||
else:
|
else:
|
||||||
owner = self.get_values().getowner(subconfigs, validate_meta=validate_meta)
|
owner = self.get_values().getowner(subconfigs)
|
||||||
return owner
|
return owner
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -1338,10 +1236,6 @@ class KernelGroupConfig(_CommonConfig):
|
||||||
# pylint: disable=super-init-not-called
|
# pylint: disable=super-init-not-called
|
||||||
names = []
|
names = []
|
||||||
for child in children:
|
for child in children:
|
||||||
if not isinstance(child, (KernelConfig, KernelGroupConfig)):
|
|
||||||
raise TypeError(
|
|
||||||
_("child must be a Config, GroupConfig, MixConfig or MetaConfig")
|
|
||||||
)
|
|
||||||
name_ = child._impl_name
|
name_ = child._impl_name
|
||||||
names.append(name_)
|
names.append(name_)
|
||||||
if len(names) != len(set(names)):
|
if len(names) != len(set(names)):
|
||||||
|
|
@ -1369,58 +1263,61 @@ class KernelGroupConfig(_CommonConfig):
|
||||||
|
|
||||||
def reset_cache(
|
def reset_cache(
|
||||||
self,
|
self,
|
||||||
subconfig,
|
option_bag,
|
||||||
resetted_opts=None,
|
resetted_opts=None,
|
||||||
):
|
):
|
||||||
if resetted_opts is None:
|
if resetted_opts is None:
|
||||||
resetted_opts = []
|
resetted_opts = []
|
||||||
if isinstance(self, KernelMixConfig):
|
if isinstance(self, KernelMixConfig):
|
||||||
super().reset_cache(
|
super().reset_cache(
|
||||||
subconfig,
|
option_bag,
|
||||||
resetted_opts=copy(resetted_opts),
|
resetted_opts=copy(resetted_opts),
|
||||||
)
|
)
|
||||||
for child in self._impl_children:
|
for child in self._impl_children:
|
||||||
if subconfig is not None:
|
if option_bag is not None:
|
||||||
parent_subconfig = subconfig.change_context(child)
|
coption_bag = option_bag.copy()
|
||||||
|
cconfig_bag = coption_bag.config_bag.copy()
|
||||||
|
cconfig_bag.context = child
|
||||||
|
coption_bag.config_bag = cconfig_bag
|
||||||
else:
|
else:
|
||||||
parent_subconfig = None
|
coption_bag = None
|
||||||
child.reset_cache(
|
child.reset_cache(
|
||||||
parent_subconfig,
|
coption_bag,
|
||||||
resetted_opts=copy(resetted_opts),
|
resetted_opts=copy(resetted_opts),
|
||||||
)
|
)
|
||||||
|
|
||||||
def set_value(
|
def set_value(
|
||||||
self,
|
self,
|
||||||
subconfig,
|
option_bag,
|
||||||
value,
|
value,
|
||||||
only_config=False,
|
only_config=False,
|
||||||
):
|
):
|
||||||
"""Setattr not in current KernelGroupConfig, but in each children"""
|
"""Setattr not in current KernelGroupConfig, but in each children"""
|
||||||
ret = []
|
ret = []
|
||||||
for child in self._impl_children:
|
for child in self._impl_children:
|
||||||
cconfig_bag = subconfig.config_bag.copy()
|
cconfig_bag = option_bag.config_bag.copy()
|
||||||
cconfig_bag.context = child
|
cconfig_bag.context = child
|
||||||
if isinstance(child, KernelGroupConfig):
|
if isinstance(child, KernelGroupConfig):
|
||||||
ret.extend(
|
ret.extend(
|
||||||
child.set_value(
|
child.set_value(
|
||||||
subconfig,
|
option_bag,
|
||||||
value,
|
value,
|
||||||
only_config=only_config,
|
only_config=only_config,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
settings = child.get_settings()
|
settings = child.get_settings()
|
||||||
properties = settings.get_context_properties()
|
properties = settings.get_context_properties(child.properties_cache)
|
||||||
permissives = settings.get_context_permissives()
|
permissives = settings.get_context_permissives()
|
||||||
cconfig_bag.properties = properties
|
cconfig_bag.properties = properties
|
||||||
cconfig_bag.permissives = permissives
|
cconfig_bag.permissives = permissives
|
||||||
try:
|
try:
|
||||||
# GROUP
|
# GROUP
|
||||||
coption_bag = child.get_sub_config(
|
coption_bag = child.get_sub_option_bag(
|
||||||
cconfig_bag,
|
cconfig_bag,
|
||||||
subconfig.path,
|
option_bag.path,
|
||||||
subconfig.index,
|
option_bag.index,
|
||||||
validate_properties=False,
|
False,
|
||||||
)
|
)
|
||||||
child.set_value(
|
child.set_value(
|
||||||
coption_bag,
|
coption_bag,
|
||||||
|
|
@ -1430,7 +1327,7 @@ class KernelGroupConfig(_CommonConfig):
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
ret.append(
|
ret.append(
|
||||||
PropertiesOptionError(
|
PropertiesOptionError(
|
||||||
err.subconfig,
|
err._option_bag,
|
||||||
err.proptype,
|
err.proptype,
|
||||||
err._settings,
|
err._settings,
|
||||||
err._opt_type,
|
err._opt_type,
|
||||||
|
|
@ -1493,7 +1390,7 @@ class KernelGroupConfig(_CommonConfig):
|
||||||
cconfig_bag.context = child
|
cconfig_bag.context = child
|
||||||
if cconfig_bag.properties is None:
|
if cconfig_bag.properties is None:
|
||||||
settings = child.get_settings()
|
settings = child.get_settings()
|
||||||
properties = settings.get_context_properties()
|
properties = settings.get_context_properties(child.properties_cache)
|
||||||
permissives = settings.get_context_permissives()
|
permissives = settings.get_context_permissives()
|
||||||
cconfig_bag.properties = properties
|
cconfig_bag.properties = properties
|
||||||
cconfig_bag.permissives = permissives
|
cconfig_bag.permissives = permissives
|
||||||
|
|
@ -1527,7 +1424,6 @@ class KernelGroupConfig(_CommonConfig):
|
||||||
def reset(
|
def reset(
|
||||||
self,
|
self,
|
||||||
path: str,
|
path: str,
|
||||||
only_children: bool,
|
|
||||||
config_bag: ConfigBag,
|
config_bag: ConfigBag,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""reset value for specified path"""
|
"""reset value for specified path"""
|
||||||
|
|
@ -1536,19 +1432,19 @@ class KernelGroupConfig(_CommonConfig):
|
||||||
cconfig_bag = config_bag.copy()
|
cconfig_bag = config_bag.copy()
|
||||||
cconfig_bag.context = child
|
cconfig_bag.context = child
|
||||||
settings = child.get_settings()
|
settings = child.get_settings()
|
||||||
properties = settings.get_context_properties()
|
properties = settings.get_context_properties(child.properties_cache)
|
||||||
permissives = settings.get_context_permissives()
|
permissives = settings.get_context_permissives()
|
||||||
cconfig_bag.properties = properties
|
cconfig_bag.properties = properties
|
||||||
cconfig_bag.permissives = permissives
|
cconfig_bag.permissives = permissives
|
||||||
cconfig_bag.remove_validation()
|
cconfig_bag.remove_validation()
|
||||||
# GROUP
|
# GROUP
|
||||||
subconfig = child.get_sub_config(
|
option_bag = child.get_sub_option_bag(
|
||||||
cconfig_bag,
|
cconfig_bag,
|
||||||
path,
|
path,
|
||||||
None,
|
None,
|
||||||
validate_properties=False,
|
False,
|
||||||
)
|
)[-1]
|
||||||
child.get_values().reset(subconfig)
|
child.get_values().reset(option_bag)
|
||||||
|
|
||||||
def getconfig(
|
def getconfig(
|
||||||
self,
|
self,
|
||||||
|
|
@ -1603,7 +1499,7 @@ class KernelMixConfig(KernelGroupConfig):
|
||||||
|
|
||||||
def set_value(
|
def set_value(
|
||||||
self,
|
self,
|
||||||
subconfig,
|
option_bag,
|
||||||
value,
|
value,
|
||||||
only_config=False,
|
only_config=False,
|
||||||
force_default=False,
|
force_default=False,
|
||||||
|
|
@ -1634,10 +1530,10 @@ class KernelMixConfig(KernelGroupConfig):
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
for child in self._impl_children:
|
for child in self._impl_children:
|
||||||
cconfig_bag = subconfig.config_bag.copy()
|
cconfig_bag = option_bag.config_bag.copy()
|
||||||
cconfig_bag.context = child
|
cconfig_bag.context = child
|
||||||
settings = child.get_settings()
|
settings = child.get_settings()
|
||||||
properties = settings.get_context_properties()
|
properties = settings.get_context_properties(child.properties_cache)
|
||||||
cconfig_bag.properties = properties
|
cconfig_bag.properties = properties
|
||||||
cconfig_bag.permissives = settings.get_context_permissives()
|
cconfig_bag.permissives = settings.get_context_permissives()
|
||||||
try:
|
try:
|
||||||
|
|
@ -1649,16 +1545,14 @@ class KernelMixConfig(KernelGroupConfig):
|
||||||
not force_default and not force_default_if_same
|
not force_default and not force_default_if_same
|
||||||
)
|
)
|
||||||
# MIX
|
# MIX
|
||||||
moption_bag = obj.get_sub_config(
|
moption_bag = obj.get_sub_option_bag(
|
||||||
cconfig_bag,
|
cconfig_bag,
|
||||||
subconfig.path,
|
option_bag.path,
|
||||||
subconfig.index,
|
option_bag.index,
|
||||||
validate_properties=validate_properties,
|
validate_properties,
|
||||||
)
|
)[-1]
|
||||||
if force_default_if_same:
|
if force_default_if_same:
|
||||||
if not child.get_values().hasvalue(
|
if not child.get_values().hasvalue(option_bag.path):
|
||||||
subconfig.path, index=subconfig.index
|
|
||||||
):
|
|
||||||
child_value = undefined
|
child_value = undefined
|
||||||
else:
|
else:
|
||||||
child_value = child.get_value(moption_bag)
|
child_value = child.get_value(moption_bag)
|
||||||
|
|
@ -1678,7 +1572,7 @@ class KernelMixConfig(KernelGroupConfig):
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
ret.append(
|
ret.append(
|
||||||
PropertiesOptionError(
|
PropertiesOptionError(
|
||||||
err.subconfig,
|
err._option_bag,
|
||||||
err.proptype,
|
err.proptype,
|
||||||
err._settings,
|
err._settings,
|
||||||
err._opt_type,
|
err._opt_type,
|
||||||
|
|
@ -1691,12 +1585,12 @@ class KernelMixConfig(KernelGroupConfig):
|
||||||
|
|
||||||
try:
|
try:
|
||||||
# MIX
|
# MIX
|
||||||
moption_bag = self.get_sub_config(
|
moption_bag = self.get_sub_option_bag(
|
||||||
subconfig.config_bag,
|
option_bag.config_bag,
|
||||||
subconfig.path,
|
option_bag.path,
|
||||||
subconfig.index,
|
option_bag.index,
|
||||||
validate_properties=not only_config,
|
not only_config,
|
||||||
)
|
)[-1]
|
||||||
if only_config:
|
if only_config:
|
||||||
ret = super().set_value(
|
ret = super().set_value(
|
||||||
moption_bag,
|
moption_bag,
|
||||||
|
|
@ -1725,37 +1619,37 @@ class KernelMixConfig(KernelGroupConfig):
|
||||||
rconfig_bag.remove_validation()
|
rconfig_bag.remove_validation()
|
||||||
if self.impl_type == "meta":
|
if self.impl_type == "meta":
|
||||||
# MIX
|
# MIX
|
||||||
subconfig = self.get_sub_config(
|
option_bag = self.get_sub_option_bag(
|
||||||
config_bag,
|
config_bag,
|
||||||
path,
|
path,
|
||||||
None,
|
None,
|
||||||
validate_properties=True,
|
True,
|
||||||
)
|
)[-1]
|
||||||
elif not only_children:
|
elif not only_children:
|
||||||
try:
|
try:
|
||||||
# MIX
|
# MIX
|
||||||
subconfig = self.get_sub_config(
|
option_bag = self.get_sub_option_bag(
|
||||||
rconfig_bag,
|
rconfig_bag,
|
||||||
path,
|
path,
|
||||||
None,
|
None,
|
||||||
validate_properties=True,
|
True,
|
||||||
)
|
)[-1]
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
only_children = True
|
only_children = True
|
||||||
for child in self._impl_children:
|
for child in self._impl_children:
|
||||||
rconfig_bag.context = child
|
rconfig_bag.context = child
|
||||||
try:
|
try:
|
||||||
if self.impl_type == "meta":
|
if self.impl_type == "meta":
|
||||||
moption_bag = subconfig
|
moption_bag = option_bag
|
||||||
moption_bag.config_bag = rconfig_bag
|
moption_bag.config_bag = rconfig_bag
|
||||||
else:
|
else:
|
||||||
# MIX
|
# MIX
|
||||||
moption_bag = child.get_sub_config(
|
moption_bag = child.get_sub_option_bag(
|
||||||
rconfig_bag,
|
rconfig_bag,
|
||||||
path,
|
path,
|
||||||
None,
|
None,
|
||||||
validate_properties=True,
|
True,
|
||||||
)
|
)[-1]
|
||||||
child.get_values().reset(moption_bag)
|
child.get_values().reset(moption_bag)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
@ -1766,8 +1660,8 @@ class KernelMixConfig(KernelGroupConfig):
|
||||||
rconfig_bag,
|
rconfig_bag,
|
||||||
)
|
)
|
||||||
if not only_children:
|
if not only_children:
|
||||||
subconfig.config_bag = config_bag
|
option_bag.config_bag = config_bag
|
||||||
self.get_values().reset(subconfig)
|
self.get_values().reset(option_bag)
|
||||||
|
|
||||||
def new_config(
|
def new_config(
|
||||||
self,
|
self,
|
||||||
|
|
@ -1894,10 +1788,6 @@ class KernelMetaConfig(KernelMixConfig):
|
||||||
raise TypeError(_("child must be a Config or MetaConfig"))
|
raise TypeError(_("child must be a Config or MetaConfig"))
|
||||||
if descr is None:
|
if descr is None:
|
||||||
descr = child.get_description()
|
descr = child.get_description()
|
||||||
if child.impl_getname() is None:
|
|
||||||
raise ConfigError(
|
|
||||||
_("children in MetaConfig must have name")
|
|
||||||
)
|
|
||||||
elif descr is not child.get_description():
|
elif descr is not child.get_description():
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
_(
|
_(
|
||||||
|
|
@ -1917,5 +1807,5 @@ class KernelMetaConfig(KernelMixConfig):
|
||||||
config,
|
config,
|
||||||
):
|
):
|
||||||
if self._impl_descr is not config.get_description():
|
if self._impl_descr is not config.get_description():
|
||||||
raise ValueError(_("metaconfig must have the same optiondescription"))
|
raise ValueError(_("metaconfig must " "have the same optiondescription"))
|
||||||
super().add_config(config)
|
super().add_config(config)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2012-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -18,30 +18,12 @@
|
||||||
import weakref
|
import weakref
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
|
|
||||||
from typing import Literal, Union, Optional
|
|
||||||
|
|
||||||
|
|
||||||
TiramisuErrorCode = Literal[
|
|
||||||
"option-dynamic",
|
|
||||||
"option-not-found",
|
|
||||||
"property-frozen",
|
|
||||||
"property-error",
|
|
||||||
"property-mandatory",
|
|
||||||
"leadership-group_type",
|
|
||||||
"leadership-wrong_property",
|
|
||||||
"leadership-force_default_on_freeze",
|
|
||||||
"leadership-greater",
|
|
||||||
"leadership-follower-greater",
|
|
||||||
"leadership-follower-callback-list",
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
def display_list(
|
def display_list(
|
||||||
lst,
|
lst,
|
||||||
*,
|
*,
|
||||||
separator: str="and",
|
separator="and",
|
||||||
add_quote: bool=False,
|
add_quote=False,
|
||||||
sort: bool=True,
|
|
||||||
) -> str():
|
) -> str():
|
||||||
if not lst:
|
if not lst:
|
||||||
return '""'
|
return '""'
|
||||||
|
|
@ -62,13 +44,15 @@ def display_list(
|
||||||
for l in lst:
|
for l in lst:
|
||||||
if not isinstance(l, str):
|
if not isinstance(l, str):
|
||||||
l = str(l)
|
l = str(l)
|
||||||
|
lst_.append(_(l))
|
||||||
|
lst__ = []
|
||||||
|
for l in lst_:
|
||||||
if add_quote and not l.startswith('"'):
|
if add_quote and not l.startswith('"'):
|
||||||
l = '"{}"'.format(l)
|
l = '"{}"'.format(l)
|
||||||
lst_.append(_(l))
|
lst__.append(l)
|
||||||
if sort:
|
lst__.sort()
|
||||||
lst_.sort()
|
last = lst__[-1]
|
||||||
last = lst_[-1]
|
return ", ".join(lst__[:-1]) + _(" {} ").format(separator) + "{}".format(last)
|
||||||
return ", ".join(lst_[:-1]) + _(" {} ").format(separator) + "{}".format(last)
|
|
||||||
|
|
||||||
|
|
||||||
# Exceptions for an Option
|
# Exceptions for an Option
|
||||||
|
|
@ -82,11 +66,13 @@ class PropertiesOptionError(AttributeError):
|
||||||
settings,
|
settings,
|
||||||
opt_type=None,
|
opt_type=None,
|
||||||
name=None,
|
name=None,
|
||||||
|
orig_opt=None,
|
||||||
help_properties=None,
|
help_properties=None,
|
||||||
):
|
):
|
||||||
if opt_type:
|
if opt_type:
|
||||||
self._opt_type = opt_type
|
self._opt_type = opt_type
|
||||||
self._name = name
|
self._name = name
|
||||||
|
self._orig_opt = orig_opt
|
||||||
else:
|
else:
|
||||||
if subconfig.option.impl_is_optiondescription():
|
if subconfig.option.impl_is_optiondescription():
|
||||||
self._opt_type = "optiondescription"
|
self._opt_type = "optiondescription"
|
||||||
|
|
@ -96,28 +82,15 @@ class PropertiesOptionError(AttributeError):
|
||||||
subconfig, with_quote=True
|
subconfig, with_quote=True
|
||||||
)
|
)
|
||||||
self._orig_opt = None
|
self._orig_opt = None
|
||||||
self.subconfig = subconfig
|
self._subconfig = subconfig
|
||||||
self.proptype = proptype
|
self.proptype = proptype
|
||||||
self.help_properties = help_properties
|
self.help_properties = help_properties
|
||||||
self._settings = settings
|
self._settings = settings
|
||||||
self.msg = None
|
self.msg = None
|
||||||
if not self.help_properties:
|
|
||||||
self.help_properties = self.proptype
|
|
||||||
properties = list(self.help_properties)
|
|
||||||
if properties == ["frozen"]:
|
|
||||||
self.code = "property-frozen"
|
|
||||||
elif properties == ["mandatory"]:
|
|
||||||
self.code = "property-mandatory"
|
|
||||||
else:
|
|
||||||
self.code = "property-error"
|
|
||||||
super().__init__(None)
|
super().__init__(None)
|
||||||
|
|
||||||
def display_properties(self, force_property=False, add_quote=True):
|
def set_orig_opt(self, opt):
|
||||||
if force_property:
|
self._orig_opt = opt
|
||||||
properties = self.proptype
|
|
||||||
else:
|
|
||||||
properties = self.help_properties
|
|
||||||
return display_list(list(properties), add_quote=add_quote)
|
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# this part is a bit slow, so only execute when display
|
# this part is a bit slow, so only execute when display
|
||||||
|
|
@ -125,81 +98,42 @@ class PropertiesOptionError(AttributeError):
|
||||||
return self.msg
|
return self.msg
|
||||||
if self._settings is None:
|
if self._settings is None:
|
||||||
return "error"
|
return "error"
|
||||||
arguments = [self._opt_type]
|
if self.help_properties:
|
||||||
if self._orig_opt:
|
properties = list(self.help_properties)
|
||||||
arguments.append(
|
|
||||||
self._orig_opt.impl_get_display_name(subconfig, with_quote=True)
|
|
||||||
)
|
|
||||||
arguments.append(self._name)
|
|
||||||
index = self.subconfig.index
|
|
||||||
if index is not None:
|
|
||||||
arguments.append(index)
|
|
||||||
if self.code == "property-frozen":
|
|
||||||
if index is not None:
|
|
||||||
if self._orig_opt:
|
|
||||||
msg = _(
|
|
||||||
'cannot modify the {0} {1} at index "{2}" because {3} is frozen'
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
msg = _(
|
|
||||||
'cannot modify the {0} {1} at index "{2}" because is frozen'
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
if self._orig_opt:
|
|
||||||
msg = _("cannot modify the {0} {1} because {2} is frozen")
|
|
||||||
else:
|
|
||||||
msg = _("cannot modify the {0} {1} because is frozen")
|
|
||||||
elif self.code == "property-mandatory":
|
|
||||||
if index is not None:
|
|
||||||
if self._orig_opt:
|
|
||||||
msg = _(
|
|
||||||
'cannot access to {0} {1} at index "{2}" because {3} hasn\'t value'
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
msg = _('{0} {1} at index "{2}" is mandatory but hasn\'t value')
|
|
||||||
else:
|
|
||||||
if self._orig_opt:
|
|
||||||
msg = _("cannot access to {0} {1} because {2} hasn't value")
|
|
||||||
else:
|
|
||||||
msg = _("{0} {1} is mandatory but hasn't value")
|
|
||||||
else:
|
else:
|
||||||
if index is not None:
|
properties = list(self.proptype)
|
||||||
if self._orig_opt:
|
only_one = len(properties) == 1
|
||||||
msg = _(
|
properties_msg = display_list(properties, add_quote=True)
|
||||||
'cannot access to {0} {1} at index "{2}" because {3} has {4} {5}'
|
if only_one:
|
||||||
)
|
prop_msg = _("property")
|
||||||
else:
|
else:
|
||||||
msg = _(
|
prop_msg = _("properties")
|
||||||
'cannot access to {0} {1} at index "{2}" because has {3} {4}'
|
if properties == ["frozen"]:
|
||||||
)
|
if self._orig_opt:
|
||||||
|
msg = _('cannot modify the {0} {1} because "{2}" has {3} {4}')
|
||||||
else:
|
else:
|
||||||
if self._orig_opt:
|
msg = _("cannot modify the {0} {1} because has {2} {3}")
|
||||||
msg = _("cannot access to {0} {1} because {2} has {3} {4}")
|
else:
|
||||||
else:
|
if self._orig_opt:
|
||||||
msg = _("cannot access to {0} {1} because has {2} {3}")
|
msg = _('cannot access to {0} {1} because "{2}" has {3} {4}')
|
||||||
only_one = len(self.help_properties) == 1
|
|
||||||
if only_one:
|
|
||||||
arguments.append(_("property"))
|
|
||||||
else:
|
else:
|
||||||
arguments.append(_("properties"))
|
msg = _("cannot access to {0} {1} because has {2} {3}")
|
||||||
arguments.append(self.display_properties())
|
if self._orig_opt:
|
||||||
self.msg = msg.format(*arguments)
|
# FIXME _orig_opt ?
|
||||||
|
self.msg = msg.format(
|
||||||
|
self._opt_type,
|
||||||
|
self._orig_opt.impl_get_display_name(subconfig, with_quote=True),
|
||||||
|
self._name,
|
||||||
|
prop_msg,
|
||||||
|
properties_msg,
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.msg = msg.format(self._opt_type, self._name, prop_msg, properties_msg)
|
||||||
del self._opt_type, self._name
|
del self._opt_type, self._name
|
||||||
del self._settings, self._orig_opt
|
del self._settings, self._orig_opt
|
||||||
return self.msg
|
return self.msg
|
||||||
|
|
||||||
|
|
||||||
class AttributeOptionError(AttributeError):
|
|
||||||
def __init__(self, path: str, code: TiramisuErrorCode) -> None:
|
|
||||||
self.path = path
|
|
||||||
self.code = code
|
|
||||||
|
|
||||||
def __str__(self) -> str:
|
|
||||||
if self.code == "option-dynamic":
|
|
||||||
return _('cannot access to "{0}" it\'s a dynamic option').format(self.path)
|
|
||||||
return _('"{0}" is not an option').format(self.path)
|
|
||||||
|
|
||||||
|
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
# Exceptions for a Config
|
# Exceptions for a Config
|
||||||
class ConfigError(Exception):
|
class ConfigError(Exception):
|
||||||
|
|
@ -210,22 +144,10 @@ class ConfigError(Exception):
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
exp,
|
exp,
|
||||||
*,
|
ori_err=None,
|
||||||
prefix: Optional[str] = None,
|
|
||||||
subconfig: Optional["Subconfig"]=None,
|
|
||||||
):
|
):
|
||||||
super().__init__(exp)
|
super().__init__(exp)
|
||||||
self.err_msg = exp
|
self.ori_err = ori_err
|
||||||
self.subconfig = subconfig
|
|
||||||
self.prefix = prefix
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
msg = self.prefix
|
|
||||||
if msg:
|
|
||||||
msg += ", {}".format(self.err_msg)
|
|
||||||
else:
|
|
||||||
msg = self.err_msg
|
|
||||||
return msg
|
|
||||||
|
|
||||||
|
|
||||||
class ConflictError(Exception):
|
class ConflictError(Exception):
|
||||||
|
|
@ -236,74 +158,8 @@ class ConflictError(Exception):
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
# miscellaneous exceptions
|
# miscellaneous exceptions
|
||||||
class LeadershipError(Exception):
|
class LeadershipError(Exception):
|
||||||
def __init__(
|
"problem with a leadership's value length"
|
||||||
self,
|
pass
|
||||||
subconfig: Union[str, "SubConfig"],
|
|
||||||
code,
|
|
||||||
*,
|
|
||||||
prop=None,
|
|
||||||
index=None,
|
|
||||||
length=None,
|
|
||||||
callback=None,
|
|
||||||
args=None,
|
|
||||||
kwargs=None,
|
|
||||||
ret=None,
|
|
||||||
):
|
|
||||||
if isinstance(subconfig, str):
|
|
||||||
self.path = self.display_name = subconfig
|
|
||||||
else:
|
|
||||||
self.path = subconfig.path
|
|
||||||
option = subconfig.option
|
|
||||||
self.display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
|
||||||
self.code = code
|
|
||||||
if prop is not None:
|
|
||||||
self.prop = prop
|
|
||||||
if index is not None:
|
|
||||||
self.index = index
|
|
||||||
if length is not None:
|
|
||||||
self.length = length
|
|
||||||
if callback is not None:
|
|
||||||
self.callback = callback
|
|
||||||
if args is not None:
|
|
||||||
self.args = args
|
|
||||||
if kwargs is not None:
|
|
||||||
self.kwargs = kwargs
|
|
||||||
if ret is not None:
|
|
||||||
self.ret = ret
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
if self.code == "leadership-group_type":
|
|
||||||
return _('cannot set "group_type" attribute for the Leadership {0}').format(
|
|
||||||
self.display_name
|
|
||||||
)
|
|
||||||
if self.code == "leadership-wrong_property":
|
|
||||||
return _('the leader {0} cannot have "{1}" property').format(
|
|
||||||
self.display_name, self.prop
|
|
||||||
)
|
|
||||||
if self.code == "leadership-force_default_on_freeze":
|
|
||||||
return _(
|
|
||||||
'the leader {0} cannot have "force_default_on_freeze" or "force_metaconfig_on_freeze" property without "frozen"'
|
|
||||||
).format(self.display_name)
|
|
||||||
if self.code == "leadership-reduce":
|
|
||||||
return _("cannot reduce length of the leader {0}").format(self.display_name)
|
|
||||||
if self.code == "leadership-greater":
|
|
||||||
return _(
|
|
||||||
'index "{0}" is greater than the leadership length "{1}" for option {2}'
|
|
||||||
).format(self.index, self.length, self.display_name)
|
|
||||||
if self.code == "leadership-follower-greater":
|
|
||||||
return _(
|
|
||||||
"the follower option {0} has greater length ({1}) than the leader length ({2})"
|
|
||||||
).format(self.display_name, self.index, self.length)
|
|
||||||
if self.code == "leadership-follower-callback-list":
|
|
||||||
if self.args or self.kwargs:
|
|
||||||
return _(
|
|
||||||
'the "{0}" function with positional arguments "{1}" and keyword arguments "{2}" must not return a list ("{3}") for the follower option {4}'
|
|
||||||
).format(
|
|
||||||
self.callback, self.args, self.kwargs, self.ret, self.display_name
|
|
||||||
)
|
|
||||||
return _(
|
|
||||||
'the "{0}" function must not return a list ("{1}") for the follower option {2}'
|
|
||||||
).format(self.callback, self.ret, self.display_name)
|
|
||||||
|
|
||||||
|
|
||||||
class ConstError(TypeError):
|
class ConstError(TypeError):
|
||||||
|
|
@ -316,9 +172,7 @@ class _CommonError:
|
||||||
self.val = val
|
self.val = val
|
||||||
self.display_type = display_type
|
self.display_type = display_type
|
||||||
self.opt = weakref.ref(opt)
|
self.opt = weakref.ref(opt)
|
||||||
self.name = opt.impl_get_display_name(subconfig, with_quote=True)
|
self.name = opt.impl_get_display_name(subconfig)
|
||||||
if subconfig:
|
|
||||||
self.path = subconfig.path
|
|
||||||
self.err_msg = err_msg
|
self.err_msg = err_msg
|
||||||
self.index = index
|
self.index = index
|
||||||
super().__init__(self.err_msg)
|
super().__init__(self.err_msg)
|
||||||
|
|
@ -327,9 +181,7 @@ class _CommonError:
|
||||||
try:
|
try:
|
||||||
msg = self.prefix
|
msg = self.prefix
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
self.prefix = self.tmpl.format(
|
self.prefix = self.tmpl.format(self.val, _(self.display_type), self.name)
|
||||||
self.val, _(self.display_type), self.name, self.index
|
|
||||||
)
|
|
||||||
msg = self.prefix
|
msg = self.prefix
|
||||||
if self.err_msg:
|
if self.err_msg:
|
||||||
if msg:
|
if msg:
|
||||||
|
|
@ -344,20 +196,13 @@ class _CommonError:
|
||||||
class ValueWarning(_CommonError, UserWarning):
|
class ValueWarning(_CommonError, UserWarning):
|
||||||
tmpl = None
|
tmpl = None
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if ValueWarning.tmpl is None:
|
if ValueWarning.tmpl is None:
|
||||||
if kwargs.get("index") is None:
|
ValueWarning.tmpl = _('attention, "{0}" could be an invalid {1} for "{2}"')
|
||||||
ValueWarning.tmpl = _(
|
if len(args) == 1 and not kwargs:
|
||||||
'attention, "{0}" could be an invalid {1} for {2}'
|
self.msg = args[0]
|
||||||
)
|
|
||||||
else:
|
|
||||||
ValueWarning.tmpl = _(
|
|
||||||
'attention, "{0}" could be an invalid {1} for {2} at index "{3}"'
|
|
||||||
)
|
|
||||||
if list(kwargs) == ["msg"]:
|
|
||||||
self.msg = kwargs["msg"]
|
|
||||||
else:
|
else:
|
||||||
super().__init__(**kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
self.msg = None
|
self.msg = None
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
@ -369,20 +214,10 @@ class ValueWarning(_CommonError, UserWarning):
|
||||||
class ValueOptionError(_CommonError, ValueError):
|
class ValueOptionError(_CommonError, ValueError):
|
||||||
tmpl = None
|
tmpl = None
|
||||||
|
|
||||||
def __init__(self, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if ValueOptionError.tmpl is None:
|
if ValueOptionError.tmpl is None:
|
||||||
opt = kwargs.get("opt")
|
ValueOptionError.tmpl = _('"{0}" is an invalid {1} for "{2}"')
|
||||||
if opt and opt._do_not_display_value_in_error:
|
super().__init__(*args, **kwargs)
|
||||||
if kwargs.get("index") is None:
|
|
||||||
self.tmpl = _("{2} has an invalid {1}")
|
|
||||||
else:
|
|
||||||
self.tmpl = _('{2} at index "{3}" has an invalid {1}')
|
|
||||||
else:
|
|
||||||
if kwargs.get("index") is None:
|
|
||||||
self.tmpl = _('"{0}" is an invalid {1} for {2}')
|
|
||||||
else:
|
|
||||||
self.tmpl = _('"{0}" is an invalid {1} for {2} at index "{3}"')
|
|
||||||
super().__init__(**kwargs)
|
|
||||||
|
|
||||||
|
|
||||||
class ValueErrorWarning(ValueWarning):
|
class ValueErrorWarning(ValueWarning):
|
||||||
|
|
@ -390,45 +225,5 @@ class ValueErrorWarning(ValueWarning):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
if ValueErrorWarning.tmpl is None:
|
if ValueErrorWarning.tmpl is None:
|
||||||
ValueErrorWarning.tmpl = _('"{0}" is an invalid {1} for {2}')
|
ValueErrorWarning.tmpl = _('"{0}" is an invalid {1} for "{2}"')
|
||||||
super().__init__(*args, **kwargs)
|
super().__init__(*args, **kwargs)
|
||||||
|
|
||||||
|
|
||||||
class CancelParam(Exception):
|
|
||||||
def __init__(self, origin_path, current_path):
|
|
||||||
super().__init__()
|
|
||||||
self.origin_path = origin_path
|
|
||||||
self.current_path = current_path
|
|
||||||
|
|
||||||
def __ne__(self, value):
|
|
||||||
return value is None or value == ""
|
|
||||||
|
|
||||||
def __eq__(self, value):
|
|
||||||
return value is None or value == ""
|
|
||||||
|
|
||||||
def __bool__(self):
|
|
||||||
return False
|
|
||||||
|
|
||||||
|
|
||||||
class ValueErrorIndexes(ValueError):
|
|
||||||
def __init__(self, msg, indexes):
|
|
||||||
super().__init__(msg)
|
|
||||||
self.indexes = indexes
|
|
||||||
|
|
||||||
|
|
||||||
class Errors:
|
|
||||||
@staticmethod
|
|
||||||
def raise_carry_out_calculation_error(
|
|
||||||
subconfig, message, original_error, option=None, extra_keys=[]
|
|
||||||
):
|
|
||||||
if option is None:
|
|
||||||
option = subconfig.option
|
|
||||||
display_name = option.impl_get_display_name(subconfig, with_quote=True)
|
|
||||||
if original_error:
|
|
||||||
raise ConfigError(
|
|
||||||
message.format(display_name, original_error, *extra_keys), subconfig=subconfig,
|
|
||||||
) from original_error
|
|
||||||
raise ConfigError(message.format(display_name, extra_keys), subconfig=subconfig)
|
|
||||||
|
|
||||||
|
|
||||||
errors = Errors()
|
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
# Copyright (C) 2018-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2018-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -28,7 +28,7 @@ FUNCTION_WAITING_FOR_ERROR = []
|
||||||
|
|
||||||
def function_waiting_for_dict(function):
|
def function_waiting_for_dict(function):
|
||||||
"""functions (calculation or validation) receive by default only the value of other options
|
"""functions (calculation or validation) receive by default only the value of other options
|
||||||
if you use this decoractor, it will recieve a dict with option informations
|
all functions declared with this function recieve a dict with option informations
|
||||||
(value, name, ...)
|
(value, name, ...)
|
||||||
"""
|
"""
|
||||||
name = function.__name__
|
name = function.__name__
|
||||||
|
|
@ -38,8 +38,8 @@ def function_waiting_for_dict(function):
|
||||||
|
|
||||||
|
|
||||||
def function_waiting_for_error(function):
|
def function_waiting_for_error(function):
|
||||||
"""functions (calculation or validation) receiven by default, only the value of other options
|
"""functions (calculation or validation) receive by default only the value of other options
|
||||||
if you use this decoractor, it will pass PropertyError too
|
set PropertyError too
|
||||||
"""
|
"""
|
||||||
name = function.__name__
|
name = function.__name__
|
||||||
if name not in FUNCTION_WAITING_FOR_ERROR:
|
if name not in FUNCTION_WAITING_FOR_ERROR:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: UTF-8 -*-
|
# -*- coding: UTF-8 -*-
|
||||||
# Copyright (C) 2012-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"logger for tiramisu"
|
"logger for tiramisu"
|
||||||
# Copyright (C) 2019-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2019-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2014-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2014-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2014-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2014-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -27,7 +27,7 @@ from itertools import chain
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..setting import undefined
|
from ..setting import undefined
|
||||||
from ..autolib import Calculation, ParamOption, ParamSelfOption, ParamInformation, ParamSelfInformation
|
from ..autolib import Calculation, ParamOption, ParamInformation, ParamSelfInformation
|
||||||
|
|
||||||
STATIC_TUPLE = frozenset()
|
STATIC_TUPLE = frozenset()
|
||||||
|
|
||||||
|
|
@ -59,7 +59,6 @@ class Base:
|
||||||
"_dependencies",
|
"_dependencies",
|
||||||
"_dependencies_information",
|
"_dependencies_information",
|
||||||
"_identifiers_dependencies",
|
"_identifiers_dependencies",
|
||||||
"could_conflict",
|
|
||||||
"__weakref__",
|
"__weakref__",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -89,12 +88,9 @@ class Base:
|
||||||
assert isinstance(properties, frozenset), _(
|
assert isinstance(properties, frozenset), _(
|
||||||
"invalid properties type {0} for {1}," " must be a frozenset"
|
"invalid properties type {0} for {1}," " must be a frozenset"
|
||||||
).format(type(properties), name)
|
).format(type(properties), name)
|
||||||
if not self.impl_is_optiondescription() and "novalidator" not in properties:
|
|
||||||
properties = properties | {"validator"}
|
|
||||||
_setattr = object.__setattr__
|
_setattr = object.__setattr__
|
||||||
_setattr(self, "_name", name)
|
_setattr(self, "_name", name)
|
||||||
_setattr(self, "_informations", {"doc": doc})
|
_setattr(self, "_informations", {"doc": doc})
|
||||||
_setattr(self, "could_conflict", [])
|
|
||||||
for prop in properties:
|
for prop in properties:
|
||||||
if not isinstance(prop, str):
|
if not isinstance(prop, str):
|
||||||
if not isinstance(prop, Calculation):
|
if not isinstance(prop, Calculation):
|
||||||
|
|
@ -104,7 +100,9 @@ class Base:
|
||||||
"Calculation"
|
"Calculation"
|
||||||
).format(type(prop), name)
|
).format(type(prop), name)
|
||||||
)
|
)
|
||||||
self.value_dependency(prop, type_="property")
|
for param in chain(prop.params.args, prop.params.kwargs.values()):
|
||||||
|
if isinstance(param, ParamOption):
|
||||||
|
param.option._add_dependency(self)
|
||||||
if properties:
|
if properties:
|
||||||
_setattr(self, "_properties", properties)
|
_setattr(self, "_properties", properties)
|
||||||
self.set_informations(informations)
|
self.set_informations(informations)
|
||||||
|
|
@ -148,12 +146,11 @@ class Base:
|
||||||
def _add_dependency(
|
def _add_dependency(
|
||||||
self,
|
self,
|
||||||
option,
|
option,
|
||||||
type_,
|
|
||||||
is_identifier: bool = False,
|
is_identifier: bool = False,
|
||||||
) -> None:
|
) -> None:
|
||||||
woption = weakref.ref(option)
|
woption = weakref.ref(option)
|
||||||
options = self.get_dependencies(None)
|
options = self.get_dependencies(None)
|
||||||
options.add((type_ == "default", woption))
|
options.add(woption)
|
||||||
self._dependencies = tuple(
|
self._dependencies = tuple(
|
||||||
options
|
options
|
||||||
) # pylint: disable=attribute-defined-outside-init
|
) # pylint: disable=attribute-defined-outside-init
|
||||||
|
|
@ -189,7 +186,6 @@ class Base:
|
||||||
else:
|
else:
|
||||||
dico = tuple([keys, tuple(dico.values())])
|
dico = tuple([keys, tuple(dico.values())])
|
||||||
_setattr(self, "_informations", dico)
|
_setattr(self, "_informations", dico)
|
||||||
_setattr(self, "could_conflict", tuple(self.could_conflict))
|
|
||||||
extra = getattr(self, "_extra", None)
|
extra = getattr(self, "_extra", None)
|
||||||
if extra is not None:
|
if extra is not None:
|
||||||
_setattr(
|
_setattr(
|
||||||
|
|
@ -393,22 +389,12 @@ class BaseOption(Base):
|
||||||
self,
|
self,
|
||||||
value: Any,
|
value: Any,
|
||||||
is_identifier: bool = False,
|
is_identifier: bool = False,
|
||||||
type_: str = 'default'
|
|
||||||
) -> Any:
|
) -> Any:
|
||||||
if not isinstance(is_identifier, bool):
|
|
||||||
raise Exception()
|
|
||||||
"""parse dependancy to add dependencies"""
|
"""parse dependancy to add dependencies"""
|
||||||
for param in chain(value.params.args, value.params.kwargs.values()):
|
for param in chain(value.params.args, value.params.kwargs.values()):
|
||||||
if isinstance(param, ParamOption):
|
if isinstance(param, ParamOption):
|
||||||
# pylint: disable=protected-access
|
# pylint: disable=protected-access
|
||||||
if is_identifier:
|
param.option._add_dependency(self, is_identifier=is_identifier)
|
||||||
_type_ = "identifier"
|
|
||||||
else:
|
|
||||||
_type_ = type_
|
|
||||||
param.option._add_dependency(self, _type_, is_identifier=is_identifier)
|
|
||||||
self._has_dependency = True
|
|
||||||
elif isinstance(param, ParamSelfOption) and not param.dynamic:
|
|
||||||
self._add_dependency(self, "self")
|
|
||||||
self._has_dependency = True
|
self._has_dependency = True
|
||||||
elif isinstance(param, ParamInformation):
|
elif isinstance(param, ParamInformation):
|
||||||
dest = self
|
dest = self
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -30,7 +30,6 @@ class BoolOption(Option):
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "boolean"
|
_type = "boolean"
|
||||||
_t_type = _("boolean")
|
|
||||||
|
|
||||||
def validate(
|
def validate(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -23,22 +23,27 @@
|
||||||
from ipaddress import ip_address
|
from ipaddress import ip_address
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .stroption import StrOption
|
from .option import Option
|
||||||
|
|
||||||
|
|
||||||
class BroadcastOption(StrOption):
|
class BroadcastOption(Option):
|
||||||
"""represents the choice of a broadcast"""
|
"""represents the choice of a broadcast"""
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "broadcast address"
|
_type = "broadcast address"
|
||||||
_t_type = _("broadcast address")
|
|
||||||
|
|
||||||
def validate(
|
def validate(
|
||||||
self,
|
self,
|
||||||
value: str,
|
value: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
"""validate"""
|
"""validate"""
|
||||||
super().validate(value)
|
if not isinstance(value, str):
|
||||||
|
raise ValueError(_("invalid string"))
|
||||||
|
if value.count(".") != 3:
|
||||||
|
raise ValueError()
|
||||||
|
for val in value.split("."):
|
||||||
|
if val.startswith("0") and len(val) > 1:
|
||||||
|
raise ValueError()
|
||||||
try:
|
try:
|
||||||
ip_address(value)
|
ip_address(value)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -21,12 +21,11 @@
|
||||||
"""ChoiceOption
|
"""ChoiceOption
|
||||||
"""
|
"""
|
||||||
from typing import Any
|
from typing import Any
|
||||||
from itertools import chain
|
|
||||||
|
|
||||||
from ..setting import undefined
|
from ..setting import undefined
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .option import Option
|
from .option import Option
|
||||||
from ..autolib import Calculation, get_calculated_value, ParamOption
|
from ..autolib import Calculation, get_calculated_value
|
||||||
from ..error import ConfigError, display_list
|
from ..error import ConfigError, display_list
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -38,15 +37,12 @@ class ChoiceOption(Option):
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "choice"
|
_type = "choice"
|
||||||
_t_type = _("choice")
|
|
||||||
|
|
||||||
def __init__(self, name, doc, values, *args, **kwargs):
|
def __init__(self, name, doc, values, *args, **kwargs):
|
||||||
"""
|
"""
|
||||||
:param values: is a list of values the option can possibly take
|
:param values: is a list of values the option can possibly take
|
||||||
"""
|
"""
|
||||||
if isinstance(values, Calculation):
|
if not isinstance(values, (Calculation, tuple)):
|
||||||
self.value_dependency(values, type_="choice")
|
|
||||||
elif not isinstance(values, tuple):
|
|
||||||
raise TypeError(
|
raise TypeError(
|
||||||
_("values must be a tuple or a calculation for {0}").format(name)
|
_("values must be a tuple or a calculation for {0}").format(name)
|
||||||
)
|
)
|
||||||
|
|
@ -73,8 +69,7 @@ class ChoiceOption(Option):
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
_('the calculated values "{0}" for "{1}" is not a list' "").format(
|
_('the calculated values "{0}" for "{1}" is not a list' "").format(
|
||||||
values, self.impl_getname()
|
values, self.impl_getname()
|
||||||
),
|
)
|
||||||
subconfig=subconfig,
|
|
||||||
)
|
)
|
||||||
return values
|
return values
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -31,7 +31,6 @@ class DateOption(StrOption):
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "date"
|
_type = "date"
|
||||||
_t_type = _("date")
|
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
def validate(self, value: str) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -21,7 +21,6 @@
|
||||||
"""DomainnameOption
|
"""DomainnameOption
|
||||||
"""
|
"""
|
||||||
import re
|
import re
|
||||||
import socket
|
|
||||||
from ipaddress import ip_interface
|
from ipaddress import ip_interface
|
||||||
from typing import Any, Optional, List
|
from typing import Any, Optional, List
|
||||||
|
|
||||||
|
|
@ -43,7 +42,6 @@ class DomainnameOption(StrOption):
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "domain name"
|
_type = "domain name"
|
||||||
_t_type = _("domain name")
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|
@ -55,18 +53,12 @@ class DomainnameOption(StrOption):
|
||||||
type: str = "domainname",
|
type: str = "domainname",
|
||||||
allow_without_dot: bool = False,
|
allow_without_dot: bool = False,
|
||||||
allow_startswith_dot: bool = False,
|
allow_startswith_dot: bool = False,
|
||||||
test_existence: bool = False,
|
|
||||||
_extra: dict = None,
|
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> None:
|
) -> None:
|
||||||
# pylint: disable=too-many-branches,too-many-locals,too-many-arguments
|
# pylint: disable=too-many-branches,too-many-locals,too-many-arguments
|
||||||
if _extra is None:
|
|
||||||
extra = {}
|
|
||||||
else:
|
|
||||||
extra = _extra
|
|
||||||
if type not in ["netbios", "hostname", "domainname"]:
|
if type not in ["netbios", "hostname", "domainname"]:
|
||||||
raise ValueError(_("unknown type {0} for hostname").format(type))
|
raise ValueError(_("unknown type {0} for hostname").format(type))
|
||||||
extra["type"] = type
|
extra = {"_dom_type": type}
|
||||||
if not isinstance(allow_ip, bool):
|
if not isinstance(allow_ip, bool):
|
||||||
raise ValueError(_("allow_ip must be a boolean"))
|
raise ValueError(_("allow_ip must be a boolean"))
|
||||||
if not isinstance(allow_cidr_network, bool):
|
if not isinstance(allow_cidr_network, bool):
|
||||||
|
|
@ -75,8 +67,7 @@ class DomainnameOption(StrOption):
|
||||||
raise ValueError(_("allow_without_dot must be a boolean"))
|
raise ValueError(_("allow_without_dot must be a boolean"))
|
||||||
if not isinstance(allow_startswith_dot, bool):
|
if not isinstance(allow_startswith_dot, bool):
|
||||||
raise ValueError(_("allow_startswith_dot must be a boolean"))
|
raise ValueError(_("allow_startswith_dot must be a boolean"))
|
||||||
extra["allow_without_dot"] = allow_without_dot
|
extra["_allow_without_dot"] = allow_without_dot
|
||||||
extra["test_existence"] = test_existence
|
|
||||||
if type == "domainname":
|
if type == "domainname":
|
||||||
if allow_without_dot:
|
if allow_without_dot:
|
||||||
min_time = 0
|
min_time = 0
|
||||||
|
|
@ -85,20 +76,14 @@ class DomainnameOption(StrOption):
|
||||||
regexp = r"((?!-)[a-z0-9-]{{{1},{0}}}\.){{{1},}}[a-z0-9-]{{1,{0}}}".format(
|
regexp = r"((?!-)[a-z0-9-]{{{1},{0}}}\.){{{1},}}[a-z0-9-]{{1,{0}}}".format(
|
||||||
self._get_len(type), min_time
|
self._get_len(type), min_time
|
||||||
)
|
)
|
||||||
msg = _(
|
|
||||||
'must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are allowed'
|
|
||||||
)
|
|
||||||
msg_warning = _(
|
|
||||||
'must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are recommanded'
|
|
||||||
)
|
|
||||||
else:
|
else:
|
||||||
regexp = r"((?!-)[a-z0-9-]{{1,{0}}})".format(self._get_len(type))
|
regexp = r"((?!-)[a-z0-9-]{{1,{0}}})".format(self._get_len(type))
|
||||||
msg = _(
|
msg = _(
|
||||||
'must start with lowercase characters followed by lowercase characters, number and "-" characters are allowed'
|
'must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are allowed'
|
||||||
)
|
)
|
||||||
msg_warning = _(
|
msg_warning = _(
|
||||||
'must start with lowercase characters followed by lowercase characters, number and "-" characters are recommanded'
|
'must start with lowercase characters followed by lowercase characters, number, "-" and "." characters are recommanded'
|
||||||
)
|
)
|
||||||
if allow_ip:
|
if allow_ip:
|
||||||
msg = _("could be a IP, otherwise {}").format(msg)
|
msg = _("could be a IP, otherwise {}").format(msg)
|
||||||
msg_warning = _("could be a IP, otherwise {}").format(msg_warning)
|
msg_warning = _("could be a IP, otherwise {}").format(msg_warning)
|
||||||
|
|
@ -120,15 +105,15 @@ class DomainnameOption(StrOption):
|
||||||
name,
|
name,
|
||||||
doc,
|
doc,
|
||||||
)
|
)
|
||||||
extra["allow_ip"] = allow_ip
|
extra["_allow_ip"] = allow_ip
|
||||||
if allow_cidr_network:
|
if allow_cidr_network:
|
||||||
extra["_network"] = NetworkOption(
|
extra["_network"] = NetworkOption(
|
||||||
name,
|
name,
|
||||||
doc,
|
doc,
|
||||||
cidr=True,
|
cidr=True,
|
||||||
)
|
)
|
||||||
extra["allow_cidr_network"] = allow_cidr_network
|
extra["_allow_cidr_network"] = allow_cidr_network
|
||||||
extra["allow_startswith_dot"] = allow_startswith_dot
|
extra["_allow_startswith_dot"] = allow_startswith_dot
|
||||||
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
name,
|
name,
|
||||||
|
|
@ -152,13 +137,13 @@ class DomainnameOption(StrOption):
|
||||||
_("invalid length (max {0})" "").format(part_name_length)
|
_("invalid length (max {0})" "").format(part_name_length)
|
||||||
)
|
)
|
||||||
|
|
||||||
part_name_length = self._get_len(self.impl_get_extra("type"))
|
part_name_length = self._get_len(self.impl_get_extra("_dom_type"))
|
||||||
if self.impl_get_extra("type") == "domainname":
|
if self.impl_get_extra("_dom_type") == "domainname":
|
||||||
if not self.impl_get_extra("allow_without_dot") and not "." in value:
|
if not self.impl_get_extra("_allow_without_dot") and not "." in value:
|
||||||
raise ValueError(_("must have dot"))
|
raise ValueError(_("must have dot"))
|
||||||
if len(value) > 255:
|
if len(value) > 255:
|
||||||
raise ValueError(_("invalid length (max 255)"))
|
raise ValueError(_("invalid length (max 255)"))
|
||||||
if self.impl_get_extra("allow_startswith_dot") and value.startswith("."):
|
if self.impl_get_extra("_allow_startswith_dot") and value.startswith("."):
|
||||||
val = value[1:]
|
val = value[1:]
|
||||||
else:
|
else:
|
||||||
val = value
|
val = value
|
||||||
|
|
@ -170,22 +155,10 @@ class DomainnameOption(StrOption):
|
||||||
_valid_length(dom)
|
_valid_length(dom)
|
||||||
else:
|
else:
|
||||||
_valid_length(value)
|
_valid_length(value)
|
||||||
self._validate_domain_resolution(value)
|
|
||||||
|
|
||||||
def _validate_domain_resolution(self, value: str) -> None:
|
|
||||||
if not value.startswith(".") and self.impl_get_extra("test_existence") is True:
|
|
||||||
try:
|
|
||||||
socket.gethostbyname(value)
|
|
||||||
except socket.gaierror as err:
|
|
||||||
raise ValueError(_("DNS resolution failed").format(value)) from err
|
|
||||||
except Exception as err:
|
|
||||||
raise ValueError(
|
|
||||||
_("error resolving DNS: {1}").format(value, err)
|
|
||||||
) from err
|
|
||||||
|
|
||||||
def _validate_ip_network(self, value: str) -> None:
|
def _validate_ip_network(self, value: str) -> None:
|
||||||
allow_ip = self.impl_get_extra("allow_ip")
|
allow_ip = self.impl_get_extra("_allow_ip")
|
||||||
allow_cidr_network = self.impl_get_extra("allow_cidr_network")
|
allow_cidr_network = self.impl_get_extra("_allow_cidr_network")
|
||||||
if allow_ip is False and allow_cidr_network is False:
|
if allow_ip is False and allow_cidr_network is False:
|
||||||
raise ValueError(_("must not be an IP"))
|
raise ValueError(_("must not be an IP"))
|
||||||
if allow_ip is True:
|
if allow_ip is True:
|
||||||
|
|
@ -211,7 +184,7 @@ class DomainnameOption(StrOption):
|
||||||
def _second_level_validation_domain(self, value: str, warnings_only: bool) -> None:
|
def _second_level_validation_domain(self, value: str, warnings_only: bool) -> None:
|
||||||
if self.impl_get_extra("_has_upper").search(value):
|
if self.impl_get_extra("_has_upper").search(value):
|
||||||
raise ValueError(_("some characters are uppercase"))
|
raise ValueError(_("some characters are uppercase"))
|
||||||
if self.impl_get_extra("allow_startswith_dot") and value.startswith("."):
|
if self.impl_get_extra("_allow_startswith_dot") and value.startswith("."):
|
||||||
val = value[1:]
|
val = value[1:]
|
||||||
else:
|
else:
|
||||||
val = value
|
val = value
|
||||||
|
|
@ -227,8 +200,8 @@ class DomainnameOption(StrOption):
|
||||||
def _second_level_validation_ip_network(
|
def _second_level_validation_ip_network(
|
||||||
self, value: str, warnings_only: bool
|
self, value: str, warnings_only: bool
|
||||||
) -> None:
|
) -> None:
|
||||||
allow_ip = self.impl_get_extra("allow_ip")
|
allow_ip = self.impl_get_extra("_allow_ip")
|
||||||
allow_cidr_network = self.impl_get_extra("allow_cidr_network")
|
allow_cidr_network = self.impl_get_extra("_allow_cidr_network")
|
||||||
# it's an IP so validate with IPOption
|
# it's an IP so validate with IPOption
|
||||||
if allow_ip is True and allow_cidr_network is False:
|
if allow_ip is True and allow_cidr_network is False:
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -31,6 +31,7 @@ from ..i18n import _
|
||||||
from .optiondescription import OptionDescription
|
from .optiondescription import OptionDescription
|
||||||
from .baseoption import BaseOption
|
from .baseoption import BaseOption
|
||||||
from ..setting import ConfigBag, undefined
|
from ..setting import ConfigBag, undefined
|
||||||
|
from ..error import ConfigError
|
||||||
from ..autolib import Calculation, get_calculated_value
|
from ..autolib import Calculation, get_calculated_value
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -81,9 +82,6 @@ class DynOptionDescription(OptionDescription):
|
||||||
identifier = identifier.replace(".", "_")
|
identifier = identifier.replace(".", "_")
|
||||||
return identifier
|
return identifier
|
||||||
|
|
||||||
def name_could_conflict(self, dynchild, child):
|
|
||||||
return child.impl_getname().startswith(dynchild.impl_getname())
|
|
||||||
|
|
||||||
def impl_is_dynoptiondescription(self) -> bool:
|
def impl_is_dynoptiondescription(self) -> bool:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
@ -106,8 +104,6 @@ class DynOptionDescription(OptionDescription):
|
||||||
parent: "SubConfig",
|
parent: "SubConfig",
|
||||||
*,
|
*,
|
||||||
uncalculated: bool = False,
|
uncalculated: bool = False,
|
||||||
from_display_name: bool = False,
|
|
||||||
convert: bool = False,
|
|
||||||
) -> List[str]:
|
) -> List[str]:
|
||||||
"""get dynamic identifiers"""
|
"""get dynamic identifiers"""
|
||||||
subconfig = parent.get_child(
|
subconfig = parent.get_child(
|
||||||
|
|
@ -115,7 +111,6 @@ class DynOptionDescription(OptionDescription):
|
||||||
None,
|
None,
|
||||||
False,
|
False,
|
||||||
properties=None,
|
properties=None,
|
||||||
check_dynamic_without_identifiers=False,
|
|
||||||
)
|
)
|
||||||
identifiers = self._identifiers
|
identifiers = self._identifiers
|
||||||
if isinstance(identifiers, list):
|
if isinstance(identifiers, list):
|
||||||
|
|
@ -129,18 +124,16 @@ class DynOptionDescription(OptionDescription):
|
||||||
)[0]
|
)[0]
|
||||||
if values is None:
|
if values is None:
|
||||||
values = []
|
values = []
|
||||||
|
values_ = []
|
||||||
if __debug__:
|
if __debug__:
|
||||||
if not isinstance(values, list):
|
if not isinstance(values, list):
|
||||||
if not from_display_name:
|
|
||||||
name = self.impl_get_display_name(subconfig, with_quote=True)
|
|
||||||
else:
|
|
||||||
name = self.impl_getname()
|
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
_(
|
_(
|
||||||
"DynOptionDescription identifiers for option {0}, is not a list ({1})"
|
"DynOptionDescription identifiers for option {0}, is not a list ({1})"
|
||||||
).format(name, values)
|
).format(
|
||||||
|
self.impl_get_display_name(subconfig, with_quote=True), values
|
||||||
|
)
|
||||||
)
|
)
|
||||||
values_ = []
|
|
||||||
for val in values:
|
for val in values:
|
||||||
cval = self.convert_identifier_to_path(val)
|
cval = self.convert_identifier_to_path(val)
|
||||||
if not isinstance(cval, str) or re.match(NAME_REGEXP, cval) is None:
|
if not isinstance(cval, str) or re.match(NAME_REGEXP, cval) is None:
|
||||||
|
|
@ -150,15 +143,9 @@ class DynOptionDescription(OptionDescription):
|
||||||
cval, self.impl_get_display_name(subconfig, with_quote=True)
|
cval, self.impl_get_display_name(subconfig, with_quote=True)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
elif convert:
|
|
||||||
values_.append(cval)
|
|
||||||
else:
|
else:
|
||||||
values_.append(val)
|
values_.append(val)
|
||||||
if (
|
if __debug__ and len(values_) > len(set(values_)):
|
||||||
__debug__
|
|
||||||
and "demoting_error_warning" not in subconfig.config_bag.properties
|
|
||||||
and len(values_) > len(set(values_))
|
|
||||||
):
|
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
_(
|
_(
|
||||||
'DynOptionDescription "{0}" identifiers return a list with same values "{1}"'
|
'DynOptionDescription "{0}" identifiers return a list with same values "{1}"'
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -34,4 +34,3 @@ class EmailOption(RegexpOption):
|
||||||
r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$"
|
r"^[a-zA-Z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$"
|
||||||
)
|
)
|
||||||
_type = "email address"
|
_type = "email address"
|
||||||
_t_type = _("email address")
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -32,7 +32,6 @@ class FilenameOption(StrOption):
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "file name"
|
_type = "file name"
|
||||||
_t_type = _("file name")
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|
@ -53,9 +52,9 @@ class FilenameOption(StrOption):
|
||||||
if typ not in ["file", "directory"]:
|
if typ not in ["file", "directory"]:
|
||||||
raise ValueError(f'unknown type "{typ}" for "{name}"')
|
raise ValueError(f'unknown type "{typ}" for "{name}"')
|
||||||
extra = {
|
extra = {
|
||||||
"allow_relative": allow_relative,
|
"_allow_relative": allow_relative,
|
||||||
"test_existence": test_existence,
|
"_test_existence": test_existence,
|
||||||
"types": types,
|
"_types": types,
|
||||||
}
|
}
|
||||||
super().__init__(name, *args, extra=extra, **kwargs)
|
super().__init__(name, *args, extra=extra, **kwargs)
|
||||||
|
|
||||||
|
|
@ -64,10 +63,10 @@ class FilenameOption(StrOption):
|
||||||
value: str,
|
value: str,
|
||||||
) -> None:
|
) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
if not self.impl_get_extra("allow_relative") and not value.startswith("/"):
|
if not self.impl_get_extra("_allow_relative") and not value.startswith("/"):
|
||||||
raise ValueError(_('must starts with "/"'))
|
raise ValueError(_('must starts with "/"'))
|
||||||
if value is not None and self.impl_get_extra("test_existence"):
|
if value is not None and self.impl_get_extra("_test_existence"):
|
||||||
types = self.impl_get_extra("types")
|
types = self.impl_get_extra("_types")
|
||||||
file = Path(value)
|
file = Path(value)
|
||||||
found = False
|
found = False
|
||||||
if "file" in types and file.is_file():
|
if "file" in types and file.is_file():
|
||||||
|
|
@ -75,12 +74,8 @@ class FilenameOption(StrOption):
|
||||||
if not found and "directory" in types and file.is_dir():
|
if not found and "directory" in types and file.is_dir():
|
||||||
found = True
|
found = True
|
||||||
if not found:
|
if not found:
|
||||||
translated_types = [
|
|
||||||
{"file": _("file"), "directory": _("directory")}.get(typ)
|
|
||||||
for typ in types
|
|
||||||
]
|
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
_("cannot find this {0}").format(
|
_('cannot find {0} "{1}"').format(
|
||||||
display_list(translated_types, separator="or"), value
|
display_list(types, separator="or"), value
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -30,7 +30,6 @@ class FloatOption(Option):
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "float"
|
_type = "float"
|
||||||
_t_type = _("float")
|
|
||||||
|
|
||||||
def validate(self, value: float) -> None:
|
def validate(self, value: float) -> None:
|
||||||
if not isinstance(value, float):
|
if not isinstance(value, float):
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -29,26 +29,13 @@ class IntOption(Option):
|
||||||
"represents a choice of an integer"
|
"represents a choice of an integer"
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "integer"
|
_type = "integer"
|
||||||
_t_type = _("integer")
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(self, *args, min_number=None, max_number=None, **kwargs):
|
||||||
self,
|
|
||||||
*args,
|
|
||||||
min_number=None,
|
|
||||||
max_number=None,
|
|
||||||
min_integer=None,
|
|
||||||
max_integer=None,
|
|
||||||
**kwargs,
|
|
||||||
):
|
|
||||||
extra = {}
|
extra = {}
|
||||||
if min_number is not None:
|
if min_number is not None:
|
||||||
extra["min_integer"] = min_number
|
extra["min_number"] = min_number
|
||||||
if min_integer is not None:
|
|
||||||
extra["min_integer"] = min_integer
|
|
||||||
if max_number is not None:
|
if max_number is not None:
|
||||||
extra["max_integer"] = max_number
|
extra["max_number"] = max_number
|
||||||
if max_integer is not None:
|
|
||||||
extra["max_integer"] = max_integer
|
|
||||||
super().__init__(*args, extra=extra, **kwargs)
|
super().__init__(*args, extra=extra, **kwargs)
|
||||||
|
|
||||||
def validate(
|
def validate(
|
||||||
|
|
@ -56,20 +43,20 @@ class IntOption(Option):
|
||||||
value: int,
|
value: int,
|
||||||
) -> None:
|
) -> None:
|
||||||
if not isinstance(value, int):
|
if not isinstance(value, int):
|
||||||
raise ValueError(_("it's not an integer"))
|
raise ValueError()
|
||||||
|
|
||||||
def second_level_validation(self, value, warnings_only):
|
def second_level_validation(self, value, warnings_only):
|
||||||
min_integer = self.impl_get_extra("min_integer")
|
min_number = self.impl_get_extra("min_number")
|
||||||
if min_integer is not None and value < min_integer:
|
if min_number is not None and value < min_number:
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
msg = _('value should be equal or greater than "{0}"')
|
msg = _('value should be equal or greater than "{0}"')
|
||||||
else:
|
else:
|
||||||
msg = _('value must be equal or greater than "{0}"')
|
msg = _('value must be equal or greater than "{0}"')
|
||||||
raise ValueError(msg.format(min_integer))
|
raise ValueError(msg.format(min_number))
|
||||||
max_integer = self.impl_get_extra("max_integer")
|
max_number = self.impl_get_extra("max_number")
|
||||||
if max_integer is not None and value > max_integer:
|
if max_number is not None and value > max_number:
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
msg = _('value should be less than "{0}"')
|
msg = _('value should be less than "{0}"')
|
||||||
else:
|
else:
|
||||||
msg = _('value must be less than "{0}"')
|
msg = _('value must be less than "{0}"')
|
||||||
raise ValueError(msg.format(max_integer))
|
raise ValueError(msg.format(max_number))
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -31,7 +31,6 @@ class IPOption(StrOption):
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "IP"
|
_type = "IP"
|
||||||
_t_type = _("IP")
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|
@ -44,9 +43,9 @@ class IPOption(StrOption):
|
||||||
):
|
):
|
||||||
if extra is None:
|
if extra is None:
|
||||||
extra = {}
|
extra = {}
|
||||||
extra["private_only"] = private_only
|
extra["_private_only"] = private_only
|
||||||
extra["allow_reserved"] = allow_reserved
|
extra["_allow_reserved"] = allow_reserved
|
||||||
extra["cidr"] = cidr
|
extra["_cidr"] = cidr
|
||||||
super().__init__(*args, extra=extra, **kwargs)
|
super().__init__(*args, extra=extra, **kwargs)
|
||||||
|
|
||||||
def _validate_cidr(self, value):
|
def _validate_cidr(self, value):
|
||||||
|
|
@ -54,9 +53,6 @@ class IPOption(StrOption):
|
||||||
ip_obj = ip_interface(value)
|
ip_obj = ip_interface(value)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
raise ValueError() from err
|
raise ValueError() from err
|
||||||
self._second_level_cidr(ip_obj)
|
|
||||||
|
|
||||||
def _second_level_cidr(self, ip_obj):
|
|
||||||
if ip_obj.ip == ip_obj.network.network_address:
|
if ip_obj.ip == ip_obj.network.network_address:
|
||||||
raise ValueError(_("it's in fact a network address"))
|
raise ValueError(_("it's in fact a network address"))
|
||||||
if ip_obj.ip == ip_obj.network.broadcast_address:
|
if ip_obj.ip == ip_obj.network.broadcast_address:
|
||||||
|
|
@ -70,7 +66,7 @@ class IPOption(StrOption):
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
def validate(self, value: str) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
if self.impl_get_extra("cidr"):
|
if self.impl_get_extra("_cidr"):
|
||||||
if "/" not in value:
|
if "/" not in value:
|
||||||
raise ValueError(_('CIDR address must have a "/"'))
|
raise ValueError(_('CIDR address must have a "/"'))
|
||||||
self._validate_cidr(value)
|
self._validate_cidr(value)
|
||||||
|
|
@ -79,13 +75,13 @@ class IPOption(StrOption):
|
||||||
|
|
||||||
def second_level_validation(self, value: str, warnings_only: bool) -> None:
|
def second_level_validation(self, value: str, warnings_only: bool) -> None:
|
||||||
ip_obj = ip_interface(value)
|
ip_obj = ip_interface(value)
|
||||||
if not self.impl_get_extra("allow_reserved") and ip_obj.is_reserved:
|
if not self.impl_get_extra("_allow_reserved") and ip_obj.is_reserved:
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
msg = _("shouldn't be reserved IP")
|
msg = _("shouldn't be reserved IP")
|
||||||
else:
|
else:
|
||||||
msg = _("mustn't be reserved IP")
|
msg = _("mustn't be reserved IP")
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
if self.impl_get_extra("private_only") and not ip_obj.is_private:
|
if self.impl_get_extra("_private_only") and not ip_obj.is_private:
|
||||||
if warnings_only:
|
if warnings_only:
|
||||||
msg = _("should be private IP")
|
msg = _("should be private IP")
|
||||||
else:
|
else:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"Leadership support"
|
"Leadership support"
|
||||||
# Copyright (C) 2014-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2014-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -51,7 +51,9 @@ class Leadership(OptionDescription):
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> None:
|
) -> None:
|
||||||
if "group_type" in kwargs:
|
if "group_type" in kwargs:
|
||||||
raise LeadershipError(name, "leadership-group_type")
|
raise LeadershipError(
|
||||||
|
_('cannot set "group_type" attribute for a Leadership')
|
||||||
|
)
|
||||||
super().__init__(
|
super().__init__(
|
||||||
name,
|
name,
|
||||||
doc,
|
doc,
|
||||||
|
|
@ -73,10 +75,9 @@ class Leadership(OptionDescription):
|
||||||
if __debug__:
|
if __debug__:
|
||||||
self._check_default_value(child)
|
self._check_default_value(child)
|
||||||
# remove empty property for follower
|
# remove empty property for follower
|
||||||
if not child.impl_is_submulti():
|
child._properties = frozenset(child._properties - {"empty", "unique"})
|
||||||
child._properties = frozenset(child._properties - {"empty", "unique"})
|
|
||||||
followers.append(child)
|
followers.append(child)
|
||||||
child._add_dependency(self, "leadership")
|
child._add_dependency(self)
|
||||||
child._leadership = weakref.ref(self)
|
child._leadership = weakref.ref(self)
|
||||||
if __debug__:
|
if __debug__:
|
||||||
leader = children[0]
|
leader = children[0]
|
||||||
|
|
@ -84,7 +85,9 @@ class Leadership(OptionDescription):
|
||||||
if prop not in ALLOWED_LEADER_PROPERTIES and not isinstance(
|
if prop not in ALLOWED_LEADER_PROPERTIES and not isinstance(
|
||||||
prop, Calculation
|
prop, Calculation
|
||||||
):
|
):
|
||||||
raise LeadershipError(name, "leadership-wrong_property", prop=prop)
|
raise LeadershipError(
|
||||||
|
_('leader cannot have "{}" property').format(prop)
|
||||||
|
)
|
||||||
|
|
||||||
def _check_child_is_valid(
|
def _check_child_is_valid(
|
||||||
self,
|
self,
|
||||||
|
|
@ -109,7 +112,7 @@ class Leadership(OptionDescription):
|
||||||
if not child.impl_is_multi():
|
if not child.impl_is_multi():
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
_(
|
_(
|
||||||
"only multi option are allowed in leadership {0} but option "
|
"only multi option allowed in leadership {0} but option "
|
||||||
"{1} is not a multi"
|
"{1} is not a multi"
|
||||||
""
|
""
|
||||||
).format(
|
).format(
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2020-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2020-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -32,4 +32,3 @@ class MACOption(RegexpOption):
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_regexp = re.compile(r"^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$")
|
_regexp = re.compile(r"^([0-9A-Fa-f]{2}[:]){5}([0-9A-Fa-f]{2})$")
|
||||||
_type = "mac address"
|
_type = "mac address"
|
||||||
_t_type = _("mac address")
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -30,7 +30,6 @@ class NetmaskOption(StrOption):
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "netmask address"
|
_type = "netmask address"
|
||||||
_t_type = _("netmask address")
|
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
def validate(self, value: str) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -23,22 +23,36 @@
|
||||||
from ipaddress import ip_network
|
from ipaddress import ip_network
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .ipoption import IPOption
|
|
||||||
from .stroption import StrOption
|
from .stroption import StrOption
|
||||||
|
|
||||||
|
|
||||||
class NetworkOption(IPOption):
|
class NetworkOption(StrOption):
|
||||||
"represents the choice of a network"
|
"represents the choice of a network"
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "network address"
|
_type = "network address"
|
||||||
_t_type = _("network address")
|
|
||||||
|
|
||||||
def __init__(self, *args, cidr=False, **kwargs):
|
def __init__(self, *args, cidr=False, **kwargs):
|
||||||
super().__init__(*args, cidr=cidr, **kwargs)
|
extra = {"_cidr": cidr}
|
||||||
|
super().__init__(*args, extra=extra, **kwargs)
|
||||||
|
|
||||||
def _second_level_cidr(self, ip_obj):
|
def validate(self, value: str) -> None:
|
||||||
if ip_obj.ip != ip_obj.network.network_address:
|
super().validate(value)
|
||||||
raise ValueError(_("it's not a network address"))
|
if value.count(".") != 3:
|
||||||
|
raise ValueError()
|
||||||
|
cidr = self.impl_get_extra("_cidr")
|
||||||
|
if cidr:
|
||||||
|
if "/" not in value:
|
||||||
|
raise ValueError(_("must use CIDR notation"))
|
||||||
|
value_ = value.split("/")[0]
|
||||||
|
else:
|
||||||
|
value_ = value
|
||||||
|
for val in value_.split("."):
|
||||||
|
if val.startswith("0") and len(val) > 1:
|
||||||
|
raise ValueError()
|
||||||
|
try:
|
||||||
|
ip_network(value)
|
||||||
|
except ValueError as err:
|
||||||
|
raise ValueError() from err
|
||||||
|
|
||||||
def second_level_validation(self, value: str, warnings_only: bool) -> None:
|
def second_level_validation(self, value: str, warnings_only: bool) -> None:
|
||||||
if ip_network(value).network_address.is_reserved:
|
if ip_network(value).network_address.is_reserved:
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"option types and option description"
|
"option types and option description"
|
||||||
# Copyright (C) 2012-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -53,8 +53,6 @@ class Option(BaseOption):
|
||||||
"_choice_values_params",
|
"_choice_values_params",
|
||||||
)
|
)
|
||||||
_type = None
|
_type = None
|
||||||
_t_type = None
|
|
||||||
_do_not_display_value_in_error = False
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|
@ -129,6 +127,11 @@ 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,
|
||||||
|
# None,
|
||||||
|
# undefined,
|
||||||
|
# properties=None,
|
||||||
|
# )
|
||||||
try:
|
try:
|
||||||
self.validate(value)
|
self.validate(value)
|
||||||
self.validate_with_option(
|
self.validate_with_option(
|
||||||
|
|
@ -180,19 +183,16 @@ class Option(BaseOption):
|
||||||
# undefined,
|
# undefined,
|
||||||
# properties=None,
|
# properties=None,
|
||||||
# )
|
# )
|
||||||
self_properties = getattr(self, "_properties", {})
|
|
||||||
self.impl_validate(
|
self.impl_validate(
|
||||||
None,
|
None,
|
||||||
default,
|
default,
|
||||||
loaded=True,
|
loaded=True,
|
||||||
self_properties=self_properties,
|
|
||||||
)
|
)
|
||||||
self.impl_validate(
|
self.impl_validate(
|
||||||
None,
|
None,
|
||||||
default,
|
default,
|
||||||
check_error=False,
|
check_error=False,
|
||||||
loaded=True,
|
loaded=True,
|
||||||
self_properties=self_properties,
|
|
||||||
)
|
)
|
||||||
self.value_dependencies(default)
|
self.value_dependencies(default)
|
||||||
if (is_multi and default != []) or (not is_multi and default is not None):
|
if (is_multi and default != []) or (not is_multi and default is not None):
|
||||||
|
|
@ -215,10 +215,8 @@ class Option(BaseOption):
|
||||||
"""is a dynsymlinkoption?"""
|
"""is a dynsymlinkoption?"""
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def get_type(self, translation=True) -> str:
|
def get_type(self) -> str:
|
||||||
"""get the type of option"""
|
"""get the type of option"""
|
||||||
if translation:
|
|
||||||
return self._t_type
|
|
||||||
return self._type
|
return self._type
|
||||||
|
|
||||||
def impl_getdefault(self) -> Any:
|
def impl_getdefault(self) -> Any:
|
||||||
|
|
@ -263,40 +261,33 @@ class Option(BaseOption):
|
||||||
*,
|
*,
|
||||||
check_error: bool = True,
|
check_error: bool = True,
|
||||||
loaded: bool = False,
|
loaded: bool = False,
|
||||||
self_properties: frozenset = frozenset(),
|
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""Return True if value is really valid
|
"""Return True if value is really valid
|
||||||
If not validate or invalid return it returns False
|
If not validate or invalid return it returns False
|
||||||
"""
|
"""
|
||||||
if check_error:
|
if (
|
||||||
if subconfig:
|
check_error
|
||||||
config_properties = subconfig.config_bag.properties
|
and subconfig
|
||||||
self_properties = subconfig.properties
|
and not "validator" in subconfig.config_bag.properties
|
||||||
else:
|
):
|
||||||
config_properties = {"validator"}
|
return False
|
||||||
if (
|
|
||||||
"validator" not in config_properties
|
|
||||||
or "validator" not in self_properties
|
|
||||||
):
|
|
||||||
return False
|
|
||||||
if subconfig:
|
if subconfig:
|
||||||
force_index = subconfig.index
|
force_index = subconfig.index
|
||||||
else:
|
else:
|
||||||
force_index = None
|
force_index = None
|
||||||
is_warnings_only = getattr(self, "_warnings_only", False)
|
is_warnings_only = getattr(self, "_warnings_only", False)
|
||||||
|
|
||||||
def _is_not_unique(current_value, values):
|
def _is_not_unique(value):
|
||||||
if current_value is None:
|
# if set(value) has not same length than value
|
||||||
return
|
|
||||||
if not subconfig or not check_error or "unique" not in subconfig.properties:
|
if not subconfig or not check_error or "unique" not in subconfig.properties:
|
||||||
return
|
return
|
||||||
indexes = [
|
lvalue = [val for val in value if val is not None]
|
||||||
index for index, value in enumerate(values) if value == current_value
|
if len(set(lvalue)) == len(lvalue):
|
||||||
]
|
return
|
||||||
if len(indexes) > 1:
|
for idx, val in enumerate(value):
|
||||||
raise ValueError(
|
if val not in value[idx + 1 :]:
|
||||||
_('the value "{}" is not unique' "").format(current_value)
|
continue
|
||||||
)
|
raise ValueError(_('the value "{}" is not unique' "").format(val))
|
||||||
|
|
||||||
def calculation_validator(
|
def calculation_validator(
|
||||||
val,
|
val,
|
||||||
|
|
@ -338,12 +329,12 @@ class Option(BaseOption):
|
||||||
except ValueWarning as warn:
|
except ValueWarning as warn:
|
||||||
warnings.warn_explicit(
|
warnings.warn_explicit(
|
||||||
ValueWarning(
|
ValueWarning(
|
||||||
subconfig=subconfig,
|
subconfig,
|
||||||
val=val,
|
val,
|
||||||
display_type=_(self.get_type()),
|
_(self.get_type()),
|
||||||
opt=self,
|
self,
|
||||||
err_msg=str(warn),
|
str(warn),
|
||||||
index=_index,
|
_index,
|
||||||
),
|
),
|
||||||
ValueWarning,
|
ValueWarning,
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
|
|
@ -358,7 +349,7 @@ class Option(BaseOption):
|
||||||
if _value is None:
|
if _value is None:
|
||||||
return
|
return
|
||||||
if isinstance(_value, list):
|
if isinstance(_value, list):
|
||||||
raise ValueError(_("it must not be a list"))
|
raise ValueError(_("which must not be a list"))
|
||||||
if isinstance(_value, Calculation) and not subconfig:
|
if isinstance(_value, Calculation) and not subconfig:
|
||||||
return
|
return
|
||||||
# option validation
|
# option validation
|
||||||
|
|
@ -379,12 +370,12 @@ class Option(BaseOption):
|
||||||
if is_warnings_only:
|
if is_warnings_only:
|
||||||
warnings.warn_explicit(
|
warnings.warn_explicit(
|
||||||
ValueWarning(
|
ValueWarning(
|
||||||
subconfig=subconfig,
|
subconfig,
|
||||||
val=_value,
|
_value,
|
||||||
display_type=_(self.get_type()),
|
_(self.get_type()),
|
||||||
opt=self,
|
self,
|
||||||
err_msg=str(err),
|
str(err),
|
||||||
index=_index,
|
_index,
|
||||||
),
|
),
|
||||||
ValueWarning,
|
ValueWarning,
|
||||||
self.__class__.__name__,
|
self.__class__.__name__,
|
||||||
|
|
@ -399,102 +390,70 @@ class Option(BaseOption):
|
||||||
_index,
|
_index,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
val = value
|
||||||
err_index = force_index
|
err_index = force_index
|
||||||
ret = True
|
try:
|
||||||
if not self.impl_is_multi():
|
if not self.impl_is_multi():
|
||||||
try:
|
|
||||||
do_validation(
|
do_validation(
|
||||||
value,
|
val,
|
||||||
None,
|
None,
|
||||||
)
|
)
|
||||||
except ValueError as err:
|
elif force_index is not None:
|
||||||
self.validate_parse_error(value, err_index, err, subconfig)
|
if self.impl_is_submulti():
|
||||||
ret = False
|
if not isinstance(value, list):
|
||||||
elif force_index is not None:
|
raise ValueError(_("which must be a list"))
|
||||||
if self.impl_is_submulti():
|
for val in value:
|
||||||
if not isinstance(value, list):
|
|
||||||
raise ValueError(_("it must be a list"))
|
|
||||||
for val in value:
|
|
||||||
try:
|
|
||||||
do_validation(
|
do_validation(
|
||||||
val,
|
val,
|
||||||
force_index,
|
force_index,
|
||||||
)
|
)
|
||||||
_is_not_unique(val, value)
|
_is_not_unique(value)
|
||||||
except ValueError as err:
|
else:
|
||||||
self.validate_parse_error(val, err_index, err, subconfig)
|
|
||||||
ret = False
|
|
||||||
else:
|
|
||||||
try:
|
|
||||||
do_validation(
|
do_validation(
|
||||||
value,
|
val,
|
||||||
force_index,
|
force_index,
|
||||||
)
|
)
|
||||||
except ValueError as err:
|
elif isinstance(value, Calculation) and not subconfig:
|
||||||
self.validate_parse_error(value, err_index, err, subconfig)
|
pass
|
||||||
ret = False
|
elif self.impl_is_submulti():
|
||||||
elif isinstance(value, Calculation) and not subconfig:
|
for err_index, lval in enumerate(value):
|
||||||
pass
|
if isinstance(lval, Calculation):
|
||||||
elif self.impl_is_submulti():
|
continue
|
||||||
for err_index, lval in enumerate(value):
|
if not isinstance(lval, list):
|
||||||
if isinstance(lval, Calculation):
|
raise ValueError(
|
||||||
continue
|
_('which "{}" must be a list of list' "").format(lval)
|
||||||
if not isinstance(lval, list):
|
)
|
||||||
raise ValueError(
|
for val in lval:
|
||||||
_('which "{}" must be a list of list' "").format(lval)
|
|
||||||
)
|
|
||||||
for val in lval:
|
|
||||||
try:
|
|
||||||
do_validation(val, err_index)
|
do_validation(val, err_index)
|
||||||
_is_not_unique(val, lval)
|
_is_not_unique(lval)
|
||||||
except ValueError as err:
|
elif not isinstance(value, list):
|
||||||
self.validate_parse_error(val, err_index, err, subconfig)
|
raise ValueError(_("which must be a list"))
|
||||||
ret = False
|
else:
|
||||||
elif not isinstance(value, list):
|
# FIXME suboptimal, not several time for whole=True!
|
||||||
msg = ValueError(_("it must be a list"))
|
for err_index, val in enumerate(value):
|
||||||
self.validate_parse_error(value, None, msg, subconfig)
|
|
||||||
ret = False
|
|
||||||
else:
|
|
||||||
# FIXME suboptimal, not several time for whole=True!
|
|
||||||
for err_index, val in enumerate(value):
|
|
||||||
try:
|
|
||||||
do_validation(
|
do_validation(
|
||||||
val,
|
val,
|
||||||
err_index,
|
err_index,
|
||||||
)
|
)
|
||||||
_is_not_unique(val, value)
|
_is_not_unique(value)
|
||||||
except ValueError as err:
|
except ValueError as err:
|
||||||
self.validate_parse_error(val, err_index, err, subconfig)
|
if (
|
||||||
ret = False
|
not subconfig
|
||||||
# return False
|
or "demoting_error_warning" not in subconfig.config_bag.properties
|
||||||
return ret
|
):
|
||||||
|
raise ValueOptionError(
|
||||||
def validate_parse_error(self, val, index, err, subconfig):
|
subconfig, val, _(self.get_type()), self, str(err), err_index
|
||||||
if (
|
) from err
|
||||||
not subconfig
|
warnings.warn_explicit(
|
||||||
or "demoting_error_warning" not in subconfig.config_bag.properties
|
ValueErrorWarning(
|
||||||
):
|
subconfig, val, _(self.get_type()), self, str(err), err_index
|
||||||
raise ValueOptionError(
|
),
|
||||||
subconfig=subconfig,
|
ValueErrorWarning,
|
||||||
val=val,
|
self.__class__.__name__,
|
||||||
display_type=_(self.get_type()),
|
0,
|
||||||
opt=self,
|
)
|
||||||
err_msg=str(err),
|
return False
|
||||||
index=index,
|
return True
|
||||||
) from err
|
|
||||||
warnings.warn_explicit(
|
|
||||||
ValueErrorWarning(
|
|
||||||
subconfig=subconfig,
|
|
||||||
val=val,
|
|
||||||
display_type=_(self.get_type()),
|
|
||||||
opt=self,
|
|
||||||
err_msg=str(err),
|
|
||||||
index=index,
|
|
||||||
),
|
|
||||||
ValueErrorWarning,
|
|
||||||
self.__class__.__name__,
|
|
||||||
0,
|
|
||||||
)
|
|
||||||
|
|
||||||
def validate_with_option(
|
def validate_with_option(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2014-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2014-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -29,7 +29,7 @@ from ..setting import ConfigBag, groups, undefined, owners, Undefined
|
||||||
from .baseoption import BaseOption
|
from .baseoption import BaseOption
|
||||||
|
|
||||||
# from .syndynoption import SubDynOptionDescription, SynDynOptionDescription
|
# from .syndynoption import SubDynOptionDescription, SynDynOptionDescription
|
||||||
from ..error import ConfigError, ConflictError, AttributeOptionError, PropertiesOptionError
|
from ..error import ConfigError, ConflictError
|
||||||
|
|
||||||
|
|
||||||
class CacheOptionDescription(BaseOption):
|
class CacheOptionDescription(BaseOption):
|
||||||
|
|
@ -106,24 +106,7 @@ class CacheOptionDescription(BaseOption):
|
||||||
if "force_store_value" in properties:
|
if "force_store_value" in properties:
|
||||||
force_store_values.append(option)
|
force_store_values.append(option)
|
||||||
if option.impl_is_readonly():
|
if option.impl_is_readonly():
|
||||||
previous_path = option.impl_getpath()
|
raise ConflictError(_("duplicate option: {0}").format(option))
|
||||||
if "." in previous_path:
|
|
||||||
previous_path = _('"{0}" option description').format(
|
|
||||||
previous_path.rsplit(".", 1)[0]
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
previous_path = _("root option description")
|
|
||||||
if currpath:
|
|
||||||
current_path = _('"{0}" option description').format(
|
|
||||||
".".join(currpath)
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
current_path = _("root option description")
|
|
||||||
raise ConflictError(
|
|
||||||
_('option "{0}" is include in {1} but is also in {2}').format(
|
|
||||||
option.impl_get_display_name(None), current_path, previous_path
|
|
||||||
)
|
|
||||||
)
|
|
||||||
if not self.impl_is_readonly() and display_name:
|
if not self.impl_is_readonly() and display_name:
|
||||||
option._display_name_function = (
|
option._display_name_function = (
|
||||||
display_name # pylint: disable=protected-access
|
display_name # pylint: disable=protected-access
|
||||||
|
|
@ -164,39 +147,34 @@ class CacheOptionDescription(BaseOption):
|
||||||
parent,
|
parent,
|
||||||
allow_dynoption=True,
|
allow_dynoption=True,
|
||||||
)
|
)
|
||||||
try:
|
if doption.impl_is_dynoptiondescription():
|
||||||
if doption.impl_is_dynoptiondescription():
|
new_parents.extend(
|
||||||
new_parents.extend(
|
parent.dyn_to_subconfig(
|
||||||
parent.dyn_to_subconfig(
|
doption,
|
||||||
doption,
|
True,
|
||||||
True,
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
else:
|
)
|
||||||
new_parents.append(
|
else:
|
||||||
parent.get_child(
|
new_parents.append(
|
||||||
doption,
|
parent.get_child(
|
||||||
None,
|
doption,
|
||||||
name=name,
|
None,
|
||||||
validate_properties=True,
|
True,
|
||||||
)
|
name=name,
|
||||||
)
|
)
|
||||||
except PropertiesOptionError:
|
)
|
||||||
continue
|
|
||||||
parents = new_parents
|
parents = new_parents
|
||||||
subconfigs = new_parents
|
subconfigs = new_parents
|
||||||
else:
|
else:
|
||||||
try:
|
subconfigs = [
|
||||||
subconfigs = [
|
context.get_sub_config(
|
||||||
context.get_sub_config(
|
config_bag,
|
||||||
config_bag,
|
option.impl_getpath(),
|
||||||
option.impl_getpath(),
|
None,
|
||||||
None,
|
properties=None,
|
||||||
validate_properties=True,
|
validate_properties=False,
|
||||||
)
|
)
|
||||||
]
|
]
|
||||||
except PropertiesOptionError:
|
|
||||||
continue
|
|
||||||
|
|
||||||
if option.impl_is_follower():
|
if option.impl_is_follower():
|
||||||
for follower_subconfig in subconfigs:
|
for follower_subconfig in subconfigs:
|
||||||
|
|
@ -211,14 +189,32 @@ class CacheOptionDescription(BaseOption):
|
||||||
idx_follower_subconfig = parent.get_child(
|
idx_follower_subconfig = parent.get_child(
|
||||||
follower_subconfig.option,
|
follower_subconfig.option,
|
||||||
index,
|
index,
|
||||||
validate_properties=True,
|
validate_properties=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
value = values.get_value(idx_follower_subconfig)[0]
|
||||||
|
if value is None:
|
||||||
|
continue
|
||||||
|
values.set_storage_value(
|
||||||
|
follower_subconfig.path,
|
||||||
|
index,
|
||||||
|
value,
|
||||||
|
owners.forced,
|
||||||
)
|
)
|
||||||
values.set_force_store_value(idx_follower_subconfig)
|
|
||||||
else:
|
else:
|
||||||
for subconfig in subconfigs:
|
for subconfig in subconfigs:
|
||||||
|
subconfig.properties = frozenset()
|
||||||
|
value = values.get_value(subconfig)[0]
|
||||||
|
if value is None:
|
||||||
|
continue
|
||||||
if values.hasvalue(subconfig.path):
|
if values.hasvalue(subconfig.path):
|
||||||
continue
|
continue
|
||||||
values.set_force_store_value(subconfig)
|
values.set_storage_value(
|
||||||
|
subconfig.path,
|
||||||
|
None,
|
||||||
|
value,
|
||||||
|
owners.forced,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class OptionDescriptionWalk(CacheOptionDescription):
|
class OptionDescriptionWalk(CacheOptionDescription):
|
||||||
|
|
@ -236,20 +232,19 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||||
|
|
||||||
def get_child_not_dynamic(
|
def get_child_not_dynamic(
|
||||||
self,
|
self,
|
||||||
name: str,
|
name,
|
||||||
allow_dynoption: bool,
|
allow_dynoption,
|
||||||
parent: "SubConfig",
|
|
||||||
):
|
):
|
||||||
if name in self._children[0]: # pylint: disable=no-member
|
if name in self._children[0]: # pylint: disable=no-member
|
||||||
option = self._children[1][
|
option = self._children[1][
|
||||||
self._children[0].index(name)
|
self._children[0].index(name)
|
||||||
] # pylint: disable=no-member
|
] # pylint: disable=no-member
|
||||||
if option.impl_is_dynoptiondescription() and not allow_dynoption:
|
if option.impl_is_dynoptiondescription() and not allow_dynoption:
|
||||||
if parent.path:
|
raise AttributeError(
|
||||||
path = parent.path + "." + name
|
_(
|
||||||
else:
|
'unknown option "{0}" in root optiondescription (it\'s a dynamic option)'
|
||||||
path = name
|
).format(name)
|
||||||
raise AttributeOptionError(path, "option-dynamic")
|
)
|
||||||
return option
|
return option
|
||||||
|
|
||||||
def get_child(
|
def get_child(
|
||||||
|
|
@ -266,7 +261,6 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||||
option = self.get_child_not_dynamic(
|
option = self.get_child_not_dynamic(
|
||||||
name,
|
name,
|
||||||
allow_dynoption,
|
allow_dynoption,
|
||||||
parent,
|
|
||||||
)
|
)
|
||||||
if option:
|
if option:
|
||||||
return option
|
return option
|
||||||
|
|
@ -280,16 +274,45 @@ class OptionDescriptionWalk(CacheOptionDescription):
|
||||||
if not with_identifier:
|
if not with_identifier:
|
||||||
return child
|
return child
|
||||||
return identifier, child
|
return identifier, child
|
||||||
if parent.path is None:
|
if self.impl_get_group_type() == groups.root: # pylint: disable=no-member
|
||||||
path = name
|
raise AttributeError(
|
||||||
else:
|
_('unknown option "{0}" in root optiondescription').format(name)
|
||||||
path = parent.path + "." + name
|
)
|
||||||
raise AttributeOptionError(path, "option-not-found")
|
raise AttributeError(
|
||||||
|
_('unknown option "{0}" in optiondescription {1}').format(
|
||||||
|
name, self.impl_get_display_name(parent, with_quote=True)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
def get_children(self) -> List[BaseOption]:
|
def get_children(self) -> List[BaseOption]:
|
||||||
"""get children"""
|
"""get children"""
|
||||||
return self._children[1]
|
return self._children[1]
|
||||||
|
|
||||||
|
def get_children_recursively(
|
||||||
|
self,
|
||||||
|
bytype: Optional[BaseOption],
|
||||||
|
byname: Optional[str],
|
||||||
|
config_bag: ConfigBag,
|
||||||
|
self_opt: BaseOption = None,
|
||||||
|
*,
|
||||||
|
option_identifiers: Optional[list] = None,
|
||||||
|
) -> Iterator[Union[BaseOption]]:
|
||||||
|
"""get children recursively"""
|
||||||
|
if self_opt is None:
|
||||||
|
self_opt = self
|
||||||
|
for option in self_opt.get_children():
|
||||||
|
if option.impl_is_optiondescription():
|
||||||
|
for subopt in option.get_children_recursively(
|
||||||
|
bytype,
|
||||||
|
byname,
|
||||||
|
config_bag,
|
||||||
|
):
|
||||||
|
yield subopt
|
||||||
|
elif (byname is None or option.impl_getname() == byname) and (
|
||||||
|
bytype is None or isinstance(option, bytype)
|
||||||
|
):
|
||||||
|
yield option
|
||||||
|
|
||||||
|
|
||||||
class OptionDescription(OptionDescriptionWalk):
|
class OptionDescription(OptionDescriptionWalk):
|
||||||
"""Config's schema (organisation, group) and container of Options
|
"""Config's schema (organisation, group) and container of Options
|
||||||
|
|
@ -322,38 +345,35 @@ class OptionDescription(OptionDescriptionWalk):
|
||||||
properties=properties,
|
properties=properties,
|
||||||
)
|
)
|
||||||
child_names = []
|
child_names = []
|
||||||
fix_child_names = []
|
if __debug__:
|
||||||
dynopts = []
|
dynopt_names = []
|
||||||
for child in children:
|
for child in children:
|
||||||
name = child.impl_getname()
|
name = child.impl_getname()
|
||||||
child_names.append(name)
|
child_names.append(name)
|
||||||
if child.impl_is_dynoptiondescription():
|
if __debug__ and child.impl_is_dynoptiondescription():
|
||||||
dynopts.append(child)
|
dynopt_names.append(name)
|
||||||
else:
|
|
||||||
fix_child_names.append(name)
|
|
||||||
|
|
||||||
# before sorting
|
# before sorting
|
||||||
children_ = (tuple(child_names), tuple(children))
|
children_ = (tuple(child_names), tuple(children))
|
||||||
|
|
||||||
# better performance like this
|
if __debug__:
|
||||||
fix_child_names.sort()
|
# better performance like this
|
||||||
old = None
|
child_names.sort()
|
||||||
for child_name in fix_child_names:
|
old = None
|
||||||
if child_name == old:
|
for child in child_names:
|
||||||
raise ConflictError(
|
if child == old:
|
||||||
_('the option name "{0}" is duplicate in "{1}"').format(
|
raise ConflictError(
|
||||||
child_name, self.impl_get_display_name(None)
|
_("duplicate option name: " '"{0}"').format(child)
|
||||||
)
|
)
|
||||||
)
|
if dynopt_names:
|
||||||
old = child_name
|
for dynopt in dynopt_names:
|
||||||
for dynopt in dynopts:
|
if child != dynopt and child.startswith(dynopt):
|
||||||
if dynopt.could_conflict:
|
raise ConflictError(
|
||||||
continue
|
_(
|
||||||
for child in children:
|
'the option\'s name "{0}" start as the dynoptiondescription\'s name "{1}"'
|
||||||
if child != dynopt and dynopt.name_could_conflict(dynopt, child):
|
).format(child, dynopt)
|
||||||
dynopt.could_conflict.append(weakref.ref(child))
|
)
|
||||||
child.could_conflict.append(weakref.ref(dynopt))
|
old = child
|
||||||
break
|
|
||||||
self._children = children_
|
self._children = children_
|
||||||
# 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 = None
|
self._group_type = None
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -31,8 +31,6 @@ class PasswordOption(StrOption):
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "password"
|
_type = "password"
|
||||||
_t_type = _("password")
|
|
||||||
_do_not_display_value_in_error = True
|
|
||||||
|
|
||||||
def __init__(self, *args, min_len=None, max_len=None, forbidden_char=[], **kwargs):
|
def __init__(self, *args, min_len=None, max_len=None, forbidden_char=[], **kwargs):
|
||||||
extra = {}
|
extra = {}
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2023-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2023-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -37,7 +37,6 @@ class PermissionsOption(IntOption):
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
perm_re = re.compile(r"^[0-7]{3,4}$")
|
perm_re = re.compile(r"^[0-7]{3,4}$")
|
||||||
_type = "unix file permissions"
|
_type = "unix file permissions"
|
||||||
_t_type = _("unix file permissions")
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -20,6 +20,8 @@
|
||||||
# ____________________________________________________________
|
# ____________________________________________________________
|
||||||
"""PortOption
|
"""PortOption
|
||||||
"""
|
"""
|
||||||
|
import re
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from .stroption import StrOption
|
from .stroption import StrOption
|
||||||
|
|
||||||
|
|
@ -36,8 +38,8 @@ class PortOption(StrOption):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
|
port_re = re.compile(r"^[0-9]*$")
|
||||||
_type = "port"
|
_type = "port"
|
||||||
_t_type = _("port")
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|
@ -48,21 +50,15 @@ class PortOption(StrOption):
|
||||||
allow_registred: bool = True,
|
allow_registred: bool = True,
|
||||||
allow_protocol: bool = False,
|
allow_protocol: bool = False,
|
||||||
allow_private: bool = False,
|
allow_private: bool = False,
|
||||||
_extra: dict = None,
|
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> None:
|
) -> None:
|
||||||
if _extra is None:
|
|
||||||
extra = {}
|
extra = {
|
||||||
else:
|
"_allow_range": allow_range,
|
||||||
extra = _extra
|
"_allow_protocol": allow_protocol,
|
||||||
extra["allow_range"] = allow_range
|
"_min_value": None,
|
||||||
extra["allow_protocol"] = allow_protocol
|
"_max_value": None,
|
||||||
extra["allow_zero"] = allow_zero
|
}
|
||||||
extra["allow_wellknown"] = allow_wellknown
|
|
||||||
extra["allow_registred"] = allow_registred
|
|
||||||
extra["allow_private"] = allow_private
|
|
||||||
extra["_min_value"] = None
|
|
||||||
extra["_max_value"] = None
|
|
||||||
ports_min = [0, 1, 1024, 49152]
|
ports_min = [0, 1, 1024, 49152]
|
||||||
ports_max = [0, 1023, 49151, 65535]
|
ports_max = [0, 1023, 49151, 65535]
|
||||||
is_finally = False
|
is_finally = False
|
||||||
|
|
@ -86,11 +82,11 @@ class PortOption(StrOption):
|
||||||
|
|
||||||
def validate(self, value: str) -> None:
|
def validate(self, value: str) -> None:
|
||||||
super().validate(value)
|
super().validate(value)
|
||||||
if self.impl_get_extra("allow_protocol") and (
|
if self.impl_get_extra("_allow_protocol") and (
|
||||||
value.startswith("tcp:") or value.startswith("udp:")
|
value.startswith("tcp:") or value.startswith("udp:")
|
||||||
):
|
):
|
||||||
value = [value[4:]]
|
value = [value[4:]]
|
||||||
elif self.impl_get_extra("allow_range") and ":" in str(value):
|
elif self.impl_get_extra("_allow_range") and ":" in str(value):
|
||||||
value = value.split(":")
|
value = value.split(":")
|
||||||
if len(value) != 2:
|
if len(value) != 2:
|
||||||
raise ValueError(_("range must have two values only"))
|
raise ValueError(_("range must have two values only"))
|
||||||
|
|
@ -102,11 +98,11 @@ class PortOption(StrOption):
|
||||||
value = [value]
|
value = [value]
|
||||||
|
|
||||||
for val in value:
|
for val in value:
|
||||||
if not val.isdecimal():
|
if not self.port_re.search(val):
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
def second_level_validation(self, value: str, warnings_only: bool) -> None:
|
def second_level_validation(self, value: str, warnings_only: bool) -> None:
|
||||||
if self.impl_get_extra("allow_protocol") and (
|
if self.impl_get_extra("_allow_protocol") and (
|
||||||
value.startswith("tcp:") or value.startswith("udp:")
|
value.startswith("tcp:") or value.startswith("udp:")
|
||||||
):
|
):
|
||||||
value = [value[4:]]
|
value = [value[4:]]
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -31,7 +31,6 @@ class StrOption(Option):
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "string"
|
_type = "string"
|
||||||
_t_type = _("string")
|
|
||||||
|
|
||||||
def validate(
|
def validate(
|
||||||
self,
|
self,
|
||||||
|
|
@ -39,7 +38,7 @@ class StrOption(Option):
|
||||||
) -> None:
|
) -> None:
|
||||||
"""validation"""
|
"""validation"""
|
||||||
if not isinstance(value, str):
|
if not isinstance(value, str):
|
||||||
raise ValueError(_("it's not a string"))
|
raise ValueError()
|
||||||
|
|
||||||
|
|
||||||
class RegexpOption(StrOption):
|
class RegexpOption(StrOption):
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
"""
|
"""
|
||||||
from typing import Any, Optional, Dict
|
from typing import Any, Optional, Dict
|
||||||
from .baseoption import BaseOption, valid_name
|
from .baseoption import BaseOption, valid_name
|
||||||
|
from ..error import ConfigError
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -54,7 +55,7 @@ class SymLinkOption(BaseOption):
|
||||||
self._name = name
|
self._name = name
|
||||||
self._opt = opt
|
self._opt = opt
|
||||||
self._leadership = None
|
self._leadership = None
|
||||||
opt._add_dependency(self, "symlink")
|
opt._add_dependency(self)
|
||||||
|
|
||||||
def __getattr__(
|
def __getattr__(
|
||||||
self,
|
self,
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -37,7 +37,6 @@ class URLOption(StrOption):
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
|
path_re = re.compile(r"^[A-Za-z0-9\-\._~:/\?#\[\]@!%\$&\'\(\)\*\+,;=]+$")
|
||||||
_type = "URL"
|
_type = "URL"
|
||||||
_t_type = _("URL")
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
|
|
@ -55,25 +54,24 @@ class URLOption(StrOption):
|
||||||
**kwargs,
|
**kwargs,
|
||||||
) -> None:
|
) -> None:
|
||||||
# pylint: disable=too-many-arguments,too-many-locals,redefined-builtin
|
# pylint: disable=too-many-arguments,too-many-locals,redefined-builtin
|
||||||
extra = {}
|
extra = {
|
||||||
extra["_domainname"] = DomainnameOption(
|
"_domainname": DomainnameOption(
|
||||||
name,
|
name,
|
||||||
doc,
|
doc,
|
||||||
allow_ip=allow_ip,
|
allow_ip=allow_ip,
|
||||||
type=type,
|
type=type,
|
||||||
allow_without_dot=allow_without_dot,
|
allow_without_dot=allow_without_dot,
|
||||||
_extra=extra,
|
),
|
||||||
)
|
"_port": PortOption(
|
||||||
extra["_port"] = PortOption(
|
name,
|
||||||
name,
|
doc,
|
||||||
doc,
|
allow_range=allow_range,
|
||||||
allow_range=allow_range,
|
allow_zero=allow_zero,
|
||||||
allow_zero=allow_zero,
|
allow_wellknown=allow_wellknown,
|
||||||
allow_wellknown=allow_wellknown,
|
allow_registred=allow_registred,
|
||||||
allow_registred=allow_registred,
|
allow_private=allow_private,
|
||||||
allow_private=allow_private,
|
),
|
||||||
_extra=extra,
|
}
|
||||||
)
|
|
||||||
super().__init__(
|
super().__init__(
|
||||||
name,
|
name,
|
||||||
doc,
|
doc,
|
||||||
|
|
@ -112,18 +110,10 @@ class URLOption(StrOption):
|
||||||
domain, port, files = self._get_domain_port_files(value)
|
domain, port, files = self._get_domain_port_files(value)
|
||||||
# validate port
|
# validate port
|
||||||
portoption = self.impl_get_extra("_port")
|
portoption = self.impl_get_extra("_port")
|
||||||
try:
|
portoption.validate(port)
|
||||||
portoption.validate(port)
|
|
||||||
except ValueError as err:
|
|
||||||
msg = _('the port "{0}" is invalid: {1}').format(domain, err)
|
|
||||||
raise ValueError(msg) from err
|
|
||||||
# validate domainname
|
# validate domainname
|
||||||
domainnameoption = self.impl_get_extra("_domainname")
|
domainnameoption = self.impl_get_extra("_domainname")
|
||||||
try:
|
domainnameoption.validate(domain)
|
||||||
domainnameoption.validate(domain)
|
|
||||||
except ValueError as err:
|
|
||||||
msg = _('the domain "{0}" is invalid: {1}').format(domain, err)
|
|
||||||
raise ValueError(msg) from err
|
|
||||||
# validate files
|
# validate files
|
||||||
if files is not None and files != "" and not self.path_re.search(files):
|
if files is not None and files != "" and not self.path_re.search(files):
|
||||||
raise ValueError(_("must ends with a valid resource name"))
|
raise ValueError(_("must ends with a valid resource name"))
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
# Copyright (C) 2017-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2017-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -33,7 +33,6 @@ class UsernameOption(RegexpOption):
|
||||||
# regexp build with 'man 8 adduser' informations
|
# regexp build with 'man 8 adduser' informations
|
||||||
_regexp = re.compile(r"^[a-z_][a-z0-9_-]{0,30}[$a-z0-9_-]{0,1}$")
|
_regexp = re.compile(r"^[a-z_][a-z0-9_-]{0,30}[$a-z0-9_-]{0,1}$")
|
||||||
_type = "unix username"
|
_type = "unix username"
|
||||||
_t_type = _("unix username")
|
|
||||||
|
|
||||||
|
|
||||||
class GroupnameOption(UsernameOption):
|
class GroupnameOption(UsernameOption):
|
||||||
|
|
@ -41,4 +40,3 @@ class GroupnameOption(UsernameOption):
|
||||||
|
|
||||||
__slots__ = tuple()
|
__slots__ = tuple()
|
||||||
_type = "unix groupname"
|
_type = "unix groupname"
|
||||||
_t_type = _("unix groupname")
|
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"sets the options of the configuration objects Config object itself"
|
"sets the options of the configuration objects Config object itself"
|
||||||
# Copyright (C) 2012-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2012-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -94,7 +94,7 @@ EXPIRATION_TIME = 5
|
||||||
# demoting_error_warning
|
# demoting_error_warning
|
||||||
# all value errors are convert to warning (ValueErrorWarning)
|
# all value errors are convert to warning (ValueErrorWarning)
|
||||||
DEFAULT_PROPERTIES = frozenset(["cache", "validator", "warnings"])
|
DEFAULT_PROPERTIES = frozenset(["cache", "validator", "warnings"])
|
||||||
SPECIAL_PROPERTIES = {"frozen", "mandatory", "empty", "force_store_value", "validator"}
|
SPECIAL_PROPERTIES = {"frozen", "mandatory", "empty", "force_store_value"}
|
||||||
|
|
||||||
# Config can be in two defaut mode:
|
# Config can be in two defaut mode:
|
||||||
#
|
#
|
||||||
|
|
@ -143,36 +143,12 @@ RW_REMOVE = frozenset(
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
PROPERTIES_MAKE_SENSE = (
|
|
||||||
"cache"
|
|
||||||
"demoting_error_warning",
|
|
||||||
"disabled",
|
|
||||||
"empty",
|
|
||||||
"everything_frozen",
|
|
||||||
"expire",
|
|
||||||
"force_default_on_freeze",
|
|
||||||
"force_metaconfig_on_freeze",
|
|
||||||
"force_store_value",
|
|
||||||
"frozen",
|
|
||||||
"hidden",
|
|
||||||
"mandatory",
|
|
||||||
"notempty",
|
|
||||||
"notunique",
|
|
||||||
"novalidator",
|
|
||||||
"permissive",
|
|
||||||
"unique",
|
|
||||||
"validator",
|
|
||||||
"warnings",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
FORBIDDEN_SET_PROPERTIES = frozenset(["force_store_value"])
|
FORBIDDEN_SET_PROPERTIES = frozenset(["force_store_value"])
|
||||||
FORBIDDEN_SET_PERMISSIVES = frozenset(
|
FORBIDDEN_SET_PERMISSIVES = frozenset(
|
||||||
[
|
[
|
||||||
"force_default_on_freeze",
|
"force_default_on_freeze",
|
||||||
"force_metaconfig_on_freeze",
|
"force_metaconfig_on_freeze",
|
||||||
"force_store_value",
|
"force_store_value",
|
||||||
"validator",
|
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
ALLOWED_LEADER_PROPERTIES = {
|
ALLOWED_LEADER_PROPERTIES = {
|
||||||
|
|
@ -182,8 +158,6 @@ ALLOWED_LEADER_PROPERTIES = {
|
||||||
"unique",
|
"unique",
|
||||||
"force_store_value",
|
"force_store_value",
|
||||||
"mandatory",
|
"mandatory",
|
||||||
"validator",
|
|
||||||
"novalidator",
|
|
||||||
"force_default_on_freeze",
|
"force_default_on_freeze",
|
||||||
"force_metaconfig_on_freeze",
|
"force_metaconfig_on_freeze",
|
||||||
"frozen",
|
"frozen",
|
||||||
|
|
@ -499,7 +473,7 @@ class Settings:
|
||||||
and new_prop not in ALLOWED_LEADER_PROPERTIES
|
and new_prop not in ALLOWED_LEADER_PROPERTIES
|
||||||
):
|
):
|
||||||
raise LeadershipError(
|
raise LeadershipError(
|
||||||
subconfig, "leadership-wrong_property", prop=new_prop
|
_('leader cannot have "{new_prop}" property')
|
||||||
)
|
)
|
||||||
props.add(new_prop)
|
props.add(new_prop)
|
||||||
props -= self.getpermissives(subconfig)
|
props -= self.getpermissives(subconfig)
|
||||||
|
|
@ -587,15 +561,19 @@ class Settings:
|
||||||
not_allowed_properties = properties - ALLOWED_LEADER_PROPERTIES
|
not_allowed_properties = properties - ALLOWED_LEADER_PROPERTIES
|
||||||
if not_allowed_properties:
|
if not_allowed_properties:
|
||||||
raise LeadershipError(
|
raise LeadershipError(
|
||||||
subconfig,
|
_('leader cannot have "{0}" property').format(
|
||||||
"leadership-wrong_property",
|
display_list(not_allowed_properties)
|
||||||
prop=display_list(not_allowed_properties),
|
)
|
||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
"force_default_on_freeze" in properties
|
"force_default_on_freeze" in properties
|
||||||
or "force_metaconfig_on_freeze" in properties
|
or "force_metaconfig_on_freeze" in properties
|
||||||
) and "frozen" not in properties:
|
) and "frozen" not in properties:
|
||||||
raise LeadershipError(subconfig, "leadership-force_default_on_freeze")
|
raise LeadershipError(
|
||||||
|
_(
|
||||||
|
'a leader ({0}) cannot have "force_default_on_freeze" or "force_metaconfig_on_freeze" property without "frozen"'
|
||||||
|
).format(opt.impl_get_display_name())
|
||||||
|
)
|
||||||
self._properties.setdefault(subconfig.path, {})[subconfig.index] = properties
|
self._properties.setdefault(subconfig.path, {})[subconfig.index] = properties
|
||||||
# values too because of follower values could have a PropertiesOptionError has value
|
# values too because of follower values could have a PropertiesOptionError has value
|
||||||
subconfig.config_bag.context.reset_cache(subconfig)
|
subconfig.config_bag.context.reset_cache(subconfig)
|
||||||
|
|
@ -638,8 +616,7 @@ class Settings:
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
_("cannot add those permissives: {0}").format(
|
_("cannot add those permissives: {0}").format(
|
||||||
" ".join(forbidden_permissives)
|
" ".join(forbidden_permissives)
|
||||||
),
|
)
|
||||||
subconfig=subconfig,
|
|
||||||
)
|
)
|
||||||
self._permissives.setdefault(path, {})[index] = permissives
|
self._permissives.setdefault(path, {})[index] = permissives
|
||||||
if subconfig is not None:
|
if subconfig is not None:
|
||||||
|
|
|
||||||
|
|
@ -646,9 +646,9 @@ class TiramisuDict:
|
||||||
if self.remotable == "all" or childapi.has_dependency():
|
if self.remotable == "all" or childapi.has_dependency():
|
||||||
obj_form["remote"] = True
|
obj_form["remote"] = True
|
||||||
if childtype == "IPOption" and (
|
if childtype == "IPOption" and (
|
||||||
child.impl_get_extra("private_only")
|
child.impl_get_extra("_private_only")
|
||||||
or not child.impl_get_extra("allow_reserved")
|
or not child.impl_get_extra("_allow_reserved")
|
||||||
or child.impl_get_extra("cidr")
|
or child.impl_get_extra("_cidr")
|
||||||
):
|
):
|
||||||
obj_form["remote"] = True
|
obj_form["remote"] = True
|
||||||
if childtype == "DateOption":
|
if childtype == "DateOption":
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
"takes care of the option's values and multi values"
|
"takes care of the option's values and multi values"
|
||||||
# Copyright (C) 2013-2026 Team tiramisu (see AUTHORS for all contributors)
|
# Copyright (C) 2013-2024 Team tiramisu (see AUTHORS for all contributors)
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify it
|
# This program is free software: you can redistribute it and/or modify it
|
||||||
# under the terms of the GNU Lesser General Public License as published by the
|
# under the terms of the GNU Lesser General Public License as published by the
|
||||||
|
|
@ -110,64 +110,22 @@ class Values:
|
||||||
value, owner = self._values.get(subconfig.path, {}).get(
|
value, owner = self._values.get(subconfig.path, {}).get(
|
||||||
subconfig.index, default_value
|
subconfig.index, default_value
|
||||||
)
|
)
|
||||||
self_properties = subconfig.properties or tuple()
|
if owner == owners.default or (
|
||||||
if owner != owners.default and (
|
"frozen" in subconfig.properties
|
||||||
"frozen" in self_properties
|
|
||||||
and (
|
and (
|
||||||
"force_default_on_freeze" in self_properties
|
"force_default_on_freeze" in subconfig.properties
|
||||||
or self.check_force_to_metaconfig(subconfig)
|
or self.check_force_to_metaconfig(subconfig)
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
# the value is a default value
|
# the value is a default value
|
||||||
# get it
|
# get it
|
||||||
value = self.get_default_value(subconfig)
|
value = self.get_default_value(subconfig)
|
||||||
if owner == owners.default:
|
|
||||||
if(
|
|
||||||
"force_store_value" in subconfig.config_bag.properties
|
|
||||||
and "force_store_value" in self_properties
|
|
||||||
):
|
|
||||||
value = self.get_default_value(subconfig)
|
|
||||||
if value is not None:
|
|
||||||
owner = owners.forced
|
|
||||||
self._setvalue(
|
|
||||||
subconfig,
|
|
||||||
value,
|
|
||||||
owner,
|
|
||||||
)
|
|
||||||
else:
|
|
||||||
# the value is a default value
|
|
||||||
# get it
|
|
||||||
value = self.get_default_value(subconfig)
|
|
||||||
value, has_calculation = get_calculated_value(
|
value, has_calculation = get_calculated_value(
|
||||||
subconfig,
|
subconfig,
|
||||||
value,
|
value,
|
||||||
)
|
)
|
||||||
return value, has_calculation
|
return value, has_calculation
|
||||||
|
|
||||||
def set_force_store_value(self, subconfig):
|
|
||||||
value = self.get_default_value(subconfig)
|
|
||||||
if value is None:
|
|
||||||
return None
|
|
||||||
owner = owners.forced
|
|
||||||
self._setvalue(
|
|
||||||
subconfig,
|
|
||||||
value,
|
|
||||||
owner,
|
|
||||||
)
|
|
||||||
return value, owner
|
|
||||||
|
|
||||||
def get_default_owner(
|
|
||||||
self,
|
|
||||||
subconfig: "SubConfig",
|
|
||||||
) -> Any:
|
|
||||||
msubconfig = self._get_modified_parent(subconfig)
|
|
||||||
if msubconfig is not None:
|
|
||||||
# retrieved value from parent config
|
|
||||||
return msubconfig.config_bag.context.get_values().getowner(
|
|
||||||
msubconfig
|
|
||||||
)
|
|
||||||
return owners.default
|
|
||||||
|
|
||||||
def get_default_value(
|
def get_default_value(
|
||||||
self,
|
self,
|
||||||
subconfig: "SubConfig",
|
subconfig: "SubConfig",
|
||||||
|
|
@ -231,9 +189,10 @@ class Values:
|
||||||
if subconfig.config_bag.context.impl_type == "config":
|
if subconfig.config_bag.context.impl_type == "config":
|
||||||
return True
|
return True
|
||||||
# it's a not a config, force to metaconfig only in *explicitly* set
|
# it's a not a config, force to metaconfig only in *explicitly* set
|
||||||
return "force_metaconfig_on_freeze" in settings.get_personalize_properties(
|
return "force_metaconfig_on_freeze" in settings.get_stored_properties(
|
||||||
subconfig.path,
|
subconfig.path,
|
||||||
subconfig.index,
|
subconfig.index,
|
||||||
|
frozenset(),
|
||||||
)
|
)
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -268,8 +227,8 @@ class Values:
|
||||||
force_allow_empty_list: bool,
|
force_allow_empty_list: bool,
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""convenience method to know if an option is empty"""
|
"""convenience method to know if an option is empty"""
|
||||||
option = subconfig.option
|
|
||||||
index = subconfig.index
|
index = subconfig.index
|
||||||
|
option = subconfig.option
|
||||||
if index is None and option.impl_is_submulti():
|
if index is None and option.impl_is_submulti():
|
||||||
# index is not set
|
# index is not set
|
||||||
isempty = True
|
isempty = True
|
||||||
|
|
@ -277,16 +236,9 @@ class Values:
|
||||||
isempty = self._isempty_multi(val, force_allow_empty_list)
|
isempty = self._isempty_multi(val, force_allow_empty_list)
|
||||||
if isempty:
|
if isempty:
|
||||||
break
|
break
|
||||||
elif option.impl_is_submulti():
|
elif (
|
||||||
if index is None:
|
index is None or (index is not None and option.impl_is_submulti())
|
||||||
isempty = False
|
) and option.impl_is_multi():
|
||||||
for v in value:
|
|
||||||
if self._isempty_multi(v, force_allow_empty_list):
|
|
||||||
isempty = True
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
isempty = self._isempty_multi(value, force_allow_empty_list)
|
|
||||||
elif index is None and option.impl_is_multi():
|
|
||||||
# it's a single list
|
# it's a single list
|
||||||
isempty = self._isempty_multi(value, force_allow_empty_list)
|
isempty = self._isempty_multi(value, force_allow_empty_list)
|
||||||
else:
|
else:
|
||||||
|
|
@ -300,9 +252,9 @@ class Values:
|
||||||
) -> bool:
|
) -> bool:
|
||||||
if not isinstance(value, list):
|
if not isinstance(value, list):
|
||||||
return False
|
return False
|
||||||
if not force_allow_empty_list:
|
return (
|
||||||
return value == []
|
(not force_allow_empty_list and value == []) or None in value or "" in value
|
||||||
return None in value or "" in value
|
)
|
||||||
|
|
||||||
# ______________________________________________________________________
|
# ______________________________________________________________________
|
||||||
# set value
|
# set value
|
||||||
|
|
@ -313,10 +265,9 @@ class Values:
|
||||||
) -> None:
|
) -> None:
|
||||||
"""set value to option"""
|
"""set value to option"""
|
||||||
owner = self.get_context_owner()
|
owner = self.get_context_owner()
|
||||||
self_properties = subconfig.properties
|
|
||||||
setting_properties = subconfig.config_bag.properties
|
setting_properties = subconfig.config_bag.properties
|
||||||
ori_value = value
|
ori_value = value
|
||||||
if "validator" in setting_properties and "validator" in self_properties:
|
if "validator" in setting_properties:
|
||||||
value, has_calculation = self.setvalue_validation(
|
value, has_calculation = self.setvalue_validation(
|
||||||
subconfig,
|
subconfig,
|
||||||
value,
|
value,
|
||||||
|
|
@ -336,23 +287,14 @@ class Values:
|
||||||
):
|
):
|
||||||
leader = subconfig.option.impl_get_leadership()
|
leader = subconfig.option.impl_get_leadership()
|
||||||
parent = subconfig.parent
|
parent = subconfig.parent
|
||||||
try:
|
parent._length = len(value)
|
||||||
if isinstance(value, Calculation):
|
leader.follower_force_store_value(
|
||||||
value, has_calculation = get_calculated_value(
|
value,
|
||||||
subconfig,
|
parent,
|
||||||
value,
|
owners.forced,
|
||||||
)
|
)
|
||||||
# parent._length = len(value)
|
|
||||||
leader.follower_force_store_value(
|
|
||||||
value,
|
|
||||||
parent,
|
|
||||||
owners.forced,
|
|
||||||
)
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
validator = (
|
validator = (
|
||||||
"validator" in setting_properties
|
"validator" in setting_properties
|
||||||
and "validator" in self_properties
|
|
||||||
and "demoting_error_warning" not in setting_properties
|
and "demoting_error_warning" not in setting_properties
|
||||||
)
|
)
|
||||||
if validator and not has_calculation:
|
if validator and not has_calculation:
|
||||||
|
|
@ -362,11 +304,7 @@ class Values:
|
||||||
value,
|
value,
|
||||||
validated=validator,
|
validated=validator,
|
||||||
)
|
)
|
||||||
elif (
|
elif "validator" in setting_properties and has_calculation:
|
||||||
"validator" in setting_properties
|
|
||||||
and "validator" in self_properties
|
|
||||||
and has_calculation
|
|
||||||
):
|
|
||||||
cache = subconfig.config_bag.context.get_values_cache()
|
cache = subconfig.config_bag.context.get_values_cache()
|
||||||
cache.delcache(subconfig.path)
|
cache.delcache(subconfig.path)
|
||||||
|
|
||||||
|
|
@ -452,15 +390,12 @@ class Values:
|
||||||
woption(),
|
woption(),
|
||||||
true_path=subconfig.path,
|
true_path=subconfig.path,
|
||||||
validate_properties=False,
|
validate_properties=False,
|
||||||
check_dynamic_without_identifiers=False,
|
|
||||||
)
|
)
|
||||||
if not isinstance(options, list):
|
if not isinstance(options, list):
|
||||||
options = [options]
|
options = [options]
|
||||||
for option in options:
|
for option in options:
|
||||||
parent = option.parent
|
parent = option.parent
|
||||||
for identifier in identifier_values:
|
for identifier in identifier_values:
|
||||||
if identifier is None:
|
|
||||||
continue
|
|
||||||
name = option.option.impl_getname(identifier)
|
name = option.option.impl_getname(identifier)
|
||||||
opt_subconfig = parent.get_child(
|
opt_subconfig = parent.get_child(
|
||||||
option.option,
|
option.option,
|
||||||
|
|
@ -493,28 +428,36 @@ class Values:
|
||||||
If not found, return None
|
If not found, return None
|
||||||
For follower option, return the Config where leader is modified
|
For follower option, return the Config where leader is modified
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
def build_option_bag(subconfig, parent):
|
||||||
|
doption_bag = subconfig.copy()
|
||||||
|
config_bag = subconfig.config_bag.copy()
|
||||||
|
config_bag.context = parent
|
||||||
|
config_bag.unrestraint()
|
||||||
|
doption_bag.config_bag = config_bag
|
||||||
|
return doption_bag
|
||||||
|
|
||||||
for parent in subconfig.config_bag.context.get_parents():
|
for parent in subconfig.config_bag.context.get_parents():
|
||||||
parent_subconfig = subconfig.change_context(parent)
|
doption_bag = build_option_bag(subconfig, parent)
|
||||||
parent_subconfig.config_bag.unrestraint()
|
|
||||||
parent_subconfig.properties = subconfig.properties
|
|
||||||
if "force_metaconfig_on_freeze" in subconfig.properties:
|
if "force_metaconfig_on_freeze" in subconfig.properties:
|
||||||
# remove force_metaconfig_on_freeze only if option in metaconfig
|
# remove force_metaconfig_on_freeze only if option in metaconfig
|
||||||
# hasn't force_metaconfig_on_freeze properties
|
# hasn't force_metaconfig_on_freeze properties
|
||||||
ori_properties = parent_subconfig.properties
|
ori_properties = doption_bag.properties
|
||||||
settings = parent_subconfig.config_bag.context.get_settings()
|
settings = doption_bag.config_bag.context.get_settings()
|
||||||
parent_subconfig.properties = settings.getproperties(parent_subconfig)
|
doption_bag.properties = settings.getproperties(doption_bag)
|
||||||
if not self.check_force_to_metaconfig(parent_subconfig):
|
if not self.check_force_to_metaconfig(doption_bag):
|
||||||
parent_subconfig.properties = ori_properties - {
|
doption_bag.properties = ori_properties - {
|
||||||
"force_metaconfig_on_freeze"
|
"force_metaconfig_on_freeze"
|
||||||
}
|
}
|
||||||
else:
|
else:
|
||||||
parent_subconfig.properties = ori_properties
|
doption_bag.properties = ori_properties
|
||||||
parent_owner = parent.get_values().getowner(
|
parent_owner = parent.get_values().getowner(
|
||||||
parent_subconfig,
|
doption_bag,
|
||||||
|
parent,
|
||||||
only_default=True,
|
only_default=True,
|
||||||
)
|
)
|
||||||
if parent_owner != owners.default:
|
if parent_owner != owners.default:
|
||||||
return parent_subconfig
|
return doption_bag
|
||||||
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
@ -568,18 +511,14 @@ class Values:
|
||||||
was present
|
was present
|
||||||
:returns: a `setting.owners.Owner` object
|
:returns: a `setting.owners.Owner` object
|
||||||
"""
|
"""
|
||||||
self_properties = subconfig.properties
|
# context = subconfig.config_bag.context
|
||||||
|
# settings = context.get_settings()
|
||||||
|
# settings.validate_properties(subconfig)
|
||||||
if (
|
if (
|
||||||
"frozen" in self_properties
|
"frozen" in subconfig.properties
|
||||||
and "force_default_on_freeze" in self_properties
|
and "force_default_on_freeze" in subconfig.properties
|
||||||
):
|
):
|
||||||
return owners.default
|
return owners.default
|
||||||
setting_properties = subconfig.config_bag.properties
|
|
||||||
if (
|
|
||||||
"force_store_value" in setting_properties
|
|
||||||
and "force_store_value" in self_properties
|
|
||||||
):
|
|
||||||
self.set_force_store_value(subconfig)
|
|
||||||
if only_default:
|
if only_default:
|
||||||
if self.hasvalue(
|
if self.hasvalue(
|
||||||
subconfig.path,
|
subconfig.path,
|
||||||
|
|
@ -595,18 +534,19 @@ class Values:
|
||||||
)[1]
|
)[1]
|
||||||
if validate_meta is not False and (
|
if validate_meta is not False and (
|
||||||
owner is owners.default
|
owner is owners.default
|
||||||
or "frozen" in self_properties
|
or "frozen" in subconfig.properties
|
||||||
and "force_metaconfig_on_freeze" in self_properties
|
and "force_metaconfig_on_freeze" in subconfig.properties
|
||||||
):
|
):
|
||||||
msubconfig = self._get_modified_parent(subconfig)
|
msubconfig = self._get_modified_parent(subconfig)
|
||||||
if msubconfig is not None:
|
if msubconfig is not None:
|
||||||
values = msubconfig.config_bag.context.get_values()
|
values = msubconfig.config_bag.context.get_values()
|
||||||
owner = values.getowner(
|
owner = values.getowner(
|
||||||
msubconfig,
|
msubconfig,
|
||||||
|
parent,
|
||||||
only_default=only_default,
|
only_default=only_default,
|
||||||
)
|
)
|
||||||
elif "force_metaconfig_on_freeze" in self_properties:
|
elif "force_metaconfig_on_freeze" in subconfig.properties:
|
||||||
owner = owners.default
|
return owners.default
|
||||||
return owner
|
return owner
|
||||||
|
|
||||||
def set_owner(
|
def set_owner(
|
||||||
|
|
@ -630,8 +570,7 @@ class Values:
|
||||||
raise ConfigError(
|
raise ConfigError(
|
||||||
_(
|
_(
|
||||||
'"{0}" is a default value, so we cannot change owner to "{1}"'
|
'"{0}" is a default value, so we cannot change owner to "{1}"'
|
||||||
).format(subconfig.path, owner),
|
).format(subconfig.path, owner)
|
||||||
subconfig=subconfig,
|
|
||||||
)
|
)
|
||||||
subconfig.config_bag.context.get_settings().validate_frozen(subconfig)
|
subconfig.config_bag.context.get_settings().validate_frozen(subconfig)
|
||||||
self._values[subconfig.path][subconfig.index][1] = owner
|
self._values[subconfig.path][subconfig.index][1] = owner
|
||||||
|
|
@ -648,41 +587,43 @@ class Values:
|
||||||
"""reset value for an option"""
|
"""reset value for an option"""
|
||||||
config_bag = subconfig.config_bag
|
config_bag = subconfig.config_bag
|
||||||
hasvalue = self.hasvalue(subconfig.path)
|
hasvalue = self.hasvalue(subconfig.path)
|
||||||
self_properties = subconfig.properties
|
|
||||||
context = config_bag.context
|
context = config_bag.context
|
||||||
setting_properties = config_bag.properties
|
setting_properties = config_bag.properties
|
||||||
if (
|
if validate:
|
||||||
validate
|
if hasvalue and "validator" in setting_properties:
|
||||||
and hasvalue
|
fake_context = context.gen_fake_context()
|
||||||
and "validator" in setting_properties
|
fake_config_bag = config_bag.copy()
|
||||||
and "validator" in self_properties
|
fake_config_bag.remove_validation()
|
||||||
):
|
fake_config_bag.context = fake_context
|
||||||
fake_context = context.gen_fake_context()
|
fake_subconfig = fake_context.get_sub_config(
|
||||||
fake_config_bag = config_bag.copy()
|
fake_config_bag,
|
||||||
fake_config_bag.remove_validation()
|
subconfig.path,
|
||||||
fake_config_bag.context = fake_context
|
subconfig.index,
|
||||||
fake_subconfig = fake_context.get_sub_config(
|
validate_properties=False,
|
||||||
fake_config_bag,
|
)
|
||||||
subconfig.path,
|
fake_values = fake_context.get_values()
|
||||||
subconfig.index,
|
fake_values.reset(fake_subconfig)
|
||||||
validate_properties=False,
|
fake_subconfig.config_bag.properties = setting_properties
|
||||||
)
|
value = fake_values.get_default_value(fake_subconfig)
|
||||||
fake_values = fake_context.get_values()
|
fake_values.setvalue_validation(
|
||||||
fake_values.reset(fake_subconfig)
|
fake_subconfig,
|
||||||
fake_subconfig.config_bag.properties = setting_properties
|
value,
|
||||||
value = fake_values.get_default_value(fake_subconfig)
|
)
|
||||||
fake_values.setvalue_validation(
|
# if hasvalue:
|
||||||
fake_subconfig,
|
|
||||||
value,
|
|
||||||
)
|
|
||||||
opt = subconfig.option
|
opt = subconfig.option
|
||||||
if opt.impl_is_leader():
|
if opt.impl_is_leader():
|
||||||
opt.impl_get_leadership().reset(subconfig.parent)
|
opt.impl_get_leadership().reset(subconfig.parent)
|
||||||
if (
|
if (
|
||||||
"force_store_value" in setting_properties
|
"force_store_value" in setting_properties
|
||||||
and "force_store_value" in self_properties
|
and "force_store_value" in subconfig.properties
|
||||||
):
|
):
|
||||||
self.set_force_store_value(subconfig)
|
value = self.get_default_value(subconfig)
|
||||||
|
|
||||||
|
self._setvalue(
|
||||||
|
subconfig,
|
||||||
|
value,
|
||||||
|
owners.forced,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
value = None
|
value = None
|
||||||
if subconfig.path in self._values:
|
if subconfig.path in self._values:
|
||||||
|
|
@ -721,11 +662,10 @@ class Values:
|
||||||
index=subconfig.index,
|
index=subconfig.index,
|
||||||
):
|
):
|
||||||
return
|
return
|
||||||
self_properties = subconfig.properties
|
|
||||||
config_bag = subconfig.config_bag
|
config_bag = subconfig.config_bag
|
||||||
context = config_bag.context
|
context = config_bag.context
|
||||||
setting_properties = config_bag.properties
|
setting_properties = config_bag.properties
|
||||||
if "validator" in setting_properties and "validator" in self_properties:
|
if "validator" in setting_properties:
|
||||||
fake_context = context.gen_fake_context()
|
fake_context = context.gen_fake_context()
|
||||||
fake_config_bag = config_bag.copy()
|
fake_config_bag = config_bag.copy()
|
||||||
fake_config_bag.remove_validation()
|
fake_config_bag.remove_validation()
|
||||||
|
|
@ -746,11 +686,17 @@ class Values:
|
||||||
)
|
)
|
||||||
if (
|
if (
|
||||||
"force_store_value" in setting_properties
|
"force_store_value" in setting_properties
|
||||||
and "force_store_value" in self_properties
|
and "force_store_value" in subconfig.properties
|
||||||
):
|
):
|
||||||
force_store_value = self.set_force_store_value(subconfig)
|
value = self.get_default_value(
|
||||||
if force_store_value:
|
subconfig,
|
||||||
value, owner = force_store_value
|
)
|
||||||
|
|
||||||
|
self._setvalue(
|
||||||
|
subconfig,
|
||||||
|
value,
|
||||||
|
owners.forced,
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
self.resetvalue_index(subconfig)
|
self.resetvalue_index(subconfig)
|
||||||
context.reset_cache(subconfig)
|
context.reset_cache(subconfig)
|
||||||
|
|
@ -792,8 +738,8 @@ class Values:
|
||||||
if index >= length:
|
if index >= length:
|
||||||
raise IndexError(
|
raise IndexError(
|
||||||
_(
|
_(
|
||||||
f"index {index} is greater than the length {length} "
|
"index {index} is greater than the length {length} "
|
||||||
f"for option {subconfig.option.impl_get_display_name(subconfig, with_quote=True)}"
|
"for option {subconfig.option.impl_get_display_name(with_quote=True)}"
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
current_value.pop(index)
|
current_value.pop(index)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue