2020-01-22 20:46:18 +01:00
|
|
|
# Copyright (C) 2012-2020 Team tiramisu (see AUTHORS for all contributors)
|
2012-07-13 09:37:35 +02:00
|
|
|
#
|
2013-09-22 22:33:09 +02:00
|
|
|
# This program is free software: you can redistribute it and/or modify it
|
|
|
|
# under the terms of the GNU Lesser General Public License as published by the
|
|
|
|
# Free Software Foundation, either version 3 of the License, or (at your
|
|
|
|
# option) any later version.
|
2012-07-13 09:37:35 +02:00
|
|
|
#
|
2013-09-22 22:33:09 +02:00
|
|
|
# This program is distributed in the hope that it will be useful, but WITHOUT
|
|
|
|
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
|
|
|
|
# FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
|
|
|
|
# details.
|
2012-07-13 09:37:35 +02:00
|
|
|
#
|
2013-09-22 22:33:09 +02:00
|
|
|
# You should have received a copy of the GNU Lesser General Public License
|
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2012-07-13 09:37:35 +02:00
|
|
|
#
|
2012-09-18 09:48:41 +02:00
|
|
|
# The original `Config` design model is unproudly borrowed from
|
2012-07-13 09:37:35 +02:00
|
|
|
# the rough gus of pypy: pypy: http://codespeak.net/svn/pypy/dist/pypy/config/
|
|
|
|
# the whole pypy projet is under MIT licence
|
|
|
|
# ____________________________________________________________
|
|
|
|
"enables us to carry out a calculation and return an option's value"
|
2018-04-28 08:39:07 +02:00
|
|
|
from typing import Any, Optional, Union, Callable, Dict, List
|
2019-09-01 09:41:53 +02:00
|
|
|
from itertools import chain
|
2018-04-28 08:39:07 +02:00
|
|
|
|
2019-11-20 08:28:26 +01:00
|
|
|
from .error import PropertiesOptionError, ConfigError, LeadershipError, ValueWarning
|
2015-11-29 23:03:08 +01:00
|
|
|
from .i18n import _
|
2018-08-01 08:37:58 +02:00
|
|
|
from .setting import undefined, ConfigBag, OptionBag, Undefined
|
2012-07-13 09:37:35 +02:00
|
|
|
# ____________________________________________________________
|
2013-04-03 12:20:26 +02:00
|
|
|
|
2013-09-19 21:38:46 +02:00
|
|
|
|
2019-09-01 09:41:53 +02:00
|
|
|
class Params:
|
|
|
|
__slots__ = ('args', 'kwargs')
|
|
|
|
def __init__(self, args=None, kwargs=None, **kwgs):
|
|
|
|
if args is None:
|
|
|
|
args = tuple()
|
|
|
|
if kwargs is None:
|
|
|
|
kwargs = {}
|
|
|
|
if kwgs:
|
|
|
|
kwargs.update(kwgs)
|
|
|
|
if isinstance(args, Param):
|
|
|
|
args = (args,)
|
|
|
|
else:
|
|
|
|
if not isinstance(args, tuple):
|
|
|
|
raise ValueError(_('args in params must be a tuple'))
|
|
|
|
for arg in args:
|
|
|
|
if not isinstance(arg, Param):
|
|
|
|
raise ValueError(_('arg in params must be a Param'))
|
|
|
|
if not isinstance(kwargs, dict):
|
|
|
|
raise ValueError(_('kwargs in params must be a dict'))
|
|
|
|
for arg in kwargs.values():
|
|
|
|
if not isinstance(arg, Param):
|
|
|
|
raise ValueError(_('arg in params must be a Param'))
|
|
|
|
self.args = args
|
|
|
|
self.kwargs = kwargs
|
|
|
|
|
|
|
|
|
|
|
|
class Param:
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class ParamOption(Param):
|
|
|
|
__slots__ = ('todict',
|
|
|
|
'option',
|
|
|
|
'notraisepropertyerror',
|
|
|
|
'raisepropertyerror')
|
|
|
|
def __init__(self,
|
|
|
|
option: 'Option',
|
|
|
|
notraisepropertyerror: bool=False,
|
|
|
|
raisepropertyerror: bool=False,
|
|
|
|
todict: bool=False) -> None:
|
|
|
|
if __debug__ and not hasattr(option, 'impl_is_symlinkoption'):
|
|
|
|
raise ValueError(_('paramoption needs an option not {}').format(type(option)))
|
|
|
|
if option.impl_is_symlinkoption():
|
|
|
|
cur_opt = option.impl_getopt()
|
|
|
|
else:
|
|
|
|
cur_opt = option
|
|
|
|
assert isinstance(notraisepropertyerror, bool), _('param must have a boolean not a {} for notraisepropertyerror').format(type(notraisepropertyerror))
|
|
|
|
assert isinstance(raisepropertyerror, bool), _('param must have a boolean not a {} for raisepropertyerror').format(type(raisepropertyerror))
|
|
|
|
self.todict = todict
|
|
|
|
self.option = cur_opt
|
|
|
|
self.notraisepropertyerror = notraisepropertyerror
|
|
|
|
self.raisepropertyerror = raisepropertyerror
|
|
|
|
|
|
|
|
|
|
|
|
class ParamSelfOption(Param):
|
2019-10-27 11:09:15 +01:00
|
|
|
__slots__ = ('todict', 'whole')
|
2019-09-01 09:41:53 +02:00
|
|
|
def __init__(self,
|
2019-10-27 11:09:15 +01:00
|
|
|
todict: bool=False,
|
|
|
|
whole: bool=undefined) -> None:
|
|
|
|
"""whole: send all value for a multi, not only indexed value"""
|
2019-09-01 09:41:53 +02:00
|
|
|
self.todict = todict
|
2019-10-27 11:09:15 +01:00
|
|
|
if whole is not undefined:
|
|
|
|
self.whole = whole
|
2019-09-01 09:41:53 +02:00
|
|
|
|
|
|
|
|
|
|
|
class ParamValue(Param):
|
|
|
|
__slots__ = ('value',)
|
|
|
|
def __init__(self, value):
|
|
|
|
self.value = value
|
|
|
|
|
|
|
|
|
|
|
|
class ParamIndex(Param):
|
|
|
|
__slots__ = tuple()
|
|
|
|
|
|
|
|
|
2019-10-27 11:09:15 +01:00
|
|
|
class ParamSuffix(Param):
|
|
|
|
__slots__ = tuple()
|
|
|
|
|
|
|
|
|
2019-09-01 09:41:53 +02:00
|
|
|
class Calculation:
|
|
|
|
__slots__ = ('function',
|
|
|
|
'params',
|
|
|
|
'help_function',
|
2019-11-20 08:28:26 +01:00
|
|
|
'_has_index',
|
2019-10-27 11:09:15 +01:00
|
|
|
'warnings_only')
|
2019-09-01 09:41:53 +02:00
|
|
|
def __init__(self,
|
|
|
|
function: Callable,
|
2019-09-28 16:32:48 +02:00
|
|
|
params: Params=Params(),
|
2019-10-27 11:09:15 +01:00
|
|
|
help_function: Optional[Callable]=None,
|
|
|
|
warnings_only: bool=False):
|
2019-09-01 09:41:53 +02:00
|
|
|
assert isinstance(function, Callable), _('first argument ({0}) must be a function').format(function)
|
|
|
|
if help_function:
|
|
|
|
assert isinstance(help_function, Callable), _('help_function ({0}) must be a function').format(help_function)
|
|
|
|
self.help_function = help_function
|
|
|
|
else:
|
|
|
|
self.help_function = None
|
|
|
|
self.function = function
|
2019-09-28 16:32:48 +02:00
|
|
|
self.params = params
|
|
|
|
for arg in chain(self.params.args, self.params.kwargs.values()):
|
|
|
|
if isinstance(arg, ParamIndex):
|
2019-11-20 08:28:26 +01:00
|
|
|
self._has_index = True
|
2019-09-28 16:32:48 +02:00
|
|
|
break
|
2019-10-27 11:09:15 +01:00
|
|
|
if warnings_only is True:
|
|
|
|
self.warnings_only = warnings_only
|
2019-09-01 09:41:53 +02:00
|
|
|
|
2019-12-24 15:24:20 +01:00
|
|
|
async def execute(self,
|
2019-09-01 09:41:53 +02:00
|
|
|
option_bag: OptionBag,
|
2019-10-27 11:09:15 +01:00
|
|
|
leadership_must_have_index: bool=False,
|
|
|
|
orig_value: Any=undefined,
|
|
|
|
allow_raises=False) -> Any:
|
2019-12-24 15:24:20 +01:00
|
|
|
return await carry_out_calculation(option_bag.option,
|
|
|
|
callback=self.function,
|
|
|
|
callback_params=self.params,
|
|
|
|
index=option_bag.index,
|
|
|
|
config_bag=option_bag.config_bag,
|
|
|
|
leadership_must_have_index=leadership_must_have_index,
|
|
|
|
orig_value=orig_value,
|
|
|
|
allow_raises=allow_raises)
|
|
|
|
|
|
|
|
async def help(self,
|
|
|
|
option_bag: OptionBag,
|
|
|
|
leadership_must_have_index: bool=False) -> str:
|
2019-09-01 09:41:53 +02:00
|
|
|
if not self.help_function:
|
2020-01-22 20:46:18 +01:00
|
|
|
return await self.execute(option_bag,
|
|
|
|
leadership_must_have_index=leadership_must_have_index)
|
2019-12-24 15:24:20 +01:00
|
|
|
return await carry_out_calculation(option_bag.option,
|
|
|
|
callback=self.help_function,
|
|
|
|
callback_params=self.params,
|
|
|
|
index=option_bag.index,
|
|
|
|
config_bag=option_bag.config_bag,
|
|
|
|
leadership_must_have_index=leadership_must_have_index)
|
2019-09-01 09:41:53 +02:00
|
|
|
|
2019-11-20 08:28:26 +01:00
|
|
|
def has_index(self, current_option):
|
|
|
|
if hasattr(self, '_has_index'):
|
|
|
|
return self._has_index
|
|
|
|
self._has_index = False
|
|
|
|
for arg in chain(self.params.args, self.params.kwargs.values()):
|
|
|
|
if isinstance(arg, ParamOption) and arg.option.impl_get_leadership() and \
|
|
|
|
arg.option.impl_get_leadership().in_same_group(current_option):
|
|
|
|
self._has_index = True
|
|
|
|
break
|
|
|
|
return self._has_index
|
|
|
|
|
2019-09-01 09:41:53 +02:00
|
|
|
|
|
|
|
class Break(Exception):
|
|
|
|
pass
|
|
|
|
|
|
|
|
|
2019-12-24 15:24:20 +01:00
|
|
|
async def manager_callback(callbk: Union[ParamOption, ParamValue],
|
|
|
|
option,
|
|
|
|
index: Optional[int],
|
|
|
|
orig_value,
|
|
|
|
config_bag: ConfigBag,
|
|
|
|
leadership_must_have_index: bool) -> Any:
|
2018-04-15 21:13:16 +02:00
|
|
|
"""replace Param by true value"""
|
2019-10-27 11:09:15 +01:00
|
|
|
def calc_index(callbk, index, same_leadership):
|
|
|
|
if index is not None:
|
|
|
|
if hasattr(callbk, 'whole'):
|
|
|
|
whole = callbk.whole
|
|
|
|
else:
|
|
|
|
# if value is same_leadership, follower are isolate by default
|
|
|
|
# otherwise option is a whole option
|
|
|
|
whole = not same_leadership
|
|
|
|
if not whole:
|
|
|
|
return index
|
|
|
|
return None
|
|
|
|
|
2019-12-24 15:24:20 +01:00
|
|
|
async def calc_self(callbk, option, index, value, config_bag):
|
2019-10-27 11:09:15 +01:00
|
|
|
# index must be apply only if follower
|
|
|
|
is_follower = option.impl_is_follower()
|
|
|
|
apply_index = calc_index(callbk, index, is_follower)
|
|
|
|
if value is undefined or (apply_index is None and is_follower):
|
|
|
|
if config_bag is undefined:
|
|
|
|
return undefined
|
|
|
|
path = option.impl_getpath()
|
2019-12-25 20:44:56 +01:00
|
|
|
option_bag = await get_option_bag(config_bag,
|
|
|
|
option,
|
2020-01-22 20:46:18 +01:00
|
|
|
apply_index,
|
|
|
|
True)
|
2019-12-24 15:24:20 +01:00
|
|
|
new_value = await get_value(callbk, option_bag, path)
|
2019-10-27 11:09:15 +01:00
|
|
|
if apply_index is None and is_follower:
|
|
|
|
new_value[index] = value
|
|
|
|
value = new_value
|
|
|
|
elif apply_index is not None and not is_follower:
|
|
|
|
value = value[apply_index]
|
|
|
|
return value
|
|
|
|
|
2019-12-24 15:24:20 +01:00
|
|
|
async def get_value(callbk, option_bag, path):
|
2019-10-27 11:09:15 +01:00
|
|
|
try:
|
|
|
|
# get value
|
2019-12-24 15:24:20 +01:00
|
|
|
value = await config_bag.context.getattr(path,
|
|
|
|
option_bag)
|
2019-10-27 11:09:15 +01:00
|
|
|
except PropertiesOptionError as err:
|
|
|
|
# raise PropertiesOptionError (which is catched) because must not add value None in carry_out_calculation
|
|
|
|
if callbk.notraisepropertyerror or callbk.raisepropertyerror:
|
|
|
|
raise err
|
|
|
|
raise ConfigError(_('unable to carry out a calculation for "{}"'
|
|
|
|
', {}').format(option.impl_get_display_name(), err), err)
|
|
|
|
except ValueError as err:
|
|
|
|
raise ValueError(_('the option "{0}" is used in a calculation but is invalid ({1})').format(option_bag.option.impl_get_display_name(), err))
|
|
|
|
return value
|
|
|
|
|
2019-12-24 15:24:20 +01:00
|
|
|
async def get_option_bag(config_bag,
|
|
|
|
opt,
|
2020-01-22 20:46:18 +01:00
|
|
|
index_,
|
|
|
|
self_calc):
|
2019-10-27 11:09:15 +01:00
|
|
|
# don't validate if option is option that we tried to validate
|
|
|
|
config_bag = config_bag.copy()
|
|
|
|
config_bag.properties = config_bag.true_properties - {'warnings'}
|
|
|
|
config_bag.set_permissive()
|
|
|
|
#config_bag.properties -= {'warnings'}
|
|
|
|
option_bag = OptionBag()
|
|
|
|
option_bag.set_option(opt,
|
|
|
|
index_,
|
|
|
|
config_bag)
|
2020-01-22 20:46:18 +01:00
|
|
|
if not self_calc:
|
|
|
|
option_bag.properties = await config_bag.context.cfgimpl_get_settings().getproperties(option_bag)
|
|
|
|
else:
|
|
|
|
option_bag.config_bag.unrestraint()
|
|
|
|
option_bag.config_bag.remove_validation()
|
|
|
|
# if we are in properties calculation, cannot calculated properties
|
|
|
|
option_bag.properties = await config_bag.context.cfgimpl_get_settings().getproperties(option_bag,
|
|
|
|
apply_requires=False)
|
2019-10-27 11:09:15 +01:00
|
|
|
return option_bag
|
|
|
|
|
2018-04-15 21:13:16 +02:00
|
|
|
if isinstance(callbk, ParamValue):
|
|
|
|
return callbk.value
|
2019-10-27 11:09:15 +01:00
|
|
|
|
2018-04-15 21:13:16 +02:00
|
|
|
if isinstance(callbk, ParamIndex):
|
|
|
|
return index
|
2019-10-27 11:09:15 +01:00
|
|
|
|
|
|
|
if isinstance(callbk, ParamSuffix):
|
|
|
|
if not option.issubdyn():
|
|
|
|
raise ConfigError('option "{}" is not in a dynoptiondescription'.format(option.impl_get_display_name()))
|
|
|
|
return option.impl_getsuffix()
|
|
|
|
|
2019-09-01 09:41:53 +02:00
|
|
|
if isinstance(callbk, ParamSelfOption):
|
2019-10-27 11:09:15 +01:00
|
|
|
if leadership_must_have_index and option.impl_get_leadership() and index is None:
|
|
|
|
raise Break()
|
2019-12-24 15:24:20 +01:00
|
|
|
value = await calc_self(callbk, option, index, orig_value, config_bag)
|
2019-10-27 11:09:15 +01:00
|
|
|
if not callbk.todict:
|
|
|
|
return value
|
|
|
|
return {'name': option.impl_get_display_name(),
|
|
|
|
'value': value}
|
|
|
|
|
|
|
|
# it's ParamOption
|
|
|
|
callbk_option = callbk.option
|
|
|
|
if callbk_option.issubdyn():
|
|
|
|
callbk_option = callbk_option.to_dynoption(option.rootpath,
|
2019-12-21 18:29:21 +01:00
|
|
|
option.impl_getsuffix(),
|
|
|
|
callbk_option.getsubdyn())
|
2019-10-27 11:09:15 +01:00
|
|
|
if leadership_must_have_index and callbk_option.impl_get_leadership() and index is None:
|
2019-09-01 09:41:53 +02:00
|
|
|
raise Break()
|
2019-10-27 11:09:15 +01:00
|
|
|
if config_bag is undefined:
|
|
|
|
return undefined
|
|
|
|
if index is not None and callbk_option.impl_get_leadership() and \
|
|
|
|
callbk_option.impl_get_leadership().in_same_group(option):
|
|
|
|
if not callbk_option.impl_is_follower():
|
|
|
|
# leader
|
2018-04-15 21:13:16 +02:00
|
|
|
index_ = None
|
2019-10-27 11:09:15 +01:00
|
|
|
with_index = True
|
|
|
|
else:
|
|
|
|
# follower
|
2018-04-15 21:13:16 +02:00
|
|
|
index_ = index
|
|
|
|
with_index = False
|
|
|
|
else:
|
|
|
|
index_ = None
|
|
|
|
with_index = False
|
2019-10-27 11:09:15 +01:00
|
|
|
path = callbk_option.impl_getpath()
|
2019-12-25 20:44:56 +01:00
|
|
|
option_bag = await get_option_bag(config_bag,
|
|
|
|
callbk_option,
|
2020-01-22 20:46:18 +01:00
|
|
|
index_,
|
|
|
|
False)
|
2019-12-24 15:24:20 +01:00
|
|
|
value = await get_value(callbk, option_bag, path)
|
2019-10-27 11:09:15 +01:00
|
|
|
if with_index:
|
|
|
|
value = value[index]
|
2019-09-01 09:41:53 +02:00
|
|
|
if not callbk.todict:
|
2018-04-15 21:13:16 +02:00
|
|
|
return value
|
2019-10-27 11:09:15 +01:00
|
|
|
return {'name': callbk_option.impl_get_display_name(),
|
2019-09-01 09:41:53 +02:00
|
|
|
'value': value}
|
2018-04-15 21:13:16 +02:00
|
|
|
|
|
|
|
|
2019-12-24 15:24:20 +01:00
|
|
|
async def carry_out_calculation(option,
|
|
|
|
callback: Callable,
|
|
|
|
callback_params: Optional[Params],
|
|
|
|
index: Optional[int],
|
|
|
|
config_bag: Optional[ConfigBag],
|
|
|
|
orig_value=undefined,
|
|
|
|
leadership_must_have_index: bool=False,
|
|
|
|
allow_raises: int=False):
|
2013-08-21 14:52:48 +02:00
|
|
|
"""a function that carries out a calculation for an option's value
|
2013-04-03 12:20:26 +02:00
|
|
|
|
2014-01-30 22:55:15 +01:00
|
|
|
:param option: the option
|
2013-08-21 14:52:48 +02:00
|
|
|
:param callback: the name of the callback function
|
|
|
|
:type callback: str
|
|
|
|
:param callback_params: the callback's parameters
|
|
|
|
(only keyword parameters are allowed)
|
|
|
|
:type callback_params: dict
|
|
|
|
:param index: if an option is multi, only calculates the nth value
|
|
|
|
:type index: int
|
2019-10-27 11:09:15 +01:00
|
|
|
:param allow_raises: to know if carry_out_calculation is used to validate a value
|
2013-09-19 21:38:46 +02:00
|
|
|
|
2013-09-23 22:40:10 +02:00
|
|
|
The callback_params is a dict. Key is used to build args (if key is '')
|
|
|
|
and kwargs (otherwise). Values are tuple of:
|
|
|
|
- values
|
|
|
|
- tuple with option and boolean's force_permissive (True when don't raise
|
|
|
|
if PropertiesOptionError)
|
2019-10-27 11:09:15 +01:00
|
|
|
Values could have multiple values only when key is ''."""
|
2019-11-20 08:28:26 +01:00
|
|
|
def fake_items(iterator):
|
|
|
|
return ((None, i) for i in iterator)
|
2017-12-19 23:11:45 +01:00
|
|
|
args = []
|
|
|
|
kwargs = {}
|
2018-04-15 21:13:16 +02:00
|
|
|
if callback_params:
|
2019-11-20 08:28:26 +01:00
|
|
|
for key, callbk in chain(fake_items(callback_params.args), callback_params.kwargs.items()):
|
2018-04-15 21:13:16 +02:00
|
|
|
try:
|
2019-12-24 15:24:20 +01:00
|
|
|
value = await manager_callback(callbk,
|
|
|
|
option,
|
|
|
|
index,
|
|
|
|
orig_value,
|
|
|
|
config_bag,
|
|
|
|
leadership_must_have_index)
|
2018-04-15 21:13:16 +02:00
|
|
|
if value is undefined:
|
|
|
|
return undefined
|
2019-11-20 08:28:26 +01:00
|
|
|
if key is None:
|
|
|
|
args.append(value)
|
|
|
|
else:
|
|
|
|
kwargs[key] = value
|
2019-09-01 09:41:53 +02:00
|
|
|
except PropertiesOptionError as err:
|
|
|
|
if callbk.raisepropertyerror:
|
|
|
|
raise err
|
|
|
|
if callbk.todict:
|
2019-11-20 08:28:26 +01:00
|
|
|
if key is None:
|
|
|
|
args.append({'propertyerror': str(err)})
|
|
|
|
else:
|
|
|
|
kwargs[key] = {'propertyerror': str(err)}
|
2019-09-01 09:41:53 +02:00
|
|
|
except Break:
|
|
|
|
continue
|
2017-12-19 23:11:45 +01:00
|
|
|
ret = calculate(option,
|
|
|
|
callback,
|
2019-10-27 11:09:15 +01:00
|
|
|
allow_raises,
|
2017-12-19 23:11:45 +01:00
|
|
|
args,
|
|
|
|
kwargs)
|
|
|
|
if isinstance(ret, list) and not option.impl_is_dynoptiondescription() and \
|
2019-02-23 19:06:23 +01:00
|
|
|
option.impl_is_follower():
|
2017-12-19 23:11:45 +01:00
|
|
|
if args or kwargs:
|
2019-06-12 08:45:56 +02:00
|
|
|
raise LeadershipError(_('the "{}" function with positional arguments "{}" '
|
|
|
|
'and keyword arguments "{}" must not return '
|
|
|
|
'a list ("{}") for the follower option "{}"'
|
2019-02-23 19:06:23 +01:00
|
|
|
'').format(callback.__name__,
|
|
|
|
args,
|
|
|
|
kwargs,
|
|
|
|
ret,
|
|
|
|
option.impl_get_display_name()))
|
2018-04-09 21:37:49 +02:00
|
|
|
else:
|
2019-06-12 08:45:56 +02:00
|
|
|
raise LeadershipError(_('the "{}" function must not return a list ("{}") '
|
|
|
|
'for the follower option "{}"'
|
2019-02-23 19:06:23 +01:00
|
|
|
'').format(callback.__name__,
|
|
|
|
ret,
|
2019-06-12 08:45:56 +02:00
|
|
|
option.impl_get_display_name()))
|
2017-12-19 23:11:45 +01:00
|
|
|
return ret
|
2012-09-18 09:48:41 +02:00
|
|
|
|
2013-04-03 12:20:26 +02:00
|
|
|
|
2018-04-28 08:39:07 +02:00
|
|
|
def calculate(option,
|
|
|
|
callback: Callable,
|
2019-10-27 11:09:15 +01:00
|
|
|
allow_raises: bool,
|
2018-04-28 08:39:07 +02:00
|
|
|
args,
|
|
|
|
kwargs):
|
2013-05-23 14:55:52 +02:00
|
|
|
"""wrapper that launches the 'callback'
|
2013-05-10 16:02:27 +02:00
|
|
|
|
2013-09-23 22:40:10 +02:00
|
|
|
:param callback: callback function
|
|
|
|
:param args: in the callback's arity, the unnamed parameters
|
|
|
|
:param kwargs: in the callback's arity, the named parameters
|
2013-05-23 14:55:52 +02:00
|
|
|
|
2013-05-10 16:02:27 +02:00
|
|
|
"""
|
2016-10-14 22:20:14 +02:00
|
|
|
try:
|
2016-03-17 19:14:02 +01:00
|
|
|
return callback(*args, **kwargs)
|
2016-10-14 22:20:14 +02:00
|
|
|
except ValueError as err:
|
2019-10-27 11:09:15 +01:00
|
|
|
if allow_raises:
|
2017-11-28 22:42:30 +01:00
|
|
|
raise err
|
2017-02-11 18:11:05 +01:00
|
|
|
error = err
|
2019-11-20 08:28:26 +01:00
|
|
|
except ValueWarning as err:
|
|
|
|
raise err
|
2017-02-11 18:11:05 +01:00
|
|
|
except Exception as err:
|
2019-11-20 08:28:26 +01:00
|
|
|
# import traceback
|
|
|
|
# traceback.print_exc()
|
2017-02-11 18:11:05 +01:00
|
|
|
error = err
|
2017-12-19 23:11:45 +01:00
|
|
|
if args or kwargs:
|
2017-02-12 10:38:57 +01:00
|
|
|
msg = _('unexpected error "{0}" in function "{1}" with arguments "{3}" and "{4}" '
|
|
|
|
'for option "{2}"').format(str(error),
|
2017-07-09 09:49:03 +02:00
|
|
|
callback.__name__,
|
2017-02-12 10:38:57 +01:00
|
|
|
option.impl_get_display_name(),
|
|
|
|
args,
|
|
|
|
kwargs)
|
|
|
|
else:
|
|
|
|
msg = _('unexpected error "{0}" in function "{1}" for option "{2}"'
|
|
|
|
'').format(str(error),
|
2017-07-09 09:49:03 +02:00
|
|
|
callback.__name__,
|
2017-02-12 10:38:57 +01:00
|
|
|
option.impl_get_display_name())
|
2018-10-31 08:00:19 +01:00
|
|
|
del error
|
2017-02-12 10:38:57 +01:00
|
|
|
raise ConfigError(msg)
|