TiramisuOption.list() with follower
This commit is contained in:
parent
ad31fc85bb
commit
3641eb39d8
6 changed files with 51 additions and 21 deletions
|
@ -268,7 +268,7 @@ def test_cache_leadership():
|
|||
assert set(cache.keys()) == set([None, 'ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
|
||||
assert set(cache['ip_admin_eth0'].keys()) == set([None])
|
||||
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
|
||||
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([0, None])
|
||||
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == {0}
|
||||
#
|
||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.set(['192.168.1.2', '192.168.1.1'])
|
||||
cfg.option('ip_admin_eth0.ip_admin_eth0').value.get()
|
||||
|
@ -286,7 +286,7 @@ def test_cache_leadership():
|
|||
assert set(cache.keys()) == set([None, 'ip_admin_eth0', 'ip_admin_eth0.ip_admin_eth0', 'ip_admin_eth0.netmask_admin_eth0'])
|
||||
assert set(cache['ip_admin_eth0'].keys()) == set([None])
|
||||
assert set(cache['ip_admin_eth0.ip_admin_eth0'].keys()) == set([None])
|
||||
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([None, 0, 1])
|
||||
assert set(cache['ip_admin_eth0.netmask_admin_eth0'].keys()) == set([0, 1])
|
||||
#DEL, insert, ...
|
||||
# assert not list_sessions()
|
||||
|
||||
|
@ -398,19 +398,20 @@ def test_cache_leader_and_followers():
|
|||
val_val2_props = {idx_val2: (val1_val2_props, None), None: (set(), None)}
|
||||
compare(settings.get_cached(), {None: {None: (set(global_props), None)},
|
||||
'val1.val1': {None: (val1_val1_props, None)},
|
||||
'val1.val2': val_val2_props})
|
||||
})
|
||||
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
|
||||
cfg.value.dict()
|
||||
#has value
|
||||
idx_val2 = 0
|
||||
val_val2 = None
|
||||
val_val2_props = {idx_val2: (val1_val2_props, None), None: (set(), None)}
|
||||
val_val2_props = {idx_val2: (val1_val2_props, None)}
|
||||
compare(settings.get_cached(), {None: {None: (global_props, None)},
|
||||
'val1': {None: (val1_props, None)},
|
||||
'val1.val1': {None: (val1_val1_props, None)},
|
||||
'val1.val2': val_val2_props})
|
||||
compare(values.get_cached(), {'val1.val1': {None: ([None], None)},
|
||||
'val1.val2': {idx_val2: (val_val2, None)}})
|
||||
'val1.val2': {idx_val2: (val_val2, None)},
|
||||
})
|
||||
cfg.option('val1.val1').value.set([undefined, undefined])
|
||||
cfg.value.dict()
|
||||
cfg.option('val1.val2', 1).value.set('oui')
|
||||
|
@ -446,7 +447,7 @@ def test_cache_leader_callback():
|
|||
cfg.option('val1.val1').value.set([undefined])
|
||||
compare(settings.get_cached(), {None: {None: (set(global_props), None)},
|
||||
'val1.val1': {None: (val1_val1_props, None)},
|
||||
'val1.val2': {None: (val1_val2_props, None)}})
|
||||
})
|
||||
|
||||
compare(values.get_cached(), {'val1.val1': {None: ([None], None, True)}})
|
||||
cfg.value.dict()
|
||||
|
|
|
@ -880,3 +880,17 @@ def test_pprint_not_todict():
|
|||
def test_property_invalid_type():
|
||||
with pytest.raises(ValueError):
|
||||
s3 = StrOption("string3", "", default=["string"], default_multi="string", multi=True, properties=(1,))
|
||||
|
||||
|
||||
def test_settings_list_with_follower():
|
||||
leader = StrOption("leader", "leader", default=['leader'], multi=True)
|
||||
option = StrOption("str", "str", default_multi="dhcp", multi=True, properties=frozenset({'disabled'}))
|
||||
ip = StrOption(name="ip",
|
||||
doc="ip",
|
||||
multi=True,
|
||||
properties=frozenset({"basic", "mandatory", Calculation(calc_value, Params(ParamValue('disabled'), kwargs={'condition': ParamOption(option, notraisepropertyerror=True), 'expected': ParamValue("ipv4"), 'reverse_condition': ParamValue(True)}), calc_value_property_help)}),
|
||||
)
|
||||
descr = Leadership("root", "", [leader, option, ip])
|
||||
cfg = Config(OptionDescription('root', 'root', [descr]))
|
||||
cfg.property.read_write()
|
||||
assert len(cfg.option('root').list('all')) == 2
|
||||
|
|
|
@ -89,12 +89,15 @@ class TiramisuHelp:
|
|||
class CommonTiramisu(TiramisuHelp):
|
||||
_validate_properties = True
|
||||
|
||||
def _get_options_bag(self) -> OptionBag:
|
||||
def _get_options_bag(self,
|
||||
follower_not_apply_requires: bool,
|
||||
) -> OptionBag:
|
||||
try:
|
||||
options_bag = self._config_bag.context.get_sub_option_bag(self._config_bag,
|
||||
self._path,
|
||||
self._index,
|
||||
self._validate_properties,
|
||||
follower_not_apply_requires=follower_not_apply_requires,
|
||||
)
|
||||
except AssertionError as err:
|
||||
raise ConfigError(str(err))
|
||||
|
@ -122,7 +125,7 @@ def option_type(typ):
|
|||
)]
|
||||
kwargs['is_group'] = True
|
||||
return func(self, options_bag, *args[1:], **kwargs)
|
||||
options_bag = self._get_options_bag()
|
||||
options_bag = self._get_options_bag('with_index' not in types)
|
||||
option = options_bag[-1].option
|
||||
if option.impl_is_optiondescription() and 'optiondescription' in types or \
|
||||
not option.impl_is_optiondescription() and (
|
||||
|
@ -135,12 +138,13 @@ def option_type(typ):
|
|||
if not option.impl_is_optiondescription() and \
|
||||
not option.impl_is_symlinkoption() and \
|
||||
option.impl_is_follower():
|
||||
# default is "without_index"
|
||||
if 'with_index' not in types and 'with_or_without_index' not in types and \
|
||||
self._index is not None:
|
||||
msg = _('please do not specify index '
|
||||
f'({self.__class__.__name__}.{func.__name__})')
|
||||
raise ConfigError(_(msg))
|
||||
if 'with_index' in types and self._index is None:
|
||||
if self._index is None and 'with_index' in types:
|
||||
msg = _('please specify index with a follower option '
|
||||
f'({self.__class__.__name__}.{func.__name__})')
|
||||
raise ConfigError(msg)
|
||||
|
@ -251,7 +255,7 @@ class _TiramisuOptionOptionDescription:
|
|||
option_bag = options_bag[-1]
|
||||
return option_bag.path
|
||||
|
||||
@option_type(['optiondescription', 'option', 'symlink'])
|
||||
@option_type(['optiondescription', 'option', 'symlink', 'with_or_without_index'])
|
||||
def has_dependency(self,
|
||||
options_bag: List[OptionBag],
|
||||
self_is_dep=True,
|
||||
|
@ -355,7 +359,7 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
|
|||
return 'optiondescription'
|
||||
return option_bag.option.get_type()
|
||||
|
||||
@option_type('option')
|
||||
@option_type(['option', 'with_or_without_index'])
|
||||
def pattern(self, options_bag: List[OptionBag]) -> str:
|
||||
"""Get the option pattern"""
|
||||
option_bag = options_bag[-1]
|
||||
|
|
|
@ -539,6 +539,8 @@ def carry_out_calculation(option,
|
|||
- tuple with option and boolean's force_permissive (True when don't raise
|
||||
if PropertiesOptionError)
|
||||
Values could have multiple values only when key is ''."""
|
||||
if not option.impl_is_optiondescription() and option.impl_is_follower() and index is None:
|
||||
raise Exception('follower must have index in carry_out_calculation!')
|
||||
def fake_items(iterator):
|
||||
return ((None, i) for i in iterator)
|
||||
args = []
|
||||
|
|
|
@ -342,6 +342,7 @@ class _SubConfig:
|
|||
opt.impl_getpath(),
|
||||
None,
|
||||
True,
|
||||
follower_not_apply_requires=flatten_leadership,
|
||||
)[-1],
|
||||
types=types,
|
||||
recursive=recursive,
|
||||
|
@ -721,6 +722,7 @@ class _CommonConfig(_SubConfig):
|
|||
validate_properties: bool,
|
||||
leadership_length: int=None,
|
||||
properties=undefined,
|
||||
follower_not_apply_requires: bool=False,
|
||||
) -> List[OptionBag]:
|
||||
"""Get the suboption for path and the name of the option
|
||||
:returns: tuple (config, name)"""
|
||||
|
@ -734,12 +736,12 @@ class _CommonConfig(_SubConfig):
|
|||
option_bag = bag
|
||||
if option_bag.option != option_bag.config_bag.context.get_description():
|
||||
path = path[len(option_bag.path) + 1:]
|
||||
path = path.split('.')
|
||||
last_idx = len(path) - 1
|
||||
split_path = path.split('.')
|
||||
last_idx = len(split_path) - 1
|
||||
suboption = option_bag.option
|
||||
options_bag = []
|
||||
sub_option_bag = option_bag
|
||||
for idx, step in enumerate(path):
|
||||
for idx, step in enumerate(split_path):
|
||||
if not suboption.impl_is_optiondescription():
|
||||
raise TypeError(f'{suboption.impl_getpath()} is not an optiondescription')
|
||||
|
||||
|
@ -753,9 +755,9 @@ class _CommonConfig(_SubConfig):
|
|||
)
|
||||
if idx == last_idx:
|
||||
option_index = index
|
||||
else:
|
||||
option_index = None
|
||||
if idx == last_idx:
|
||||
apply_requires = not follower_not_apply_requires or \
|
||||
option.impl_is_optiondescription() or \
|
||||
not option.impl_is_follower()
|
||||
if option_index is not None:
|
||||
if option.impl_is_optiondescription() or \
|
||||
option.impl_is_symlinkoption() or \
|
||||
|
@ -771,11 +773,14 @@ class _CommonConfig(_SubConfig):
|
|||
f'"{option.impl_get_display_name()}"'))
|
||||
option_properties = properties
|
||||
else:
|
||||
option_index = None
|
||||
apply_requires = True
|
||||
option_properties = undefined
|
||||
sub_option_bag = OptionBag(option,
|
||||
option_index,
|
||||
option_bag.config_bag,
|
||||
properties=option_properties,
|
||||
apply_requires=apply_requires,
|
||||
)
|
||||
if validate_properties:
|
||||
self.get_settings().validate_properties(sub_option_bag)
|
||||
|
|
|
@ -165,16 +165,20 @@ class Leadership(OptionDescription):
|
|||
dyn = self
|
||||
values = config_bag.context.get_values()
|
||||
for idx, follower in enumerate(dyn.get_children(config_bag)):
|
||||
if not idx:
|
||||
# it's a master
|
||||
apply_requires = True
|
||||
indexes = [None]
|
||||
else:
|
||||
apply_requires = False
|
||||
indexes = range(len(value))
|
||||
foption_bag = OptionBag(follower,
|
||||
None,
|
||||
config_bag,
|
||||
apply_requires=apply_requires,
|
||||
)
|
||||
if 'force_store_value' not in foption_bag.properties:
|
||||
continue
|
||||
if idx == 0:
|
||||
indexes = [None]
|
||||
else:
|
||||
indexes = range(len(value))
|
||||
for index in indexes:
|
||||
foption_bag_index = OptionBag(follower,
|
||||
index,
|
||||
|
|
Loading…
Reference in a new issue