refactor and better test in api

This commit is contained in:
Emmanuel Garette 2017-11-13 22:45:53 +01:00
parent a8d022b67f
commit 007a22ca94
9 changed files with 406 additions and 348 deletions

View File

@ -210,8 +210,8 @@ def test_callback_submulti_list_list():
def test_values_with_master_and_slaves_submulti():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti)
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-reseau", multi=submulti)
interface1 = MasterSlaves('f_ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
conf = OptionDescription('conf', '', [interface1])
cfg = Config(conf)

View File

@ -2,6 +2,7 @@
"""
import pytest
from py.test import raises
import weakref
from .autopath import do_autopath
do_autopath()
from tiramisu import Config, StrOption, OptionDescription, MasterSlaves, DynOptionDescription, \
@ -55,7 +56,10 @@ def autocheck_owner_without_value(api, path, **kwargs):
isslave = False
# check if owner is a string "default"
if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False):
assert api.option(path).owner.get() == 'default'
if not isslave:
assert api.option(path).owner.get() == 'default'
else:
assert api.option(path, 0).owner.get() == 'default'
else:
if not isslave:
raises(PropertiesOptionError, "api.option(path).owner.get()")
@ -76,7 +80,10 @@ def autocheck_owner_without_value(api, path, **kwargs):
# check if default owner
raises(APIError, "api.unrestraint.option(path).owner.isdefault()")
if not kwargs.get('permissive', False) and not kwargs.get('propertyerror', False):
assert api.option(path).owner.isdefault()
if not isslave:
assert api.option(path).owner.isdefault()
else:
assert api.option(path, 0).owner.isdefault()
else:
raises(PropertiesOptionError, "api.option(path).owner.isdefault()")
if not kwargs.get('propertyerror', False):
@ -141,7 +148,6 @@ def autocheck_value(api, path, **kwargs):
api.option(path).value.set([first_value[0]])
elif isslave:
api.option(path, 0).value.set(first_value[0])
raise Exception('pouet')
else:
api.option(path).value.set(first_value)
else:
@ -321,6 +327,14 @@ def autocheck_value2(*args, **kwargs):
autocheck_value(*args, **kwargs)
@autocheck
def autocheck_display(api, path, **kwargs):
"""re set value
"""
#FIXME utile ?
print(api.config)
@autocheck
def autocheck_property(api, path, **kwargs):
"""get property from path
@ -756,6 +770,7 @@ def check_all(api, path, multi, **kwargs):
text = u' {} launch tests for {}'.format(ICON, path)
if multi:
text += u' as a multi'
text += u', kwargs: {}'.format(kwargs)
print(text)
for func in autocheck_registers:
if DISPLAY:
@ -764,6 +779,7 @@ def check_all(api, path, multi, **kwargs):
def make_api(options, multi):
weakrefs = []
def make_option(path, option_infos):
#FIXME
option_type = 'str'
@ -779,7 +795,9 @@ def make_api(options, multi):
if multi:
kwargs['multi'] = True
tiramisu_option = OPTIONS_TYPE[option_type]['option']
return tiramisu_option(*args, **kwargs)
obj = tiramisu_option(*args, **kwargs)
weakrefs.append(weakref.ref(obj))
return obj
def make_optiondescriptions(path, collected):
infos = collected.get('properties', {})
@ -809,7 +827,9 @@ def make_api(options, multi):
options.append(option)
if properties != []:
kwargs['properties'] = tuple(properties)
return optiondescription(path, "{}'s optiondescription".format(path), options, **kwargs)
obj = optiondescription(path, "{}'s optiondescription".format(path), options, **kwargs)
weakrefs.append(weakref.ref(obj))
return obj
collect_options = {}
for path, option in options.items():
@ -826,16 +846,20 @@ def make_api(options, multi):
rootod = make_optiondescriptions('root', collect_options)
if rootod is None:
return
cfg = Config(rootod)
return getapi(cfg)
return None, None
cfg = Config(rootod, session_id='conftest')
weakrefs.append(weakref.ref(cfg))
api = getapi(cfg)
weakrefs.append(weakref.ref(api))
return api, weakrefs
DICT_PATHS = [
#test a config without optiondescription
OrderedDict([('first', {}),
('second', {'second': {'disabled': True}}),
('third', {'third': {'hidden': True}})]),
('third', {'third': {'hidden': True}})
]),
#test a config with an optiondescription
OrderedDict([('subod.first', {}),
('subod.second', {'second': {'disabled': True}}),
@ -864,8 +888,22 @@ DICT_PATHS = [
('subodval2.thirdval2', None)]),
#test a config with dynoption subdir
OrderedDict([('subod.subsubod.first', {'subsubod': {'dyn': True}}),
('subod.subsubod.second', {'second': {'disabled': True}}),
('subod.subsubod.third', {'third': {'hidden': True}}),
('subod.subsubod.second', {'subsubod': {'dyn': True}, 'second': {'disabled': True}}),
('subod.subsubod.third', {'subsubod': {'dyn': True}, 'third': {'hidden': True}}),
('subod.subsubodval1.firstval1', None),
('subod.subsubodval1.secondval1', None),
('subod.subsubodval1.thirdval1', None),
('subod.subsubodval2.firstval2', None),
('subod.subsubodval2.secondval2', None),
('subod.subsubodval2.thirdval2', None)]),
#test a config with hidden subsubod
OrderedDict([('subod.subsubod.first', {'subsubod': {'hidden': True}}),
('subod.subsubod.second', {'subsubod': {'hidden': True}}),
('subod.subsubod.third', {'subsubod': {'hidden': True}})]),
#test a config with hidden dyn subsubod
OrderedDict([('subod.subsubod.first', {'subsubod': {'dyn': True, 'hidden': True}}),
('subod.subsubod.second', {'subsubod': {'dyn': True, 'hidden': True}}),
('subod.subsubod.third', {'subsubod': {'dyn': True, 'hidden': True}}),
('subod.subsubodval1.firstval1', None),
('subod.subsubodval1.secondval1', None),
('subod.subsubodval1.thirdval1', None),
@ -883,63 +921,40 @@ def paths(request):
def test_options(paths):
def get_kwargs_option(options, kwargs, od=False):
if options.get('hidden', False) is True:
kwargs['permissive'] = True
if not od:
kwargs.setdefault('extra_properties', []).append('hidden')
if options.get('disabled', False) is True:
kwargs['propertyerror'] = True
if not od:
kwargs.setdefault('extra_properties', []).append('disabled')
def get_kwargs(path):
kwargs = {}
spath = path.split('.')
get_kwargs_option(paths[path].get(spath[-1], {}), kwargs)
if len(spath) > 1:
get_kwargs_option(paths[path].get(spath[-2], {}), kwargs, od=True)
return kwargs
lpaths = list(paths.keys())
for multi in (False, True):
api = make_api(paths, multi)
api, weakrefs = make_api(paths, multi)
if api is None:
continue
if len(lpaths) == 9:
check_all(api, lpaths[3], multi)
check_all(api, lpaths[4], multi, propertyerror=True, extra_properties=['disabled'])
check_all(api, lpaths[5], multi, permissive=True, extra_properties=['hidden'])
check_all(api, lpaths[6], multi)
check_all(api, lpaths[7], multi, propertyerror=True, extra_properties=['disabled'])
check_all(api, lpaths[8], multi, permissive=True, extra_properties=['hidden'])
check_all(api, lpaths[3], multi, **get_kwargs(lpaths[0]))
check_all(api, lpaths[4], multi, **get_kwargs(lpaths[1]))
check_all(api, lpaths[5], multi, **get_kwargs(lpaths[2]))
check_all(api, lpaths[6], multi, **get_kwargs(lpaths[0]))
check_all(api, lpaths[7], multi, **get_kwargs(lpaths[1]))
check_all(api, lpaths[8], multi, **get_kwargs(lpaths[2]))
else:
check_all(api, lpaths[0], multi)
check_all(api, lpaths[1], multi, propertyerror=True, extra_properties=['disabled'])
check_all(api, lpaths[2], multi, permissive=True, extra_properties=['hidden'])
DICT_PATHS2 = [
OrderedDict([('subod.subsubod.first', {'subsubod': {'hidden': True}}),
('subod.subsubod.second', {}),
('subod.subsubod.third', {})]),
OrderedDict([('subod.subsubod.first', {'subsubod': {'dyn': True, 'hidden': True}}),
('subod.subsubod.second', {}),
('subod.subsubod.third', {}),
('subod.subsubodval1.firstval1', None),
('subod.subsubodval1.secondval1', None),
('subod.subsubodval1.thirdval1', None),
('subod.subsubodval2.firstval2', None),
('subod.subsubodval2.secondval2', None),
('subod.subsubodval2.thirdval2', None)])
]
@pytest.fixture(scope="function", params=DICT_PATHS2)
def paths2(request):
if DISPLAY:
print(u'\n{} {}: {}'.format(ICON, request.function.__name__, request.param))
return request.param
def test_tree_od_permissive(paths2):
"""permissive when optiondescription is hidden
"""
lpaths = list(paths2.keys())
for multi in (False, True):
api = make_api(paths2, multi)
if api is None:
continue
if len(lpaths) == 9:
check_all(api, lpaths[3], multi, permissive=True)
check_all(api, lpaths[4], multi, permissive=True)
check_all(api, lpaths[5], multi, permissive=True)
check_all(api, lpaths[6], multi, permissive=True)
check_all(api, lpaths[7], multi, permissive=True)
check_all(api, lpaths[8], multi, permissive=True)
else:
check_all(api, lpaths[0], multi, permissive=True)
check_all(api, lpaths[1], multi, permissive=True)
check_all(api, lpaths[2], multi, permissive=True)
check_all(api, lpaths[0], multi, **get_kwargs(lpaths[0]))
check_all(api, lpaths[1], multi, **get_kwargs(lpaths[1]))
check_all(api, lpaths[2], multi, **get_kwargs(lpaths[2]))
del(api)
for wr in weakrefs:
assert wr() is None

View File

@ -15,7 +15,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________
from inspect import ismethod, getdoc
from .error import APIError
from .error import APIError, PropertiesOptionError
from .i18n import _
from .setting import owners, undefined
try:
@ -377,7 +377,7 @@ class TiramisuAPI(object):
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
settings = self.config.cfgimpl_get_settings()
#FIXME ?
# #FIXME ?
self.config.read_write()
settings.setpermissive(('hidden',))
#/FIXME ?
@ -386,8 +386,12 @@ class TiramisuAPI(object):
validate = not self.force_unrestraint
settings = self.config.cfgimpl_get_settings()
setting_properties = settings.get_global_properties()
if validate:
s_properties = setting_properties
else:
s_properties = None
opt = self.config.unwrap_from_path(path,
setting_properties=setting_properties,
setting_properties=s_properties,
validate=validate,
validate_properties=validate,
force_permissive=self.force_permissive,

View File

@ -87,6 +87,28 @@ class SubConfig(object):
validate=validate,
force_permissive=force_permissive)
def reset_one_option_cache(self, values, settings, resetted_opts, opt, only):
if 'values' in only:
tresetted_opts = copy(resetted_opts)
opt.reset_cache(opt, values, 'values', tresetted_opts)
if 'settings' in only:
tresetted_opts = copy(resetted_opts)
opt.reset_cache(opt, settings, 'settings', tresetted_opts)
else:
if 'properties' in only:
tresetted_opts = copy(resetted_opts)
opt.reset_cache(opt, settings, 'properties', tresetted_opts)
if 'permissives' in only:
tresetted_opts = copy(resetted_opts)
opt.reset_cache(opt, settings, 'permissives', tresetted_opts)
resetted_opts |= tresetted_opts
for option in opt._get_dependencies(self):
if option in resetted_opts:
continue
self.reset_one_option_cache(values, settings, resetted_opts, option(), only)
del(option)
def cfgimpl_reset_cache(self,
only_expired=False,
only=('values', 'properties', 'permissives', 'settings'),
@ -98,27 +120,6 @@ class SubConfig(object):
:param only_expired: if True reset only expired cached values
:type only_expired: boolean
"""
def reset_one_option_cache(opt, resetted_opts):
if 'values' in only:
tresetted_opts = copy(resetted_opts)
opt.reset_cache(opt, values, 'values', tresetted_opts)
if 'settings' in only:
tresetted_opts = copy(resetted_opts)
opt.reset_cache(opt, settings, 'settings', tresetted_opts)
else:
if 'properties' in only:
tresetted_opts = copy(resetted_opts)
opt.reset_cache(opt, settings, 'properties', tresetted_opts)
if 'permissives' in only:
tresetted_opts = copy(resetted_opts)
opt.reset_cache(opt, settings, 'permissives', tresetted_opts)
resetted_opts |= tresetted_opts
for option in opt._get_dependencies(self):
if option in resetted_opts:
continue
reset_one_option_cache(option, resetted_opts)
def reset_expired_cache():
# reset cache for expired cache value ony
@ -153,7 +154,11 @@ class SubConfig(object):
if not None in (opt, path):
if opt not in resetted_opts:
reset_one_option_cache(opt, resetted_opts)
self.reset_one_option_cache(values,
settings,
resetted_opts,
opt,
only)
elif only_expired:
reset_expired_cache()
@ -164,15 +169,13 @@ class SubConfig(object):
path,
setting_properties,
validate_properties=True,
force_permissive=False,
returns_raise=False):
force_permissive=False):
""":returns: tuple (config, name)"""
path = path.split('.')
for step in path[:-1]:
self = self.getattr(step,
force_permissive=force_permissive,
validate_properties=validate_properties,
returns_raise=returns_raise,
setting_properties=setting_properties)
if isinstance(self, Exception):
return self, None
@ -182,13 +185,16 @@ class SubConfig(object):
def __iter__(self, force_permissive=False):
"""Pythonesque way of parsing group's ordered options.
iteration only on Options (not OptionDescriptions)"""
setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings(
)._getproperties(read_write=True)
for child in self.cfgimpl_get_description()._impl_getchildren(
context=self._cfgimpl_get_context()):
if not child.impl_is_optiondescription():
try:
name = child.impl_getname()
yield name, self.getattr(name,
force_permissive=force_permissive)
force_permissive=force_permissive,
setting_properties=setting_properties)
except GeneratorExit: # pragma: optional cover
if sys.version_info[0] < 3:
raise StopIteration
@ -224,15 +230,19 @@ class SubConfig(object):
if group_type is not None and not isinstance(group_type,
groups.GroupType): # pragma: optional cover
raise TypeError(_("unknown group_type: {0}").format(group_type))
context = self._cfgimpl_get_context()
setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
for child in self.cfgimpl_get_description()._impl_getchildren(
context=self._cfgimpl_get_context()):
context=context):
if child.impl_is_optiondescription():
try:
if group_type is None or (group_type is not None and
child.impl_get_group_type()
== group_type):
name = child.impl_getname()
yield name, self.getattr(name, force_permissive=force_permissive)
yield name, self.getattr(name,
force_permissive=force_permissive,
setting_properties=setting_properties)
except GeneratorExit: # pragma: optional cover
if sys.version_info[0] < 3:
raise StopIteration
@ -391,7 +401,7 @@ class SubConfig(object):
raise ret
def __getattr__(self, name):
setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().getcontextproperties()
setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().get_global_properties()
return self.getattr(name, setting_properties)
def _get_subpath(self, name):
@ -408,7 +418,6 @@ class SubConfig(object):
validate=True,
validate_properties=True,
index=None,
returns_raise=False,
returns_option=False):
"""
attribute notation mechanism for accessing the value of an option
@ -423,7 +432,6 @@ class SubConfig(object):
homeconfig, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive,
validate_properties=validate_properties,
returns_raise=returns_raise,
setting_properties=setting_properties)
if isinstance(homeconfig, Exception):
cfg = homeconfig
@ -433,8 +441,7 @@ class SubConfig(object):
validate=validate,
validate_properties=validate_properties,
setting_properties=setting_properties,
index=index,
returns_raise=returns_raise)
index=index)
else:
option = self.cfgimpl_get_description().__getattr__(name,
context=context)
@ -454,8 +461,7 @@ class SubConfig(object):
validate_properties=validate_properties,
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index,
returns_raise=True)
index=index)
elif option.impl_is_optiondescription():
if setting_properties:
props = self.cfgimpl_get_settings().validate_properties(option,
@ -464,11 +470,6 @@ class SubConfig(object):
path=subpath,
force_permissive=force_permissive,
setting_properties=setting_properties)
if props:
if returns_raise:
return props
else:
raise props
if returns_option is True:
return option
return SubConfig(option,
@ -482,11 +483,6 @@ class SubConfig(object):
ret = self.cfgimpl_get_description().impl_validate(context,
force_permissive,
setting_properties)
if ret:
if returns_raise:
return ret
else:
raise ret
cfg = self.cfgimpl_get_values().get_cached_value(option,
path=subpath,
validate=validate,
@ -494,8 +490,6 @@ class SubConfig(object):
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index)
if not returns_raise and isinstance(cfg, Exception):
raise cfg
if returns_option is True:
return option
else:
@ -549,14 +543,12 @@ class SubConfig(object):
def _filter_by_value():
if byvalue is undefined:
return True
value = self.getattr(path, force_permissive=force_permissive,
setting_properties=setting_properties,
returns_raise=True)
if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError):
return False
raise value # pragma: no cover
elif isinstance(value, list):
try:
value = self.getattr(path, force_permissive=force_permissive,
setting_properties=setting_properties)
except PropertiesOptionError:
return False
if isinstance(value, list):
return byvalue in value
else:
return value == byvalue
@ -581,15 +573,12 @@ class SubConfig(object):
continue
#remove option with propertyerror, ...
if byvalue is undefined and check_properties:
value = self.getattr(path,
force_permissive=force_permissive,
setting_properties=setting_properties,
returns_raise=True)
if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError):
continue
else:
raise value # pragma: no cover
try:
value = self.getattr(path,
force_permissive=force_permissive,
setting_properties=setting_properties)
except PropertiesOptionError:
continue
if type_ == 'value':
retval = value
elif type_ == 'path':
@ -707,20 +696,19 @@ class SubConfig(object):
def _make_sub_dict(self, opt, path, pathsvalues, _currpath, flatten,
setting_properties, force_permissive=False, fullpath=False):
value = self.getattr(path,
force_permissive=force_permissive,
setting_properties=setting_properties,
returns_raise=True)
if isinstance(value, Exception):
if not isinstance(value, PropertiesOptionError): # pragma: no cover
raise value
try:
value = self.getattr(path,
force_permissive=force_permissive,
setting_properties=setting_properties)
except PropertiesOptionError as err:
pass
else:
if opt.impl_is_optiondescription():
pathsvalues += value.make_dict(flatten,
_currpath + path.split('.'),
force_permissive=force_permissive,
setting_properties=setting_properties,
fullpath=fullpath)
pathsvalues += value.make_dict(flatten,
_currpath + path.split('.'),
force_permissive=force_permissive,
setting_properties=setting_properties,
fullpath=fullpath)
else:
if flatten:
name = opt.impl_getname()
@ -792,34 +780,32 @@ class _CommonConfig(SubConfig):
force_permissive=force_permissive,
validate_properties=validate_properties,
setting_properties=setting_properties)
if isinstance(self, Exception):
return self
option = self.cfgimpl_get_description().__getattr__(path,
context=self._cfgimpl_get_context())
if not validate_properties:
return self.cfgimpl_get_description().__getattr__(path,
context=self._cfgimpl_get_context())
return option
else:
option = self.cfgimpl_get_description().__getattr__(path,
context=self._cfgimpl_get_context())
if not validate_properties:
if index is None and option.impl_is_master_slaves('slave'):
subpath = self._get_subpath(path)
props = self.cfgimpl_get_settings().validate_properties(option,
True,
False,
path=subpath,
force_permissive=force_permissive,
setting_properties=setting_properties)
if props:
raise props
return option
else:
if index is None and option.impl_is_master_slaves('slave'):
subpath = self._get_subpath(path)
props = self.cfgimpl_get_settings().validate_properties(option,
True,
False,
path=subpath,
force_permissive=force_permissive,
setting_properties=setting_properties)
if props:
raise props
return option
else:
return self.getattr(path,
validate=validate,
force_permissive=force_permissive,
index=index,
setting_properties=setting_properties,
validate_properties=validate_properties,
returns_option=True)
return self.getattr(path,
validate=validate,
force_permissive=force_permissive,
index=index,
setting_properties=setting_properties,
validate_properties=validate_properties,
returns_option=True)
def cfgimpl_get_path(self, dyn=True):
return None
@ -1037,7 +1023,6 @@ class GroupConfig(_CommonConfig):
force_permissive=False,
validate=True,
index=None,
returns_raise=False,
validate_properties=True,
returns_option=False):
for child in self._impl_children:
@ -1047,7 +1032,6 @@ class GroupConfig(_CommonConfig):
validate,
index=index,
setting_properties=setting_properties,
returns_raise=returns_raise,
validate_properties=validate_properties,
returns_option=False)
@ -1117,8 +1101,7 @@ class MetaConfig(GroupConfig):
continue
if force_dont_change_value:
child_value = child.getattr(path,
setting_properties=setting_properties,
returns_raise=True)
setting_properties=setting_properties)
if isinstance(child_value, Exception):
ret.append(child_value)
elif value != child_value:

