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):
if not isslave:
assert api.option(path).owner.get() == 'default' 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):
if not isslave:
assert api.option(path).owner.isdefault() 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,18 +87,7 @@ class SubConfig(object):
validate=validate, validate=validate,
force_permissive=force_permissive) force_permissive=force_permissive)
def cfgimpl_reset_cache(self, def reset_one_option_cache(self, values, settings, resetted_opts, opt, only):
only_expired=False,
only=('values', 'properties', 'permissives', 'settings'),
opt=None,
path=None,
resetted_opts=None):
"""reset all settings in cache
: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: if 'values' in only:
tresetted_opts = copy(resetted_opts) tresetted_opts = copy(resetted_opts)
opt.reset_cache(opt, values, 'values', tresetted_opts) opt.reset_cache(opt, values, 'values', tresetted_opts)
@ -117,8 +106,20 @@ class SubConfig(object):
for option in opt._get_dependencies(self): for option in opt._get_dependencies(self):
if option in resetted_opts: if option in resetted_opts:
continue continue
reset_one_option_cache(option, resetted_opts) 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'),
opt=None,
path=None,
resetted_opts=None):
"""reset all settings in cache
:param only_expired: if True reset only expired cached values
:type only_expired: boolean
"""
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
try:
value = self.getattr(path, force_permissive=force_permissive, value = self.getattr(path, force_permissive=force_permissive,
setting_properties=setting_properties, setting_properties=setting_properties)
returns_raise=True) except PropertiesOptionError:
if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError):
return False return False
raise value # pragma: no cover if isinstance(value, list):
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:
try:
value = self.getattr(path, value = self.getattr(path,
force_permissive=force_permissive, force_permissive=force_permissive,
setting_properties=setting_properties, setting_properties=setting_properties)
returns_raise=True) except PropertiesOptionError:
if isinstance(value, Exception):
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,13 +696,12 @@ 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):
try:
value = self.getattr(path, value = self.getattr(path,
force_permissive=force_permissive, force_permissive=force_permissive,
setting_properties=setting_properties, setting_properties=setting_properties)
returns_raise=True) except PropertiesOptionError as err:
if isinstance(value, Exception): pass
if not isinstance(value, PropertiesOptionError): # pragma: no cover
raise value
else: else:
if opt.impl_is_optiondescription(): if opt.impl_is_optiondescription():
pathsvalues += value.make_dict(flatten, pathsvalues += value.make_dict(flatten,
@ -792,10 +780,8 @@ 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 not validate_properties: if isinstance(self, Exception):
return self.cfgimpl_get_description().__getattr__(path, return self
context=self._cfgimpl_get_context())
else:
option = self.cfgimpl_get_description().__getattr__(path, option = self.cfgimpl_get_description().__getattr__(path,
context=self._cfgimpl_get_context()) context=self._cfgimpl_get_context())
if not validate_properties: if not validate_properties:
@ -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,17 +194,16 @@ class Option(OnlyOption):
_index = None _index = None
else: else:
_index = index _index = index
try:
opt_value = context.getattr(path, validate=False, opt_value = context.getattr(path, validate=False,
index=_index, index=_index,
force_permissive=True, force_permissive=True)
returns_raise=True) except PropertiesOptionError as err:
if isinstance(opt_value, Exception):
if isinstance(opt_value, PropertiesOptionError):
if debug: # pragma: no cover if debug: # pragma: no cover
log.debug('propertyerror in _launch_consistency: {0}'.format(opt_value)) log.debug('propertyerror in _launch_consistency: {0}'.format(err))
if transitive: if transitive:
opt_value.set_orig_opt(option) err.set_orig_opt(option)
return opt_value raise err
else: else:
opt_value = None opt_value = None
else: # pragma: no cover else: # pragma: no cover
@ -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:
mastervalue = values.get_cached_value(master,
path=masterp,
validate=validate,
force_permissive=force_permissive, force_permissive=force_permissive,
validate_properties=validate_properties, validate_properties=validate_properties,
self_properties=self_properties, self_properties=self_properties,
from_masterslave=True, from_masterslave=True,
setting_properties=setting_properties, setting_properties=setting_properties,
check_frozen=check_frozen) check_frozen=check_frozen)
if isinstance(mastervalue, Exception): except PropertiesOptionError as mastervalue:
if isinstance(mastervalue, PropertiesOptionError):
mastervalue.set_orig_opt(opt) mastervalue.set_orig_opt(opt)
return mastervalue 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,7 +842,10 @@ 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:
value = values.get_cached_value(opt,
path,
validate,
force_permissive, force_permissive,
trusted_cached_properties, trusted_cached_properties,
validate_properties, validate_properties,
@ -808,16 +856,13 @@ class MasterSlaves(OptionDescription):
setting_properties=setting_properties, setting_properties=setting_properties,
from_masterslave=True, from_masterslave=True,
check_frozen=check_frozen) check_frozen=check_frozen)
if isinstance(value, Exception): except PropertiesOptionError as perr:
if isinstance(value, PropertiesOptionError): err = perr
err = value
if index is None: if index is None:
multi.append(value) multi.append(err)
else: else:
multi = value multi = err
else: if index is None:
return value
elif 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,
validate,
undefined,
None, None,
True, setting_properties,
setting_properties=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,20 +733,21 @@ class Settings(object):
idx = index idx = index
else: else:
idx = None idx = None
value = context.getattr(reqpath, force_permissive=True, try:
value = context.getattr(reqpath,
force_permissive=True,
_setting_properties=setting_properties, _setting_properties=setting_properties,
index=idx, returns_raise=True) index=idx)
if isinstance(value, Exception): except PropertiesOptionError as err:
if isinstance(value, PropertiesOptionError):
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 opt.impl_getrequires():
for require in requires: for require in requires:
all_properties.append(require[1]) all_properties.append(require[1])
if not set(value.proptype) - set(all_properties): if not set(err.proptype) - set(all_properties):
continue continue
properties = value.proptype properties = err.proptype
if same_action and action not in properties: # pragma: optional cover 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')
@ -753,12 +759,10 @@ class Settings(object):
option.impl_get_display_name(), option.impl_get_display_name(),
prop_msg, prop_msg,
display_list(properties))) display_list(properties)))
orig_value = value orig_value = err
# transitive action, force expected # transitive action, force expected
value = expected[0] value = expected[0]
inverse = False inverse = False
else: # pragma: no cover
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
try:
value = meta.cfgimpl_get_values().get_cached_value(opt, value = meta.cfgimpl_get_values().get_cached_value(opt,
path, path,
index=index, index=index,
_orig_context=_orig_context) _orig_context=_orig_context)
if isinstance(value, Exception): 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
raise value pass
else: else:
return value return value
@ -476,15 +476,15 @@ 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
try:
value = self._getvalue(opt, value = self._getvalue(opt,
path, path,
self_properties, self_properties,
index, index,
validate, validate,
_orig_context) _orig_context)
if isinstance(value, Exception): 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
@ -496,8 +496,6 @@ class Values(object):
# 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