feat: add subconfig in errors

This commit is contained in:
egarette@silique.fr 2025-12-19 13:30:30 +01:00
parent 050979f6d3
commit fe108b1238
13 changed files with 41 additions and 24 deletions

View file

@ -402,12 +402,12 @@ def test_prefix_error():
try:
cfg.option('test1').value.set('yes')
except Exception as err:
assert str(err) == _('"{0}" is an invalid {1} for "{2}", which is not an integer').format('yes', _('integer'), 'test1')
assert str(err) == _('"{0}" is an invalid {1} for "{2}", it\'s not an integer').format('yes', _('integer'), 'test1')
try:
cfg.option('test1').value.set('yes')
except Exception as err:
err.prefix = ''
assert str(err) == _('which is not an integer')
assert str(err) == _('it\'s not an integer')
# assert not list_sessions()

View file

@ -583,6 +583,7 @@ class _TiramisuOptionOptionDescription:
convert: bool = False,
):
"""Get identifiers for dynamic option"""
subconfig = self._subconfig
if not only_self:
if self._subconfig.is_dynamic_without_identifiers and not uncalculated:
raise AttributeOptionError(self._subconfig.path, "option-dynamic")
@ -590,7 +591,6 @@ class _TiramisuOptionOptionDescription:
return self._subconfig.identifiers
identifiers = []
dynconfig = None
subconfig = self._subconfig
while not dynconfig:
if subconfig.option.impl_is_optiondescription() and subconfig.option.impl_is_dynoptiondescription():
dynconfig = subconfig
@ -607,7 +607,8 @@ class _TiramisuOptionOptionDescription:
raise ConfigError(
_(
"the option {0} is not a dynamic option, cannot get identifiers with only_self parameter to True"
).format(self._subconfig.path)
).format(self._subconfig.path),
subconfig=subconfig,
)
return self._subconfig.option.get_identifiers(
self._subconfig.parent,

View file

@ -462,7 +462,7 @@ def manager_callback(
or param.raisepropertyerror
):
raise err from err
raise ConfigError(err)
raise ConfigError(err, subconfig=subconfig)
except ValueError as err:
display_name = subconfig.option.impl_get_display_name(
subconfig, with_quote=True
@ -626,7 +626,7 @@ def manager_callback(
properties = config_bag.context.get_settings().getproperties(
subconfig,
uncalculated=True,
) - {'validator'}
) - {'validator', 'mandatory', 'empty'}
for subconfig_ in subconfigs:
if subconfig.path == subconfig_.path:
values.append(orig_value)
@ -958,6 +958,7 @@ def calculate(
raise err from err
error = err
except ConfigError as err:
err.subconfig = subconfig
raise err from err
except Exception as err:
error = err

View file

@ -522,7 +522,7 @@ class SubConfig:
)
if check_index and index is not None:
if option.impl_is_optiondescription() or not option.impl_is_follower():
raise ConfigError("index must be set only with a follower option")
raise ConfigError("index must be set only with a follower option", subconfig=subsubconfig,)
length = self.get_length_leadership()
if index >= length:
raise LeadershipError(
@ -1426,7 +1426,7 @@ class KernelGroupConfig(_CommonConfig):
# pylint: disable=protected-access
ret.append(
PropertiesOptionError(
err._subconfig,
err.subconfig,
err.proptype,
err._settings,
err._opt_type,
@ -1674,7 +1674,7 @@ class KernelMixConfig(KernelGroupConfig):
# pylint: disable=protected-access
ret.append(
PropertiesOptionError(
err._subconfig,
err.subconfig,
err.proptype,
err._settings,
err._opt_type,

View file

@ -18,7 +18,7 @@
import weakref
from .i18n import _
from typing import Literal, Union
from typing import Literal, Union, Optional
TiramisuErrorCode = Literal[
@ -101,7 +101,7 @@ class PropertiesOptionError(AttributeError):
subconfig, with_quote=True
)
self._orig_opt = None
self._subconfig = subconfig
self.subconfig = subconfig
self.proptype = proptype
self.help_properties = help_properties
self._settings = settings
@ -136,7 +136,7 @@ class PropertiesOptionError(AttributeError):
self._orig_opt.impl_get_display_name(subconfig, with_quote=True)
)
arguments.append(self._name)
index = self._subconfig.index
index = self.subconfig.index
if index is not None:
arguments.append(index)
if self.code == "property-frozen":
@ -215,10 +215,22 @@ class ConfigError(Exception):
def __init__(
self,
exp,
ori_err=None,
*,
prefix: Optional[str] = None,
subconfig: Optional["Subconfig"]=None,
):
super().__init__(exp)
self.ori_err = ori_err
self.err_msg = exp
self.subconfig = subconfig
self.prefix = prefix
def __str__(self):
msg = self.prefix
if msg:
msg += ", {}".format(self.err_msg)
else:
msg = self.err_msg
return msg
class ConflictError(Exception):
@ -419,9 +431,9 @@ class Errors:
display_name = option.impl_get_display_name(subconfig, with_quote=True)
if original_error:
raise ConfigError(
message.format(display_name, original_error, *extra_keys)
message.format(display_name, original_error, *extra_keys), subconfig=subconfig,
) from original_error
raise ConfigError(message.format(display_name, extra_keys))
raise ConfigError(message.format(display_name, extra_keys), subconfig=subconfig)
errors = Errors()

View file

@ -395,6 +395,8 @@ class BaseOption(Base):
is_identifier: bool = False,
type_: str = 'default'
) -> Any:
if not isinstance(is_identifier, bool):
raise Exception()
"""parse dependancy to add dependencies"""
for param in chain(value.params.args, value.params.kwargs.values()):
if isinstance(param, ParamOption):

View file

@ -45,7 +45,7 @@ class ChoiceOption(Option):
:param values: is a list of values the option can possibly take
"""
if isinstance(values, Calculation):
self.value_dependency(values, "choice")
self.value_dependency(values, type_="choice")
elif not isinstance(values, tuple):
raise TypeError(
_("values must be a tuple or a calculation for {0}").format(name)
@ -73,7 +73,8 @@ class ChoiceOption(Option):
raise ConfigError(
_('the calculated values "{0}" for "{1}" is not a list' "").format(
values, self.impl_getname()
)
),
subconfig=subconfig,
)
return values

View file

@ -31,7 +31,6 @@ from ..i18n import _
from .optiondescription import OptionDescription
from .baseoption import BaseOption
from ..setting import ConfigBag, undefined
from ..error import ConfigError
from ..autolib import Calculation, get_calculated_value

View file

@ -56,7 +56,7 @@ class IntOption(Option):
value: int,
) -> None:
if not isinstance(value, int):
raise ValueError(_("which is not an integer"))
raise ValueError(_("it's not an integer"))
def second_level_validation(self, value, warnings_only):
min_integer = self.impl_get_extra("min_integer")

View file

@ -39,7 +39,7 @@ class StrOption(Option):
) -> None:
"""validation"""
if not isinstance(value, str):
raise ValueError(_("which is not a string"))
raise ValueError(_("it's not a string"))
class RegexpOption(StrOption):

View file

@ -22,7 +22,6 @@
"""
from typing import Any, Optional, Dict
from .baseoption import BaseOption, valid_name
from ..error import ConfigError
from ..i18n import _

View file

@ -638,7 +638,8 @@ class Settings:
raise ConfigError(
_("cannot add those permissives: {0}").format(
" ".join(forbidden_permissives)
)
),
subconfig=subconfig,
)
self._permissives.setdefault(path, {})[index] = permissives
if subconfig is not None:

View file

@ -615,7 +615,8 @@ class Values:
raise ConfigError(
_(
'"{0}" is a default value, so we cannot change owner to "{1}"'
).format(subconfig.path, owner)
).format(subconfig.path, owner),
subconfig=subconfig,
)
subconfig.config_bag.context.get_settings().validate_frozen(subconfig)
self._values[subconfig.path][subconfig.index][1] = owner