View File

@ -21,6 +21,7 @@
import re
from types import FunctionType
import sys
import weakref
from ..i18n import _
from ..setting import undefined
@ -164,7 +165,7 @@ class Base(object):
_setattr(self, '_calc_properties', calc_properties)
if requires is not undefined:
_setattr(self, '_requires', requires)
if properties is not undefined:
if properties:
_setattr(self, '_properties', properties)
def _build_validator_params(self, validator, validator_params):
@ -213,14 +214,15 @@ class Base(object):
def _get_dependencies(self, context):
if context:
od = context.cfgimpl_get_description()
ret = set(getattr(self, '_dependencies', STATIC_TUPLE))
if context and hasattr(od, '_dependencies'):
return set(od._dependencies) | set(getattr(self, '_dependencies', STATIC_TUPLE))
return set(od._dependencies) | ret
else:
return getattr(self, '_dependencies', STATIC_TUPLE)
return ret
def _add_dependency(self, option):
options = set(self._get_dependencies(None))
options.add(option)
options = self._get_dependencies(None)
options.add(weakref.ref(option))
self._dependencies = tuple(options)
def impl_set_callback(self, callback, callback_params=None, _init=False):
@ -260,7 +262,7 @@ class Base(object):
return not isinstance(getattr(self, '_informations', dict()), dict)
def impl_getproperties(self):
return self._properties
return getattr(self, '_properties', STATIC_TUPLE)
def _set_readonly(self):
if not self.impl_is_readonly():
@ -277,7 +279,7 @@ class Base(object):
_setattr(self, '_extra', tuple([tuple(extra.keys()), tuple(extra.values())]))
def _impl_setsubdyn(self, subdyn):
self._subdyn = subdyn
self._subdyn = weakref.ref(subdyn)
def impl_getrequires(self):
return getattr(self, '_requires', STATIC_TUPLE)
@ -599,7 +601,7 @@ class SymLinkOption(OnlyOption):
return True
def impl_getproperties(self):
return self._impl_getopt()._properties
return self._impl_getopt().impl_getproperties()
def impl_get_callback(self):
return self._impl_getopt().impl_get_callback()

