feat: property.get(uncalculated=True) is now possible for an dynoptiondescription without identifiers
This commit is contained in:
parent
e8921795d3
commit
e0f16b14c7
5 changed files with 69 additions and 14 deletions
|
|
@ -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
|
from tiramisu.error import PropertiesOptionError, ConfigError, ConflictError, ValueOptionError, AttributeOptionError
|
||||||
|
|
||||||
|
|
||||||
def display_name(kls, subconfig, with_quote=False) -> str:
|
def display_name(kls, subconfig, with_quote=False) -> str:
|
||||||
|
|
@ -317,6 +317,20 @@ def test_prop_dyndescription():
|
||||||
# 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))
|
||||||
|
|
@ -451,6 +465,30 @@ def test_callback_dyndescription_outside_optional():
|
||||||
# assert not list_sessions()
|
# 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)
|
||||||
|
with pytest.raises(AttributeOptionError):
|
||||||
|
cfg.option('od.dod2val1.dod.st').property.get(uncalculated=True)
|
||||||
|
|
||||||
|
|
||||||
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')
|
||||||
|
|
|
||||||
|
|
@ -26,6 +26,7 @@ from .error import (
|
||||||
LeadershipError,
|
LeadershipError,
|
||||||
ValueErrorWarning,
|
ValueErrorWarning,
|
||||||
PropertiesOptionError,
|
PropertiesOptionError,
|
||||||
|
AttributeOptionError,
|
||||||
)
|
)
|
||||||
from .i18n import _
|
from .i18n import _
|
||||||
from .setting import (
|
from .setting import (
|
||||||
|
|
@ -123,7 +124,6 @@ class TiramisuHelp:
|
||||||
|
|
||||||
class CommonTiramisu(TiramisuHelp):
|
class CommonTiramisu(TiramisuHelp):
|
||||||
_validate_properties = True
|
_validate_properties = True
|
||||||
_allow_dynoption = False
|
|
||||||
|
|
||||||
def _set_subconfig(self) -> None:
|
def _set_subconfig(self) -> None:
|
||||||
if not self._subconfig:
|
if not self._subconfig:
|
||||||
|
|
@ -133,7 +133,7 @@ class CommonTiramisu(TiramisuHelp):
|
||||||
self._path,
|
self._path,
|
||||||
self._index,
|
self._index,
|
||||||
validate_properties=False,
|
validate_properties=False,
|
||||||
allow_dynoption=self._allow_dynoption,
|
allow_dynoption=True,
|
||||||
)
|
)
|
||||||
except AssertionError as err:
|
except AssertionError as err:
|
||||||
raise ConfigError(str(err))
|
raise ConfigError(str(err))
|
||||||
|
|
@ -149,8 +149,6 @@ def option_type(typ):
|
||||||
@wraps(func)
|
@wraps(func)
|
||||||
def wrapped(*args, **kwargs):
|
def wrapped(*args, **kwargs):
|
||||||
self = args[0]
|
self = args[0]
|
||||||
if isinstance(typ, list) and "allow_dynoption" in typ:
|
|
||||||
self._allow_dynoption = True
|
|
||||||
config_bag = self._config_bag
|
config_bag = self._config_bag
|
||||||
if self._config_bag.context.impl_type == "group" and "group" in types:
|
if self._config_bag.context.impl_type == "group" and "group" in types:
|
||||||
options_bag = [
|
options_bag = [
|
||||||
|
|
@ -164,6 +162,9 @@ def option_type(typ):
|
||||||
kwargs["is_group"] = True
|
kwargs["is_group"] = True
|
||||||
return func(self, options_bag, *args[1:], **kwargs)
|
return func(self, options_bag, *args[1:], **kwargs)
|
||||||
self._set_subconfig()
|
self._set_subconfig()
|
||||||
|
if (not isinstance(typ, list) or "allow_dynoption" not in typ) and self._subconfig.is_dynamic_without_identifiers:
|
||||||
|
raise AttributeOptionError(self._subconfig.path, "option-dynamic")
|
||||||
|
|
||||||
option = self._subconfig.option
|
option = self._subconfig.option
|
||||||
error_type = None
|
error_type = None
|
||||||
if "dynamic" in types:
|
if "dynamic" in types:
|
||||||
|
|
@ -668,7 +669,7 @@ class TiramisuOptionProperty(CommonTiramisuOption):
|
||||||
|
|
||||||
_validate_properties = False
|
_validate_properties = False
|
||||||
|
|
||||||
@option_type(["option", "optiondescription", "with_index", "symlink"])
|
@option_type(["option", "optiondescription", "with_index", "symlink", "allow_dynoption"])
|
||||||
def get(
|
def get(
|
||||||
self,
|
self,
|
||||||
*,
|
*,
|
||||||
|
|
@ -677,6 +678,8 @@ class TiramisuOptionProperty(CommonTiramisuOption):
|
||||||
uncalculated: bool = False,
|
uncalculated: bool = False,
|
||||||
):
|
):
|
||||||
"""Get properties for an option"""
|
"""Get properties for an option"""
|
||||||
|
if self._subconfig.is_dynamic_without_identifiers and not uncalculated:
|
||||||
|
raise AttributeOptionError(self._subconfig.path, "option-dynamic")
|
||||||
settings = self._config_bag.context.get_settings()
|
settings = self._config_bag.context.get_settings()
|
||||||
if not only_raises:
|
if not only_raises:
|
||||||
return settings.getproperties(
|
return settings.getproperties(
|
||||||
|
|
@ -797,9 +800,8 @@ class TiramisuOptionInformation(CommonTiramisuOption):
|
||||||
"""Manage option's informations"""
|
"""Manage option's informations"""
|
||||||
|
|
||||||
_validate_properties = False
|
_validate_properties = False
|
||||||
_allow_dynoption = True
|
|
||||||
|
|
||||||
@option_type(["option", "optiondescription", "with_or_without_index", "symlink"])
|
@option_type(["option", "optiondescription", "with_or_without_index", "symlink", "allow_dynoption"])
|
||||||
def get(
|
def get(
|
||||||
self,
|
self,
|
||||||
name: str,
|
name: str,
|
||||||
|
|
@ -812,7 +814,7 @@ class TiramisuOptionInformation(CommonTiramisuOption):
|
||||||
default,
|
default,
|
||||||
)
|
)
|
||||||
|
|
||||||
@option_type(["option", "optiondescription"])
|
@option_type(["option", "optiondescription", "allow_dynoption"])
|
||||||
def set(self, key: str, value: Any) -> None:
|
def set(self, key: str, value: Any) -> None:
|
||||||
"""Set information"""
|
"""Set information"""
|
||||||
self._config_bag.context.get_values().set_information(
|
self._config_bag.context.get_values().set_information(
|
||||||
|
|
@ -821,7 +823,7 @@ class TiramisuOptionInformation(CommonTiramisuOption):
|
||||||
value,
|
value,
|
||||||
)
|
)
|
||||||
|
|
||||||
@option_type(["option", "optiondescription"])
|
@option_type(["option", "optiondescription", "allow_dynoption"])
|
||||||
def remove(
|
def remove(
|
||||||
self,
|
self,
|
||||||
key: str,
|
key: str,
|
||||||
|
|
@ -832,7 +834,7 @@ class TiramisuOptionInformation(CommonTiramisuOption):
|
||||||
path=self._path,
|
path=self._path,
|
||||||
)
|
)
|
||||||
|
|
||||||
@option_type(["option", "optiondescription", "with_or_without_index", "symlink"])
|
@option_type(["option", "optiondescription", "with_or_without_index", "symlink", "allow_dynoption"])
|
||||||
def list(self) -> list:
|
def list(self) -> list:
|
||||||
"""List information's keys"""
|
"""List information's keys"""
|
||||||
lst1 = set(self._subconfig.option._list_information())
|
lst1 = set(self._subconfig.option._list_information())
|
||||||
|
|
@ -1106,7 +1108,6 @@ class TiramisuOption(
|
||||||
self._path = path
|
self._path = path
|
||||||
self._index = index
|
self._index = index
|
||||||
self._config_bag = config_bag
|
self._config_bag = config_bag
|
||||||
self._allow_dynoption = allow_dynoption
|
|
||||||
self._subconfig = subconfig
|
self._subconfig = subconfig
|
||||||
if not self._registers:
|
if not self._registers:
|
||||||
_registers(self._registers, "TiramisuOption")
|
_registers(self._registers, "TiramisuOption")
|
||||||
|
|
|
||||||
|
|
@ -25,7 +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 PropertiesOptionError, ConfigError, ConflictError, LeadershipError
|
from .error import 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
|
||||||
|
|
@ -237,6 +237,7 @@ class SubConfig:
|
||||||
"apply_requires",
|
"apply_requires",
|
||||||
"transitive_properties",
|
"transitive_properties",
|
||||||
"is_dynamic",
|
"is_dynamic",
|
||||||
|
"is_dynamic_without_identifiers",
|
||||||
"identifiers",
|
"identifiers",
|
||||||
"_length",
|
"_length",
|
||||||
)
|
)
|
||||||
|
|
@ -254,6 +255,7 @@ class SubConfig:
|
||||||
# for python 3.9 properties: Union[list[str], undefined] = undefined,
|
# for python 3.9 properties: Union[list[str], undefined] = undefined,
|
||||||
properties=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
|
||||||
|
|
@ -269,10 +271,17 @@ 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 parent and parent.is_dynamic or self.option.impl_is_dynoptiondescription():
|
if 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 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:
|
||||||
|
|
@ -433,6 +442,7 @@ class SubConfig:
|
||||||
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:
|
||||||
|
|
@ -461,6 +471,7 @@ class SubConfig:
|
||||||
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():
|
||||||
|
|
@ -512,6 +523,7 @@ class SubConfig:
|
||||||
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()
|
||||||
|
|
@ -571,6 +583,7 @@ class SubConfig:
|
||||||
None,
|
None,
|
||||||
validate_properties,
|
validate_properties,
|
||||||
true_path=true_path,
|
true_path=true_path,
|
||||||
|
check_dynamic_without_identifiers=check_dynamic_without_identifiers,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
parents = new_parents
|
parents = new_parents
|
||||||
|
|
@ -581,6 +594,7 @@ class SubConfig:
|
||||||
search_option,
|
search_option,
|
||||||
index,
|
index,
|
||||||
validate_properties,
|
validate_properties,
|
||||||
|
check_dynamic_without_identifiers=check_dynamic_without_identifiers,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
if subconfigs_is_a_list:
|
if subconfigs_is_a_list:
|
||||||
|
|
|
||||||
|
|
@ -115,6 +115,7 @@ 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):
|
||||||
|
|
|
||||||
|
|
@ -395,6 +395,7 @@ 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]
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue