simplify find() in api and PropertiesOptionError
This commit is contained in:
parent
5eb2f04202
commit
9e378faef0
|
@ -24,7 +24,7 @@ def return_calc_list(val):
|
||||||
return [val]
|
return [val]
|
||||||
|
|
||||||
|
|
||||||
def return_error():
|
def return_error(*args, **kwargs):
|
||||||
raise Exception('test')
|
raise Exception('test')
|
||||||
|
|
||||||
|
|
||||||
|
@ -83,6 +83,24 @@ def test_choiceoption_function_error():
|
||||||
raises(ConfigError, "api.option('choice').value.set('val1')")
|
raises(ConfigError, "api.option('choice').value.set('val1')")
|
||||||
|
|
||||||
|
|
||||||
|
def test_choiceoption_function_error_args():
|
||||||
|
choice = ChoiceOption('choice', '', values=return_error, values_params={'': ('val1',)})
|
||||||
|
odesc = OptionDescription('od', '', [choice])
|
||||||
|
cfg = Config(odesc)
|
||||||
|
api = getapi(cfg)
|
||||||
|
api.property.read_write()
|
||||||
|
raises(ConfigError, "api.option('choice').value.set('val1')")
|
||||||
|
|
||||||
|
|
||||||
|
def test_choiceoption_function_error_kwargs():
|
||||||
|
choice = ChoiceOption('choice', '', values=return_error, values_params={'kwargs': ('val1',)})
|
||||||
|
odesc = OptionDescription('od', '', [choice])
|
||||||
|
cfg = Config(odesc)
|
||||||
|
api = getapi(cfg)
|
||||||
|
api.property.read_write()
|
||||||
|
raises(ConfigError, "api.option('choice').value.set('val1')")
|
||||||
|
|
||||||
|
|
||||||
def test_choiceoption_calc_function():
|
def test_choiceoption_calc_function():
|
||||||
choice = ChoiceOption('choice', "", values=return_calc_list, values_params={'': ('val1',)})
|
choice = ChoiceOption('choice', "", values=return_calc_list, values_params={'': ('val1',)})
|
||||||
odesc = OptionDescription('od', '', [choice])
|
odesc = OptionDescription('od', '', [choice])
|
||||||
|
|
|
@ -195,6 +195,11 @@ def test_find_in_config():
|
||||||
assert len(ret) == 1
|
assert len(ret) == 1
|
||||||
_is_same_opt(ret[0].option.get(), api.option('gc.prop').option.get())
|
_is_same_opt(ret[0].option.get(), api.option('gc.prop').option.get())
|
||||||
#
|
#
|
||||||
|
ret = api.option.find('prop', value=None)
|
||||||
|
ret = api.option.find('prop')
|
||||||
|
assert len(ret) == 1
|
||||||
|
_is_same_opt(ret[0].option.get(), api.option('gc.prop').option.get())
|
||||||
|
#
|
||||||
api.property.read_write()
|
api.property.read_write()
|
||||||
raises(AttributeError, "assert api.option.find('prop').option.get()")
|
raises(AttributeError, "assert api.option.find('prop').option.get()")
|
||||||
ret = api.unrestraint.option.find(name='prop')
|
ret = api.unrestraint.option.find(name='prop')
|
||||||
|
|
|
@ -48,6 +48,11 @@ def make_metaconfig(double=False):
|
||||||
return api
|
return api
|
||||||
|
|
||||||
|
|
||||||
|
def test_unknown_config():
|
||||||
|
api = make_metaconfig()
|
||||||
|
raises(ConfigError, "api.config('unknown')")
|
||||||
|
|
||||||
|
|
||||||
#FIXME ne pas mettre 2 meta dans une config
|
#FIXME ne pas mettre 2 meta dans une config
|
||||||
#FIXME ne pas mettre 2 OD differents dans un meta
|
#FIXME ne pas mettre 2 OD differents dans un meta
|
||||||
def test_none():
|
def test_none():
|
||||||
|
|
|
@ -10,6 +10,7 @@ from tiramisu import ChoiceOption, BoolOption, IntOption, FloatOption, \
|
||||||
getapi, undefined
|
getapi, undefined
|
||||||
from tiramisu.api import TIRAMISU_VERSION
|
from tiramisu.api import TIRAMISU_VERSION
|
||||||
from tiramisu.error import PropertiesOptionError, ConflictError, SlaveError, ConfigError
|
from tiramisu.error import PropertiesOptionError, ConflictError, SlaveError, ConfigError
|
||||||
|
from tiramisu.i18n import _
|
||||||
|
|
||||||
|
|
||||||
def return_val():
|
def return_val():
|
||||||
|
@ -652,7 +653,13 @@ def test_consistency_master_and_slaves_master_mandatory_transitive():
|
||||||
maconfig = OptionDescription('rootconfig', '', [interface1, interface2])
|
maconfig = OptionDescription('rootconfig', '', [interface1, interface2])
|
||||||
api = getapi(Config(maconfig))
|
api = getapi(Config(maconfig))
|
||||||
api.property.read_write()
|
api.property.read_write()
|
||||||
raises(PropertiesOptionError, "api.option('val1.val1').value.get()")
|
err = None
|
||||||
|
try:
|
||||||
|
api.option('val1.val1').value.get()
|
||||||
|
except PropertiesOptionError as error:
|
||||||
|
err = error
|
||||||
|
assert err, 'should raises'
|
||||||
|
assert str(err) == str(_('cannot access to {0} "{1}" because "{2}" has {3} {4}').format('option', 'val1', 'val2', 'property', '"disabled"'))
|
||||||
raises(PropertiesOptionError, "api.option('val3.val3').value.get()")
|
raises(PropertiesOptionError, "api.option('val3.val3').value.get()")
|
||||||
assert list(api.value.mandatory_warnings()) == []
|
assert list(api.value.mandatory_warnings()) == []
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ from .autopath import do_autopath
|
||||||
do_autopath()
|
do_autopath()
|
||||||
|
|
||||||
from copy import copy
|
from copy import copy
|
||||||
|
from tiramisu.i18n import _
|
||||||
from tiramisu.setting import groups
|
from tiramisu.setting import groups
|
||||||
from tiramisu import setting
|
from tiramisu import setting
|
||||||
setting.expires_time = 1
|
setting.expires_time = 1
|
||||||
|
@ -93,16 +94,17 @@ def test_requires_invalid():
|
||||||
|
|
||||||
|
|
||||||
def test_requires_same_action():
|
def test_requires_same_action():
|
||||||
a = BoolOption('activate_service', '', True)
|
activate_service = BoolOption('activate_service', '', True)
|
||||||
b = BoolOption('activate_service_web', '', True,
|
activate_service_web = BoolOption('activate_service_web', '', True,
|
||||||
requires=[{'option': a, 'expected': False, 'action': 'new'}])
|
requires=[{'option': activate_service, 'expected': False,
|
||||||
|
'action': 'new'}])
|
||||||
|
|
||||||
d = IPOption('ip_address_service_web', '',
|
ip_address_service_web = IPOption('ip_address_service_web', '',
|
||||||
requires=[{'option': b, 'expected': False,
|
requires=[{'option': activate_service_web, 'expected': False,
|
||||||
'action': 'disabled', 'inverse': False,
|
'action': 'disabled', 'inverse': False,
|
||||||
'transitive': True, 'same_action': False}])
|
'transitive': True, 'same_action': False}])
|
||||||
od = OptionDescription('service', '', [a, b, d])
|
od1 = OptionDescription('service', '', [activate_service, activate_service_web, ip_address_service_web])
|
||||||
api = getapi(Config(od))
|
api = getapi(Config(od1))
|
||||||
api.property.read_write()
|
api.property.read_write()
|
||||||
api.property.add('new')
|
api.property.add('new')
|
||||||
api.option('activate_service').value.get()
|
api.option('activate_service').value.get()
|
||||||
|
@ -122,6 +124,8 @@ def test_requires_same_action():
|
||||||
api.option('ip_address_service_web').value.get()
|
api.option('ip_address_service_web').value.get()
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
props = err.proptype
|
props = err.proptype
|
||||||
|
submsg = '"disabled" (' + _('the value of "{0}" is {1}').format('activate_service', '"False"') + ')'
|
||||||
|
assert str(err) == str(_('cannot access to {0} "{1}" because has {2} {3}').format('option', 'ip_address_service_web', 'property', submsg))
|
||||||
assert frozenset(props) == frozenset(['disabled'])
|
assert frozenset(props) == frozenset(['disabled'])
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -662,7 +662,6 @@ class TiramisuOption(CommonTiramisu):
|
||||||
for path in self.config_bag.config.find(byname=name,
|
for path in self.config_bag.config.find(byname=name,
|
||||||
byvalue=value,
|
byvalue=value,
|
||||||
bytype=None,
|
bytype=None,
|
||||||
type_='path',
|
|
||||||
_subpath=self.path,
|
_subpath=self.path,
|
||||||
config_bag=self.config_bag):
|
config_bag=self.config_bag):
|
||||||
config_bag = self.config_bag.copy('nooption')
|
config_bag = self.config_bag.copy('nooption')
|
||||||
|
@ -900,7 +899,6 @@ class TiramisuContextOption(TiramisuContext):
|
||||||
for path in self.config_bag.config.find(byname=name,
|
for path in self.config_bag.config.find(byname=name,
|
||||||
byvalue=value,
|
byvalue=value,
|
||||||
bytype=None,
|
bytype=None,
|
||||||
type_='path',
|
|
||||||
#_subpath=self.path,
|
#_subpath=self.path,
|
||||||
config_bag=self.config_bag):
|
config_bag=self.config_bag):
|
||||||
config_bag = self.config_bag.copy('nooption')
|
config_bag = self.config_bag.copy('nooption')
|
||||||
|
|
|
@ -185,7 +185,7 @@ class SubConfig(object):
|
||||||
`setting.groups`
|
`setting.groups`
|
||||||
"""
|
"""
|
||||||
if group_type is not None and not isinstance(group_type,
|
if group_type is not None and not isinstance(group_type,
|
||||||
groups.GroupType): # pragma: optional cover
|
groups.GroupType):
|
||||||
raise TypeError(_("unknown group_type: {0}").format(group_type))
|
raise TypeError(_("unknown group_type: {0}").format(group_type))
|
||||||
for child in self.cfgimpl_get_description().impl_getchildren(config_bag):
|
for child in self.cfgimpl_get_description().impl_getchildren(config_bag):
|
||||||
if child.impl_is_optiondescription():
|
if child.impl_is_optiondescription():
|
||||||
|
@ -199,7 +199,7 @@ class SubConfig(object):
|
||||||
yield name, self.getattr(name,
|
yield name, self.getattr(name,
|
||||||
None,
|
None,
|
||||||
nconfig_bag)
|
nconfig_bag)
|
||||||
except PropertiesOptionError: # pragma: optional cover
|
except PropertiesOptionError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def cfgimpl_get_children(self,
|
def cfgimpl_get_children(self,
|
||||||
|
@ -227,12 +227,12 @@ class SubConfig(object):
|
||||||
old `SubConfig`, `Values`, `Multi` or `Settings`)
|
old `SubConfig`, `Values`, `Multi` or `Settings`)
|
||||||
"""
|
"""
|
||||||
context = self._impl_context()
|
context = self._impl_context()
|
||||||
if context is None: # pragma: optional cover
|
if context is None: # pragma: no cover
|
||||||
raise ConfigError(_('the context does not exist anymore'))
|
raise ConfigError(_('the context does not exist anymore'))
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def cfgimpl_get_description(self):
|
def cfgimpl_get_description(self):
|
||||||
if self._impl_descr is None: # pragma: optional cover
|
if self._impl_descr is None:
|
||||||
raise ConfigError(_('no option description found for this config'
|
raise ConfigError(_('no option description found for this config'
|
||||||
' (may be GroupConfig)'))
|
' (may be GroupConfig)'))
|
||||||
else:
|
else:
|
||||||
|
@ -252,7 +252,7 @@ class SubConfig(object):
|
||||||
_commit=True):
|
_commit=True):
|
||||||
|
|
||||||
context = self.cfgimpl_get_context()
|
context = self.cfgimpl_get_context()
|
||||||
if '.' in name: # pragma: optional cover
|
if '.' in name:
|
||||||
# when set_value
|
# when set_value
|
||||||
self, name = self.cfgimpl_get_home_by_path(name,
|
self, name = self.cfgimpl_get_home_by_path(name,
|
||||||
config_bag)
|
config_bag)
|
||||||
|
@ -281,7 +281,7 @@ class SubConfig(object):
|
||||||
name,
|
name,
|
||||||
index,
|
index,
|
||||||
config_bag):
|
config_bag):
|
||||||
if '.' in name: # pragma: optional cover
|
if '.' in name:
|
||||||
self, name = self.cfgimpl_get_home_by_path(name,
|
self, name = self.cfgimpl_get_home_by_path(name,
|
||||||
config_bag)
|
config_bag)
|
||||||
option = config_bag.option
|
option = config_bag.option
|
||||||
|
@ -385,7 +385,6 @@ class SubConfig(object):
|
||||||
byname,
|
byname,
|
||||||
byvalue,
|
byvalue,
|
||||||
config_bag,
|
config_bag,
|
||||||
type_='option',
|
|
||||||
_subpath=None,
|
_subpath=None,
|
||||||
raise_if_not_found=True,
|
raise_if_not_found=True,
|
||||||
only_path=undefined,
|
only_path=undefined,
|
||||||
|
@ -397,8 +396,6 @@ class SubConfig(object):
|
||||||
:return: find list or an exception if nothing has been found
|
:return: find list or an exception if nothing has been found
|
||||||
"""
|
"""
|
||||||
def _filter_by_value(sconfig_bag):
|
def _filter_by_value(sconfig_bag):
|
||||||
if byvalue is undefined:
|
|
||||||
return True
|
|
||||||
try:
|
try:
|
||||||
value = self.getattr(path,
|
value = self.getattr(path,
|
||||||
None,
|
None,
|
||||||
|
@ -410,9 +407,6 @@ class SubConfig(object):
|
||||||
else:
|
else:
|
||||||
return value == byvalue
|
return value == byvalue
|
||||||
|
|
||||||
if type_ not in ('option', 'path', 'value'): # pragma: optional cover
|
|
||||||
raise ValueError(_('unknown type_ type {0}'
|
|
||||||
'for find').format(type_))
|
|
||||||
found = False
|
found = False
|
||||||
if only_path is not undefined:
|
if only_path is not undefined:
|
||||||
options = [(only_path, only_option)]
|
options = [(only_path, only_option)]
|
||||||
|
@ -424,10 +418,10 @@ class SubConfig(object):
|
||||||
for path, option in options:
|
for path, option in options:
|
||||||
sconfig_bag = config_bag.copy('nooption')
|
sconfig_bag = config_bag.copy('nooption')
|
||||||
sconfig_bag.option = option
|
sconfig_bag.option = option
|
||||||
if not _filter_by_value(sconfig_bag):
|
if byvalue is not undefined and not _filter_by_value(sconfig_bag):
|
||||||
continue
|
continue
|
||||||
#remove option with propertyerror, ...
|
elif sconfig_bag.validate_properties:
|
||||||
if sconfig_bag.validate_properties:
|
#remove option with propertyerror, ...
|
||||||
try:
|
try:
|
||||||
self.unwrap_from_path(path,
|
self.unwrap_from_path(path,
|
||||||
sconfig_bag)
|
sconfig_bag)
|
||||||
|
@ -436,18 +430,10 @@ class SubConfig(object):
|
||||||
sconfig_bag)
|
sconfig_bag)
|
||||||
except PropertiesOptionError:
|
except PropertiesOptionError:
|
||||||
continue
|
continue
|
||||||
if type_ == 'value':
|
|
||||||
retval = self.getattr(path,
|
|
||||||
None,
|
|
||||||
sconfig_bag)
|
|
||||||
elif type_ == 'path':
|
|
||||||
retval = path
|
|
||||||
elif type_ == 'option':
|
|
||||||
retval = option
|
|
||||||
found = True
|
found = True
|
||||||
yield retval
|
yield path
|
||||||
return self._find_return_results(found,
|
self._find_return_results(found,
|
||||||
raise_if_not_found)
|
raise_if_not_found)
|
||||||
|
|
||||||
def _find_return_results(self,
|
def _find_return_results(self,
|
||||||
found,
|
found,
|
||||||
|
@ -502,7 +488,7 @@ class SubConfig(object):
|
||||||
pathsvalues = []
|
pathsvalues = []
|
||||||
if _currpath is None:
|
if _currpath is None:
|
||||||
_currpath = []
|
_currpath = []
|
||||||
if withoption is None and withvalue is not undefined: # pragma: optional cover
|
if withoption is None and withvalue is not undefined:
|
||||||
raise ValueError(_("make_dict can't filtering with value without "
|
raise ValueError(_("make_dict can't filtering with value without "
|
||||||
"option"))
|
"option"))
|
||||||
context = self.cfgimpl_get_context()
|
context = self.cfgimpl_get_context()
|
||||||
|
@ -510,7 +496,6 @@ class SubConfig(object):
|
||||||
for path in context.find(bytype=None,
|
for path in context.find(bytype=None,
|
||||||
byname=withoption,
|
byname=withoption,
|
||||||
byvalue=withvalue,
|
byvalue=withvalue,
|
||||||
type_='path',
|
|
||||||
_subpath=self.cfgimpl_get_path(False),
|
_subpath=self.cfgimpl_get_path(False),
|
||||||
config_bag=config_bag):
|
config_bag=config_bag):
|
||||||
path = '.'.join(path.split('.')[:-1])
|
path = '.'.join(path.split('.')[:-1])
|
||||||
|
@ -526,7 +511,7 @@ class SubConfig(object):
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
tmypath = mypath + '.'
|
tmypath = mypath + '.'
|
||||||
if not path.startswith(tmypath): # pragma: optional cover
|
if not path.startswith(tmypath):
|
||||||
raise AttributeError(_('unexpected path {0}, '
|
raise AttributeError(_('unexpected path {0}, '
|
||||||
'should start with {1}'
|
'should start with {1}'
|
||||||
'').format(path, mypath))
|
'').format(path, mypath))
|
||||||
|
@ -751,7 +736,7 @@ class Config(_CommonConfig):
|
||||||
properties, permissives, values, session_id = get_storages(self,
|
properties, permissives, values, session_id = get_storages(self,
|
||||||
session_id,
|
session_id,
|
||||||
persistent)
|
persistent)
|
||||||
if not valid_name(session_id): # pragma: optional cover
|
if not valid_name(session_id):
|
||||||
raise ValueError(_("invalid session ID: {0} for config").format(session_id))
|
raise ValueError(_("invalid session ID: {0} for config").format(session_id))
|
||||||
self._impl_settings = Settings(self,
|
self._impl_settings = Settings(self,
|
||||||
properties,
|
properties,
|
||||||
|
@ -869,7 +854,15 @@ class GroupConfig(_CommonConfig):
|
||||||
nconfig_bag,
|
nconfig_bag,
|
||||||
_commit=False)
|
_commit=False)
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
ret.append(PropertiesOptionError(str(err), err.proptype))
|
ret.append(PropertiesOptionError(err._path,
|
||||||
|
err._index,
|
||||||
|
err._config_bag,
|
||||||
|
err.proptype,
|
||||||
|
err._settings,
|
||||||
|
err._opt_type,
|
||||||
|
err._requires,
|
||||||
|
err._name,
|
||||||
|
err._orig_opt))
|
||||||
except (ValueError, SlaveError) as err:
|
except (ValueError, SlaveError) as err:
|
||||||
ret.append(err)
|
ret.append(err)
|
||||||
if _commit:
|
if _commit:
|
||||||
|
@ -896,7 +889,6 @@ class GroupConfig(_CommonConfig):
|
||||||
byvalue=undefined,
|
byvalue=undefined,
|
||||||
byname=byname,
|
byname=byname,
|
||||||
config_bag=config_bag,
|
config_bag=config_bag,
|
||||||
type_='path',
|
|
||||||
raise_if_not_found=raise_if_not_found))
|
raise_if_not_found=raise_if_not_found))
|
||||||
byname = None
|
byname = None
|
||||||
byoption = self.cfgimpl_get_description().impl_get_opt_by_path(bypath)
|
byoption = self.cfgimpl_get_description().impl_get_opt_by_path(bypath)
|
||||||
|
@ -918,7 +910,6 @@ class GroupConfig(_CommonConfig):
|
||||||
next(child.find(None,
|
next(child.find(None,
|
||||||
byname,
|
byname,
|
||||||
byvalue,
|
byvalue,
|
||||||
type_='path',
|
|
||||||
config_bag=config_bag,
|
config_bag=config_bag,
|
||||||
raise_if_not_found=False,
|
raise_if_not_found=False,
|
||||||
only_path=bypath,
|
only_path=bypath,
|
||||||
|
@ -935,22 +926,13 @@ class GroupConfig(_CommonConfig):
|
||||||
|
|
||||||
def impl_getname(self):
|
def impl_getname(self):
|
||||||
return self._impl_name
|
return self._impl_name
|
||||||
# def __str__(self):
|
|
||||||
# ret = ''
|
|
||||||
# for child in self._impl_children:
|
|
||||||
# ret += "({0})\n".format(child._impl_name)
|
|
||||||
# if self._impl_descr is not None:
|
|
||||||
# ret += super(GroupConfig, self).__str__()
|
|
||||||
# return ret
|
|
||||||
#
|
|
||||||
# __repr__ = __str__
|
|
||||||
|
|
||||||
def getconfig(self,
|
def getconfig(self,
|
||||||
name):
|
name):
|
||||||
for child in self._impl_children:
|
for child in self._impl_children:
|
||||||
if name == child.impl_getname():
|
if name == child.impl_getname():
|
||||||
return child
|
return child
|
||||||
raise ConfigError(_('unknown config {}').format(name))
|
raise ConfigError(_('unknown config "{}"').format(name))
|
||||||
|
|
||||||
|
|
||||||
class MetaConfig(GroupConfig):
|
class MetaConfig(GroupConfig):
|
||||||
|
|
|
@ -55,27 +55,48 @@ def display_list(lst, separator='and', add_quote=False):
|
||||||
class PropertiesOptionError(AttributeError):
|
class PropertiesOptionError(AttributeError):
|
||||||
"attempt to access to an option with a property that is not allowed"
|
"attempt to access to an option with a property that is not allowed"
|
||||||
def __init__(self,
|
def __init__(self,
|
||||||
msg,
|
path,
|
||||||
|
index,
|
||||||
|
config_bag,
|
||||||
proptype,
|
proptype,
|
||||||
settings=None,
|
settings,
|
||||||
datas=None,
|
opt_type=None,
|
||||||
option_type=None):
|
requires=None,
|
||||||
|
name=None,
|
||||||
|
orig_opt=None):
|
||||||
|
self._path = path
|
||||||
|
self._index = index
|
||||||
|
if opt_type:
|
||||||
|
self._opt_type = opt_type
|
||||||
|
self._requires = requires
|
||||||
|
self._name = name
|
||||||
|
self._orig_opt = orig_opt
|
||||||
|
else:
|
||||||
|
if config_bag.option.impl_is_optiondescription():
|
||||||
|
self._opt_type = 'optiondescription'
|
||||||
|
else:
|
||||||
|
self._opt_type = 'option'
|
||||||
|
self._requires = config_bag.option.impl_getrequires()
|
||||||
|
self._name = config_bag.option.impl_get_display_name()
|
||||||
|
self._orig_opt = None
|
||||||
|
self._config_bag = config_bag.copy('nooption')
|
||||||
self.proptype = proptype
|
self.proptype = proptype
|
||||||
self._settings = settings
|
self._settings = settings
|
||||||
self._datas = datas
|
self.msg = None
|
||||||
self._type = option_type
|
super(PropertiesOptionError, self).__init__(None)
|
||||||
self._orig_opt = None
|
|
||||||
super(PropertiesOptionError, self).__init__(msg)
|
|
||||||
|
|
||||||
def set_orig_opt(self, opt):
|
def set_orig_opt(self, opt):
|
||||||
self._orig_opt = opt
|
self._orig_opt = opt
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
#this part is a bit slow, so only execute when display
|
#this part is a bit slow, so only execute when display
|
||||||
if self._settings is None:
|
if self.msg:
|
||||||
req = {}
|
return self.msg
|
||||||
else:
|
req = self._settings.apply_requires(self._path,
|
||||||
req = self._settings.apply_requires(**self._datas)
|
self._requires,
|
||||||
|
self._index,
|
||||||
|
True,
|
||||||
|
self._config_bag)
|
||||||
#if req != {} or self._orig_opt is not None:
|
#if req != {} or self._orig_opt is not None:
|
||||||
if req != {}:
|
if req != {}:
|
||||||
only_one = len(req) == 1
|
only_one = len(req) == 1
|
||||||
|
@ -91,17 +112,20 @@ class PropertiesOptionError(AttributeError):
|
||||||
else:
|
else:
|
||||||
prop_msg = _('properties')
|
prop_msg = _('properties')
|
||||||
if self._orig_opt:
|
if self._orig_opt:
|
||||||
return str(_('cannot access to {0} "{1}" because "{2}" has {3} {4}'
|
self.msg = str(_('cannot access to {0} "{1}" because "{2}" has {3} {4}'
|
||||||
'').format(self._type,
|
'').format(self._opt_type,
|
||||||
self._orig_opt.impl_get_display_name(),
|
self._orig_opt.impl_get_display_name(),
|
||||||
self._datas['config_bag'].option.impl_get_display_name(),
|
self._name,
|
||||||
|
prop_msg,
|
||||||
|
msg))
|
||||||
|
self.msg = str(_('cannot access to {0} "{1}" because has {2} {3}'
|
||||||
|
'').format(self._opt_type,
|
||||||
|
self._name,
|
||||||
prop_msg,
|
prop_msg,
|
||||||
msg))
|
msg))
|
||||||
return str(_('cannot access to {0} "{1}" because has {2} {3}'
|
del self._path, self._index, self._requires, self._opt_type, self._name, self._config_bag
|
||||||
'').format(self._type,
|
del self._settings, self._orig_opt
|
||||||
self._datas['config_bag'].option.impl_get_display_name(),
|
return self.msg
|
||||||
prop_msg,
|
|
||||||
msg))
|
|
||||||
|
|
||||||
|
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
|
|
|
@ -25,7 +25,7 @@ from inspect import signature
|
||||||
|
|
||||||
from ..i18n import _
|
from ..i18n import _
|
||||||
from ..setting import undefined
|
from ..setting import undefined
|
||||||
from ..error import ConfigError
|
from ..error import ConfigError, display_list
|
||||||
|
|
||||||
STATIC_TUPLE = frozenset()
|
STATIC_TUPLE = frozenset()
|
||||||
|
|
||||||
|
@ -162,7 +162,7 @@ class Base(object):
|
||||||
set_forbidden_properties = calc_properties & properties
|
set_forbidden_properties = calc_properties & properties
|
||||||
if set_forbidden_properties != frozenset():
|
if set_forbidden_properties != frozenset():
|
||||||
raise ValueError(_('conflict: properties already set in '
|
raise ValueError(_('conflict: properties already set in '
|
||||||
'requirement {0}').format(list(set_forbidden_properties)))
|
'requirement {0}').format(display_list(list(set_forbidden_properties))))
|
||||||
_setattr = object.__setattr__
|
_setattr = object.__setattr__
|
||||||
_setattr(self, '_name', name)
|
_setattr(self, '_name', name)
|
||||||
_setattr(self, '_informations', {'doc': doc})
|
_setattr(self, '_informations', {'doc': doc})
|
||||||
|
@ -249,10 +249,9 @@ class Base(object):
|
||||||
if calculator_args or calculator_kwargs:
|
if calculator_args or calculator_kwargs:
|
||||||
# there is more args/kwargs than expected!
|
# there is more args/kwargs than expected!
|
||||||
raise ConfigError(_('cannot find those arguments "{}" in function "{}" for "{}"'
|
raise ConfigError(_('cannot find those arguments "{}" in function "{}" for "{}"'
|
||||||
'').format(list(calculator_args | calculator_kwargs),
|
'').format(display_list(list(calculator_args | calculator_kwargs)),
|
||||||
calculator.__name__,
|
calculator.__name__,
|
||||||
self.impl_get_display_name()))
|
self.impl_get_display_name()))
|
||||||
has_self = False
|
|
||||||
has_index = False
|
has_index = False
|
||||||
if is_multi and func_args:
|
if is_multi and func_args:
|
||||||
# there is extra args/kwargs
|
# there is extra args/kwargs
|
||||||
|
@ -267,16 +266,13 @@ class Base(object):
|
||||||
has_index = True
|
has_index = True
|
||||||
params.append(('index',))
|
params.append(('index',))
|
||||||
func_args.pop()
|
func_args.pop()
|
||||||
if func_args:
|
|
||||||
raise ConfigError(_('missing those arguements "{}" in function "{}" for "{}"'
|
|
||||||
'').format(list(func_args),
|
|
||||||
calculator.__name__,
|
|
||||||
self.impl_get_display_name()))
|
|
||||||
calculator_params[''] = tuple(params)
|
calculator_params[''] = tuple(params)
|
||||||
|
if func_args:
|
||||||
|
raise ConfigError(_('missing those arguments "{}" in function "{}" for "{}"'
|
||||||
|
'').format(display_list(list(func_args)),
|
||||||
|
calculator.__name__,
|
||||||
|
self.impl_get_display_name()))
|
||||||
if not self.impl_is_optiondescription() and self.impl_is_multi():
|
if not self.impl_is_optiondescription() and self.impl_is_multi():
|
||||||
if add_value and not has_self and 'self' in func_kwargs:
|
|
||||||
# only for validator
|
|
||||||
calculator_params['self'] = (self, False)
|
|
||||||
if not has_index and 'index' in func_kwargs:
|
if not has_index and 'index' in func_kwargs:
|
||||||
calculator_params['index'] = (('index',),)
|
calculator_params['index'] = (('index',),)
|
||||||
return calculator_params
|
return calculator_params
|
||||||
|
@ -573,8 +569,9 @@ def validate_requires_arg(new_option,
|
||||||
option = exp['option']
|
option = exp['option']
|
||||||
option._add_dependency(new_option)
|
option._add_dependency(new_option)
|
||||||
if option is not None:
|
if option is not None:
|
||||||
err = option._validate(exp['value'], undefined)
|
try:
|
||||||
if err:
|
option._validate(exp['value'], undefined)
|
||||||
|
except ValueError as err:
|
||||||
raise ValueError(_('malformed requirements expected value '
|
raise ValueError(_('malformed requirements expected value '
|
||||||
'must be valid for option {0}'
|
'must be valid for option {0}'
|
||||||
': {1}').format(name, err))
|
': {1}').format(name, err))
|
||||||
|
@ -588,11 +585,13 @@ def validate_requires_arg(new_option,
|
||||||
else:
|
else:
|
||||||
option = get_option(require)
|
option = get_option(require)
|
||||||
if expected is not None:
|
if expected is not None:
|
||||||
err = option._validate(expected, undefined)
|
try:
|
||||||
if err:
|
option._validate(expected, undefined)
|
||||||
|
except ValueError as err:
|
||||||
raise ValueError(_('malformed requirements expected value '
|
raise ValueError(_('malformed requirements expected value '
|
||||||
'must be valid for option {0}'
|
'must be valid for option {0}'
|
||||||
': {1}').format(name, err))
|
': {1}').format(name, err))
|
||||||
|
option._add_dependency(new_option)
|
||||||
_set_expected(action,
|
_set_expected(action,
|
||||||
inverse,
|
inverse,
|
||||||
transitive,
|
transitive,
|
||||||
|
|
|
@ -373,6 +373,7 @@ class Settings(object):
|
||||||
apply_requires)
|
apply_requires)
|
||||||
if apply_requires:
|
if apply_requires:
|
||||||
props |= self.apply_requires(path,
|
props |= self.apply_requires(path,
|
||||||
|
opt.impl_getrequires(),
|
||||||
index,
|
index,
|
||||||
False,
|
False,
|
||||||
config_bag)
|
config_bag)
|
||||||
|
@ -405,9 +406,11 @@ class Settings(object):
|
||||||
|
|
||||||
def apply_requires(self,
|
def apply_requires(self,
|
||||||
path,
|
path,
|
||||||
|
current_requires,
|
||||||
index,
|
index,
|
||||||
debug,
|
readable,
|
||||||
config_bag):
|
config_bag,
|
||||||
|
name=None):
|
||||||
"""carries out the jit (just in time) requirements between options
|
"""carries out the jit (just in time) requirements between options
|
||||||
|
|
||||||
a requirement is a tuple of this form that comes from the option's
|
a requirement is a tuple of this form that comes from the option's
|
||||||
|
@ -451,11 +454,10 @@ class Settings(object):
|
||||||
:param path: the option's path in the config
|
:param path: the option's path in the config
|
||||||
:type path: str
|
:type path: str
|
||||||
"""
|
"""
|
||||||
opt = config_bag.option
|
#current_requires = opt.impl_getrequires()
|
||||||
current_requires = opt.impl_getrequires()
|
|
||||||
|
|
||||||
# filters the callbacks
|
# filters the callbacks
|
||||||
if debug:
|
if readable:
|
||||||
calc_properties = {}
|
calc_properties = {}
|
||||||
else:
|
else:
|
||||||
calc_properties = set()
|
calc_properties = set()
|
||||||
|
@ -467,25 +469,21 @@ class Settings(object):
|
||||||
all_properties = None
|
all_properties = None
|
||||||
for requires in current_requires:
|
for requires in current_requires:
|
||||||
for require in requires:
|
for require in requires:
|
||||||
exps, action, inverse, \
|
exps, action, inverse, transitive, same_action, operator = require
|
||||||
transitive, same_action, operator = require
|
|
||||||
breaked = False
|
breaked = False
|
||||||
for exp in exps:
|
for option, expected in exps:
|
||||||
option, expected = exp
|
|
||||||
reqpath = option.impl_getpath(context)
|
reqpath = option.impl_getpath(context)
|
||||||
if reqpath == path or reqpath.startswith(path + '.'): # pragma: optional cover
|
#FIXME c'est un peut tard !
|
||||||
|
if reqpath == path or reqpath.startswith(path + '.'):
|
||||||
raise RequirementError(_("malformed requirements "
|
raise RequirementError(_("malformed requirements "
|
||||||
"imbrication detected for option:"
|
"imbrication detected for option:"
|
||||||
" '{0}' with requirement on: "
|
" '{0}' with requirement on: "
|
||||||
"'{1}'").format(path, reqpath))
|
"'{1}'").format(path, reqpath))
|
||||||
if not option.impl_is_multi():
|
idx = None
|
||||||
idx = None
|
is_indexed = False
|
||||||
is_indexed = False
|
if option.impl_is_master_slaves('slave'):
|
||||||
elif option.impl_is_master_slaves('slave'):
|
|
||||||
idx = index
|
idx = index
|
||||||
is_indexed = False
|
elif option.impl_is_multi():
|
||||||
else:
|
|
||||||
idx = None
|
|
||||||
is_indexed = True
|
is_indexed = True
|
||||||
sconfig_bag = config_bag.copy('nooption')
|
sconfig_bag = config_bag.copy('nooption')
|
||||||
sconfig_bag.option = option
|
sconfig_bag.option = option
|
||||||
|
@ -497,40 +495,44 @@ class Settings(object):
|
||||||
if is_indexed:
|
if is_indexed:
|
||||||
value = value[index]
|
value = value[index]
|
||||||
except PropertiesOptionError as err:
|
except PropertiesOptionError as err:
|
||||||
|
properties = err.proptype
|
||||||
if not transitive:
|
if not transitive:
|
||||||
if all_properties is None:
|
if all_properties is None:
|
||||||
all_properties = []
|
all_properties = []
|
||||||
for requires_ in opt.impl_getrequires():
|
for requires_ in current_requires:
|
||||||
for require_ in requires_:
|
for require_ in requires_:
|
||||||
all_properties.append(require_[1])
|
all_properties.append(require_[1])
|
||||||
if not set(err.proptype) - set(all_properties):
|
if not set(properties) - set(all_properties):
|
||||||
continue
|
continue
|
||||||
properties = err.proptype
|
if same_action and action not in properties:
|
||||||
if same_action and action not in properties: # pragma: optional cover
|
|
||||||
if len(properties) == 1:
|
if len(properties) == 1:
|
||||||
prop_msg = _('property')
|
prop_msg = _('property')
|
||||||
else:
|
else:
|
||||||
prop_msg = _('properties')
|
prop_msg = _('properties')
|
||||||
raise RequirementError(_('cannot access to option "{0}" because '
|
raise RequirementError(_('cannot access to option "{0}" because '
|
||||||
'required option "{1}" has {2} {3}'
|
'required option "{1}" has {2} {3}'
|
||||||
'').format(opt.impl_get_display_name(),
|
'').format(name,
|
||||||
option.impl_get_display_name(),
|
option.impl_get_display_name(),
|
||||||
prop_msg,
|
prop_msg,
|
||||||
display_list(list(properties))))
|
display_list(list(properties))))
|
||||||
orig_value = err
|
# transitive action, add action
|
||||||
# transitive action, force expected
|
|
||||||
value = expected[0]
|
|
||||||
inverse = False
|
|
||||||
else:
|
|
||||||
orig_value = value
|
|
||||||
if (not inverse and value in expected or
|
|
||||||
inverse and value not in expected):
|
|
||||||
if operator != 'and':
|
if operator != 'and':
|
||||||
if debug:
|
if readable:
|
||||||
if isinstance(orig_value, PropertiesOptionError):
|
for msg in self.apply_requires(err.path,
|
||||||
for msg in orig_value._settings.apply_requires(**orig_value._datas).values():
|
err.requires,
|
||||||
calc_properties.setdefault(action, []).extend(msg)
|
err.index,
|
||||||
else:
|
True,
|
||||||
|
err.config_bag).values():
|
||||||
|
calc_properties.setdefault(action, []).extend(msg)
|
||||||
|
else:
|
||||||
|
calc_properties.add(action)
|
||||||
|
breaked = True
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
if (not inverse and value in expected or
|
||||||
|
inverse and value not in expected):
|
||||||
|
if operator != 'and':
|
||||||
|
if readable:
|
||||||
if not inverse:
|
if not inverse:
|
||||||
msg = _('the value of "{0}" is {1}')
|
msg = _('the value of "{0}" is {1}')
|
||||||
else:
|
else:
|
||||||
|
@ -538,12 +540,12 @@ class Settings(object):
|
||||||
calc_properties.setdefault(action, []).append(
|
calc_properties.setdefault(action, []).append(
|
||||||
msg.format(option.impl_get_display_name(),
|
msg.format(option.impl_get_display_name(),
|
||||||
display_list(expected, 'or', add_quote=True)))
|
display_list(expected, 'or', add_quote=True)))
|
||||||
else:
|
else:
|
||||||
calc_properties.add(action)
|
calc_properties.add(action)
|
||||||
breaked = True
|
breaked = True
|
||||||
break
|
break
|
||||||
elif operator == 'and':
|
elif operator == 'and':
|
||||||
break
|
break
|
||||||
else:
|
else:
|
||||||
if operator == 'and':
|
if operator == 'and':
|
||||||
calc_properties.add(action)
|
calc_properties.add(action)
|
||||||
|
@ -691,11 +693,6 @@ class Settings(object):
|
||||||
config_bag)
|
config_bag)
|
||||||
config_bag.properties = self_properties
|
config_bag.properties = self_properties
|
||||||
properties = self_properties & config_bag.setting_properties - {'frozen', 'mandatory', 'empty'}
|
properties = self_properties & config_bag.setting_properties - {'frozen', 'mandatory', 'empty'}
|
||||||
if not opt.impl_is_optiondescription():
|
|
||||||
opt_type = 'option'
|
|
||||||
else:
|
|
||||||
opt_type = 'optiondescription'
|
|
||||||
|
|
||||||
|
|
||||||
# remove permissive properties
|
# remove permissive properties
|
||||||
if (config_bag.force_permissive is True or 'permissive' in config_bag.setting_properties) and properties:
|
if (config_bag.force_permissive is True or 'permissive' in config_bag.setting_properties) and properties:
|
||||||
|
@ -703,15 +700,11 @@ class Settings(object):
|
||||||
properties -= self.get_context_permissive()
|
properties -= self.get_context_permissive()
|
||||||
# at this point an option should not remain in properties
|
# at this point an option should not remain in properties
|
||||||
if properties != frozenset():
|
if properties != frozenset():
|
||||||
datas = {'path': path,
|
raise PropertiesOptionError(path,
|
||||||
'config_bag': config_bag,
|
index,
|
||||||
'index': index,
|
config_bag,
|
||||||
'debug': True}
|
|
||||||
raise PropertiesOptionError(None,
|
|
||||||
properties,
|
properties,
|
||||||
self,
|
self)
|
||||||
datas,
|
|
||||||
opt_type)
|
|
||||||
|
|
||||||
def validate_mandatory(self,
|
def validate_mandatory(self,
|
||||||
path,
|
path,
|
||||||
|
@ -735,17 +728,15 @@ class Settings(object):
|
||||||
index=index):
|
index=index):
|
||||||
is_mandatory = True
|
is_mandatory = True
|
||||||
if is_mandatory:
|
if is_mandatory:
|
||||||
datas = {'path': path,
|
raise PropertiesOptionError(path,
|
||||||
'config_bag': config_bag,
|
index,
|
||||||
'index': index,
|
config_bag,
|
||||||
'debug': True}
|
|
||||||
raise PropertiesOptionError(None,
|
|
||||||
['mandatory'],
|
['mandatory'],
|
||||||
self,
|
self)
|
||||||
datas,
|
|
||||||
'option')
|
|
||||||
|
|
||||||
def validate_frozen(self,
|
def validate_frozen(self,
|
||||||
|
path,
|
||||||
|
index,
|
||||||
config_bag):
|
config_bag):
|
||||||
if config_bag.setting_properties and \
|
if config_bag.setting_properties and \
|
||||||
('everything_frozen' in config_bag.setting_properties or
|
('everything_frozen' in config_bag.setting_properties or
|
||||||
|
@ -753,7 +744,11 @@ class Settings(object):
|
||||||
not ((config_bag.force_permissive is True or
|
not ((config_bag.force_permissive is True or
|
||||||
'permissive' in config_bag.setting_properties) and
|
'permissive' in config_bag.setting_properties) and
|
||||||
'frozen' in self.get_context_permissive()):
|
'frozen' in self.get_context_permissive()):
|
||||||
return True
|
raise PropertiesOptionError(path,
|
||||||
|
index,
|
||||||
|
config_bag,
|
||||||
|
['frozen'],
|
||||||
|
self)
|
||||||
return False
|
return False
|
||||||
#____________________________________________________________
|
#____________________________________________________________
|
||||||
# read only/read write
|
# read only/read write
|
||||||
|
|
|
@ -56,7 +56,7 @@ class Values(object):
|
||||||
old `SubConfig`, `Values`, `Multi` or `Settings`)
|
old `SubConfig`, `Values`, `Multi` or `Settings`)
|
||||||
"""
|
"""
|
||||||
context = self.context()
|
context = self.context()
|
||||||
if context is None:
|
if context is None: # pragma: no cover
|
||||||
raise ConfigError(_('the context does not exist anymore'))
|
raise ConfigError(_('the context does not exist anymore'))
|
||||||
return context
|
return context
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ class Values(object):
|
||||||
# if value is a list and index is set
|
# if value is a list and index is set
|
||||||
if opt.impl_is_submulti() and (value == [] or not isinstance(value[0], list)):
|
if opt.impl_is_submulti() and (value == [] or not isinstance(value[0], list)):
|
||||||
# return value only if it's a submulti and not a list of list
|
# return value only if it's a submulti and not a list of list
|
||||||
_reset_cache(value,)
|
_reset_cache(value)
|
||||||
return value
|
return value
|
||||||
|
|
||||||
if len(value) > index:
|
if len(value) > index:
|
||||||
|
@ -251,28 +251,20 @@ class Values(object):
|
||||||
return value[index]
|
return value[index]
|
||||||
# there is no calculate value for this index,
|
# there is no calculate value for this index,
|
||||||
# so return an other default value
|
# so return an other default value
|
||||||
elif isinstance(value, list):
|
|
||||||
# value is a list, but no index specified
|
|
||||||
if opt.impl_is_submulti() and (value != [] and not isinstance(value[0], list)):
|
|
||||||
# if submulti, return a list of value
|
|
||||||
value = [value]
|
|
||||||
_reset_cache(value)
|
|
||||||
return value
|
|
||||||
# otherwise just return the value
|
|
||||||
return value
|
|
||||||
elif index is not None:
|
|
||||||
# if not list but with index
|
|
||||||
if opt.impl_is_submulti():
|
|
||||||
# if submulti, return a list of value
|
|
||||||
value = [value]
|
|
||||||
_reset_cache(value)
|
|
||||||
return value
|
|
||||||
else:
|
else:
|
||||||
# not a list or index is None
|
|
||||||
if opt.impl_is_submulti():
|
if opt.impl_is_submulti():
|
||||||
# return a list of list for a submulti
|
if isinstance(value, list):
|
||||||
value = [[value]]
|
# value is a list, but no index specified
|
||||||
elif opt.impl_is_multi():
|
if (value != [] and not isinstance(value[0], list)):
|
||||||
|
# if submulti, return a list of value
|
||||||
|
value = [value]
|
||||||
|
elif index is not None:
|
||||||
|
# if submulti, return a list of value
|
||||||
|
value = [value]
|
||||||
|
else:
|
||||||
|
# return a list of list for a submulti
|
||||||
|
value = [[value]]
|
||||||
|
elif opt.impl_is_multi() and not isinstance(value, list) and index is None:
|
||||||
# return a list for a multi
|
# return a list for a multi
|
||||||
value = [value]
|
value = [value]
|
||||||
_reset_cache(value)
|
_reset_cache(value)
|
||||||
|
@ -375,16 +367,9 @@ class Values(object):
|
||||||
config_bag)
|
config_bag)
|
||||||
config_bag.properties = self_properties
|
config_bag.properties = self_properties
|
||||||
opt = config_bag.option
|
opt = config_bag.option
|
||||||
if settings.validate_frozen(config_bag):
|
settings.validate_frozen(path,
|
||||||
datas = {'path': path,
|
index,
|
||||||
'config_bag': config_bag,
|
config_bag)
|
||||||
'index': index,
|
|
||||||
'debug': True}
|
|
||||||
raise PropertiesOptionError(None,
|
|
||||||
['frozen'],
|
|
||||||
settings,
|
|
||||||
datas,
|
|
||||||
'option')
|
|
||||||
settings.validate_mandatory(path,
|
settings.validate_mandatory(path,
|
||||||
index,
|
index,
|
||||||
value,
|
value,
|
||||||
|
@ -673,16 +658,9 @@ class Values(object):
|
||||||
None,
|
None,
|
||||||
config_bag)
|
config_bag)
|
||||||
config_bag.properties = self_properties
|
config_bag.properties = self_properties
|
||||||
if settings.validate_frozen(config_bag):
|
settings.validate_frozen(path,
|
||||||
datas = {'path': path,
|
index,
|
||||||
'config_bag': config_bag,
|
config_bag)
|
||||||
'index': index,
|
|
||||||
'debug': True}
|
|
||||||
raise PropertiesOptionError(None,
|
|
||||||
['frozen'],
|
|
||||||
settings,
|
|
||||||
datas,
|
|
||||||
'option')
|
|
||||||
|
|
||||||
#______________________________________________________________________
|
#______________________________________________________________________
|
||||||
# information
|
# information
|
||||||
|
|
Loading…
Reference in New Issue