View File

@ -194,21 +194,20 @@ class Option(OnlyOption):
_index = None
else:
_index = index
opt_value = context.getattr(path, validate=False,
index=_index,
force_permissive=True,
returns_raise=True)
if isinstance(opt_value, Exception):
if isinstance(opt_value, PropertiesOptionError):
if debug: # pragma: no cover
log.debug('propertyerror in _launch_consistency: {0}'.format(opt_value))
if transitive:
opt_value.set_orig_opt(option)
return opt_value
else:
opt_value = None
else: # pragma: no cover
return opt_value
try:
opt_value = context.getattr(path, validate=False,
index=_index,
force_permissive=True)
except PropertiesOptionError as err:
if debug: # pragma: no cover
log.debug('propertyerror in _launch_consistency: {0}'.format(err))
if transitive:
err.set_orig_opt(option)
raise err
else:
opt_value = None
else: # pragma: no cover
return opt_value
elif index is None:
opt_value = opt.impl_getdefault()
else:
@ -472,7 +471,10 @@ class Option(OnlyOption):
return False
def impl_get_master_slaves(self):
return getattr(self, '_master_slaves', None)
masterslave = getattr(self, '_master_slaves', None)
if masterslave is None:
return masterslave
return masterslave()
def impl_getdoc(self):
"accesses the Option's doc"
@ -480,7 +482,7 @@ class Option(OnlyOption):
def _valid_consistencies(self, other_opts, init=True, func=None):
if self._is_subdyn():
dynod = self._subdyn
dynod = self._subdyn()
else:
dynod = None
if self.impl_is_submulti():
@ -495,10 +497,11 @@ class Option(OnlyOption):
if dynod is None:
raise ConfigError(_('almost one option in consistency is '
'in a dynoptiondescription but not all'))
if dynod != opt._subdyn:
subod = opt._subdyn()
if dynod != subod:
raise ConfigError(_('option in consistency must be in same'
' dynoptiondescription'))
dynod = opt._subdyn
dynod = subod
elif dynod is not None:
raise ConfigError(_('almost one option in consistency is in a '
'dynoptiondescription but not all'))

