todict for tiramisu 4

This commit is contained in:
egarette@silique.fr 2023-06-19 17:19:07 +02:00
parent 0a4e1445db
commit 50f0f67629
35 changed files with 361 additions and 226 deletions

View file

@ -1,7 +1,7 @@
Authors Authors
-------- --------
Emmanuel Garette <egarette@cadoles.com> lead developer Emmanuel Garette <egarette@silique.fr> lead developer
Gwenaël Rémond <gremond@cadoles.com> developer Gwenaël Rémond <gremond@cadoles.com> developer
Daniel Dehennin <daniel.dehennin@ac-dijon.fr> contributor Daniel Dehennin <daniel.dehennin@ac-dijon.fr> contributor

View file

@ -6,7 +6,7 @@ def get_description():
option1 = ChoiceOption('choice', "Choice description", ("hide", "show"), default='hide', properties=('mandatory',)) option1 = ChoiceOption('choice', "Choice description", ("hide", "show"), default='hide', properties=('mandatory',))
hidden_property = Calculation(calc_value, hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'), Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(option1, todict=True), kwargs={'condition': ParamOption(option1),
'expected': ParamValue('hide')})) 'expected': ParamValue('hide')}))
option2 = StrOption('unicode2', "Unicode 2", properties=(hidden_property,)) option2 = StrOption('unicode2', "Unicode 2", properties=(hidden_property,))
descr1 = OptionDescription("options", "Common configuration", [option1, option2]) descr1 = OptionDescription("options", "Common configuration", [option1, option2])

View file

@ -1 +1,3 @@
{"options.unicode": null} {
"options.unicode": null
}

View file

@ -1 +1,3 @@
{"options.unicode": "val"} {
"options.unicode": "val"
}

View file

@ -8,7 +8,7 @@ def get_description():
option2 = StrOption('unicode2', "Values 'test' must show 'Unicode follower 3'", multi=True) option2 = StrOption('unicode2', "Values 'test' must show 'Unicode follower 3'", multi=True)
hidden_property = Calculation(calc_value, hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'), Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(option2, todict=True), kwargs={'condition': ParamOption(option2),
'expected': ParamValue('test'), 'expected': ParamValue('test'),
'reverse_condition': ParamValue(True)})) 'reverse_condition': ParamValue(True)}))
option3 = StrOption('unicode3', "Unicode follower 3", properties=(hidden_property,), multi=True) option3 = StrOption('unicode3', "Unicode follower 3", properties=(hidden_property,), multi=True)

View file

@ -10,7 +10,7 @@ def get_description():
option3 = StrOption('unicode3', "Unicode follower 2", multi=True) option3 = StrOption('unicode3', "Unicode follower 2", multi=True)
hidden_property = Calculation(calc_value, hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'), Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(option, todict=True), kwargs={'condition': ParamOption(option),
'expected': ParamValue('test'), 'expected': ParamValue('test'),
'reverse_condition': ParamValue(True)})) 'reverse_condition': ParamValue(True)}))
descr1 = Leadership("unicode1", "Common configuration", descr1 = Leadership("unicode1", "Common configuration",

View file

@ -9,7 +9,7 @@ def get_description():
option2 = StrOption('unicode2', "Unicode follower 2", multi=True) option2 = StrOption('unicode2', "Unicode follower 2", multi=True)
disabled_property = Calculation(calc_value, disabled_property = Calculation(calc_value,
Params(ParamValue('disabled'), Params(ParamValue('disabled'),
kwargs={'condition': ParamOption(option, todict=True), kwargs={'condition': ParamOption(option),
'expected': ParamValue('test'), 'expected': ParamValue('test'),
'reverse_condition': ParamValue(True)})) 'reverse_condition': ParamValue(True)}))
option3 = StrOption('unicode3', "Unicode follower 3", properties=(disabled_property,), multi=True) option3 = StrOption('unicode3', "Unicode follower 3", properties=(disabled_property,), multi=True)

View file

@ -8,7 +8,7 @@ def get_description():
option2 = StrOption('unicode2', "Unicode follower 1", multi=True) option2 = StrOption('unicode2', "Unicode follower 1", multi=True)
hidden_property = Calculation(calc_value, hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'), Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(option1, todict=True), kwargs={'condition': ParamOption(option1),
'expected': ParamValue('test'), 'expected': ParamValue('test'),
'reverse_condition': ParamValue(True)})) 'reverse_condition': ParamValue(True)}))
option3 = StrOption('unicode3', "Unicode follower 2", multi=True, properties=(hidden_property,)) option3 = StrOption('unicode3', "Unicode follower 2", multi=True, properties=(hidden_property,))

View file

@ -8,7 +8,7 @@ def get_description():
option2 = StrOption('unicode2', "Unicode follower 1", multi=True) option2 = StrOption('unicode2', "Unicode follower 1", multi=True)
hidden_property = Calculation(calc_value, hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'), Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(option1, todict=True), kwargs={'condition': ParamOption(option1),
'expected': ParamValue('test'), 'expected': ParamValue('test'),
'reverse_condition': ParamValue(True)})) 'reverse_condition': ParamValue(True)}))
option3 = StrOption('unicode3', "Unicode follower 2", multi=True, properties=(hidden_property,)) option3 = StrOption('unicode3', "Unicode follower 2", multi=True, properties=(hidden_property,))

View file

@ -8,7 +8,7 @@ def get_description():
option2 = StrOption('unicode2', "Values 'test' must show 'Unicode follower 2'", multi=True) option2 = StrOption('unicode2', "Values 'test' must show 'Unicode follower 2'", multi=True)
hidden_property = Calculation(calc_value, hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'), Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(option2, todict=True), kwargs={'condition': ParamOption(option2),
'expected': ParamValue('test'), 'expected': ParamValue('test'),
'reverse_condition': ParamValue(True)})) 'reverse_condition': ParamValue(True)}))
option3 = StrOption('unicode3', "Unicode follower 2", multi=True, properties=(hidden_property,)) option3 = StrOption('unicode3', "Unicode follower 2", multi=True, properties=(hidden_property,))

View file

@ -9,7 +9,7 @@ def get_description():
option2 = StrOption('unicode2', "Unicode follower 2", multi=True) option2 = StrOption('unicode2', "Unicode follower 2", multi=True)
hidden_property = Calculation(calc_value, hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'), Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(option, todict=True), kwargs={'condition': ParamOption(option),
'expected': ParamValue('test'), 'expected': ParamValue('test'),
'reverse_condition': ParamValue(True)})) 'reverse_condition': ParamValue(True)}))
option3 = StrOption('unicode3', "Unicode follower 3", properties=(hidden_property,), multi=True) option3 = StrOption('unicode3', "Unicode follower 3", properties=(hidden_property,), multi=True)

View file

