add demoting_error_warning properties
This commit is contained in:
parent
f9b9ccacf1
commit
ca4d5e3e97
10 changed files with 87 additions and 32 deletions
|
@ -350,7 +350,7 @@ def test_help():
|
|||
cfg.help(_display=False)
|
||||
cfg.config.help(_display=False)
|
||||
cfg.option.help(_display=False)
|
||||
cfg.option('o').help(_display=False)
|
||||
#FIXMEcfg.option('o').help(_display=False)
|
||||
cfg.option('o.s').help(_display=False)
|
||||
|
||||
|
||||
|
|
|
@ -326,6 +326,25 @@ def test_requires_transitive():
|
|||
assert frozenset(props) == frozenset(['disabled'])
|
||||
|
||||
|
||||
def test_requires_transitive_unrestraint():
|
||||
a = BoolOption('activate_service', '', True)
|
||||
b = BoolOption('activate_service_web', '', True,
|
||||
requires=[{'option': a, 'expected': False, 'action': 'disabled'}])
|
||||
|
||||
d = IPOption('ip_address_service_web', '',
|
||||
requires=[{'option': b, 'expected': False, 'action': 'disabled'}])
|
||||
od = OptionDescription('service', '', [a, b, d])
|
||||
api = Config(od)
|
||||
api.property.read_write()
|
||||
api.option('activate_service').value.get()
|
||||
api.option('activate_service_web').value.get()
|
||||
api.option('ip_address_service_web').value.get()
|
||||
api.option('activate_service').value.set(False)
|
||||
#
|
||||
assert api.unrestraint.option('activate_service_web').property.get() == {'disabled'}
|
||||
assert api.unrestraint.option('ip_address_service_web').property.get() == {'disabled'}
|
||||
|
||||
|
||||
def test_requires_transitive_owner():
|
||||
a = BoolOption('activate_service', '', True)
|
||||
b = BoolOption('activate_service_web', '', True,
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
#
|
||||
# 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/>.
|
||||
from .function import Params, ParamOption, ParamValue, ParamContext
|
||||
from .function import Params, ParamOption, ParamValue, ParamContext, tiramisu_copy
|
||||
from .option import *
|
||||
from .error import APIError
|
||||
from .api import Config, MetaConfig, GroupConfig, MixConfig
|
||||
|
@ -29,7 +29,8 @@ allfuncs = ['Params',
|
|||
'GroupConfig',
|
||||
'Config',
|
||||
'APIError',
|
||||
'undefined']
|
||||
'undefined',
|
||||
'tiramisu_copy']
|
||||
allfuncs.extend(all_options)
|
||||
del(all_options)
|
||||
__all__ = tuple(allfuncs)
|
||||
|
|
|
@ -77,6 +77,7 @@ class TiramisuHelp:
|
|||
|
||||
class CommonTiramisu(TiramisuHelp):
|
||||
_allow_optiondescription = True
|
||||
_validate_properties = True
|
||||
|
||||
def _get_option(self) -> Any:
|
||||
option = self._option_bag.option
|
||||
|
@ -84,11 +85,14 @@ class CommonTiramisu(TiramisuHelp):
|
|||
option = self._subconfig.cfgimpl_get_description().get_child(self._name,
|
||||
self._option_bag.config_bag,
|
||||
self._subconfig.cfgimpl_get_path())
|
||||
self._option_bag.set_option(option,
|
||||
self._option_bag.path,
|
||||
self._option_bag.index,
|
||||
self._option_bag.config_bag)
|
||||
self._option_bag.config_bag.context.cfgimpl_get_settings().validate_properties(self._option_bag)
|
||||
option_bag = OptionBag()
|
||||
option_bag.set_option(option,
|
||||
self._option_bag.path,
|
||||
self._option_bag.index,
|
||||
self._option_bag.config_bag)
|
||||
if self._validate_properties:
|
||||
option_bag.config_bag.context.cfgimpl_get_settings().validate_properties(option_bag)
|
||||
self._option_bag = option_bag
|
||||
index = self._option_bag.index
|
||||
if index is not None:
|
||||
if option.impl_is_optiondescription() or not option.impl_is_master_slaves('slave'):
|
||||
|
@ -107,6 +111,7 @@ class CommonTiramisu(TiramisuHelp):
|
|||
class CommonTiramisuOption(CommonTiramisu):
|
||||
_allow_optiondescription = False
|
||||
_slave_need_index = True
|
||||
_validate_properties = False
|
||||
|
||||
def __init__(self,
|
||||
name: str,
|
||||
|
@ -141,6 +146,13 @@ class _TiramisuOptionOptionDescription(CommonTiramisuOption):
|
|||
"""Get Tiramisu option"""
|
||||
return self._option_bag.option
|
||||
|
||||
def type(self):
|
||||
type_ = self._option_bag.option.__class__.__name__
|
||||
if type_.endswith('Option'):
|
||||
type_ = type_[:-6]
|
||||
type_ = type_.lower()
|
||||
return type_
|
||||
|
||||
def ismasterslaves(self):
|
||||
"""Test if option is a master or a slave"""
|
||||
option = self._option_bag.option
|
||||
|
@ -210,6 +222,10 @@ class _TiramisuOptionOption(_TiramisuOptionOptionDescription):
|
|||
option = self._option_bag.option
|
||||
return option.impl_is_master_slaves('slave')
|
||||
|
||||
def issymlinkoption(self) -> bool:
|
||||
option = self._option_bag.option
|
||||
return option.impl_is_symlinkoption()
|
||||
|
||||
def default(self):
|
||||
"""Get default value for an option (not for optiondescription)"""
|
||||
option = self._option_bag.option
|
||||
|
@ -254,6 +270,7 @@ class TiramisuOptionOption(CommonTiramisuOption):
|
|||
|
||||
|
||||
class TiramisuOptionOwner(CommonTiramisuOption):
|
||||
#FIXME optiondescription must not have Owner!
|
||||
"""Manage option's owner"""
|
||||
|
||||
def __init__(self,
|
||||
|
@ -420,7 +437,7 @@ class _TiramisuOptionValueOption:
|
|||
option = self._option_bag.option
|
||||
self._test_slave_index()
|
||||
return self._subconfig.getattr(self._name,
|
||||
self._option_bag)
|
||||
self._option_bag)
|
||||
|
||||
def set(self, value):
|
||||
"""Change option's value"""
|
||||
|
@ -505,13 +522,14 @@ class _TiramisuOptionValueOptionDescription:
|
|||
flatten=False,
|
||||
withvalue=undefined,
|
||||
withoption=None,
|
||||
withwarning: bool=False,
|
||||
fullpath=False):
|
||||
"""Dict with path as key and value"""
|
||||
self._get_option()
|
||||
name = self._option_bag.option.impl_getname()
|
||||
subconfig = self._subconfig.get_subconfig(self._option_bag)
|
||||
config_bag = self._option_bag.config_bag
|
||||
if config_bag.properties and 'warnings' in config_bag.properties:
|
||||
if not withwarning and config_bag.properties and 'warnings' in config_bag.properties:
|
||||
config_bag = config_bag.copy()
|
||||
config_bag.remove_warnings()
|
||||
return subconfig.make_dict(config_bag=config_bag,
|
||||
|
@ -817,11 +835,12 @@ class TiramisuContextValue(TiramisuContext):
|
|||
flatten=False,
|
||||
withvalue=undefined,
|
||||
withoption=None,
|
||||
withwarning: bool=False,
|
||||
fullpath=False):
|
||||
"""Dict with path as key and value"""
|
||||
config_bag = self._config_bag
|
||||
if config_bag.properties and 'warnings' in config_bag.properties:
|
||||
config_bag = self._config_bag.copy()
|
||||
if not withwarning and config_bag.properties and 'warnings' in config_bag.properties:
|
||||
config_bag = config_bag.copy()
|
||||
config_bag.remove_warnings()
|
||||
return config_bag.context.make_dict(config_bag,
|
||||
flatten=flatten,
|
||||
|
@ -1218,7 +1237,7 @@ class TiramisuAPI(TiramisuHelp):
|
|||
return TiramisuAPI(config_bag)
|
||||
elif subfunc == 'unrestraint':
|
||||
config_bag = self._config_bag.copy()
|
||||
config_bag.properties = frozenset(['cache'])
|
||||
config_bag.unrestraint()
|
||||
return TiramisuAPI(config_bag)
|
||||
elif subfunc == 'config':
|
||||
config_type = self._config_bag.context.impl_type
|
||||
|
@ -1235,8 +1254,7 @@ class TiramisuAPI(TiramisuHelp):
|
|||
config_bag = self._config_bag
|
||||
del config_bag.permissives
|
||||
return self._registers[subfunc](config_bag)
|
||||
else:
|
||||
raise APIError(_('please specify a valid sub function ({})').format(subfunc))
|
||||
raise APIError(_('please specify a valid sub function ({})').format(subfunc))
|
||||
|
||||
def __dir__(self):
|
||||
return list(self._registers.keys()) + ['unrestraint', 'forcepermissive', 'config']
|
||||
|
|
|
@ -80,7 +80,7 @@ def manager_callback(callbk: Union[ParamOption, ParamValue],
|
|||
if fromconsistency:
|
||||
option_bag.fromconsistency = fromconsistency.copy()
|
||||
if opt == option:
|
||||
option_bag.config_bag.properties = frozenset()
|
||||
option_bag.config_bag.unrestraint()
|
||||
option_bag.config_bag.remove_validation()
|
||||
try:
|
||||
# get value
|
||||
|
|
|
@ -192,7 +192,7 @@ class ValueWarning(UserWarning):
|
|||
class ValueErrorWarning(ValueWarning):
|
||||
def __init__(self,
|
||||
value_error):
|
||||
super(ValueWarning, self).__init__(value_error, value_error.opt())
|
||||
super(ValueErrorWarning, self).__init__(value_error, value_error.opt)
|
||||
|
||||
|
||||
class ValueOptionError(ValueError):
|
||||
|
|
|
@ -75,3 +75,7 @@ class ParamContext(Param):
|
|||
|
||||
class ParamIndex(Param):
|
||||
__slots__ = tuple()
|
||||
|
||||
|
||||
def tiramisu_copy(val):
|
||||
return val
|
||||
|
|
|
@ -179,6 +179,9 @@ class Option(BaseOption):
|
|||
def impl_is_dynsymlinkoption(self) -> bool:
|
||||
return False
|
||||
|
||||
def get_display_type(self) -> str:
|
||||
return self._display_name
|
||||
|
||||
def impl_getdefault(self) -> Any:
|
||||
"accessing the default value"
|
||||
is_multi = self.impl_is_multi()
|
||||
|
@ -347,7 +350,7 @@ class Option(BaseOption):
|
|||
is_warnings_only)
|
||||
except ValueError as err:
|
||||
if config_bag is undefined or \
|
||||
'demoting_error' not in config_bag.properties:
|
||||
'demoting_error_warning' not in config_bag.properties:
|
||||
raise ValueOptionError(val,
|
||||
self._display_name,
|
||||
option_bag.ori_option,
|
||||
|
@ -638,7 +641,7 @@ class Option(BaseOption):
|
|||
self._display_name,
|
||||
current_opt.impl_get_display_name(),
|
||||
err)
|
||||
warnings.warn_explicit(ValueWarning(msg, weakref.ref(self)),
|
||||
warnings.warn_explicit(ValueWarning(msg, weakref.ref(current_opt)),
|
||||
ValueWarning,
|
||||
self.__class__.__name__, 0)
|
||||
else:
|
||||
|
|
|
@ -39,10 +39,8 @@ class StrOption(Option):
|
|||
raise ValueError()
|
||||
|
||||
|
||||
#UnicodeOption is same as StrOption in python 3+
|
||||
class UnicodeOption(StrOption):
|
||||
__slots__ = tuple()
|
||||
_display_name = _('unicode')
|
||||
#UnicodeOption is same as StrOption
|
||||
UnicodeOption = StrOption
|
||||
|
||||
|
||||
class RegexpOption(StrOption):
|
||||
|
@ -52,8 +50,7 @@ class RegexpOption(StrOption):
|
|||
value: Any,
|
||||
option_bag: OptionBag,
|
||||
current_opt: Option=Undefined) -> None:
|
||||
if not isinstance(value, str):
|
||||
raise ValueError(_('invalid string'))
|
||||
super()._validate(value, option_bag, current_opt)
|
||||
match = self._regexp.search(value)
|
||||
if not match:
|
||||
raise ValueError()
|
||||
|
|
|
@ -176,6 +176,7 @@ class OptionBag:
|
|||
class ConfigBag:
|
||||
__slots__ = ('context', # link to the current context
|
||||
'properties', # properties for current context
|
||||
'true_properties', # properties for current context
|
||||
'permissives', # permissives for current context
|
||||
)
|
||||
def __init__(self, context, **kwargs):
|
||||
|
@ -190,6 +191,8 @@ class ConfigBag:
|
|||
if key == 'permissives':
|
||||
self.permissives = self.context.cfgimpl_get_settings().get_context_permissives()
|
||||
return self.permissives
|
||||
if key == 'true_properties':
|
||||
return self.properties
|
||||
raise KeyError('unknown key {} for ConfigBag'.format(key)) # pragma: no cover
|
||||
|
||||
def remove_warnings(self):
|
||||
|
@ -198,6 +201,10 @@ class ConfigBag:
|
|||
def remove_validation(self):
|
||||
self.properties = frozenset(self.properties - {'validator'})
|
||||
|
||||
def unrestraint(self):
|
||||
self.true_properties = self.properties
|
||||
self.properties = frozenset(['cache'])
|
||||
|
||||
def set_permissive(self):
|
||||
self.properties = frozenset(self.properties | {'permissive'})
|
||||
|
||||
|
@ -210,14 +217,15 @@ class ConfigBag:
|
|||
return
|
||||
raise KeyError('unknown key {} for ConfigBag'.format(key)) # pragma: no cover
|
||||
|
||||
#def __setattr__(self, key, value):
|
||||
# super().__setattr__(key, value)
|
||||
# def __setattr__(self, key, value):
|
||||
# super().__setattr__(key, value)
|
||||
|
||||
def copy(self):
|
||||
kwargs = {}
|
||||
for key in self.__slots__:
|
||||
if key in ['properties', 'permissives'] and \
|
||||
if key in ['properties', 'permissives', 'true_properties'] and \
|
||||
not hasattr(self.context, '_impl_settings'):
|
||||
# not for GroupConfig
|
||||
continue
|
||||
kwargs[key] = getattr(self, key)
|
||||
return ConfigBag(**kwargs)
|
||||
|
@ -503,23 +511,26 @@ class Settings(object):
|
|||
elif option.impl_is_multi() and option_bag.index is not None:
|
||||
is_indexed = True
|
||||
config_bag = option_bag.config_bag.copy()
|
||||
config_bag.set_permissive()
|
||||
soption_bag = OptionBag()
|
||||
soption_bag.set_option(option,
|
||||
reqpath,
|
||||
idx,
|
||||
config_bag)
|
||||
if option_bag.option == option:
|
||||
soption_bag.config_bag.properties = frozenset()
|
||||
soption_bag.config_bag.unrestraint()
|
||||
soption_bag.config_bag.remove_validation()
|
||||
soption_bag.apply_requires = False
|
||||
else:
|
||||
soption_bag.config_bag.properties = soption_bag.config_bag.true_properties
|
||||
soption_bag.config_bag.set_permissive()
|
||||
try:
|
||||
value = context.getattr(reqpath,
|
||||
soption_bag)
|
||||
if is_indexed:
|
||||
value = value[option_bag.index]
|
||||
except PropertiesOptionError as err:
|
||||
properties = err.proptype
|
||||
# if not transitive, properties must be verify in current requires
|
||||
# otherwise if same_action, property must be in properties
|
||||
# otherwise add property in returned properties (if operator is 'and')
|
||||
if not transitive:
|
||||
if all_properties is None:
|
||||
all_properties = []
|
||||
|
@ -550,6 +561,8 @@ class Settings(object):
|
|||
breaked = True
|
||||
break
|
||||
else:
|
||||
if is_indexed:
|
||||
value = value[option_bag.index]
|
||||
if (not inverse and value in expected or
|
||||
inverse and value not in expected):
|
||||
if operator != 'and':
|
||||
|
|
Loading…
Reference in a new issue