View File

@ -20,6 +20,7 @@
# ____________________________________________________________
from copy import copy
import re
import weakref
from ..i18n import _
@ -72,8 +73,6 @@ class CacheOptionDescription(BaseOption):
cache_option, force_store_values,
_dependencies)
else:
if option.impl_is_master_slaves('master'):
option._add_dependency(option.impl_get_master_slaves())
option._set_readonly()
is_multi = option.impl_is_multi()
if not option._is_symlinkoption() and 'force_store_value' in option.impl_getproperties():
@ -207,10 +206,17 @@ class CacheOptionDescription(BaseOption):
class OptionDescriptionWalk(CacheOptionDescription):
__slots__ = ('_children',)
def impl_get_options_paths(self, bytype, byname, _subpath, only_first, context):
def impl_get_options_paths(self,
bytype,
byname,
_subpath,
only_first,
context):
find_results = []
def _rebuild_dynpath(path, suffix, dynopt):
def _rebuild_dynpath(path,
suffix,
dynopt):
found = False
spath = path.split('.')
for length in xrange(1, len(spath)):
@ -226,19 +232,22 @@ class OptionDescriptionWalk(CacheOptionDescription):
subpath = subpath + '.' + spath[slength] + suffix
return subpath
def _filter_by_name(path, option):
def _filter_by_name(path,
option):
name = option.impl_getname()
if option._is_subdyn():
if byname.startswith(name):
found = False
for suffix in option._subdyn._impl_get_suffixes(
subdyn = option._subdyn()
for suffix in subdyn._impl_get_suffixes(
context):
if byname == name + suffix:
found = True
path = _rebuild_dynpath(path, suffix,
option._subdyn)
option = option._impl_to_dyn(
name + suffix, path)
path = _rebuild_dynpath(path,
suffix,
subdyn)
option = option._impl_to_dyn(name + suffix,
path)
break
if not found:
return False
@ -248,8 +257,10 @@ class OptionDescriptionWalk(CacheOptionDescription):
find_results.append((path, option))
return True
def _filter_by_type(path, option):
if isinstance(option, bytype):
def _filter_by_type(path,
option):
if isinstance(option,
bytype):
#if byname is not None, check option byname in _filter_by_name
#not here
if byname is None:
@ -257,7 +268,8 @@ class OptionDescriptionWalk(CacheOptionDescription):
name = option.impl_getname()
for suffix in option._subdyn._impl_get_suffixes(
context):
spath = _rebuild_dynpath(path, suffix,
spath = _rebuild_dynpath(path,
suffix,
option._subdyn)
find_results.append((spath, option._impl_to_dyn(
name + suffix, spath)))
@ -485,9 +497,11 @@ class OptionDescription(OptionDescriptionWalk):
def __getstate__(self):
raise NotImplementedError()
def _impl_get_suffixes(self, context):
def _impl_get_suffixes(self,
context):
callback, callback_params = self.impl_get_callback()
values = carry_out_calculation(self, context=context,
values = carry_out_calculation(self,
context=context,
callback=callback,
callback_params=callback_params)
if len(values) > len(set(values)):
@ -497,15 +511,28 @@ class OptionDescription(OptionDescriptionWalk):
raise ValueError(_("invalid suffix: {0} for option").format(val))
return values
def impl_validate_value(self, option, value, context):
def impl_validate_value(self,
option,
value,
context):
pass
class DynOptionDescription(OptionDescription):
def __init__(self, name, doc, children, requires=None, properties=None,
callback=None, callback_params=None):
super(DynOptionDescription, self).__init__(name, doc, children,
requires, properties)
def __init__(self,
name,
doc,
children,
requires=None,
properties=None,
callback=None,
callback_params=None):
super(DynOptionDescription, self).__init__(name,
doc,
children,
requires,
properties)
for child in children:
if isinstance(child, OptionDescription):
if child.impl_get_group_type() != groups.master:
@ -517,9 +544,12 @@ class DynOptionDescription(OptionDescription):
raise ConfigError(_('cannot set symlinkoption in a '
'dynoptiondescription'))
child._impl_setsubdyn(self)
self.impl_set_callback(callback, callback_params)
self.impl_set_callback(callback,
callback_params)
def _validate_callback(self, callback, callback_params):
def _validate_callback(self,
callback,
callback_params):
if callback is None:
raise ConfigError(_('callback is mandatory for dynoptiondescription'))
@ -532,15 +562,22 @@ class SynDynOptionDescription(object):
self._name = name
self._suffix = suffix
def __getattr__(self, name, context=undefined):
def __getattr__(self,
name,
context=undefined):
if name in dir(self._opt):
return getattr(self._opt, name)
return self._opt._getattr(name, suffix=self._suffix, context=context)
return getattr(self._opt,
name)
return self._opt._getattr(name,
suffix=self._suffix,
context=context)
def impl_getname(self):
return self._name
def _impl_getchildren(self, dyn=True, context=undefined):
def _impl_getchildren(self,
dyn=True,
context=undefined):
children = []
for child in self._opt._impl_getchildren():
yield(self._opt._impl_get_dynchild(child, self._suffix))
@ -608,7 +645,7 @@ class MasterSlaves(OptionDescription):
"not refered a slave's ones"))
#everything is ok, store references
for child in children:
child._master_slaves = self
child._master_slaves = weakref.ref(self)
master._add_dependency(self)
def is_master(self, opt):
@ -643,7 +680,7 @@ class MasterSlaves(OptionDescription):
c_opt = opt._opt
else:
c_opt = opt
return c_opt in self._children[1]
return child in self._children[1]
def reset(self,
opt,
@ -714,10 +751,16 @@ class MasterSlaves(OptionDescription):
setting_properties,
check_frozen)
else:
return self._getslave(values, opt, path, validate,
force_permissive, trusted_cached_properties,
validate_properties, setting_properties,
self_properties, index,
return self._getslave(values,
opt,
path,
validate,
force_permissive,
trusted_cached_properties,
validate_properties,
setting_properties,
self_properties,
index,
check_frozen)
def _getmaster(self,
@ -768,17 +811,19 @@ class MasterSlaves(OptionDescription):
master = self.getmaster(opt)
context = values._getcontext()
masterp = master.impl_getpath(context)
mastervalue = values.get_cached_value(master, path=masterp, validate=validate,
force_permissive=force_permissive,
validate_properties=validate_properties,
self_properties=self_properties,
from_masterslave=True,
setting_properties=setting_properties,
check_frozen=check_frozen)
if isinstance(mastervalue, Exception):
if isinstance(mastervalue, PropertiesOptionError):
mastervalue.set_orig_opt(opt)
return mastervalue
try:
mastervalue = values.get_cached_value(master,
path=masterp,
validate=validate,
force_permissive=force_permissive,
validate_properties=validate_properties,
self_properties=self_properties,
from_masterslave=True,
setting_properties=setting_properties,
check_frozen=check_frozen)
except PropertiesOptionError as mastervalue:
mastervalue.set_orig_opt(opt)
raise mastervalue
masterlen = len(mastervalue)
#self._master_is_meta = values._is_meta(master, masterp, force_permissive=force_permissive)
multi = list() # values._get_multi(opt, path)
@ -797,27 +842,27 @@ class MasterSlaves(OptionDescription):
else:
indexes = [index]
for idx in indexes:
value = values.get_cached_value(opt, path, validate,
force_permissive,
trusted_cached_properties,
validate_properties,
index=idx,
# not self_properties,
# depends to index
#self_properties=self_properties,
setting_properties=setting_properties,
from_masterslave=True,
check_frozen=check_frozen)
if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError):
err = value
if index is None:
multi.append(value)
else:
multi = value
try:
value = values.get_cached_value(opt,
path,
validate,
force_permissive,
trusted_cached_properties,
validate_properties,
index=idx,
# not self_properties,
# depends to index
#self_properties=self_properties,
setting_properties=setting_properties,
from_masterslave=True,
check_frozen=check_frozen)
except PropertiesOptionError as perr:
err = perr
if index is None:
multi.append(err)
else:
return value
elif index is None:
multi = err
if index is None:
multi.append(value)
else:
multi = value
@ -861,14 +906,16 @@ class MasterSlaves(OptionDescription):
master = self.getmaster(None)
if masterp is None:
masterp = master.impl_getpath(values._getcontext())
value = self.getitem(values,
master,
masterp,
validate,
force_permissive,
None,
True,
setting_properties=setting_properties)
value = self._getmaster(values,
master,
masterp,
validate,
force_permissive,
validate,
undefined,
None,
setting_properties,
False)
if isinstance(value, Exception):
return value
return len(value)

View File

@ -575,24 +575,29 @@ class Settings(object):
else:
opt_type = 'option'
if 'frozen' in properties:
return PropertiesOptionError(_('cannot change the value for '
'option "{0}" this option is'
' frozen').format(
opt_or_descr.impl_getname()),
props, self, datas, opt_type)
raise PropertiesOptionError(_('cannot change the value for '
'option "{0}" this option is'
' frozen').format(
opt_or_descr.impl_getname()),
props,
self,
datas,
opt_type)
else:
if len(props) == 1:
prop_msg = _('property')
else:
prop_msg = _('properties')
return PropertiesOptionError(_('cannot access to {0} "{1}" '
'because has {2} {3}'
'').format(opt_type,
opt_or_descr.impl_get_display_name(),
prop_msg,
display_list(props)),
props,
self, datas, opt_type)
raise PropertiesOptionError(_('cannot access to {0} "{1}" '
'because has {2} {3}'
'').format(opt_type,
opt_or_descr.impl_get_display_name(),
prop_msg,
display_list(props)),
props,
self,
datas,
opt_type)
def setpermissive(self, permissive, opt=None, path=None):
"""
@ -728,37 +733,36 @@ class Settings(object):
idx = index
else:
idx = None
value = context.getattr(reqpath, force_permissive=True,
_setting_properties=setting_properties,
index=idx, returns_raise=True)
if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError):
if not transitive:
if all_properties is None:
all_properties = []
for requires in opt.impl_getrequires():
for require in requires:
all_properties.append(require[1])
if not set(value.proptype) - set(all_properties):
continue
properties = value.proptype
if same_action and action not in properties: # pragma: optional cover
if len(properties) == 1:
prop_msg = _('property')
else:
prop_msg = _('properties')
raise RequirementError(_('cannot access to option "{0}" because '
'required option "{1}" has {2} {3}'
'').format(opt.impl_get_display_name(),
option.impl_get_display_name(),
prop_msg,
display_list(properties)))
orig_value = value
# transitive action, force expected
value = expected[0]
inverse = False
else: # pragma: no cover
raise value
try:
value = context.getattr(reqpath,
force_permissive=True,
_setting_properties=setting_properties,
index=idx)
except PropertiesOptionError as err:
if not transitive:
if all_properties is None:
all_properties = []
for requires in opt.impl_getrequires():
for require in requires:
all_properties.append(require[1])
if not set(err.proptype) - set(all_properties):
continue
properties = err.proptype
if same_action and action not in properties: # pragma: optional cover
if len(properties) == 1:
prop_msg = _('property')
else:
prop_msg = _('properties')
raise RequirementError(_('cannot access to option "{0}" because '
'required option "{1}" has {2} {3}'
'').format(opt.impl_get_display_name(),
option.impl_get_display_name(),
prop_msg,
display_list(properties)))
orig_value = err
# transitive action, force expected
value = expected[0]
inverse = False
else:
orig_value = value
if (not inverse and value in expected or

View File

@ -93,15 +93,15 @@ class Values(object):
meta = self._getcontext().cfgimpl_get_meta()
if meta is not None:
# retrieved value from meta config
value = meta.cfgimpl_get_values().get_cached_value(opt,
path,
index=index,
_orig_context=_orig_context)
if isinstance(value, Exception):
try:
value = meta.cfgimpl_get_values().get_cached_value(opt,
path,
index=index,
_orig_context=_orig_context)
except PropertiesOptionError:
# if properties error, return an other default value
if not isinstance(value, PropertiesOptionError): # pragma: no cover
# unexpected error, should not happened
raise value
# unexpected error, should not happened
pass
else:
return value
@ -476,28 +476,26 @@ class Values(object):
context = self._getcontext()
setting = context.cfgimpl_get_settings()
config_error = None
value = self._getvalue(opt,
path,
self_properties,
index,
validate,
_orig_context)
if isinstance(value, Exception):
try:
value = self._getvalue(opt,
path,
self_properties,
index,
validate,
_orig_context)
except ConfigError as value:
value_error = True
if isinstance(value, ConfigError):
# For calculating properties, we need value (ie for mandatory
# value).
# If value is calculating with a PropertiesOptionError's option
# _getvalue raise a ConfigError.
# We can not raise ConfigError if this option should raise
# PropertiesOptionError too. So we get config_error and raise
# ConfigError if properties did not raise.
config_error = value
# value is not set, for 'undefined' (cannot set None because of
# mandatory property)
value = undefined
else: # pragma: no cover
raise value
# For calculating properties, we need value (ie for mandatory
# value).
# If value is calculating with a PropertiesOptionError's option
# _getvalue raise a ConfigError.
# We can not raise ConfigError if this option should raise
# PropertiesOptionError too. So we get config_error and raise
# ConfigError if properties did not raise.
config_error = value
# value is not set, for 'undefined' (cannot set None because of
# mandatory property)
value = undefined
else:
value_error = False
if validate:
@ -807,6 +805,7 @@ class Values(object):
setting_properties = context.cfgimpl_get_settings()._getproperties()
setting_properties.update(['mandatory', 'empty'])
def _is_properties_option(err, path):
#FIXME hum ...
if not isinstance(err, Exception):
pass
elif isinstance(err, PropertiesOptionError):
@ -871,6 +870,7 @@ class Values(object):
context.cfgimpl_reset_cache()
for path in context.cfgimpl_get_description().impl_getpaths(
include_groups=True):
err = context.getattr(path, returns_raise=True)
if isinstance(err, Exception) and not isinstance(err, PropertiesOptionError): # pragma: no cover
raise err
try:
err = context.getattr(path)
except PropertiesOptionError as err:
pass