feat: ParamSelfOption accept dynamic=False
This commit is contained in:
parent
faf694397a
commit
050979f6d3
6 changed files with 167 additions and 78 deletions
|
|
@ -39,12 +39,18 @@ def return_true(value, param=None, identifier=None):
|
|||
raise ValueError('no value')
|
||||
|
||||
|
||||
def return_no_dyn(value, identifier):
|
||||
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):
|
||||
return value
|
||||
|
||||
|
|
@ -1138,7 +1144,7 @@ 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), ParamIdentifier())))])
|
||||
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])
|
||||
|
|
@ -1149,6 +1155,28 @@ def test_validator_param_self_option():
|
|||
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():
|
||||
val1 = StrOption('val1', '', ['val1', 'val2'], multi=True)
|
||||
st = StrOption('st', '')
|
||||
|
|
|
|||
|
|
@ -6,7 +6,7 @@ import pytest
|
|||
|
||||
from tiramisu import BoolOption, StrOption, IPOption, NetmaskOption, NetworkOption, BroadcastOption, \
|
||||
IntOption, OptionDescription, Leadership, Config, Params, ParamValue, ParamOption, \
|
||||
ParamSelfOption, ParamIndex, ParamInformation, ParamSelfInformation, ParamSelfOption, Calculation, \
|
||||
ParamSelfOption, ParamIndex, ParamInformation, ParamSelfInformation, Calculation, \
|
||||
valid_ip_netmask, valid_network_netmask, \
|
||||
valid_in_network, valid_broadcast, valid_not_equal
|
||||
from tiramisu.setting import groups
|
||||
|
|
|
|||
|
|
@ -172,15 +172,17 @@ class ParamDynOption(ParamOption):
|
|||
|
||||
|
||||
class ParamSelfOption(Param):
|
||||
__slots__ = "whole"
|
||||
__slots__ = ("whole", "dynamic")
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
whole: bool = undefined,
|
||||
dynamic: bool = True,
|
||||
) -> None:
|
||||
"""whole: send all value for a multi, not only indexed value"""
|
||||
if whole is not undefined:
|
||||
self.whole = whole
|
||||
self.dynamic = dynamic
|
||||
|
||||
|
||||
class ParamValue(Param):
|
||||
|
|
@ -613,6 +615,33 @@ def manager_callback(
|
|||
return subconfig.identifiers[param.identifier_index]
|
||||
|
||||
if isinstance(param, ParamSelfOption):
|
||||
search_option = subconfig.option
|
||||
if subconfig.option.issubdyn() and not param.dynamic:
|
||||
subconfigs = subconfig.parent.parent.get_common_child(
|
||||
search_option,
|
||||
true_path=subconfig.path,
|
||||
validate_properties=False,
|
||||
)
|
||||
values = []
|
||||
properties = config_bag.context.get_settings().getproperties(
|
||||
subconfig,
|
||||
uncalculated=True,
|
||||
) - {'validator'}
|
||||
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,
|
||||
|
|
@ -762,7 +791,9 @@ def manager_callback(
|
|||
]
|
||||
values = None
|
||||
for subconfig in subconfigs:
|
||||
callbk_option = subconfig.option
|
||||
if isinstance(subconfig, PropertiesOptionError):
|
||||
value = subconfig
|
||||
else:
|
||||
value = get_value(
|
||||
config_bag,
|
||||
subconfig,
|
||||
|
|
@ -777,6 +808,8 @@ def manager_callback(
|
|||
value = values
|
||||
if callback.__name__ not in FUNCTION_WAITING_FOR_DICT:
|
||||
return value
|
||||
# FIXME the last one?
|
||||
callbk_option = subconfig.option
|
||||
return {"name": callbk_option.impl_get_display_name(subconfig), "value": value}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -42,8 +42,14 @@ from . import autolib
|
|||
|
||||
|
||||
def get_common_path(path1, path2):
|
||||
if None in (path1, path2):
|
||||
return None
|
||||
common_path = commonprefix([path1, path2])
|
||||
if common_path in [path1, path2]:
|
||||
all_paths = [path1, path2]
|
||||
if common_path in all_paths:
|
||||
# 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("."):
|
||||
return common_path[:-1]
|
||||
|
|
@ -88,23 +94,30 @@ class CCache:
|
|||
subconfig,
|
||||
resetted_opts,
|
||||
is_default,
|
||||
*,
|
||||
force=False,
|
||||
):
|
||||
"""reset cache for one option"""
|
||||
if subconfig.path in resetted_opts:
|
||||
if not force and subconfig.path in resetted_opts:
|
||||
return
|
||||
resetted_opts.append(subconfig.path)
|
||||
config_bag = subconfig.config_bag
|
||||
# if is_default and config_bag.context.get_owner(subconfig) != owners.default:
|
||||
# return
|
||||
if not force:
|
||||
# if is_default and config_bag.context.get_owner(subconfig) != owners.default:
|
||||
# return
|
||||
for is_default, woption in subconfig.option.get_dependencies(subconfig.option):
|
||||
option = woption()
|
||||
if option.issubdyn():
|
||||
# it's an option in dynoptiondescription, remove cache for all generated option
|
||||
if option.impl_getpath() == subconfig.option.impl_getpath():
|
||||
force = True
|
||||
subconfig = subconfig.parent.parent
|
||||
self.reset_cache_dyn_option(
|
||||
subconfig,
|
||||
option,
|
||||
resetted_opts,
|
||||
is_default,
|
||||
force,
|
||||
)
|
||||
elif option.impl_is_dynoptiondescription():
|
||||
self.reset_cache_dyn_optiondescription(
|
||||
|
|
@ -182,6 +195,10 @@ class CCache:
|
|||
def get_dynamic_from_dyn_option(self, subconfig, option):
|
||||
config_bag = subconfig.config_bag
|
||||
sub_paths = option.impl_getpath()
|
||||
if not subconfig.path:
|
||||
current_paths = []
|
||||
current_paths_max_index = 0
|
||||
else:
|
||||
current_paths = subconfig.path.split(".")
|
||||
current_paths_max_index = len(current_paths) - 1
|
||||
current_subconfigs = []
|
||||
|
|
@ -189,7 +206,7 @@ class CCache:
|
|||
while True:
|
||||
current_subconfigs.insert(0, parent)
|
||||
parent = parent.parent
|
||||
if parent.path is None:
|
||||
if not parent or parent.path is None:
|
||||
break
|
||||
currents = [self.get_root(config_bag)]
|
||||
for idx, sub_path in enumerate(sub_paths.split(".")):
|
||||
|
|
@ -234,12 +251,14 @@ class CCache:
|
|||
option,
|
||||
resetted_opts,
|
||||
is_default,
|
||||
force,
|
||||
):
|
||||
for dyn_option_subconfig in self.get_dynamic_from_dyn_option(subconfig, option):
|
||||
self.reset_one_option_cache(
|
||||
dyn_option_subconfig,
|
||||
resetted_opts,
|
||||
is_default,
|
||||
force=force,
|
||||
)
|
||||
|
||||
|
||||
|
|
@ -569,10 +588,17 @@ class SubConfig:
|
|||
parents = [self.parent]
|
||||
else:
|
||||
if common_path:
|
||||
parent = self.parent
|
||||
common_parent_number = common_path.count(".") + 1
|
||||
for idx in range(current_option_path.count(".") - common_parent_number):
|
||||
parent_count = current_option_path.count(".") - common_parent_number
|
||||
if parent_count >= 0:
|
||||
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]
|
||||
else:
|
||||
common_parent_number = 0
|
||||
|
|
@ -617,14 +643,16 @@ class SubConfig:
|
|||
parents = new_parents
|
||||
subconfigs = []
|
||||
for parent in parents:
|
||||
subconfigs.append(
|
||||
parent.get_child(
|
||||
try:
|
||||
ret = parent.get_child(
|
||||
search_option,
|
||||
index,
|
||||
validate_properties,
|
||||
check_dynamic_without_identifiers=check_dynamic_without_identifiers,
|
||||
)
|
||||
)
|
||||
except PropertiesOptionError as err:
|
||||
ret = err
|
||||
subconfigs.append(ret)
|
||||
if subconfigs_is_a_list:
|
||||
return subconfigs
|
||||
return subconfigs[0]
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ from itertools import chain
|
|||
|
||||
from ..i18n import _
|
||||
from ..setting import undefined
|
||||
from ..autolib import Calculation, ParamOption, ParamInformation, ParamSelfInformation
|
||||
from ..autolib import Calculation, ParamOption, ParamSelfOption, ParamInformation, ParamSelfInformation
|
||||
|
||||
STATIC_TUPLE = frozenset()
|
||||
|
||||
|
|
@ -104,9 +104,7 @@ class Base:
|
|||
"Calculation"
|
||||
).format(type(prop), name)
|
||||
)
|
||||
for param in chain(prop.params.args, prop.params.kwargs.values()):
|
||||
if isinstance(param, ParamOption):
|
||||
param.option._add_dependency(self, "property")
|
||||
self.value_dependency(prop, type_="property")
|
||||
if properties:
|
||||
_setattr(self, "_properties", properties)
|
||||
self.set_informations(informations)
|
||||
|
|
@ -395,16 +393,20 @@ class BaseOption(Base):
|
|||
self,
|
||||
value: Any,
|
||||
is_identifier: bool = False,
|
||||
type_: str = 'default'
|
||||
) -> Any:
|
||||
"""parse dependancy to add dependencies"""
|
||||
for param in chain(value.params.args, value.params.kwargs.values()):
|
||||
if isinstance(param, ParamOption):
|
||||
# pylint: disable=protected-access
|
||||
if is_identifier:
|
||||
type_ = "identifier"
|
||||
_type_ = "identifier"
|
||||
else:
|
||||
type_ = "default"
|
||||
param.option._add_dependency(self, type_, is_identifier=is_identifier)
|
||||
_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
|
||||
elif isinstance(param, ParamInformation):
|
||||
dest = self
|
||||
|
|
|
|||
|
|
@ -45,9 +45,7 @@ class ChoiceOption(Option):
|
|||
:param values: is a list of values the option can possibly take
|
||||
"""
|
||||
if isinstance(values, Calculation):
|
||||
for param in chain(values.params.args, values.params.kwargs.values()):
|
||||
if isinstance(param, ParamOption):
|
||||
param.option._add_dependency(self, "choice")
|
||||
self.value_dependency(values, "choice")
|
||||
elif not isinstance(values, tuple):
|
||||
raise TypeError(
|
||||
_("values must be a tuple or a calculation for {0}").format(name)
|
||||
|
|
|
|||
Loading…
Reference in a new issue