@ -1,4 +1,16 @@
{"options.unicode.unicode": ["val3", "val4"], {
"options.unicode.unicode1": ["super1", "super2"], "options.unicode.unicode": [
"options.unicode.unicode2": ["pas test", "test"], {
"options.unicode.unicode3": [null, "super"]} "options.unicode.unicode": "val3",
"options.unicode.unicode1": "super1",
"options.unicode.unicode2": "pas test",
"options.unicode.unicode3": null
},
{
"options.unicode.unicode": "val4",
"options.unicode.unicode1": "super2",
"options.unicode.unicode2": "test",
"options.unicode.unicode3": "super"
}
]
}

View file

@ -1,4 +1,16 @@
{"options.unicode.unicode": ["val1", "val2"], {
"options.unicode.unicode1": [null, null], "options.unicode.unicode": [
"options.unicode.unicode2": ["follower2", "follower2"], {
"options.unicode.unicode3": [null, null]} "options.unicode.unicode": "val1",
"options.unicode.unicode1": null,
"options.unicode.unicode2": "follower2",
"options.unicode.unicode3": null
},
{
"options.unicode.unicode": "val2",
"options.unicode.unicode1": null,
"options.unicode.unicode2": "follower2",
"options.unicode.unicode3": null
}
]
}

View file

@ -1,4 +1,10 @@
{"options.unicode.unicode": ["val3"], {
"options.unicode.unicode1": ["super1"], "options.unicode.unicode": [
"options.unicode.unicode2": ["pas test"], {
"options.unicode.unicode3": [null]} "options.unicode.unicode": "val3",
"options.unicode.unicode1": "super1",
"options.unicode.unicode2": "pas test",
"options.unicode.unicode3": null
}
]
}

View file

@ -1,4 +1,22 @@
{"options.unicode.unicode": ["val3", "val4", "val5"], {
"options.unicode.unicode1": ["super1", "super2", null], "options.unicode.unicode": [
"options.unicode.unicode2": ["pas test", "test", "follower2"], {
"options.unicode.unicode3": [null, "super", null]} "options.unicode.unicode": "val3",
"options.unicode.unicode1": "super1",
"options.unicode.unicode2": "pas test",
"options.unicode.unicode3": null
},
{
"options.unicode.unicode": "val4",
"options.unicode.unicode1": "super2",
"options.unicode.unicode2": "test",
"options.unicode.unicode3": "super"
},
{
"options.unicode.unicode": "val5",
"options.unicode.unicode1": null,
"options.unicode.unicode2": "follower2",
"options.unicode.unicode3": null
}
]
}

View file

@ -1,4 +1,22 @@
{"options.unicode.unicode": ["val3", "val4", "val5"], {
"options.unicode.unicode1": ["super1", "super2", null], "options.unicode.unicode": [
"options.unicode.unicode2": ["pas test", "test", "follower2"], {
"options.unicode.unicode3": [null, "super", null]} "options.unicode.unicode": "val3",
"options.unicode.unicode1": "super1",
"options.unicode.unicode2": "pas test",
"options.unicode.unicode3": null
},
{
"options.unicode.unicode": "val4",
"options.unicode.unicode1": "super2",
"options.unicode.unicode2": "test",
"options.unicode.unicode3": "super"
},
{
"options.unicode.unicode": "val5",
"options.unicode.unicode1": null,
"options.unicode.unicode2": "follower2",
"options.unicode.unicode3": null
}
]
}

View file

@ -1,4 +1,16 @@
{"options.unicode.unicode": ["val3", "val4"], {
"options.unicode.unicode1": ["super1", "super2"], "options.unicode.unicode": [
"options.unicode.unicode2": ["pas test", "follower2"], {
"options.unicode.unicode3": [null, "super"]} "options.unicode.unicode": "val3",
"options.unicode.unicode1": "super1",
"options.unicode.unicode2": "pas test",
"options.unicode.unicode3": null
},
{
"options.unicode.unicode": "val4",
"options.unicode.unicode1": "super2",
"options.unicode.unicode2": "follower2",
"options.unicode.unicode3": "super"
}
]
}

View file

@ -1,4 +1,16 @@
{"options.unicode.unicode": ["val3", "val4"], {
"options.unicode.unicode1": ["super1", "super2"], "options.unicode.unicode": [
"options.unicode.unicode2": ["pas test", "test2"], {
"options.unicode.unicode3": [null, "super"]} "options.unicode.unicode": "val3",
"options.unicode.unicode1": "super1",
"options.unicode.unicode2": "pas test",
"options.unicode.unicode3": null
},
{
"options.unicode.unicode": "val4",
"options.unicode.unicode1": "super2",
"options.unicode.unicode2": "test2",
"options.unicode.unicode3": "super"
}
]
}

View file

@ -1 +1,3 @@
{"options.unicode": "a"} {
"options.unicode": "a"
}

View file

@ -1 +1,3 @@
{"options.unicode": "val"} {
"options.unicode": "val"
}

View file

@ -1 +1,3 @@
{"options.unicode": null} {
"options.unicode": null
}

View file

@ -1 +1,3 @@
{"options.unicode": []} {
"options.unicode": []
}

View file

@ -1 +1,5 @@
{"options.unicode": ["val"]} {
"options.unicode": [
"val"
]
}

View file

@ -1 +1,7 @@
{"options.unicode": ["c", "d", "e"]} {
"options.unicode": [
"c",
"d",
"e"
]
}

View file

@ -1 +1,6 @@
{"options.unicode": ["a", "b"]} {
"options.unicode": [
"a",
"b"
]
}

View file

@ -1 +1,7 @@
{"options.unicode": ["c", "f", "e"]} {
"options.unicode": [
"c",
"f",
"e"
]
}

View file

@ -7,7 +7,7 @@ def get_description():
option1 = StrOption('unicode1', "Value 'test' must show Unicode 2") option1 = StrOption('unicode1', "Value 'test' must show Unicode 2")
hidden_property = Calculation(calc_value, hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'), Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(option1, todict=True), kwargs={'condition': ParamOption(option1),
'expected': ParamValue('test'), 'expected': ParamValue('test'),
'reverse_condition': ParamValue(True)})) 'reverse_condition': ParamValue(True)}))
option2 = StrOption('unicode2', "Unicode 2", properties=(hidden_property,), multi=True) option2 = StrOption('unicode2', "Unicode 2", properties=(hidden_property,), multi=True)

View file

@ -10,7 +10,7 @@ def get_description():
option3 = StrOption('unicode3', "Unicode 3") option3 = StrOption('unicode3', "Unicode 3")
hidden_property = Calculation(calc_value, hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'), Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(option1, todict=True), kwargs={'condition': ParamOption(option1),
'expected': ParamValue('test'), 'expected': ParamValue('test'),
'reverse_condition': ParamValue(True)})) 'reverse_condition': ParamValue(True)}))
descr2 = OptionDescription("unicode1", "OptionDescription with 2 options", [option2, option3], properties=(hidden_property,)) descr2 = OptionDescription("unicode1", "OptionDescription with 2 options", [option2, option3], properties=(hidden_property,))

