tiramisu/tiramisu/option/option.py

723 lines
31 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
"option types and option description"
2019-02-12 06:55:47 +01:00
# Copyright (C) 2012-2019 Team tiramisu (see AUTHORS for all contributors)
#
# 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.
#
# 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.
#
# 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/>.
#
# The original `Config` design model is unproudly borrowed from
# the rough pypy's guys: http://codespeak.net/svn/pypy/dist/pypy/config/
# the whole pypy projet is under MIT licence
# ____________________________________________________________
2017-07-24 20:39:01 +02:00
import warnings
2017-11-20 17:01:36 +01:00
import weakref
2018-11-15 18:35:14 +01:00
from typing import Any, List, Callable, Optional, Dict, Union, Tuple
from .baseoption import BaseOption, submulti, STATIC_TUPLE
2017-07-24 20:39:01 +02:00
from ..i18n import _
2018-11-15 18:35:14 +01:00
from ..setting import log, undefined, OptionBag, Undefined
2017-07-24 20:39:01 +02:00
from ..autolib import carry_out_calculation
from ..error import (ConfigError, ValueWarning, ValueErrorWarning, PropertiesOptionError,
2018-10-29 21:01:01 +01:00
ValueOptionError, display_list)
from ..function import Params, ParamValue
from .syndynoption import SynDynOption
2017-07-24 20:39:01 +02:00
ALLOWED_CONST_LIST = ['_cons_not_equal']
class Option(BaseOption):
2017-07-24 20:39:01 +02:00
"""
Abstract base class for configuration option's.
Reminder: an Option object is **not** a container for the value.
"""
__slots__ = ('_extra',
'_warnings_only',
'_allow_empty_list',
#multi
'_multi',
'_unique',
#value
'_default',
'_default_multi',
#calcul
'_val_call',
#
'_master_slaves',
'_choice_values',
'_choice_values_params',
)
_empty = ''
2017-12-07 21:42:04 +01:00
def __init__(self,
2018-11-15 18:35:14 +01:00
name: str,
doc: str,
default: Any=undefined,
default_multi: Any=None,
requires: List[Dict]=None,
multi: bool=False,
unique: bool=undefined,
callback: Optional[Callable]=None,
callback_params: Optional[Params]=None,
validator: Optional[Callable]=None,
validator_params: Optional[Params]=None,
properties: Optional[List[str]]=None,
warnings_only: bool=False,
extra: Optional[Dict]=None,
allow_empty_list: bool=undefined) -> None:
2017-07-24 20:39:01 +02:00
_setattr = object.__setattr__
if not multi and default_multi is not None:
raise ValueError(_("default_multi is set whereas multi is False"
" in option: {0}").format(name))
2017-10-22 09:48:08 +02:00
if default is undefined:
if multi is False:
default = None
else:
default = []
2017-07-24 20:39:01 +02:00
if multi is True:
is_multi = True
_multi = 0
elif multi is False:
is_multi = False
_multi = 1
elif multi is submulti:
is_multi = True
_multi = submulti
else:
2018-04-12 23:04:33 +02:00
raise ValueError(_('invalid multi type "{}"').format(multi))
2017-07-24 20:39:01 +02:00
if _multi != 1:
_setattr(self, '_multi', _multi)
if multi is not False and default is None:
default = []
2018-03-19 08:33:53 +01:00
super().__init__(name,
doc,
requires=requires,
properties=properties,
is_multi=is_multi)
2017-07-24 20:39:01 +02:00
if validator is not None:
2017-12-19 23:11:45 +01:00
validator_params = self._build_calculator_params(validator,
validator_params,
2018-04-16 19:51:13 +02:00
'validator',
2017-12-19 23:11:45 +01:00
add_value=True)
2018-09-15 22:44:49 +02:00
if not validator_params:
2017-07-24 20:39:01 +02:00
val_call = (validator,)
else:
val_call = (validator, validator_params)
self._val_call = (val_call, None)
2018-04-22 10:43:19 +02:00
if extra is not None and extra != {}:
2017-07-24 20:39:01 +02:00
_setattr(self, '_extra', extra)
if unique != undefined and not isinstance(unique, bool):
2018-04-12 23:04:33 +02:00
raise ValueError(_('unique must be a boolean, not "{}"').format(unique))
2017-07-24 20:39:01 +02:00
if not is_multi and unique is True:
raise ValueError(_('unique must be set only with multi value'))
if warnings_only is True:
_setattr(self, '_warnings_only', warnings_only)
if allow_empty_list is not undefined:
_setattr(self, '_allow_empty_list', allow_empty_list)
if is_multi and default_multi is not None:
2017-11-12 14:33:05 +01:00
def test_multi_value(value):
2017-12-19 23:11:45 +01:00
try:
self._validate(value,
undefined)
except ValueError as err:
2017-11-12 14:33:05 +01:00
raise ValueError(_("invalid default_multi value {0} "
2017-12-07 21:42:04 +01:00
"for option {1}: {2}").format(str(value),
self.impl_getname(),
str(err)))
2017-11-12 14:33:05 +01:00
if _multi is submulti:
if not isinstance(default_multi, list):
2018-04-12 23:04:33 +02:00
raise ValueError(_('invalid default_multi value "{0}" '
'for option "{1}", must be a list for a submulti'
'').format(str(default_multi),
self.impl_get_display_name()))
2017-11-12 14:33:05 +01:00
for value in default_multi:
test_multi_value(value)
else:
test_multi_value(default_multi)
2017-07-24 20:39:01 +02:00
_setattr(self, '_default_multi', default_multi)
if unique is not undefined:
_setattr(self, '_unique', unique)
2018-08-01 08:37:58 +02:00
option_bag = OptionBag()
option_bag.set_option(self,
undefined,
None,
undefined)
2017-12-13 22:15:34 +01:00
self.impl_validate(default,
2018-08-01 08:37:58 +02:00
option_bag)
2017-07-24 20:39:01 +02:00
if (is_multi and default != []) or \
(not is_multi and default is not None):
if is_multi:
default = tuple(default)
_setattr(self, '_default', default)
self._impl_set_callback(callback,
callback_params)
2017-07-24 20:39:01 +02:00
2018-09-30 11:36:09 +02:00
#__________________________________________________________________________
# option's information
2018-11-15 18:35:14 +01:00
def impl_is_multi(self) -> bool:
2017-07-24 20:39:01 +02:00
return getattr(self, '_multi', 1) != 1
2018-11-15 18:35:14 +01:00
def impl_is_submulti(self) -> bool:
2018-09-30 11:36:09 +02:00
return getattr(self, '_multi', 1) == 2
2018-11-15 18:35:14 +01:00
def impl_is_unique(self) -> bool:
2017-07-24 20:39:01 +02:00
return getattr(self, '_unique', False)
2018-11-15 18:35:14 +01:00
def impl_allow_empty_list(self) -> Union[Undefined, bool]:
2018-09-30 11:36:09 +02:00
return getattr(self, '_allow_empty_list', undefined)
2018-11-15 18:35:14 +01:00
def impl_is_dynsymlinkoption(self) -> bool:
2018-09-30 11:36:09 +02:00
return False
2018-12-24 09:30:58 +01:00
def get_display_type(self) -> str:
return self._display_name
2018-11-15 18:35:14 +01:00
def impl_getdefault(self) -> Any:
2018-09-30 11:36:09 +02:00
"accessing the default value"
is_multi = self.impl_is_multi()
default = getattr(self, '_default', undefined)
if default is undefined:
if is_multi:
default = []
else:
default = None
else:
if is_multi:
default = list(default)
return default
2018-11-15 18:35:14 +01:00
def impl_getdefault_multi(self) -> Any:
2018-09-30 11:36:09 +02:00
"accessing the default value for a multi"
if self.impl_is_submulti():
default_value = []
else:
default_value = None
return getattr(self, '_default_multi', default_value)
def impl_get_extra(self,
2018-11-15 18:35:14 +01:00
key: str) -> Any:
2018-09-30 11:36:09 +02:00
extra = getattr(self, '_extra', {})
if isinstance(extra, tuple):
if key in extra[0]:
return extra[1][extra[0].index(key)]
return None
else:
return extra.get(key)
#__________________________________________________________________________
# validator
2018-11-15 18:35:14 +01:00
def impl_get_validator(self) -> Tuple[Callable, Params]:
2017-07-24 20:39:01 +02:00
val = getattr(self, '_val_call', (None,))[0]
if val is None:
2018-09-15 22:44:49 +02:00
ret_val = (None, None)
2017-07-24 20:39:01 +02:00
elif len(val) == 1:
2018-09-15 22:44:49 +02:00
ret_val = (val[0], None)
2017-07-24 20:39:01 +02:00
else:
ret_val = val
return ret_val
2017-11-12 14:33:05 +01:00
def impl_validate(self,
2018-11-15 18:35:14 +01:00
value: Any,
option_bag: OptionBag,
check_error: bool=True) -> None:
2017-07-24 20:39:01 +02:00
"""
"""
2018-09-15 22:44:49 +02:00
config_bag = option_bag.config_bag
force_index = option_bag.index
2018-09-04 08:36:02 +02:00
is_warnings_only = getattr(self, '_warnings_only', False)
if check_error and config_bag is not undefined and \
2018-08-18 07:51:04 +02:00
not 'validator' in config_bag.properties:
# just to check propertieserror
2018-08-01 08:37:58 +02:00
self.valid_consistency(option_bag,
value,
2018-09-04 08:36:02 +02:00
check_error,
is_warnings_only)
2017-12-13 22:15:34 +01:00
return
2017-07-24 20:39:01 +02:00
def _is_not_unique(value):
2018-09-12 21:05:14 +02:00
# if set(value) has not same length than value
if check_error and self.impl_is_unique() and \
len(set(value)) != len(value):
2017-07-24 20:39:01 +02:00
for idx, val in enumerate(value):
if val in value[idx+1:]:
2017-11-28 22:42:30 +01:00
raise ValueError(_('invalid value "{}", this value is already in "{}"'
2017-12-07 21:42:04 +01:00
'').format(val,
self.impl_get_display_name()))
2017-07-24 20:39:01 +02:00
2017-11-20 17:01:36 +01:00
def calculation_validator(val,
_index):
2017-07-24 20:39:01 +02:00
validator, validator_params = self.impl_get_validator()
if validator is not None:
#inject value in calculation
if validator_params is None:
args = []
kwargs = None
2017-07-24 20:39:01 +02:00
else:
args = list(validator_params.args)
kwargs = validator_params.kwargs
args.insert(0, ParamValue(val))
validator_params_ = Params(tuple(args), kwargs)
2017-07-24 20:39:01 +02:00
# Raise ValueError if not valid
2018-08-01 08:37:58 +02:00
carry_out_calculation(option_bag.ori_option,
2017-12-07 21:42:04 +01:00
callback=validator,
callback_params=validator_params_,
index=_index,
2018-09-30 20:32:00 +02:00
config_bag=option_bag.config_bag,
fromconsistency=option_bag.fromconsistency,
2017-12-27 15:48:49 +01:00
orig_value=value,
2017-12-07 21:42:04 +01:00
is_validator=True)
2017-07-24 20:39:01 +02:00
2017-11-20 17:01:36 +01:00
def do_validation(_value,
_index):
2018-09-29 21:58:41 +02:00
if isinstance(_value, list):
2017-12-30 18:31:56 +01:00
raise ValueError(_('which must not be a list').format(_value,
2017-12-07 21:42:04 +01:00
self.impl_get_display_name()))
2017-12-23 10:40:41 +01:00
if _value is not None:
2017-12-13 22:15:34 +01:00
if check_error:
2017-12-23 10:40:41 +01:00
# option validation
self._validate(_value,
2018-08-01 08:37:58 +02:00
option_bag,
option_bag.ori_option)
2017-12-23 10:40:41 +01:00
if ((check_error and not is_warnings_only) or
(not check_error and is_warnings_only)):
2018-09-04 08:36:02 +02:00
try:
calculation_validator(_value,
_index)
self._second_level_validation(_value,
is_warnings_only)
except ValueError as err:
if is_warnings_only:
warnings.warn_explicit(ValueWarning(_value,
self._display_name,
self,
err_msg = '{0}'.format(err)),
2018-09-04 08:36:02 +02:00
ValueWarning,
self.__class__.__name__, 0)
else:
raise err
2017-12-23 10:40:41 +01:00
try:
val = value
2018-08-01 08:37:58 +02:00
if not self.impl_is_multi():
2017-12-23 10:40:41 +01:00
do_validation(val, None)
elif force_index is not None:
if self.impl_is_submulti():
2017-12-30 18:31:56 +01:00
if not isinstance(value, list):
raise ValueError(_('which must be a list'))
2017-12-23 10:40:41 +01:00
_is_not_unique(value)
for idx, val in enumerate(value):
do_validation(val,
force_index)
else:
2017-12-07 21:42:04 +01:00
do_validation(val,
force_index)
2017-12-23 10:40:41 +01:00
elif not isinstance(value, list):
2017-12-30 18:31:56 +01:00
raise ValueError(_('which must be a list'))
2017-12-23 10:40:41 +01:00
elif self.impl_is_submulti():
for idx, lval in enumerate(value):
_is_not_unique(lval)
if not isinstance(lval, list):
2017-12-30 18:31:56 +01:00
raise ValueError(_('which "{}" must be a list of list'
'').format(lval))
2017-12-23 10:40:41 +01:00
for val in lval:
do_validation(val,
2017-12-19 23:11:45 +01:00
idx)
else:
2017-12-23 10:40:41 +01:00
_is_not_unique(value)
2017-12-19 23:11:45 +01:00
for idx, val in enumerate(value):
do_validation(val,
idx)
2017-12-23 10:40:41 +01:00
2018-09-05 20:22:53 +02:00
if not is_warnings_only or not check_error:
self.valid_consistency(option_bag,
value,
check_error,
is_warnings_only)
2017-12-23 10:40:41 +01:00
except ValueError as err:
2018-12-08 00:02:23 +01:00
if config_bag is undefined or \
2018-12-24 09:30:58 +01:00
'demoting_error_warning' not in config_bag.properties:
2018-12-08 00:02:23 +01:00
raise ValueOptionError(val,
self._display_name,
option_bag.ori_option,
'{0}'.format(err))
warnings.warn_explicit(ValueErrorWarning(val,
2018-12-08 00:02:23 +01:00
self._display_name,
option_bag.ori_option,
'{0}'.format(err)),
ValueErrorWarning,
self.__class__.__name__, 0)
def _validate_calculator(self,
2018-11-15 18:35:14 +01:00
callback: Callable,
callback_params: Optional[Params]=None) -> None:
if callback is None:
return
default_multi = getattr(self, '_default_multi', None)
2017-07-24 20:39:01 +02:00
is_multi = self.impl_is_multi()
default = self.impl_getdefault()
if (not is_multi and (default is not None or default_multi is not None)) or \
(is_multi and (default != [] or default_multi is not None)):
raise ValueError(_('default value not allowed if option "{0}" '
'is calculated').format(self.impl_getname()))
2018-09-30 11:36:09 +02:00
def _second_level_validation(self,
2018-11-15 18:35:14 +01:00
value: Any,
warnings_only: bool) -> None:
2018-09-30 11:36:09 +02:00
pass
2018-09-30 11:36:09 +02:00
#__________________________________________________________________________
# master/slaves
2018-11-15 18:35:14 +01:00
def impl_is_master_slaves(self,
type_: str='both') -> bool:
2018-09-30 11:36:09 +02:00
master_slaves = self.impl_get_master_slaves()
if master_slaves is not None:
if type_ == 'both':
2018-09-30 11:36:09 +02:00
return True
is_master = master_slaves.is_master(self)
if (type_ == 'master' and is_master) or (type_ == 'slave' and not is_master):
2018-09-30 11:36:09 +02:00
return True
return False
def impl_get_master_slaves(self):
masterslave = getattr(self, '_master_slaves', None)
if masterslave is None:
return masterslave
return masterslave()
#____________________________________________________________
# consistencies
2017-07-24 20:39:01 +02:00
2017-11-20 17:01:36 +01:00
def impl_add_consistency(self,
2018-11-15 18:35:14 +01:00
func: str,
2017-11-20 17:01:36 +01:00
*other_opts,
2018-11-15 18:35:14 +01:00
**params) -> None:
2017-07-24 20:39:01 +02:00
"""Add consistency means that value will be validate with other_opts
option's values.
:param func: function's name
:type func: `str`
:param other_opts: options used to validate value
:type other_opts: `list` of `tiramisu.option.Option`
:param params: extra params (warnings_only and transitive are allowed)
"""
2017-11-20 17:01:36 +01:00
if self.impl_is_readonly():
2017-07-24 20:39:01 +02:00
raise AttributeError(_("'{0}' ({1}) cannot add consistency, option is"
" read-only").format(
self.__class__.__name__,
self.impl_getname()))
2017-11-20 17:01:36 +01:00
self._valid_consistencies(other_opts,
func=func)
2017-07-24 20:39:01 +02:00
func = '_cons_{0}'.format(func)
if func not in dir(self):
raise ConfigError(_('consistency {0} not available for this option').format(func))
2017-11-20 17:01:36 +01:00
options = [weakref.ref(self)]
for option in other_opts:
options.append(weakref.ref(option))
all_cons_opts = tuple(options)
2017-07-24 20:39:01 +02:00
unknown_params = set(params.keys()) - set(['warnings_only', 'transitive'])
if unknown_params != set():
raise ValueError(_('unknown parameter {0} in consistency').format(unknown_params))
2017-11-20 17:01:36 +01:00
self._add_consistency(func,
all_cons_opts,
params)
2017-07-24 20:39:01 +02:00
#validate default value when add consistency
2018-08-01 08:37:58 +02:00
option_bag = OptionBag()
option_bag.set_option(self,
undefined,
None,
undefined)
2017-12-19 23:11:45 +01:00
self.impl_validate(self.impl_getdefault(),
2018-08-01 08:37:58 +02:00
option_bag)
2017-12-19 23:11:45 +01:00
self.impl_validate(self.impl_getdefault(),
2018-08-01 08:37:58 +02:00
option_bag,
2017-12-19 23:11:45 +01:00
check_error=False)
2017-07-24 20:39:01 +02:00
if func != '_cons_not_equal':
#consistency could generate warnings or errors
2017-09-17 15:55:32 +02:00
self._has_dependency = True
2017-11-20 17:01:36 +01:00
for wopt in all_cons_opts:
opt = wopt()
if func in ALLOWED_CONST_LIST:
if getattr(opt, '_unique', undefined) == undefined:
opt._unique = True
2017-09-17 15:55:32 +02:00
if opt != self:
self._add_dependency(opt)
opt._add_dependency(self)
2017-07-24 20:39:01 +02:00
def _add_consistency(self,
2018-11-15 18:35:14 +01:00
func: str,
all_cons_opts: List[BaseOption],
params: Dict) -> None:
cons = (-1, func, all_cons_opts, params)
consistencies = getattr(self, '_consistencies', None)
if consistencies is None:
self._consistencies = [cons]
else:
consistencies.append(cons)
def get_consistencies(self):
return getattr(self, '_consistencies', STATIC_TUPLE)
2018-11-15 18:35:14 +01:00
def has_consistencies(self, context) -> bool:
descr = context.cfgimpl_get_description()
if getattr(descr, '_cache_consistencies', None) is None:
return False
return self in descr._cache_consistencies
def valid_consistency(self,
2018-11-15 18:35:14 +01:00
option_bag: OptionBag,
value: Any,
check_error: bool,
option_warnings_only: bool) -> None:
if option_bag.config_bag is not undefined:
descr = option_bag.config_bag.context.cfgimpl_get_description()
2017-12-23 10:55:06 +01:00
# no consistency found at all
if getattr(descr, '_cache_consistencies', None) is None:
2017-07-24 20:39:01 +02:00
return
2017-12-23 10:55:06 +01:00
# get consistencies for this option
2018-09-16 21:28:18 +02:00
consistencies = descr._cache_consistencies.get(option_bag.option)
2017-07-24 20:39:01 +02:00
else:
2017-12-23 10:55:06 +01:00
# is no context, get consistencies in option
2018-08-01 08:37:58 +02:00
consistencies = option_bag.option.get_consistencies()
if consistencies:
if option_bag.config_bag is undefined:
coption_bag = option_bag.copy()
2018-08-01 08:37:58 +02:00
else:
cconfig_bag = option_bag.config_bag.copy()
cconfig_bag.remove_warnings()
2018-08-18 08:06:29 +02:00
cconfig_bag.set_permissive()
coption_bag = option_bag.copy()
coption_bag.config_bag = cconfig_bag
2018-09-05 20:22:53 +02:00
if not option_bag.fromconsistency:
fromconsistency_is_empty = True
option_bag.fromconsistency = [cons_id for cons_id, f, a, p in consistencies]
else:
fromconsistency_is_empty = False
2017-12-23 10:40:41 +01:00
for cons_id, func, all_cons_opts, params in consistencies:
2018-09-05 20:22:53 +02:00
if not fromconsistency_is_empty and cons_id in option_bag.fromconsistency:
continue
2018-09-04 08:36:02 +02:00
warnings_only = option_warnings_only or params.get('warnings_only', False)
2017-12-13 22:15:34 +01:00
if (warnings_only and not check_error) or (not warnings_only and check_error):
2017-07-24 20:39:01 +02:00
transitive = params.get('transitive', True)
#all_cons_opts[0] is the option where func is set
if option_bag.ori_option.impl_is_dynsymlinkoption():
2017-07-24 20:39:01 +02:00
opts = []
for opt in all_cons_opts:
opts.append(opt().to_dynoption(option_bag.ori_option.rootpath,
option_bag.ori_option.suffix))
2017-12-19 23:11:45 +01:00
wopt = opts[0]
2017-07-24 20:39:01 +02:00
else:
opts = all_cons_opts
2017-12-19 23:11:45 +01:00
wopt = opts[0]()
wopt.launch_consistency(self,
func,
cons_id,
coption_bag,
value,
opts,
warnings_only,
transitive)
2018-09-05 20:22:53 +02:00
if fromconsistency_is_empty:
option_bag.fromconsistency = []
2017-07-24 20:39:01 +02:00
2018-09-30 11:36:09 +02:00
def _valid_consistencies(self,
2018-11-15 18:35:14 +01:00
other_opts: List[BaseOption],
init: bool=True,
func: Optional[str]=None) -> None:
2018-09-30 11:36:09 +02:00
if self.issubdyn():
dynod = self.getsubdyn()
else:
dynod = None
if self.impl_is_submulti():
raise ConfigError(_('cannot add consistency with submulti option'))
is_multi = self.impl_is_multi()
for opt in other_opts:
if isinstance(opt, weakref.ReferenceType):
opt = opt()
assert not opt.impl_is_submulti(), _('cannot add consistency with submulti option')
assert isinstance(opt, Option), _('consistency must be set with an option, not {}').format(opt)
if opt.issubdyn():
if dynod is None:
raise ConfigError(_('almost one option in consistency is '
'in a dynoptiondescription but not all'))
subod = opt.getsubdyn()
if dynod != subod:
raise ConfigError(_('option in consistency must be in same'
' dynoptiondescription'))
dynod = subod
elif dynod is not None:
raise ConfigError(_('almost one option in consistency is in a '
'dynoptiondescription but not all'))
if self is opt:
raise ConfigError(_('cannot add consistency with itself'))
if is_multi != opt.impl_is_multi():
raise ConfigError(_('every options in consistency must be '
'multi or none'))
2018-11-15 18:35:14 +01:00
# FIXME
if init and func != 'not_equal':
opt._has_dependency = True
2018-09-30 11:36:09 +02:00
def launch_consistency(self,
current_opt: BaseOption,
func: Callable,
cons_id: int,
option_bag: OptionBag,
value: Any,
opts: List[BaseOption],
warnings_only: bool,
2018-11-15 18:35:14 +01:00
transitive: bool) -> None:
2017-12-23 10:55:06 +01:00
"""Launch consistency now
"""
all_cons_vals = []
all_cons_opts = []
length = None
for opt in opts:
if isinstance(opt, weakref.ReferenceType):
2017-12-23 10:55:06 +01:00
opt = opt()
try:
opt_value = self.get_consistency_value(option_bag,
opt,
cons_id,
value,
func)
except PropertiesOptionError as err:
if transitive:
2018-08-01 08:37:58 +02:00
err.set_orig_opt(option_bag.option)
raise err
2017-12-23 10:55:06 +01:00
else:
2018-08-01 08:37:58 +02:00
if opt.impl_is_multi() and option_bag.index is None and \
func not in ALLOWED_CONST_LIST:
len_value = len(opt_value)
if length is not None and length != len_value:
if option_bag.config_bag is undefined:
return
2018-08-01 08:37:58 +02:00
raise ValueError(_('unexpected length of "{}" in constency "{}", '
'should be "{}"').format(len(opt_value),
opt.impl_get_display_name(),
2018-09-15 22:44:49 +02:00
length)) # pragma: no cover
length = len_value
if isinstance(opt_value, list) and func in ALLOWED_CONST_LIST:
for value_ in opt_value:
all_cons_vals.append(value_)
all_cons_opts.append(opt)
else:
2018-09-15 22:44:49 +02:00
all_cons_vals.append(opt_value)
all_cons_opts.append(opt)
if option_bag.config_bag is not undefined and \
not 'validator' in option_bag.config_bag.properties:
return
all_values = []
if length is None:
2018-09-15 22:44:49 +02:00
all_values = [all_cons_vals]
elif length:
all_values = zip(*all_cons_vals)
try:
context = option_bag.config_bag if option_bag.config_bag is undefined else option_bag.config_bag.context
for values in all_values:
getattr(self, func)(current_opt,
all_cons_opts,
values,
2018-09-12 21:05:14 +02:00
warnings_only,
context)
except ValueError as err:
if warnings_only:
warnings.warn_explicit(ValueWarning(value,
self._display_name,
current_opt,
"{}".format(err)),
ValueWarning,
self.__class__.__name__, 0)
else:
raise err
2017-12-23 10:55:06 +01:00
def get_consistency_value(self,
2018-11-15 18:35:14 +01:00
option_bag: OptionBag,
current_option: BaseOption,
cons_id: int,
value: Any,
func: str) -> Any:
2018-09-16 21:28:18 +02:00
if option_bag.ori_option == current_option:
# orig_option is current option
# we have already value, so use it
return value
if option_bag.config_bag is undefined:
#if no context get default value
return current_option.impl_getdefault()
if func in ALLOWED_CONST_LIST:
index = None
index_ = None
elif current_option.impl_is_master_slaves('master'):
index = option_bag.index
index_ = None
else:
index = option_bag.index
index_ = index
#otherwise calculate value
path = current_option.impl_getpath()
coption_bag = OptionBag()
coption_bag.set_option(current_option,
path,
index_,
option_bag.config_bag)
fromconsistency = option_bag.fromconsistency.copy()
fromconsistency.append(cons_id)
coption_bag.fromconsistency = fromconsistency
current_value = option_bag.config_bag.context.getattr(path,
coption_bag)
if index_ is None and index is not None:
#if self is a slave and current_option is a master and func not in ALLOWED_CONST_LIST
#return only the value of the master for isolate slave
current_value = current_value[index]
return current_value
2017-11-23 16:56:14 +01:00
def _cons_not_equal(self,
2018-11-15 18:35:14 +01:00
current_opt: BaseOption,
opts: List[BaseOption],
vals: List[Any],
warnings_only: bool,
context) -> None:
2017-12-23 10:40:41 +01:00
equal = []
2017-07-24 20:39:01 +02:00
is_current = False
for idx_inf, val_inf in enumerate(vals):
for idx_sup, val_sup in enumerate(vals[idx_inf + 1:]):
if val_inf == val_sup is not None:
for opt_ in [opts[idx_inf], opts[idx_inf + idx_sup + 1]]:
if opt_ == current_opt:
is_current = True
else:
2017-12-23 10:40:41 +01:00
if opt_ not in equal:
equal.append(opt_)
2017-07-24 20:39:01 +02:00
if equal:
if is_current:
if warnings_only:
msg = _('should be different from the value of "{}"')
2017-07-24 20:39:01 +02:00
else:
msg = _('must be different from the value of "{}"')
2017-07-24 20:39:01 +02:00
else:
if warnings_only:
msg = _('value for {} should be different')
else:
msg = _('value for {} must be different')
equal_name = []
for opt in equal:
equal_name.append(opt.impl_get_display_name())
2017-11-28 22:42:30 +01:00
raise ValueError(msg.format(display_list(list(equal_name))))
2017-07-24 20:39:01 +02:00
def to_dynoption(self,
rootpath: str,
suffix: str) -> SynDynOption:
return SynDynOption(self,
rootpath,
suffix)