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(): def test_values_with_master_and_slaves_submulti():
ip_admin_eth0 = StrOption('ip_admin_eth0', "ip réseau autorisé", multi=True) ip_admin_eth0 = StrOption('ip_admin_eth0', "ip reseau autorise", multi=True)
netmask_admin_eth0 = StrOption('netmask_admin_eth0', "masque du sous-réseau", multi=submulti) 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]) interface1 = MasterSlaves('f_ip_admin_eth0', '', [ip_admin_eth0, netmask_admin_eth0])
conf = OptionDescription('conf', '', [interface1]) conf = OptionDescription('conf', '', [interface1])
cfg = Config(conf) cfg = Config(conf)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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