Compare commits

...

2 commits

Author SHA1 Message Date
6f2f479364 fix: allow_dynoption in group_type() 2025-10-15 11:30:22 +02:00
0513d6677e fix: black 2025-10-15 09:43:56 +02:00
6 changed files with 105 additions and 23 deletions

View file

@ -515,6 +515,8 @@ def test_dyndescription_subdyn():
assert cfg.option('od.dod2val1.dodval1.st').type() == "string" assert cfg.option('od.dod2val1.dodval1.st').type() == "string"
assert cfg.option('od.dod2.dod').type() == "optiondescription" assert cfg.option('od.dod2.dod').type() == "optiondescription"
assert cfg.option('od.dod2val1.dodval1').type() == "optiondescription" assert cfg.option('od.dod2val1.dodval1').type() == "optiondescription"
assert cfg.option('od.dod2.dod').group_type() == "default"
assert cfg.option('od.dod2val1.dodval1').group_type() == "default"
# #
with pytest.raises(AttributeOptionError): with pytest.raises(AttributeOptionError):
cfg.option('od.dod2.dod').identifiers() cfg.option('od.dod2.dod').identifiers()

View file

@ -162,7 +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: 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") raise AttributeOptionError(self._subconfig.path, "option-dynamic")
option = self._subconfig.option option = self._subconfig.option
@ -321,7 +323,15 @@ class _TiramisuOptionOptionDescription:
"""Test if option is a leader or a follower""" """Test if option is a leader or a follower"""
return self._subconfig.option.impl_is_leadership() return self._subconfig.option.impl_is_leadership()
@option_type(["optiondescription", "option", "with_or_without_index", "symlink", "allow_dynoption"]) @option_type(
[
"optiondescription",
"option",
"with_or_without_index",
"symlink",
"allow_dynoption",
]
)
def description( def description(
self, self,
with_quote: bool = False, with_quote: bool = False,
@ -338,7 +348,15 @@ class _TiramisuOptionOptionDescription:
None, None,
) )
@option_type(["optiondescription", "option", "symlink", "with_or_without_index", "allow_dynoption"]) @option_type(
[
"optiondescription",
"option",
"symlink",
"with_or_without_index",
"allow_dynoption",
]
)
def name( def name(
self, self,
*, *,
@ -351,7 +369,15 @@ class _TiramisuOptionOptionDescription:
raise AttributeOptionError(self._subconfig.path, "option-dynamic") raise AttributeOptionError(self._subconfig.path, "option-dynamic")
return self._subconfig.true_path.rsplit(".", 1)[-1] return self._subconfig.true_path.rsplit(".", 1)[-1]
@option_type(["optiondescription", "option", "with_or_without_index", "symlink", "allow_dynoption"]) @option_type(
[
"optiondescription",
"option",
"with_or_without_index",
"symlink",
"allow_dynoption",
]
)
def path( def path(
self, self,
*, *,
@ -443,7 +469,15 @@ class _TiramisuOptionOptionDescription:
) )
return options return options
@option_type(["option", "optiondescription", "symlink", "with_or_without_index", "allow_dynoption"]) @option_type(
[
"option",
"optiondescription",
"symlink",
"with_or_without_index",
"allow_dynoption",
]
)
def type(self, only_self=False, translation=False): def type(self, only_self=False, translation=False):
"""Get de option type""" """Get de option type"""
option = self._subconfig.option option = self._subconfig.option
@ -466,7 +500,15 @@ class _TiramisuOptionOptionDescription:
"""Get de option extra""" """Get de option extra"""
return self._subconfig.option.impl_get_extra(extra) return self._subconfig.option.impl_get_extra(extra)
@option_type(["option", "optiondescription", "symlink", "with_or_without_index", "allow_dynoption"]) @option_type(
[
"option",
"optiondescription",
"symlink",
"with_or_without_index",
"allow_dynoption",
]
)
def isdynamic(self, *, only_self: bool = False): def isdynamic(self, *, only_self: bool = False):
"""Test if option is a dynamic optiondescription""" """Test if option is a dynamic optiondescription"""
if not only_self: if not only_self:
@ -675,7 +717,9 @@ class TiramisuOptionProperty(CommonTiramisuOption):
_validate_properties = False _validate_properties = False
@option_type(["option", "optiondescription", "with_index", "symlink", "allow_dynoption"]) @option_type(
["option", "optiondescription", "with_index", "symlink", "allow_dynoption"]
)
def get( def get(
self, self,
*, *,
@ -807,7 +851,15 @@ class TiramisuOptionInformation(CommonTiramisuOption):
_validate_properties = False _validate_properties = False
@option_type(["option", "optiondescription", "with_or_without_index", "symlink", "allow_dynoption"]) @option_type(
[
"option",
"optiondescription",
"with_or_without_index",
"symlink",
"allow_dynoption",
]
)
def get( def get(
self, self,
name: str, name: str,
@ -840,7 +892,15 @@ class TiramisuOptionInformation(CommonTiramisuOption):
path=self._path, path=self._path,
) )
@option_type(["option", "optiondescription", "with_or_without_index", "symlink", "allow_dynoption"]) @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())
@ -1149,7 +1209,7 @@ class TiramisuOption(
subconfig=sub_subconfig, subconfig=sub_subconfig,
) )
@option_type("optiondescription") @option_type(["optiondescription", "allow_dynoption"])
def group_type(self): def group_type(self):
"""Get type for an optiondescription (only for optiondescription)""" """Get type for an optiondescription (only for optiondescription)"""
self._set_subconfig() self._set_subconfig()

View file

@ -25,7 +25,13 @@ 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, AttributeOptionError 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
@ -273,8 +279,16 @@ class SubConfig:
self.true_path = true_path self.true_path = true_path
if 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) self.is_dynamic_without_identifiers = identifiers is None or (
if check_dynamic_without_identifiers and parent and parent.is_dynamic and self.is_dynamic_without_identifiers != parent.is_dynamic_without_identifiers: 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") raise AttributeOptionError(true_path, "option-dynamic")
elif parent: elif parent:
self.is_dynamic = parent.is_dynamic self.is_dynamic = parent.is_dynamic
@ -398,7 +412,7 @@ class SubConfig:
name = dyn_child.path name = dyn_child.path
if name in children_name: if name in children_name:
raise ConflictError( raise ConflictError(
_("option name \"{0}\" is not unique in {1}").format( _('option name "{0}" is not unique in {1}').format(
name, name,
self.option.impl_get_display_name( self.option.impl_get_display_name(
self, with_quote=True self, with_quote=True
@ -420,7 +434,7 @@ class SubConfig:
name = child.impl_getpath() name = child.impl_getpath()
if name in children_name: if name in children_name:
raise ConflictError( raise ConflictError(
_("option name \"{0}\" is not unique in {1}").format( _('option name "{0}" is not unique in {1}').format(
name, name,
self.option.impl_get_display_name( self.option.impl_get_display_name(
self, with_quote=True self, with_quote=True
@ -756,7 +770,7 @@ class _Config(CCache):
): ):
if path == dyn_child.path: if path == dyn_child.path:
raise ConflictError( raise ConflictError(
_("option name \"{0}\" is not unique in {1}").format( _('option name "{0}" is not unique in {1}').format(
name, name,
option.impl_get_display_name( option.impl_get_display_name(
subconfig, with_quote=True subconfig, with_quote=True
@ -765,7 +779,7 @@ class _Config(CCache):
) )
elif child.impl_getname() == name: elif child.impl_getname() == name:
raise ConflictError( raise ConflictError(
_("option name \"{0}\" is not unique in {1}").format( _('option name "{0}" is not unique in {1}').format(
name, name,
self.option.impl_get_display_name( self.option.impl_get_display_name(
self, with_quote=True self, with_quote=True

View file

@ -364,10 +364,10 @@ class ValueOptionError(_CommonError, ValueError):
def __init__(self, **kwargs): def __init__(self, **kwargs):
if ValueOptionError.tmpl is None: if ValueOptionError.tmpl is None:
opt = kwargs.get('opt') opt = kwargs.get("opt")
if opt and opt._do_not_display_value_in_error: if opt and opt._do_not_display_value_in_error:
if kwargs.get("index") is None: if kwargs.get("index") is None:
self.tmpl = _('{2} has an invalid {1}') self.tmpl = _("{2} has an invalid {1}")
else: else:
self.tmpl = _('{2} at index "{3}" has an invalid {1}') self.tmpl = _('{2} at index "{3}" has an invalid {1}')
else: else:

View file

@ -138,9 +138,7 @@ class DynOptionDescription(OptionDescription):
raise ValueError( raise ValueError(
_( _(
"DynOptionDescription identifiers for option {0}, is not a list ({1})" "DynOptionDescription identifiers for option {0}, is not a list ({1})"
).format( ).format(name, values)
name, values
)
) )
values_ = [] values_ = []
for val in values: for val in values:

View file

@ -31,7 +31,15 @@ class IntOption(Option):
_type = "integer" _type = "integer"
_t_type = _("integer") _t_type = _("integer")
def __init__(self, *args, min_number=None, max_number=None, min_integer=None, max_integer=None, **kwargs): def __init__(
self,
*args,
min_number=None,
max_number=None,
min_integer=None,
max_integer=None,
**kwargs,
):
extra = {} extra = {}
if min_number is not None: if min_number is not None:
extra["min_integer"] = min_number extra["min_integer"] = min_number