View file

@ -7,7 +7,7 @@ def get_description():
option1 = StrOption('unicode1', "Value 'test' must show Unicode 2") option1 = StrOption('unicode1', "Value 'test' must show Unicode 2")
hidden_property = Calculation(calc_value, hidden_property = Calculation(calc_value,
Params(ParamValue('hidden'), Params(ParamValue('hidden'),
kwargs={'condition': ParamOption(option1, todict=True), kwargs={'condition': ParamOption(option1),
'expected': ParamValue('test'), 'expected': ParamValue('test'),
'reverse_condition': ParamValue(True)})) 'reverse_condition': ParamValue(True)}))
option2 = StrOption('unicode2', "Unicode 2", properties=(hidden_property,)) option2 = StrOption('unicode2', "Unicode 2", properties=(hidden_property,))

View file

@ -23,8 +23,8 @@ def datapath():
def list_data(ext='.py'): def list_data(ext='.py'):
# if ext == '.py': # if ext == '.py':
# return ['choice1_leadership_hidden.py'] # return ['unicode1_leadership_requires.py']
datadir = datapath() datadir = datapath()
filenames = listdir(datadir) filenames = listdir(datadir)
filenames.sort() filenames.sort()
@ -40,7 +40,8 @@ def load_config(filename,
add_extra_od=False, add_extra_od=False,
remote='minimum', remote='minimum',
clearable='minimum', clearable='minimum',
root=None): root=None,
):
modulepath = splitext(filename)[0] modulepath = splitext(filename)[0]
mod = __import__(modulepath) mod = __import__(modulepath)
descr = mod.get_description() descr = mod.get_description()
@ -169,7 +170,8 @@ def test_jsons(filename):
print(" {} (remote: {}, clearable: {})".format(filename, remote, clearable)) print(" {} (remote: {}, clearable: {})".format(filename, remote, clearable))
values = load_config(filename, values = load_config(filename,
remote=remote, remote=remote,
clearable=clearable) clearable=clearable,
)
# #
if not isfile(join(datadir, modulepath + '.json')) and \ if not isfile(join(datadir, modulepath + '.json')) and \
clearable == 'minimum' and \ clearable == 'minimum' and \
@ -216,6 +218,27 @@ def test_jsons(filename):
assert values == expected, "error in file {}".format(filename) assert values == expected, "error in file {}".format(filename)
def loads_yml(fh, issub, modulepath):
dico = loads(fh.read())
if issub:
new_dico_ori = {}
for key, value in dico.items():
key = modulepath + '.' + key
if isinstance(value, list):
new_value = []
for val in value:
if isinstance(val, dict):
new_val = {}
for k, v in val.items():
new_val[modulepath + '.' + k] = v
val = new_val
new_value.append(val)
value = new_value
new_dico_ori[key] = value
dico = new_dico_ori
return dico
def test_jsons_subconfig(filename): def test_jsons_subconfig(filename):
debug = False debug = False
# debug = True # debug = True
@ -311,13 +334,7 @@ def test_updates(filename_mod):
dico_ori = None dico_ori = None
else: else:
with open(join(datadir, modulepath + '.dict'), 'r') as fh: with open(join(datadir, modulepath + '.dict'), 'r') as fh:
dico_ori = loads(fh.read()) dico_ori = loads_yml(fh, issub, modulepath)
if issub:
new_dico_ori = {}
for key, value in dico_ori.items():
key = modulepath + '.' + key
new_dico_ori[key] = value
dico_ori = new_dico_ori
# modify config # modify config
with open(join(datadir, modulepath + '.mod{}'.format(idx)), 'r') as fh: with open(join(datadir, modulepath + '.mod{}'.format(idx)), 'r') as fh:
body = loads(fh.read())['body'] body = loads(fh.read())['body']
@ -343,13 +360,7 @@ def test_updates(filename_mod):
dico_mod = None dico_mod = None
else: else:
with open(join(datadir, modulepath + '.dict{}'.format(idx)), 'r') as fh: with open(join(datadir, modulepath + '.dict{}'.format(idx)), 'r') as fh:
dico_mod = loads(fh.read()) dico_mod = loads_yml(fh, issub, modulepath)
if issub:
new_dico = {}
for key, value in dico_mod.items():
key = modulepath + '.' + key
new_dico[key] = value
dico_mod = new_dico
if root is None: if root is None:
root_path = '' root_path = ''
else: else:

View file

@ -232,8 +232,9 @@ def test_leader_list(config_type):
assert ret[0].name() == 'leadership' assert ret[0].name() == 'leadership'
# #
ret = cfg.option('leadership').list('all') ret = cfg.option('leadership').list('all')
assert len(ret) == 1 assert len(ret) == 2
assert ret[0].name() == 'ip_admin_eth0' assert ret[0].name() == 'ip_admin_eth0'
assert ret[1].name() == 'netmask_admin_eth0'
# #
cfg.option('leadership.ip_admin_eth0').value.set(['a', 'b']) cfg.option('leadership.ip_admin_eth0').value.set(['a', 'b'])
cfg.option('leadership.netmask_admin_eth0', 0).value.set('c') cfg.option('leadership.netmask_admin_eth0', 0).value.set('c')

View file

@ -58,8 +58,8 @@ def test_mod_read_only_write():
od1 = OptionDescription("options", "", [s]) od1 = OptionDescription("options", "", [s])
config = Config(od1) config = Config(od1)
config2 = Config(od1) config2 = Config(od1)
assert config.property.getdefault() == {'cache', 'validator', 'warnings'} assert config.property.default() == {'cache', 'validator', 'warnings'}
assert config.property.getdefault('read_only', 'append') == {'frozen', assert config.property.default('read_only', 'append') == {'frozen',
'disabled', 'disabled',
'validator', 'validator',
'everything_frozen', 'everything_frozen',
@ -67,16 +67,16 @@ def test_mod_read_only_write():
'empty', 'empty',
'force_store_value', 'force_store_value',
} }
assert config.property.getdefault('read_only', 'remove') == {'permissive', assert config.property.default('read_only', 'remove') == {'permissive',
'hidden', 'hidden',
} }
assert config.property.getdefault('read_write', 'append') == {'frozen', assert config.property.default('read_write', 'append') == {'frozen',
'disabled', 'disabled',
'validator', 'validator',
'hidden', 'hidden',
'force_store_value', 'force_store_value',
} }
assert config.property.getdefault('read_write', 'remove') == {'permissive', assert config.property.default('read_write', 'remove') == {'permissive',
'everything_frozen', 'everything_frozen',
'mandatory', 'mandatory',
'empty', 'empty',
@ -94,12 +94,12 @@ def test_mod_read_only_write():
with pytest.raises(TypeError): with pytest.raises(TypeError):
config.property.setdefault(type='read_only', when='append', properties=['disabled']) config.property.setdefault(type='read_only', when='append', properties=['disabled'])
assert config.property.getdefault() == {'cache'} assert config.property.default() == {'cache'}
assert config.property.getdefault('read_only', 'append') == {'disabled'} assert config.property.default('read_only', 'append') == {'disabled'}
assert config.property.getdefault('read_only', 'remove') == {'hidden'} assert config.property.default('read_only', 'remove') == {'hidden'}
assert config.property.getdefault('read_write', 'append') == {'disabled', assert config.property.default('read_write', 'append') == {'disabled',
'hidden'} 'hidden'}
assert config.property.getdefault('read_write', 'remove') == set([]) assert config.property.default('read_write', 'remove') == set([])
# #
config.property.read_only() config.property.read_only()
assert config.property.get() == {'cache', 'disabled'} assert config.property.get() == {'cache', 'disabled'}
@ -108,29 +108,33 @@ def test_mod_read_only_write():
config.property.read_only() config.property.read_only()
assert config.property.get() == {'cache', 'disabled'} assert config.property.get() == {'cache', 'disabled'}
# #
assert config2.property.getdefault() == {'cache', 'validator', 'warnings'} assert config2.property.default() == {'cache', 'validator', 'warnings'}
assert config2.property.getdefault('read_only', 'append') == {'frozen', assert config2.property.default('read_only', 'append') == {'frozen',
'disabled', 'disabled',
'validator', 'validator',
'everything_frozen', 'everything_frozen',
'mandatory', 'mandatory',
'empty', 'empty',
'force_store_value'} 'force_store_value',
assert config2.property.getdefault('read_only', 'remove') == {'permissive', }
'hidden'} assert config2.property.default('read_only', 'remove') == {'permissive',
assert config2.property.getdefault('read_write', 'append') == {'frozen', 'hidden',
}
assert config2.property.default('read_write', 'append') == {'frozen',
'disabled', 'disabled',
'validator', 'validator',
'hidden', 'hidden',
'force_store_value'} 'force_store_value',
assert config2.property.getdefault('read_write', 'remove') == {'permissive', }
assert config2.property.default('read_write', 'remove') == {'permissive',
'everything_frozen', 'everything_frozen',
'mandatory', 'mandatory',
'empty'} 'empty',
}
with pytest.raises(ValueError): with pytest.raises(ValueError):
config2.property.getdefault('unknown', 'remove') config2.property.default('unknown', 'remove')
with pytest.raises(ValueError): with pytest.raises(ValueError):
config2.property.getdefault('read_write', 'unknown') config2.property.default('read_write', 'unknown')
# assert not list_sessions() # assert not list_sessions()

View file

@ -30,7 +30,7 @@ from .option import RegexpOption, OptionDescription, ChoiceOption
from .todict import TiramisuDict from .todict import TiramisuDict
TIRAMISU_VERSION = 3 TIRAMISU_VERSION = 4
class TiramisuHelp: class TiramisuHelp:
@ -166,7 +166,7 @@ class CommonTiramisuOption(CommonTiramisu):
self._config_bag = config_bag self._config_bag = config_bag
def __getattr__(self, subfunc): def __getattr__(self, subfunc):
raise ConfigError(_('please specify a valid sub function ({})').format(subfunc)) raise ConfigError(_(f'please specify a valid sub function ({self.__class__.__name__}.{subfunc})'))
class _TiramisuOptionWalk: class _TiramisuOptionWalk:
@ -188,6 +188,7 @@ class _TiramisuOptionWalk:
recursive=recursive, recursive=recursive,
types=types, types=types,
group_type=group_type, group_type=group_type,
flatten_leadership=True,
): ):
if isinstance(option_bag, dict): if isinstance(option_bag, dict):
for opts_bag in option_bag.values(): for opts_bag in option_bag.values():
@ -214,7 +215,7 @@ class _TiramisuOptionOptionDescription:
"""Manage option""" """Manage option"""
_validate_properties = False _validate_properties = False
@option_type(['optiondescription', 'option', 'with_or_without_index']) @option_type(['optiondescription', 'option', 'with_or_without_index', 'symlink'])
def get(self, options_bag: List[OptionBag]): def get(self, options_bag: List[OptionBag]):
"""Get Tiramisu option""" """Get Tiramisu option"""
option_bag = options_bag[-1] option_bag = options_bag[-1]
@ -277,7 +278,7 @@ class _TiramisuOptionOptionDescription:
option_bag = options_bag[-1] option_bag = options_bag[-1]
return option_bag.option.impl_is_optiondescription() return option_bag.option.impl_is_optiondescription()
@option_type(['optiondescription', 'option', 'with_index']) @option_type(['optiondescription', 'option', 'with_or_without_index', 'symlink'])
def properties(self, def properties(self,
options_bag: List[OptionBag], options_bag: List[OptionBag],
only_raises=False, only_raises=False,
@ -319,7 +320,7 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
"""Test if option is a leader""" """Test if option is a leader"""
return options_bag[-1].option.impl_is_leader() return options_bag[-1].option.impl_is_leader()
@option_type(['option', 'with_or_without_index']) @option_type(['option', 'with_or_without_index', 'symlink'])
def isfollower(self, options_bag: List[OptionBag]): def isfollower(self, options_bag: List[OptionBag]):
"""Test if option is a follower""" """Test if option is a follower"""
return options_bag[-1].option.impl_is_follower() return options_bag[-1].option.impl_is_follower()
@ -362,12 +363,12 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
type = option.get_type() type = option.get_type()
if isinstance(option, RegexpOption): if isinstance(option, RegexpOption):
return option._regexp.pattern return option._regexp.pattern
if type == 'integer': if type == _('integer'):
# FIXME negative too! # FIXME negative too!
return r'^[0-9]+$' return r'^[0-9]+$'
if type == 'domainname': if type == _('domain name'):
return option.impl_get_extra('_domain_re').pattern return option.impl_get_extra('_domain_re').pattern
if type in ['ip', 'network', 'netmask']: if type in [_('ip'), _('network'), _('netmask')]:
#FIXME only from 0.0.0.0 to 255.255.255.255 #FIXME only from 0.0.0.0 to 255.255.255.255
return r'^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$' return r'^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$'
@ -439,7 +440,7 @@ class TiramisuOptionProperty(CommonTiramisuOption):
"""Manage option's property""" """Manage option's property"""
_validate_properties = False _validate_properties = False
@option_type(['option', 'optiondescription', 'with_index']) @option_type(['option', 'optiondescription', 'with_or_without_index'])
def get(self, def get(self,
options_bag: List[OptionBag], options_bag: List[OptionBag],
only_raises=False, only_raises=False,
@ -495,11 +496,10 @@ class TiramisuOptionProperty(CommonTiramisuOption):
class TiramisuOptionPermissive(CommonTiramisuOption): class TiramisuOptionPermissive(CommonTiramisuOption):
"""Manage option's permissive""" """Manage option's permissive"""
@option_type(['option', 'optiondescription', 'symlink', 'with_index']) @option_type(['option', 'optiondescription', 'symlink', 'with_or_without_index'])
def get(self, options_bag: List[OptionBag]): def get(self, options_bag: List[OptionBag]):
"""Get permissives value""" """Get permissives value"""
option_bag = options_bag[-1] return self._config_bag.context.get_settings().getpermissives(options_bag[-1])
return self._config_bag.context.get_settings().getpermissives(option_bag)
@option_type(['option', 'optiondescription', 'with_or_without_index']) @option_type(['option', 'optiondescription', 'with_or_without_index'])
def set(self, def set(self,
@ -522,7 +522,7 @@ class TiramisuOptionPermissive(CommonTiramisuOption):
class TiramisuOptionInformation(CommonTiramisuOption): class TiramisuOptionInformation(CommonTiramisuOption):
"""Manage option's informations""" """Manage option's informations"""
@option_type(['option', 'optiondescription', 'with_or_without_index']) @option_type(['option', 'optiondescription', 'with_or_without_index', 'symlink'])
def get(self, def get(self,
options_bag: List[OptionBag], options_bag: List[OptionBag],
name: str, name: str,
@ -561,7 +561,7 @@ class TiramisuOptionInformation(CommonTiramisuOption):
path=option_bag.path, path=option_bag.path,
) )
@option_type(['option', 'optiondescription', 'with_or_without_index']) @option_type(['option', 'optiondescription', 'with_or_without_index', 'symlink'])
def list(self, def list(self,
options_bag: List[OptionBag], options_bag: List[OptionBag],
) -> list: ) -> list:
@ -662,7 +662,7 @@ class TiramisuOptionValue(CommonTiramisuOption):
return False return False
return True return True
@option_type(['choice', 'with_index']) @option_type(['choice', 'with_or_without_index'])
def list(self, options_bag: List[OptionBag]): def list(self, options_bag: List[OptionBag]):
"""All values available for a ChoiceOption""" """All values available for a ChoiceOption"""
option_bag = options_bag[-1] option_bag = options_bag[-1]
@ -754,7 +754,7 @@ class TiramisuOption(CommonTiramisu, _TiramisuOptionOption, TiramisuConfig):
self._index, self._index,
self._config_bag, self._config_bag,
) )
raise ConfigError(_('please specify a valid sub function ({})').format(subfunc)) raise ConfigError(_(f'please specify a valid sub function ({self.__class__.__name__}.{subfunc})'))
@option_type('optiondescription') @option_type('optiondescription')
def find(self, def find(self,
@ -793,7 +793,7 @@ class TiramisuOption(CommonTiramisu, _TiramisuOptionOption, TiramisuConfig):
recursive=False, recursive=False,
group_type=None, group_type=None,
): ):
"""List options (by default list only option)""" """List options inside an option description (by default list only option)"""
return self._list(options_bag[-1], return self._list(options_bag[-1],
type, type,
group_type, group_type,
@ -804,10 +804,9 @@ class TiramisuOption(CommonTiramisu, _TiramisuOptionOption, TiramisuConfig):
clearable: str="all", clearable: str="all",
remotable: str="minimum", remotable: str="minimum",
): ):
root = self._option_bag.option.impl_getpath() config = self._config_bag.context
config = self._option_bag.config_bag.context
self._tiramisu_dict = TiramisuDict(self._return_config(config), self._tiramisu_dict = TiramisuDict(self._return_config(config),
root=root, root=self._path,
clearable=clearable, clearable=clearable,
remotable=remotable) remotable=remotable)
@ -1098,14 +1097,15 @@ class TiramisuContextProperty(TiramisuConfig):
else: else:
raise ValueError(_('unknown type {}').format(type)) raise ValueError(_('unknown type {}').format(type))
def getdefault(self, def default(self,
type: Optional[str]=None, type: Optional[str]=None,
when: Optional[str]=None, when: Optional[str]=None,
) -> Set[str]: ) -> Set[str]:
setting = self._config_bag.context.get_settings() setting = self._config_bag.context.get_settings()
if type is None and when is None: if type is None and when is None:
return setting.default_properties return setting.default_properties
if type == 'current':
return setting.get_context_properties(self._config_bag.context.properties_cache)
if when not in ['append', 'remove']: if when not in ['append', 'remove']:
raise ValueError(_('unknown when {} (must be in append or remove)').format(when)) raise ValueError(_('unknown when {} (must be in append or remove)').format(when))
if type == 'read_only': if type == 'read_only':
@ -1448,7 +1448,7 @@ class TiramisuAPI(TiramisuHelp):
# del config_bag.permissives # del config_bag.permissives
return self._registers[subfunc](config_bag, return self._registers[subfunc](config_bag,
self._orig_config_bags) self._orig_config_bags)
raise ConfigError(_('please specify a valid sub function ({})').format(subfunc)) raise ConfigError(_(f'please specify a valid sub function ({self.__class__.__name__}.{subfunc})'))
def __dir__(self): def __dir__(self):
return list(self._registers.keys()) + \ return list(self._registers.keys()) + \
@ -1568,7 +1568,8 @@ class MixConfig(TiramisuAPI):
permissives = settings.get_context_permissives() permissives = settings.get_context_permissives()
config_bag = ConfigBag(config, config_bag = ConfigBag(config,
properties=properties, properties=properties,
permissives=permissives) permissives=permissives,
)
super().__init__(config_bag) super().__init__(config_bag)

View file

@ -321,6 +321,7 @@ class _SubConfig:
group_type=None, group_type=None,
recursive: bool=True, recursive: bool=True,
walked: bool=False, walked: bool=False,
flatten_leadership: bool=False,
): ):
"""walk to tree """walk to tree
""" """
@ -334,7 +335,7 @@ class _SubConfig:
if not recursive: if not recursive:
# it's not recursive, so stop to walk # it's not recursive, so stop to walk
return return
if not option_bag.option.impl_is_leadership(): if not option_bag.option.impl_is_leadership() or flatten_leadership:
for opt in option_bag.option.get_children(option_bag.config_bag): for opt in option_bag.option.get_children(option_bag.config_bag):
try: try:
yield from self.walk(self.get_sub_option_bag(option_bag, # pylint: disable=no-member yield from self.walk(self.get_sub_option_bag(option_bag, # pylint: disable=no-member

View file

@ -10,16 +10,9 @@ from . import SynDynOption, RegexpOption, ChoiceOption, ParamOption
from .i18n import _ from .i18n import _
TYPES = {'SymLinkOption': 'symlink', CONVERT_WEB_TYPE = {'bool': 'boolean',
'IntOption': 'integer', 'str': 'string',
'FloatOption': 'integer', 'int': 'integer',
'ChoiceOption': 'choice',
'BoolOption': 'boolean',
'PasswordOption': 'password',
'PortOption': 'integer',
'DateOption': 'date',
'DomainnameOption': 'domainname',
'StrOption': 'string'
} }
INPUTS = ['string', INPUTS = ['string',
'integer', 'integer',
@ -48,16 +41,16 @@ class Callbacks(object):
childapi, childapi,
schema, schema,
force_store_value): force_store_value):
if self.remotable == 'all' or childapi.option.isoptiondescription(): if self.remotable == 'all' or childapi.isoptiondescription():
return return
# callback, callback_params = childapi.option.callbacks() # callback, callback_params = childapi.callbacks()
# if callback is None: # FIXME ? and force_store_value and self.clearable != 'all': # if callback is None: # FIXME ? and force_store_value and self.clearable != 'all':
# return # return
# self.callbacks.append((callback, callback_params, path, childapi, schema, force_store_value)) # self.callbacks.append((callback, callback_params, path, childapi, schema, force_store_value))
def process_properties(self, form): def process_properties(self, form):
for callback, callback_params, path, childapi, schema, force_store_value in self.callbacks: for callback, callback_params, path, childapi, schema, force_store_value in self.callbacks:
if childapi.option.isfollower(): if childapi.isfollower():
self.tiramisu_web.set_remotable(path, form, childapi) self.tiramisu_web.set_remotable(path, form, childapi)
continue continue
has_option = False has_option = False
@ -65,10 +58,10 @@ class Callbacks(object):
for callback_param in chain(callback_params.args, callback_params.kwargs.values()): for callback_param in chain(callback_params.args, callback_params.kwargs.values()):
if isinstance(callback_param, ParamOption): if isinstance(callback_param, ParamOption):
has_option = True has_option = True
if 'expire' in childapi.option.properties(): if 'expire' in childapi.properties():
self.tiramisu_web.set_remotable(callback_param.option.impl_getpath(), form) self.tiramisu_web.set_remotable(callback_param.impl_getpath(), form)
if not has_option and form.get(path, {}).get('remote', False) == False: if not has_option and form.get(path, {}).get('remote', False) == False:
if 'expire' in childapi.option.properties(): if 'expire' in childapi.properties():
self.tiramisu_web.set_remotable(path, form, childapi) self.tiramisu_web.set_remotable(path, form, childapi)
elif childapi.owner.isdefault(): elif childapi.owner.isdefault():
# get calculated value and set clearable # get calculated value and set clearable
@ -82,7 +75,7 @@ class Callbacks(object):
# if callback_params is not None: # if callback_params is not None:
# for callback_param in chain(callback_params.args, callback_params.kwargs.values()): # for callback_param in chain(callback_params.args, callback_params.kwargs.values()):
# if isinstance(callback_param, ParamOption) and callback.__name__ == 'tiramisu_copy': # if isinstance(callback_param, ParamOption) and callback.__name__ == 'tiramisu_copy':
# opt_path = callback_param.option.impl_getpath() # opt_path = callback_param.impl_getpath()
# if form.get(opt_path, {}).get('remote') is not True: # if form.get(opt_path, {}).get('remote') is not True:
# form.setdefault(opt_path, {}) # form.setdefault(opt_path, {})
# form[opt_path].setdefault('copy', []).append(path) # form[opt_path].setdefault('copy', []).append(path)
@ -100,8 +93,8 @@ class Consistencies(object):
def add(self, path, childapi, form): def add(self, path, childapi, form):
return return
if not childapi.option.isoptiondescription(): if not childapi.isoptiondescription():
for consistency in childapi.option.consistencies(): for consistency in childapi.consistencies():
cons_id, func, all_cons_opts, params = consistency cons_id, func, all_cons_opts, params = consistency
if func == '_cons_not_equal' and params.get('transitive', True) is True: if func == '_cons_not_equal' and params.get('transitive', True) is True:
options_path = [] options_path = []
@ -141,15 +134,15 @@ class Requires(object):
self.action_hide = self.tiramisu_web.config._config_bag.properties self.action_hide = self.tiramisu_web.config._config_bag.properties
def set_master_remote(self, childapi, path, form): def set_master_remote(self, childapi, path, form):
if childapi.option.isoptiondescription(): if childapi.isoptiondescription():
isfollower = False isfollower = False
else: else:
isfollower = childapi.option.isfollower() isfollower = childapi.isfollower()
if isfollower: if isfollower:
parent_path = path.rsplit('.', 1)[0] parent_path = path.rsplit('.', 1)[0]
parent = self.tiramisu_web.config.unrestraint.option(parent_path) parent = self.tiramisu_web.config.unrestraint.option(parent_path)
leader = parent.list()[0] leader = parent.list()[0]
self.tiramisu_web.set_remotable(leader.option.path(), form, leader) self.tiramisu_web.set_remotable(leader.path(), form, leader)
def manage_requires(self, def manage_requires(self,
childapi, childapi,
@ -157,7 +150,7 @@ class Requires(object):
form, form,
current_action, current_action,
): ):
for requires in childapi.option.properties(uncalculated=True): for requires in childapi.properties(uncalculated=True):
if not isinstance(requires, str): if not isinstance(requires, str):
option = requires.params.kwargs['condition'].option option = requires.params.kwargs['condition'].option
expected = [requires.params.kwargs['expected'].value] expected = [requires.params.kwargs['expected'].value]
@ -210,9 +203,9 @@ class Requires(object):
if isinstance(option, ChoiceOption): if isinstance(option, ChoiceOption):
require_option = self.tiramisu_web.config.unrestraint.option(option_path) require_option = self.tiramisu_web.config.unrestraint.option(option_path)
values = self.tiramisu_web.get_enum(require_option, values = self.tiramisu_web.get_enum(require_option,
require_option.option.ismulti(), require_option.ismulti(),
option_path, option_path,
require_option.option.properties()) require_option.properties())
for value in values: for value in values:
if value not in expected: if value not in expected:
self.requires.setdefault(path, self.requires.setdefault(path,
@ -238,7 +231,7 @@ class Requires(object):
def add(self, path, childapi, form): def add(self, path, childapi, form):
#collect id of all options #collect id of all options
child = childapi.option.get() child = childapi.get()
if isinstance(child, SynDynOption): if isinstance(child, SynDynOption):
child = child.opt child = child.opt
self.options[child] = path self.options[child] = path
@ -247,7 +240,8 @@ class Requires(object):
self.manage_requires(childapi, self.manage_requires(childapi,
path, path,
form, form,
current_action) current_action,
)
def process(self, form): def process(self, form):
dependencies = {} dependencies = {}
@ -337,15 +331,15 @@ class TiramisuDict:
obj['help'] = hlp obj['help'] = hlp
def get_list(self, root, subchildapi): def get_list(self, root, subchildapi):
ret = [] #ret = []
for childapi in subchildapi.list('all'): for childapi in subchildapi.list('all'):
childname = childapi.option.name() childname = childapi.name()
if root is None: if root is None:
path = childname path = childname
else: else:
path = root + '.' + childname path = root + '.' + childname
ret.append((path, childapi)) yield (path, childapi)
return ret #return ret
def is_remote(self, path, form): def is_remote(self, path, form):
if self.remotable == 'all': if self.remotable == 'all':
@ -359,11 +353,11 @@ class TiramisuDict:
form.setdefault(path, {})['remote'] = True form.setdefault(path, {})['remote'] = True
if childapi is None: if childapi is None:
childapi = self.config.unrestraint.option(path) childapi = self.config.unrestraint.option(path)
if childapi.option.isfollower(): if childapi.isfollower():
parent_path = path.rsplit('.', 1)[0] parent_path = path.rsplit('.', 1)[0]
parent = self.config.unrestraint.option(parent_path) parent = self.config.unrestraint.option(parent_path)
leader = parent.list()[0] leader = parent.list()[0]
form.setdefault(leader.option.path(), {})['remote'] = True form.setdefault(leader.path(), {})['remote'] = True
def walk(self, def walk(self,
root, root,
@ -391,13 +385,16 @@ class TiramisuDict:
subchildapi = self.config.unrestraint.option(root) subchildapi = self.config.unrestraint.option(root)
isleadership = False isleadership = False
else: else:
isleadership = subchildapi.option.isleadership() isleadership = subchildapi.isleadership()
leader_len = None leader_len = None
for path, childapi in self.get_list(root, subchildapi): for path, childapi in self.get_list(root, subchildapi):
if isleadership and leader_len is None: if isleadership and leader_len is None:
leader_len = childapi.value.len() leader_len = childapi.value.len()
one_is_remote = False one_is_remote = False
props_no_requires = set(childapi.option.properties()) if not childapi.isoptiondescription() and childapi.isfollower():
props_no_requires = set()
else:
props_no_requires = set(childapi.properties())
if form is not None: if form is not None:
self.requires.add(path, self.requires.add(path,
childapi, childapi,
@ -412,8 +409,7 @@ class TiramisuDict:
schema, schema,
'force_store_value' in props_no_requires, 'force_store_value' in props_no_requires,
) )
childapi_option = childapi.option if model is not None and childapi.isoptiondescription() or not childapi.issymlinkoption():
if model is not None and childapi.option.isoptiondescription() or not childapi_option.issymlinkoption():
self.gen_model(model, self.gen_model(model,
childapi, childapi,
path, path,
@ -422,9 +418,9 @@ class TiramisuDict:
) )
if order is not None: if order is not None:
order.append(path) order.append(path)
if childapi.option.isoptiondescription(): if childapi.isoptiondescription():
web_type = 'optiondescription' web_type = 'optiondescription'
if childapi_option.isleadership(): if childapi.isleadership():
type_ = 'array' type_ = 'array'
else: else:
type_ = 'object' type_ = 'object'
@ -443,33 +439,32 @@ class TiramisuDict:
updates_status, updates_status,
) )
else: else:
child = childapi_option.get() child = childapi.get()
childtype = child.__class__.__name__ childtype = child.__class__.__name__
if childtype == 'SynDynOption': if childtype == 'SynDynOption':
childtype = child.opt.__class__.__name__ childtype = child.opt.__class__.__name__
if childapi_option.issymlinkoption(): if childapi.issymlinkoption():
web_type = 'symlink' web_type = 'symlink'
value = None value = None
defaultmulti = None defaultmulti = None
is_multi = False is_multi = False
else: else:
web_type = childapi_option.type() web_type = childapi.get().__class__.__name__.lower()[:-6]
value = childapi.option.default() web_type = CONVERT_WEB_TYPE.get(web_type, web_type)
value = childapi.default()
if value == []: if value == []:
value = None value = None
is_multi = childapi_option.ismulti() is_multi = childapi.ismulti()
if is_multi: if is_multi:
defaultmulti = childapi_option.defaultmulti() defaultmulti = childapi.defaultmulti()
if defaultmulti == []: if defaultmulti == []:
defaultmulti = None defaultmulti = None
else: else:
defaultmulti = None defaultmulti = None
if schema is not None: if schema is not None:
self.gen_schema(schema, self.gen_schema(schema,
childapi, childapi,
childapi_option,
path, path,
props_no_requires, props_no_requires,
value, value,
@ -483,12 +478,12 @@ class TiramisuDict:
web_type, web_type,
path, path,
child, child,
childapi_option, childapi,
childtype, childtype,
) )
if schema is not None: if schema is not None:
if web_type != 'symlink': if web_type != 'symlink':
schema[path]['title'] = childapi_option.description() schema[path]['title'] = childapi.description()
self.add_help(schema[path], self.add_help(schema[path],
childapi) childapi)
except Exception as err: except Exception as err:
@ -513,7 +508,6 @@ class TiramisuDict:
def gen_schema(self, def gen_schema(self,
schema, schema,
childapi, childapi,
childapi_option,
path, path,
props_no_requires, props_no_requires,
value, value,
@ -523,8 +517,8 @@ class TiramisuDict:
form, form,
): ):
schema[path] = {'type': web_type} schema[path] = {'type': web_type}
if childapi_option.issymlinkoption(): if childapi.issymlinkoption():
sym_option = childapi_option.get() sym_option = childapi.get()
schema[path]['opt_path'] = sym_option.impl_getopt().impl_getpath() schema[path]['opt_path'] = sym_option.impl_getopt().impl_getpath()
else: else:
if defaultmulti is not None: if defaultmulti is not None:
@ -533,7 +527,7 @@ class TiramisuDict:
if is_multi: if is_multi:
schema[path]['isMulti'] = is_multi schema[path]['isMulti'] = is_multi
if childapi_option.issubmulti(): if childapi.issubmulti():
schema[path]['isSubMulti'] = True schema[path]['isSubMulti'] = True
if 'auto_freeze' in props_no_requires: if 'auto_freeze' in props_no_requires:
@ -561,7 +555,7 @@ class TiramisuDict:
props_no_requires, props_no_requires,
): ):
values = childapi.value.list() values = childapi.value.list()
empty_is_required = not childapi.option.isfollower() and is_multi empty_is_required = not childapi.isfollower() and is_multi
if '' not in values and ((empty_is_required and not 'empty' in props_no_requires) or \ if '' not in values and ((empty_is_required and not 'empty' in props_no_requires) or \
(not empty_is_required and not 'mandatory' in props_no_requires)): (not empty_is_required and not 'mandatory' in props_no_requires)):
values = [''] + list(values) values = [''] + list(values)
@ -572,13 +566,13 @@ class TiramisuDict:
web_type, web_type,
path, path,
child, child,
childapi_option, childapi,
childtype, childtype,
): ):
obj_form = {} obj_form = {}
if path in form: if path in form:
obj_form.update(form[path]) obj_form.update(form[path])
if not childapi_option.issymlinkoption(): if not childapi.issymlinkoption():
#if childapi_option.validator() != (None, None): #if childapi_option.validator() != (None, None):
# obj_form['remote'] = True # obj_form['remote'] = True
# params = childapi_option.validator()[1] # params = childapi_option.validator()[1]
@ -590,14 +584,14 @@ class TiramisuDict:
obj_form['clearable'] = True obj_form['clearable'] = True
if self.clearable != 'none': if self.clearable != 'none':
obj_form['clearable'] = True obj_form['clearable'] = True
if self.remotable == 'all' or childapi_option.has_dependency(): if self.remotable == 'all' or childapi.has_dependency():
obj_form['remote'] = True obj_form['remote'] = True
if childtype == 'IPOption' and (child.impl_get_extra('_private_only') or not child.impl_get_extra('_allow_reserved') or child.impl_get_extra('_cidr')): if childtype == 'IPOption' and (child.impl_get_extra('_private_only') or not child.impl_get_extra('_allow_reserved') or child.impl_get_extra('_cidr')):
obj_form['remote'] = True obj_form['remote'] = True
if childtype == 'DateOption': if childtype == 'DateOption':
obj_form['remote'] = True obj_form['remote'] = True
if not obj_form.get('remote', False): if not obj_form.get('remote', False):
pattern = childapi_option.pattern() pattern = childapi.pattern()
if pattern is not None: if pattern is not None:
obj_form['pattern'] = pattern obj_form['pattern'] = pattern
if childtype == 'PortOption': if childtype == 'PortOption':
@ -619,10 +613,11 @@ class TiramisuDict:
old_properties = childapi._config_bag.properties old_properties = childapi._config_bag.properties
config = childapi._config_bag.context config = childapi._config_bag.context
settings = config.get_settings() settings = config.get_settings()
childapi._config_bag.properties = self.config.property.get(default=True) # settings.get_context_properties(config._impl_properties_cache) childapi._config_bag.properties = self.config.property.default('current') # settings.get_context_properties(config._impl_properties_cache)
childapi._config_bag.properties -= {'permissive'} childapi._config_bag.properties -= {'permissive'}
properties = childapi.property.get(only_raises=True, properties = childapi.property.get(only_raises=True,
uncalculated=True) uncalculated=True,
)
properties -= childapi.permissive.get() properties -= childapi.permissive.get()
# 'hidden=True' means cannot access with or without permissive option # 'hidden=True' means cannot access with or without permissive option
# 'display=False' means cannot access only without permissive option # 'display=False' means cannot access only without permissive option
@ -638,11 +633,11 @@ class TiramisuDict:
path, path,
index, index,
): ):
isfollower = childapi.option.isfollower() isfollower = childapi.isfollower()
props = set(childapi.property.get()) props = set(childapi.property.get())
obj = self.gen_properties(props, obj = self.gen_properties(props,
isfollower, isfollower,
childapi.option.ismulti(), childapi.ismulti(),
index) index)
self.calc_raises_properties(obj, childapi) self.calc_raises_properties(obj, childapi)
return obj return obj
@ -687,7 +682,7 @@ class TiramisuDict:
leader_len, leader_len,
updates_status, updates_status,
): ):
if childapi.option.isoptiondescription(): if childapi.isoptiondescription():
props = set(childapi.property.get()) props = set(childapi.property.get())
obj = {} obj = {}
self.calc_raises_properties(obj, childapi) self.calc_raises_properties(obj, childapi)
@ -696,7 +691,7 @@ class TiramisuDict:
lprops.sort() lprops.sort()
obj['properties'] = lprops obj['properties'] = lprops
try: try:
self.config.option(path).option.get() self.config.option(path).get()
except PropertiesOptionError: except PropertiesOptionError:
pass pass
else: else:
@ -704,7 +699,7 @@ class TiramisuDict:
path, path,
None, None,
) )
if childapi.option.isfollower(): if childapi.isfollower():
for index in range(leader_len): for index in range(leader_len):
follower_childapi = self.config.unrestraint.option(path, index) follower_childapi = self.config.unrestraint.option(path, index)
sobj = self._gen_model_properties(follower_childapi, sobj = self._gen_model_properties(follower_childapi,
@ -727,7 +722,7 @@ class TiramisuDict:
updates_status, updates_status,
) )
if obj: if obj:
if not childapi.option.isoptiondescription() and childapi.option.isfollower(): if not childapi.isoptiondescription() and childapi.isfollower():
model.setdefault(path, {})['null'] = obj model.setdefault(path, {})['null'] = obj
else: else:
model[path] = obj model[path] = obj
@ -829,9 +824,9 @@ class TiramisuDict:
return ret return ret
def del_value(self, childapi, path, index): def del_value(self, childapi, path, index):
if index is not None and childapi.option.isleader(): if index is not None and childapi.isleader():
childapi.value.pop(index) childapi.value.pop(index)
elif index is None or childapi.option.isfollower(): elif index is None or childapi.isfollower():
childapi.value.reset() childapi.value.reset()
else: else:
multi = childapi.value.get() multi = childapi.value.get()
@ -844,7 +839,7 @@ class TiramisuDict:
childapi.value.set(multi) childapi.value.set(multi)
def mod_value(self, childapi, path, index, value): def mod_value(self, childapi, path, index, value):
if index is None or childapi.option.isfollower(): if index is None or childapi.isfollower():
childapi.value.set(value) childapi.value.set(value)
else: else:
multi = childapi.value.get() multi = childapi.value.get()
@ -866,8 +861,7 @@ class TiramisuDict:
if oripath is not None and not path.startswith(oripath): if oripath is not None and not path.startswith(oripath):
raise ValueError(_('not in current area')) raise ValueError(_('not in current area'))
childapi = self.config.option(path) childapi = self.config.option(path)
childapi_option = childapi.option if childapi.isfollower():
if childapi_option.isfollower():
childapi = self.config.option(path, index) childapi = self.config.option(path, index)
with warnings.catch_warnings(record=True) as warns: with warnings.catch_warnings(record=True) as warns:
try: try:
@ -883,7 +877,7 @@ class TiramisuDict:
index, index,
) )
elif update['action'] == 'add': elif update['action'] == 'add':
if childapi_option.ismulti(): if childapi.ismulti():
self.add_value(childapi, path, update['value']) self.add_value(childapi, path, update['value'])
else: else:
raise ValueError(_('only multi option can have action "add", but "{}" is not a multi').format(path)) raise ValueError(_('only multi option can have action "add", but "{}" is not a multi').format(path))