This commit is contained in:
Emmanuel Garette 2017-11-23 16:56:14 +01:00
parent 119ca85041
commit 527ae40950
13 changed files with 1178 additions and 793 deletions

File diff suppressed because it is too large Load diff

View file

@ -395,32 +395,64 @@ class TiramisuOption(object):
class TiramisuContext(object):
def __init__(self, config):
def __init__(self,
config,
force_permissive,
force_unrestraint,
setting_properties=None):
if setting_properties is None:
setting_properties = config.cfgimpl_get_settings().get_context_properties()
self.config = config
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
self.setting_properties = setting_properties
class TiramisuContextOwner(TiramisuContext):
def get(self):
return self.config.cfgimpl_get_settings().getowner()
class TiramisuAPI(object):
icon = '\u2937'
tmpl_help = ' {} {}: {}'
class TiramisuContextOption(TiramisuContext):
def find_first(self,
name,
type='option'):
check_properties = self.force_unrestraint or self.force_unrestraint
return self.config.find_first(byname=name,
type_=type,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive,
check_properties=not self.force_unrestraint)
def find(self,
name,
type='option'):
return self.config.find(byname=name,
type_=type,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive,
check_properties=not self.force_unrestraint)
def get(self, path):
return self.config.unwrap_from_path(path,
validate=False,
validate_properties=False)
class TiramisuOptionDispatcher(TiramisuContextOption):
def __init__(self,
config,
force_permissive=False,
force_unrestraint=False):
self.config = config
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
force_permissive,
force_unrestraint):
self.setting_properties = config.cfgimpl_get_settings().get_context_properties()
super(TiramisuOptionDispatcher, self).__init__(config,
force_permissive,
force_unrestraint,
self.setting_properties)
def option(self, path, index=None):
def __call__(self, path, index=None):
validate = not self.force_unrestraint
settings = self.config.cfgimpl_get_settings()
setting_properties = settings.get_context_properties()
if validate:
s_properties = setting_properties
s_properties = self.setting_properties
else:
s_properties = None
opt = self.config.unwrap_from_path(path,
@ -435,26 +467,74 @@ class TiramisuAPI(object):
path,
index,
self.config,
setting_properties,
self.setting_properties,
self.force_permissive,
self.force_unrestraint)
class TiramisuContextConfig(TiramisuContext):
def make_dict(self):
return self.config.make_dict(self.setting_properties)
class TiramisuConfigDispatcher(TiramisuContextConfig):
def __init__(self,
config,
force_permissive,
force_unrestraint):
self.setting_properties = config.cfgimpl_get_settings().get_context_properties()
super(TiramisuConfigDispatcher, self).__init__(config,
force_permissive,
force_unrestraint,
self.setting_properties)
def __call__(self, path):
if path is None:
subconfig = self.config
else:
subconfig = self.config.getconfig(path)
return TiramisuAPI(subconfig,
force_permissive=self.force_permissive,
force_unrestraint=self.force_unrestraint)
class TiramisuAPI(object):
icon = '\u2937'
tmpl_help = ' {} {}: {}'
def __init__(self,
config,
force_permissive=False,
force_unrestraint=False):
self._config = config
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
def __getattr__(self, subfunc):
if subfunc == 'forcepermissive':
return TiramisuAPI(self.config,
return TiramisuAPI(self._config,
force_permissive=True,
force_unrestraint=self.force_unrestraint)
elif subfunc == 'unrestraint':
return TiramisuAPI(self.config,
return TiramisuAPI(self._config,
force_permissive=self.force_permissive,
force_unrestraint=True)
elif subfunc == 'help':
return self._help()
elif subfunc == 'owner':
return TiramisuContextOwner(self.config)
return TiramisuContextOwner(self._config,
self.force_permissive,
self.force_unrestraint)
elif subfunc == 'config':
return TiramisuConfigDispatcher(self._config,
force_permissive=self.force_permissive,
force_unrestraint=self.force_unrestraint)
elif subfunc == 'option':
return TiramisuOptionDispatcher(self._config,
force_permissive=self.force_permissive,
force_unrestraint=self.force_unrestraint)
else:
raise APIError(_('please specify a valid sub function'))
raise APIError(_('please specify a valid sub function ({})').format(subfunc))
def _help(self):
txt = ['[forcepermissive]']
@ -465,11 +545,11 @@ class TiramisuAPI(object):
return '\n'.join(txt)
def read_only(self):
self.config.read_write()
self._config.read_write()
def read_write(self):
settings = self.config.cfgimpl_get_settings()
self.config.read_write()
settings = self._config.cfgimpl_get_settings()
self._config.read_write()
# #FIXME ?
settings.set_context_permissive(frozenset(['hidden']))
#/FIXME ?

View file

@ -182,8 +182,7 @@ class SubConfig(object):
def __iter__(self, force_permissive=False):
"""Pythonesque way of parsing group's ordered options.
iteration only on Options (not OptionDescriptions)"""
setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings(
)._getproperties(read_write=True)
setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().get_context_properties()
for child in self.cfgimpl_get_description()._impl_getchildren(
context=self._cfgimpl_get_context()):
if not child.impl_is_optiondescription():
@ -215,7 +214,9 @@ class SubConfig(object):
except PropertiesOptionError: # pragma: optional cover
pass # option with properties
def iter_groups(self, group_type=None, force_permissive=False):
def iter_groups(self,
group_type=None,
force_permissive=False):
"""iteration on groups objects only.
All groups are returned if `group_type` is `None`, otherwise the groups
can be filtered by categories (families, or whatever).
@ -228,7 +229,7 @@ class SubConfig(object):
groups.GroupType): # pragma: optional cover
raise TypeError(_("unknown group_type: {0}").format(group_type))
context = self._cfgimpl_get_context()
setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
setting_properties = context.cfgimpl_get_settings().get_context_properties()
for child in self.cfgimpl_get_description()._impl_getchildren(
context=context):
if child.impl_is_optiondescription():
@ -303,7 +304,7 @@ class SubConfig(object):
value,
force_permissive=False,
index=None,
setting_properties=undefined,
setting_properties=None,
_commit=True):
if name.startswith('_impl_'):
@ -311,7 +312,7 @@ class SubConfig(object):
name,
value)
context = self._cfgimpl_get_context()
if setting_properties is undefined:
if setting_properties is None:
setting_properties = context.cfgimpl_get_settings().get_context_properties()
if '.' in name: # pragma: optional cover
self, name = self.cfgimpl_get_home_by_path(name,
@ -321,7 +322,7 @@ class SubConfig(object):
context=context)
if isinstance(child, (OptionDescription, SynDynOptionDescription)):
raise TypeError(_("can't assign to an OptionDescription")) # pragma: optional cover
elif child._is_symlinkoption() and \
elif child.impl_is_symlinkoption() and \
not isinstance(child, DynSymLinkOption): # pragma: no dynoptiondescription cover
raise TypeError(_("can't assign to a SymlinkOption"))
else:
@ -344,11 +345,11 @@ class SubConfig(object):
name,
index=None,
force_permissive=False,
setting_properties=undefined,
setting_properties=None,
validate=True,
not_raises=False):
context = self._cfgimpl_get_context()
if setting_properties is undefined:
if setting_properties is None:
setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
if '.' in name: # pragma: optional cover
self, name = self.cfgimpl_get_home_by_path(name,
@ -358,7 +359,7 @@ class SubConfig(object):
context=context)
if isinstance(child, (OptionDescription, SynDynOptionDescription)):
raise TypeError(_("can't delete an OptionDescription")) # pragma: optional cover
elif child._is_symlinkoption() and \
elif child.impl_is_symlinkoption() and \
not isinstance(child, DynSymLinkOption): # pragma: no dynoptiondescription cover
raise TypeError(_("can't delete a SymlinkOption"))
else:
@ -438,16 +439,14 @@ class SubConfig(object):
option = self.cfgimpl_get_description().__getattr__(name,
context=context)
subpath = self._get_subpath(name)
if isinstance(option, DynSymLinkOption):
cfg = self.cfgimpl_get_values().get_cached_value(option,
path=subpath,
validate=validate,
validate_properties=validate_properties,
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index)
elif option._is_symlinkoption(): # pragma: no dynoptiondescription cover
path = context.cfgimpl_get_description().impl_get_path_by_opt(option._impl_getopt())
if setting_properties:
self.cfgimpl_get_settings().validate_properties(option,
subpath,
setting_properties,
index=index,
force_permissive=force_permissive)
if option.impl_is_symlinkoption() and not isinstance(option, DynSymLinkOption):
path = context.cfgimpl_get_description().impl_get_path_by_opt(option.impl_getopt())
cfg = context.getattr(path,
validate=validate,
validate_properties=validate_properties,
@ -455,13 +454,6 @@ class SubConfig(object):
setting_properties=setting_properties,
index=index)
elif option.impl_is_optiondescription():
if setting_properties:
self.cfgimpl_get_settings().validate_properties(option,
True,
False,
path=subpath,
force_permissive=force_permissive,
setting_properties=setting_properties)
if returns_option is True:
return option
return SubConfig(option,
@ -471,30 +463,37 @@ class SubConfig(object):
force_permissive,
subpath)
else:
if validate:
self.cfgimpl_get_description().impl_validate(context,
force_permissive,
setting_properties)
if option.impl_is_master_slaves('slave') and index is not None and \
index >= self._impl_length:
raise IndexError(_('index ({}) is higher than the master length ({}) for "{}"'
'').format(index,
self._impl_length,
subpath))
cfg = self.cfgimpl_get_values().get_cached_value(option,
path=subpath,
validate=validate,
validate_properties=validate_properties,
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index)
if validate:
self.cfgimpl_get_description().impl_validate(context,
force_permissive,
setting_properties)
if not returns_option:
cfg = self.cfgimpl_get_values().get_cached_value(option,
path=subpath,
validate=validate,
setting_properties=setting_properties,
force_permissive=force_permissive,
index=index)
if returns_option is True:
return option
else:
return cfg
def find(self, bytype=None, byname=None, byvalue=undefined, type_='option',
check_properties=True, force_permissive=False):
def find(self,
setting_properties,
bytype=None,
byname=None,
byvalue=undefined,
type_='option',
check_properties=True,
force_permissive=False):
"""
finds a list of options recursively in the config
@ -503,15 +502,24 @@ class SubConfig(object):
:param byvalue: filter by the option's value
:returns: list of matching Option objects
"""
return self._cfgimpl_get_context()._find(bytype, byname, byvalue,
return self._cfgimpl_get_context()._find(bytype,
byname,
byvalue,
setting_properties=setting_properties,
first=False,
type_=type_,
_subpath=self.cfgimpl_get_path(False),
check_properties=check_properties,
force_permissive=force_permissive)
def find_first(self, bytype=None, byname=None, byvalue=undefined,
type_='option', raise_if_not_found=True, check_properties=True,
def find_first(self,
setting_properties,
bytype=None,
byname=None,
byvalue=undefined,
type_='option',
raise_if_not_found=True,
check_properties=True,
force_permissive=False):
"""
finds an option recursively in the config
@ -521,28 +529,42 @@ class SubConfig(object):
:param byvalue: filter by the option's value
:returns: list of matching Option objects
"""
return self._cfgimpl_get_context()._find(
bytype, byname, byvalue, first=True, type_=type_,
_subpath=self.cfgimpl_get_path(False), raise_if_not_found=raise_if_not_found,
check_properties=check_properties,
force_permissive=force_permissive)
return self._cfgimpl_get_context()._find(bytype,
byname,
byvalue,
setting_properties=setting_properties,
first=True,
type_=type_,
_subpath=self.cfgimpl_get_path(False),
raise_if_not_found=raise_if_not_found,
check_properties=check_properties,
force_permissive=force_permissive)
def _find(self, bytype, byname, byvalue, first, type_='option',
_subpath=None, check_properties=True, raise_if_not_found=True,
force_permissive=False, only_path=undefined,
only_option=undefined, setting_properties=undefined):
def _find(self,
bytype,
byname,
byvalue,
first,
type_='option',
_subpath=None,
check_properties=True,
raise_if_not_found=True,
force_permissive=False,
only_path=undefined,
only_option=undefined,
setting_properties=None):
"""
convenience method for finding an option that lives only in the subtree
:param first: return only one option if True, a list otherwise
:return: find list or an exception if nothing has been found
"""
def _filter_by_value():
if byvalue is undefined:
return True
try:
value = self.getattr(path, force_permissive=force_permissive,
value = self.getattr(path,
force_permissive=force_permissive,
setting_properties=setting_properties)
except PropertiesOptionError:
return False
@ -563,22 +585,26 @@ class SubConfig(object):
if only_path is not undefined:
options = [(only_path, only_option)]
else:
options = self.cfgimpl_get_description().impl_get_options_paths(
bytype, byname, _subpath, only_first,
self._cfgimpl_get_context())
options = self.cfgimpl_get_description().impl_get_options_paths(bytype,
byname,
_subpath,
only_first,
self._cfgimpl_get_context())
for path, option in options:
if not _filter_by_value():
continue
#remove option with propertyerror, ...
if byvalue is undefined and check_properties:
if check_properties:
try:
value = self.getattr(path,
force_permissive=force_permissive,
setting_properties=setting_properties)
self.unwrap_from_path(path,
setting_properties=setting_properties,
force_permissive=force_permissive)
except PropertiesOptionError:
continue
if type_ == 'value':
retval = value
retval = self.getattr(path,
force_permissive=force_permissive,
setting_properties=setting_properties)
elif type_ == 'path':
retval = path
elif type_ == 'option':
@ -587,9 +613,12 @@ class SubConfig(object):
return retval
else:
find_results.append(retval)
return self._find_return_results(find_results, raise_if_not_found)
return self._find_return_results(find_results,
raise_if_not_found)
def _find_return_results(self, find_results, raise_if_not_found):
def _find_return_results(self,
find_results,
raise_if_not_found):
if find_results == []: # pragma: optional cover
if raise_if_not_found:
raise AttributeError(_("no option found in config"
@ -598,12 +627,12 @@ class SubConfig(object):
return find_results
def make_dict(self,
setting_properties,
flatten=False,
_currpath=None,
withoption=None,
withvalue=undefined,
force_permissive=False,
setting_properties=undefined,
fullpath=False):
"""exports the whole config into a `dict`, for example:
@ -647,8 +676,6 @@ class SubConfig(object):
if withoption is None and withvalue is not undefined: # pragma: optional cover
raise ValueError(_("make_dict can't filtering with value without "
"option"))
if setting_properties is undefined:
setting_properties = self.cfgimpl_get_settings()._getproperties(read_write=False)
if withoption is not None:
context = self._cfgimpl_get_context()
for path in context._find(bytype=None,
@ -675,7 +702,11 @@ class SubConfig(object):
'should start with {1}'
'').format(path, mypath))
path = path[len(tmypath):]
self._make_sub_dict(opt, path, pathsvalues, _currpath, flatten,
self._make_sub_dict(opt,
path,
pathsvalues,
_currpath,
flatten,
force_permissive=force_permissive,
setting_properties=setting_properties,
fullpath=fullpath)
@ -683,7 +714,11 @@ class SubConfig(object):
if withoption is None:
for opt in self.cfgimpl_get_description().impl_getchildren():
path = opt.impl_getname()
self._make_sub_dict(opt, path, pathsvalues, _currpath, flatten,
self._make_sub_dict(opt,
path,
pathsvalues,
_currpath,
flatten,
force_permissive=force_permissive,
setting_properties=setting_properties,
fullpath=fullpath)
@ -692,8 +727,15 @@ class SubConfig(object):
return options
return pathsvalues
def _make_sub_dict(self, opt, path, pathsvalues, _currpath, flatten,
setting_properties, force_permissive=False, fullpath=False):
def _make_sub_dict(self,
opt,
path,
pathsvalues,
_currpath,
flatten,
setting_properties,
force_permissive=False,
fullpath=False):
try:
value = self.getattr(path,
force_permissive=force_permissive,
@ -702,10 +744,10 @@ class SubConfig(object):
pass
else:
if opt.impl_is_optiondescription():
pathsvalues += value.make_dict(flatten,
_currpath + path.split('.'),
pathsvalues += value.make_dict(setting_properties,
flatten=flatten,
_currpath=_currpath + path.split('.'),
force_permissive=force_permissive,
setting_properties=setting_properties,
fullpath=fullpath)
else:
if flatten:
@ -721,11 +763,12 @@ class SubConfig(object):
name = '.'.join(_currpath + [opt.impl_getname()])
pathsvalues.append((name, value))
def cfgimpl_get_path(self, dyn=True):
def cfgimpl_get_path(self,
dyn=True):
descr = self.cfgimpl_get_description()
if not dyn and descr.impl_is_dynoptiondescription():
context_descr = self._cfgimpl_get_context().cfgimpl_get_description()
return context_descr.impl_get_path_by_opt(descr._impl_getopt())
return context_descr.impl_get_path_by_opt(descr.impl_getopt())
return self._impl_path
@ -733,12 +776,14 @@ class _CommonConfig(SubConfig):
"abstract base class for the Config, GroupConfig and the MetaConfig"
__slots__ = ('_impl_values', '_impl_settings', '_impl_meta', '_impl_test')
def _impl_build_all_caches(self, force_store_values):
def _impl_build_all_caches(self,
force_store_values):
descr = self.cfgimpl_get_description()
if not descr.impl_already_build_caches():
descr._build_cache_option()
descr._build_cache(self)
descr.impl_build_force_store_values(self, force_store_values)
descr.impl_build_force_store_values(self,
force_store_values)
def read_only(self):
"read only is a global config's setting, see `settings.py`"
@ -748,7 +793,10 @@ class _CommonConfig(SubConfig):
"read write is a global config's setting, see `settings.py`"
self.cfgimpl_get_settings().read_write()
def getowner(self, opt, index=None, force_permissive=False):
def getowner(self,
opt,
index=None,
force_permissive=False):
"""convenience method to retrieve an option's owner
from the config itself
"""
@ -757,12 +805,13 @@ class _CommonConfig(SubConfig):
not isinstance(opt, DynSymLinkOption): # pragma: optional cover
raise TypeError(_('opt in getowner must be an option not {0}'
'').format(type(opt)))
return self.cfgimpl_get_values().getowner(opt, index=index,
return self.cfgimpl_get_values().getowner(opt,
index=index,
force_permissive=force_permissive)
def unwrap_from_path(self,
path,
setting_properties=undefined,
setting_properties=None,
force_permissive=False,
index=None,
validate=True,
@ -788,11 +837,9 @@ class _CommonConfig(SubConfig):
if index is None and option.impl_is_master_slaves('slave'):
subpath = self._get_subpath(path)
self.cfgimpl_get_settings().validate_properties(option,
True,
False,
path=subpath,
force_permissive=force_permissive,
setting_properties=setting_properties)
subpath,
setting_properties,
force_permissive=force_permissive)
return option
else:
return self.getattr(path,
@ -833,14 +880,21 @@ class _CommonConfig(SubConfig):
raise NotImplementedError()
def _gen_fake_values(self):
fake_config = Config(self._impl_descr, persistent=False,
fake_config = Config(self._impl_descr,
persistent=False,
force_values=get_default_values_storages(),
force_settings=self.cfgimpl_get_settings())
fake_config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation(fake=True))
return fake_config
def duplicate(self, force_values=None, force_settings=None):
config = Config(self._impl_descr, _duplicate=True, force_values=force_values,
def duplicate(self,
session_id=None,
force_values=None,
force_settings=None):
config = Config(self._impl_descr,
_duplicate=True,
session_id=session_id,
force_values=force_values,
force_settings=force_settings)
config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation())
config.cfgimpl_get_settings()._p_.set_modified_properties(self.cfgimpl_get_settings(
@ -1057,31 +1111,19 @@ class GroupConfig(_CommonConfig):
def __str__(self):
ret = ''
for child in self._impl_children:
ret += '({0})\n'.format(child._impl_name)
ret += "({0})\n".format(child._impl_name)
if self._impl_descr is not None:
ret += super(GroupConfig, self).__str__()
return ret
__repr__ = __str__
def getattr(self,
name,
setting_properties,
force_permissive=False,
validate=True,
validate_properties=True,
index=None,
returns_option=False):
def getconfig(self,
name):
for child in self._impl_children:
if name == child.impl_getname():
return child
return super(GroupConfig, self).getattr(name,
setting_properties,
force_permissive,
validate,
validate_properties=validate_properties,
index=index,
returns_option=returns_option)
raise ConfigError(_('unknown config {}').format(name))
class MetaConfig(GroupConfig):
@ -1174,12 +1216,9 @@ class MetaConfig(GroupConfig):
if childret is not None: # pragma: no cover
ret.append(childret)
setret = self.setattr(path,
value,
_commit=_commit,
not_raises=True)
if setret is not None:
ret.append(setret)
self.setattr(path,
value,
_commit=_commit)
return ret
def reset(self, path):

View file

@ -55,7 +55,12 @@ def display_list(lst, separator='and'):
# Exceptions for an Option
class PropertiesOptionError(AttributeError):
"attempt to access to an option with a property that is not allowed"
def __init__(self, msg, proptype, settings=None, datas=None, option_type=None):
def __init__(self,
msg,
proptype,
settings=None,
datas=None,
option_type=None):
self.proptype = proptype
self._settings = settings
self._datas = datas
@ -72,30 +77,32 @@ class PropertiesOptionError(AttributeError):
req = {}
else:
req = self._settings.apply_requires(**self._datas)
if req != {} or self._orig_opt is not None:
if req != {}:
only_one = len(req) == 1
msg = []
for action, msg_ in req.items():
msg.append('{0} ({1})'.format(action, display_list(msg_)))
else:
only_one = len(self.proptype) == 1
msg = self.proptype
if only_one:
prop_msg = _('property')
else:
prop_msg = _('properties')
msg = display_list(msg)
if self._orig_opt:
return str(_('cannot access to {0} "{1}" because "{2}" has {3} {4}').format(self._type,
self._orig_opt.impl_get_display_name(),
self._datas['opt'].impl_get_display_name(),
prop_msg,
msg))
else:
return str(_('cannot access to {0} "{1}" because has {2} {3}').format(self._type, self._datas['opt'].impl_get_display_name(), prop_msg, msg))
#if req != {} or self._orig_opt is not None:
if req != {}:
only_one = len(req) == 1
msg = []
for action, msg_ in req.items():
msg.append('{0} ({1})'.format(action, display_list(msg_)))
else:
return super(PropertiesOptionError, self).__str__()
only_one = len(self.proptype) == 1
msg = list(self.proptype)
if only_one:
prop_msg = _('property')
else:
prop_msg = _('properties')
msg = display_list(msg)
if self._orig_opt:
return str(_('cannot access to {0} "{1}" because "{2}" has {3} {4}'
'').format(self._type,
self._orig_opt.impl_get_display_name(),
self._datas['opt'].impl_get_display_name(),
prop_msg,
msg))
return str(_('cannot access to {0} "{1}" because has {2} {3}'
'').format(self._type,
self._datas['opt'].impl_get_display_name(),
prop_msg,
msg))
#____________________________________________________________

View file

@ -58,9 +58,10 @@ def validate_callback(callback, callback_params, type_, callbackoption):
"""
def _validate_option(option):
#validate option
if hasattr(option, '_is_symlinkoption'):
if option._is_symlinkoption():
cur_opt = option._impl_getopt()
#FIXME etrange ...
if hasattr(option, 'impl_is_symlinkoption'):
if option.impl_is_symlinkoption():
cur_opt = option.impl_getopt()
else:
cur_opt = option
else:
@ -423,7 +424,7 @@ class BaseOption(Base):
obj._pp_.delcache(path)
resetted_opts.add(opt)
def _is_symlinkoption(self):
def impl_is_symlinkoption(self):
return False
@ -442,7 +443,8 @@ def validate_requires_arg(new_option, multi, requires, name):
"""
def get_option(require):
option = require['option']
if not hasattr(option, '_is_symlinkoption'):
#FIXME etrange ...
if not hasattr(option, 'impl_is_symlinkoption'):
raise ValueError(_('malformed requirements '
'must be an option in option {0}').format(name))
if not multi and option.impl_is_multi():
@ -574,9 +576,11 @@ def validate_requires_arg(new_option, multi, requires, name):
class SymLinkOption(OnlyOption):
def __init__(self, name, opt):
def __init__(self,
name,
opt):
if not isinstance(opt, OnlyOption) or \
opt._is_symlinkoption():
opt.impl_is_symlinkoption():
raise ValueError(_('malformed symlinkoption '
'must be an option '
'for symlink {0}').format(name))
@ -591,36 +595,36 @@ class SymLinkOption(OnlyOption):
"""
return self_is_dep is True
def _is_symlinkoption(self):
def impl_is_symlinkoption(self):
return True
def __getattr__(self, name, context=undefined):
return getattr(self._impl_getopt(), name)
return getattr(self.impl_getopt(), name)
def _impl_getopt(self):
def impl_getopt(self):
return self._opt
def impl_get_information(self, key, default=undefined):
return self._impl_getopt().impl_get_information(key, default)
return self.impl_getopt().impl_get_information(key, default)
def impl_is_readonly(self):
return True
def impl_getproperties(self):
return self._impl_getopt().impl_getproperties()
return self.impl_getopt().impl_getproperties()
def impl_get_callback(self):
return self._impl_getopt().impl_get_callback()
return self.impl_getopt().impl_get_callback()
def impl_has_callback(self):
"to know if a callback has been defined or not"
return self._impl_getopt().impl_has_callback()
return self.impl_getopt().impl_has_callback()
def impl_is_multi(self):
return self._impl_getopt().impl_is_multi()
return self.impl_getopt().impl_is_multi()
def _is_subdyn(self):
return getattr(self._impl_getopt(), '_subdyn', None) is not None
return getattr(self.impl_getopt(), '_subdyn', None) is not None
def _get_consistencies(self):
return ()
@ -632,28 +636,34 @@ class SymLinkOption(OnlyOption):
class DynSymLinkOption(object):
__slots__ = ('_dyn', '_opt', '_name')
def __init__(self, name, opt, dyn):
def __init__(self,
name,
opt,
dyn):
self._name = name
self._dyn = dyn
self._opt = opt
def __getattr__(self, name, context=undefined):
return getattr(self._impl_getopt(), name)
def __getattr__(self,
name,
context=undefined):
return getattr(self.impl_getopt(), name)
def impl_getname(self):
return self._name
def impl_get_display_name(self):
return self._impl_getopt().impl_get_display_name(dyn_name=self.impl_getname())
return self.impl_getopt().impl_get_display_name(dyn_name=self.impl_getname())
def _impl_getopt(self):
def impl_getopt(self):
return self._opt
def impl_getsuffix(self):
return self._dyn.split('.')[-1][len(self._impl_getopt().impl_getname()):]
return self._dyn.split('.')[-1][len(self.impl_getopt().impl_getname()):]
def impl_getpath(self, context):
path = self._impl_getopt().impl_getpath(context)
def impl_getpath(self,
context):
path = self.impl_getopt().impl_getpath(context)
base_path = '.'.join(path.split('.')[:-2])
if self.impl_is_master_slaves() and base_path is not '':
base_path = base_path + self.impl_getsuffix()
@ -672,14 +682,16 @@ class DynSymLinkOption(object):
display_warnings=True,
multi=None,
setting_properties=undefined):
return self._impl_getopt().impl_validate(value, context, validate,
force_index,
current_opt=self,
is_multi=is_multi,
display_error=display_error,
display_warnings=display_warnings,
multi=multi,
setting_properties=setting_properties)
return self.impl_getopt().impl_validate(value,
context,
validate,
force_index,
current_opt=self,
is_multi=is_multi,
display_error=display_error,
display_warnings=display_warnings,
multi=multi,
setting_properties=setting_properties)
def impl_is_dynsymlinkoption(self):
return True

View file

@ -605,7 +605,7 @@ class Option(OnlyOption):
return
#consistencies is something like [('_cons_not_equal', (opt1, opt2))]
if isinstance(option, DynSymLinkOption):
consistencies = descr._cache_consistencies.get(option._impl_getopt())
consistencies = descr._cache_consistencies.get(option.impl_getopt())
else:
consistencies = descr._cache_consistencies.get(option)
else:
@ -618,7 +618,7 @@ class Option(OnlyOption):
#all_cons_opts[0] is the option where func is set
if isinstance(option, DynSymLinkOption):
subpath = '.'.join(option._dyn.split('.')[:-1])
namelen = len(option._impl_getopt().impl_getname())
namelen = len(option.impl_getopt().impl_getname())
suffix = option.impl_getname()[namelen:]
opts = []
for opt in all_cons_opts:
@ -640,7 +640,11 @@ class Option(OnlyOption):
if err:
return err
def _cons_not_equal(self, current_opt, opts, vals, warnings_only):
def _cons_not_equal(self,
current_opt,
opts,
vals,
warnings_only):
equal = set()
is_current = False
for idx_inf, val_inf in enumerate(vals):
@ -669,11 +673,17 @@ class Option(OnlyOption):
equal_name.append(opt.impl_get_display_name())
return ValueError(msg.format(display_list(list(equal_name))))
def _second_level_validation(self, value, warnings_only):
def _second_level_validation(self,
value,
warnings_only):
pass
def _impl_to_dyn(self, name, path):
return DynSymLinkOption(name, self, dyn=path)
def _impl_to_dyn(self,
name,
path):
return DynSymLinkOption(name,
self,
dyn=path)
def impl_getdefault_multi(self):
"accessing the default value for a multi"
@ -683,7 +693,9 @@ class Option(OnlyOption):
default_value = None
return getattr(self, '_default_multi', default_value)
def _validate_callback(self, callback, callback_params):
def _validate_callback(self,
callback,
callback_params):
"""callback_params:
* None
* {'': ((option, permissive),), 'ip': ((None,), (option, permissive))
@ -712,7 +724,8 @@ class Option(OnlyOption):
default = list(default)
return default
def _get_extra(self, key):
def _get_extra(self,
key):
extra = self._extra
if isinstance(extra, tuple):
return extra[1][extra[0].index(key)]
@ -751,14 +764,13 @@ class Option(OnlyOption):
class RegexpOption(Option):
__slots__ = tuple()
def _validate(self, value, context=undefined, current_opt=undefined):
def _validate(self,
value,
context=undefined,
current_opt=undefined):
err = self._impl_valid_unicode(value)
if err:
return err
match = self._regexp.search(value)
if not match:
return ValueError()
#FIXME compatibility
_RegexpOption = RegexpOption

View file

@ -43,8 +43,12 @@ del(sys)
class CacheOptionDescription(BaseOption):
__slots__ = ('_cache_paths', '_cache_consistencies', '_cache_force_store_values')
def _build_cache(self, config, path='', _consistencies=None,
cache_option=None, force_store_values=None,
def _build_cache(self,
config,
path='',
_consistencies=None,
cache_option=None,
force_store_values=None,
_dependencies=None):
"""validate duplicate option and set option has readonly option
"""
@ -69,13 +73,16 @@ class CacheOptionDescription(BaseOption):
subpath = path + '.' + option.impl_getname()
if isinstance(option, OptionDescription):
option._set_readonly()
option._build_cache(config, subpath, _consistencies,
cache_option, force_store_values,
_dependencies)
option._build_cache(config,
subpath,
_consistencies,
cache_option,
force_store_values,
_dependencies)
else:
option._set_readonly()
is_multi = option.impl_is_multi()
if not option._is_symlinkoption() and 'force_store_value' in option.impl_getproperties():
if not option.impl_is_symlinkoption() and 'force_store_value' in option.impl_getproperties():
force_store_values.append((subpath, option))
for func, all_cons_opts, params in option._get_consistencies():
option._valid_consistencies(all_cons_opts[1:], init=False)
@ -150,7 +157,9 @@ class CacheOptionDescription(BaseOption):
def impl_already_build_caches(self):
return getattr(self, '_cache_paths', None) is not None
def impl_build_force_store_values(self, config, force_store_values):
def impl_build_force_store_values(self,
config,
force_store_values):
session = config._impl_values._p_.getsession()
value_set = False
for subpath, option in self._cache_force_store_values:
@ -174,8 +183,10 @@ class CacheOptionDescription(BaseOption):
if value_set:
config._impl_values._p_.commit()
def _build_cache_option(self, _currpath=None, cache_path=None,
cache_option=None):
def _build_cache_option(self,
_currpath=None,
cache_path=None,
cache_option=None):
if self.impl_is_readonly() or (_currpath is None and getattr(self, '_cache_paths', None) is not None):
# cache already set
@ -195,8 +206,9 @@ class CacheOptionDescription(BaseOption):
cache_path.append(path)
if option.impl_is_optiondescription():
_currpath.append(attr)
option._build_cache_option(_currpath, cache_path,
cache_option)
option._build_cache_option(_currpath,
cache_path,
cache_option)
_currpath.pop()
if save:
_setattr = object.__setattr__
@ -236,8 +248,8 @@ class OptionDescriptionWalk(CacheOptionDescription):
option):
name = option.impl_getname()
if option._is_subdyn():
found = False
if byname.startswith(name):
found = False
subdyn = option._subdyn()
for suffix in subdyn._impl_get_suffixes(
context):
@ -249,8 +261,8 @@ class OptionDescriptionWalk(CacheOptionDescription):
option = option._impl_to_dyn(name + suffix,
path)
break
if not found:
return False
if not found:
return False
else:
if not byname == name:
return False
@ -312,12 +324,18 @@ class OptionDescriptionWalk(CacheOptionDescription):
return find_results
return find_results
def _impl_st_getchildren(self, context, only_dyn=False):
def _impl_st_getchildren(self,
context,
only_dyn=False):
for child in self._children[1]:
if only_dyn is False or child.impl_is_dynoptiondescription():
yield(child)
def _getattr(self, name, suffix=undefined, context=undefined, dyn=True):
def _getattr(self,
name,
suffix=undefined,
context=undefined,
dyn=True):
error = False
if suffix is not undefined:
if undefined in [suffix, context]: # pragma: no cover
@ -337,7 +355,8 @@ class OptionDescriptionWalk(CacheOptionDescription):
else:
return child
else:
child = self._impl_search_dynchild(name, context=context)
child = self._impl_search_dynchild(name,
context=context)
if child != []:
return child
error = True
@ -346,27 +365,35 @@ class OptionDescriptionWalk(CacheOptionDescription):
'in OptionDescription {1}'
'').format(name, self.impl_getname()))
def impl_getpaths(self, include_groups=False, _currpath=None):
def impl_getpaths(self,
include_groups=False,
_currpath=None):
"""returns a list of all paths in self, recursively
_currpath should not be provided (helps with recursion)
"""
return _impl_getpaths(self, include_groups, _currpath)
return _impl_getpaths(self,
include_groups,
_currpath)
def impl_get_opt_by_path(self, path):
def impl_get_opt_by_path(self,
path):
if getattr(self, '_cache_paths', None) is None:
raise ConfigError(_('use impl_get_opt_by_path only with root OptionDescription'))
if path not in self._cache_paths[1]:
raise AttributeError(_('no option for path {0}').format(path))
return self._cache_paths[0][self._cache_paths[1].index(path)]
def impl_get_path_by_opt(self, opt):
def impl_get_path_by_opt(self,
opt):
if getattr(self, '_cache_paths', None) is None:
raise ConfigError(_('use impl_get_path_by_opt only with root OptionDescription'))
if opt not in self._cache_paths[0]:
raise AttributeError(_('no option {0} found').format(opt))
return self._cache_paths[1][self._cache_paths[0].index(opt)]
def _impl_getchildren(self, dyn=True, context=undefined):
def _impl_getchildren(self,
dyn=True,
context=undefined):
for child in self._impl_st_getchildren(context):
cname = child.impl_getname()
if dyn and child.impl_is_dynoptiondescription():
@ -380,32 +407,47 @@ class OptionDescriptionWalk(CacheOptionDescription):
def impl_getchildren(self):
return list(self._impl_getchildren())
def __getattr__(self, name, context=undefined):
if name.startswith('_'): # or name.startswith('impl_'):
return object.__getattribute__(self, name)
def __getattr__(self,
name,
context=undefined):
if name.startswith('_'):
return object.__getattribute__(self,
name)
if '.' in name:
path = name.split('.')[0]
subpath = '.'.join(name.split('.')[1:])
return self.__getattr__(path, context=context).__getattr__(subpath, context=context)
return self._getattr(name, context=context)
return self.__getattr__(path, context=context).__getattr__(subpath,
context=context)
return self._getattr(name,
context=context)
def _impl_search_dynchild(self, name, context):
def _impl_search_dynchild(self,
name,
context):
ret = []
for child in self._impl_st_getchildren(context, only_dyn=True):
for child in self._impl_st_getchildren(context,
only_dyn=True):
cname = child.impl_getname()
if name.startswith(cname):
for value in child._impl_get_suffixes(context):
if name == cname + value:
return SynDynOptionDescription(child, name, value)
return SynDynOptionDescription(child,
name,
value)
return ret
def _impl_get_dynchild(self, child, suffix):
def _impl_get_dynchild(self,
child,
suffix):
name = child.impl_getname() + suffix
path = self.impl_getname() + suffix + '.' + name
if isinstance(child, OptionDescription):
return SynDynOptionDescription(child, name, suffix)
return SynDynOptionDescription(child,
name,
suffix)
else:
return child._impl_to_dyn(name, path)
return child._impl_to_dyn(name,
path)
class OptionDescription(OptionDescriptionWalk):
@ -414,12 +456,18 @@ class OptionDescription(OptionDescriptionWalk):
"""
__slots__ = ('_group_type',)
def __init__(self, name, doc, children, requires=None, properties=None):
def __init__(self,
name,
doc,
children,
requires=None,
properties=None):
"""
:param children: a list of options (including optiondescriptions)
"""
super(OptionDescription, self).__init__(name, doc=doc,
super(OptionDescription, self).__init__(name,
doc=doc,
requires=requires,
properties=properties)
child_names = []
@ -453,12 +501,15 @@ class OptionDescription(OptionDescriptionWalk):
def impl_getdoc(self):
return self.impl_get_information('doc')
def impl_validate(self, *args, **kwargs):
def impl_validate(self,
*args,
**kwargs):
"""usefull for OptionDescription"""
pass
# ____________________________________________________________
def impl_set_group_type(self, group_type):
def impl_set_group_type(self,
group_type):
"""sets a given group object to an OptionDescription
:param group_type: an instance of `GroupType` or `MasterGroupType`
@ -474,7 +525,7 @@ class OptionDescription(OptionDescriptionWalk):
raise Exception('please use MasterSlaves object instead of OptionDescription')
children = self.impl_getchildren()
for child in children:
if child._is_symlinkoption(): # pragma: optional cover
if child.impl_is_symlinkoption(): # pragma: optional cover
raise ValueError(_("master group {0} shall not have "
"a symlinkoption").format(self.impl_getname()))
if not isinstance(child, Option): # pragma: optional cover
@ -540,7 +591,7 @@ class DynOptionDescription(OptionDescription):
'dynoptiondescription'))
for chld in child._impl_getchildren():
chld._impl_setsubdyn(self)
if child._is_symlinkoption():
if child.impl_is_symlinkoption():
raise ConfigError(_('cannot set symlinkoption in a '
'dynoptiondescription'))
child._impl_setsubdyn(self)
@ -586,7 +637,7 @@ class SynDynOptionDescription(object):
return self._impl_getchildren()
def impl_getpath(self, context):
path = self._impl_getopt().impl_getpath(context).split('.')
path = self.impl_getopt().impl_getpath(context).split('.')
path[-1] += self._suffix
path.append(self._name)
return '.'.join(path)
@ -594,7 +645,7 @@ class SynDynOptionDescription(object):
def impl_getpaths(self, include_groups=False, _currpath=None):
return _impl_getpaths(self, include_groups, _currpath)
def _impl_getopt(self):
def impl_getopt(self):
return self._opt
@ -624,7 +675,7 @@ class MasterSlaves(OptionDescription):
slaves.append(child)
child._add_dependency(self)
for idx, child in enumerate(children):
if child._is_symlinkoption(): # pragma: optional cover
if child.impl_is_symlinkoption(): # pragma: optional cover
raise ValueError(_("master group {0} shall not have "
"a symlinkoption").format(self.impl_getname()))
if not isinstance(child, Option): # pragma: optional cover

View file

@ -21,10 +21,10 @@
import re
from ..i18n import _
from .option import _RegexpOption
from .option import RegexpOption
class UsernameOption(_RegexpOption):
class UsernameOption(RegexpOption):
__slots__ = tuple()
#regexp build with 'man 8 adduser' informations
_regexp = re.compile(r"^[a-z_][a-z0-9_-]{0,30}[$a-z0-9_-]{0,1}$")

View file

@ -208,6 +208,12 @@ owners.user = owners.Owner('user')
"""forced
special owner when value is forced"""
owners.forced = owners.Owner('forced')
"""meta
special owner when value comes from metaconfig"""
owners.meta = owners.Owner('meta')
forbidden_owners = (owners.default, owners.forced, owners.meta)
# ____________________________________________________________
@ -298,8 +304,16 @@ class Settings(object):
ntime,
index)
if not is_cached:
props = self._p_.getproperties(path,
opt.impl_getproperties())
meta = self._getcontext().cfgimpl_get_meta()
if meta is None:
props = self._p_.getproperties(path,
opt.impl_getproperties())
else:
props = meta.cfgimpl_get_settings().getproperties(opt,
path,
setting_properties,
index=index,
apply_requires=False)
if apply_requires:
requires = self.apply_requires(opt,
path,
@ -326,7 +340,10 @@ class Settings(object):
def getpermissive(self,
path):
return self._pp_.getpermissive(path)
meta = self._getcontext().cfgimpl_get_meta()
if meta is None:
return self._pp_.getpermissive(path)
return meta.cfgimpl_get_settings().getpermissive(path)
def apply_requires(self,
opt,
@ -481,13 +498,11 @@ class Settings(object):
opt,
path,
properties):
# force=False):
"""save properties for specified path
(never save properties if same has option properties)
"""
if self._getcontext().cfgimpl_get_meta() is not None:
raise ConfigError(_('cannot change global property with metaconfig'))
#if not force:
raise ConfigError(_('cannot change property with metaconfig'))
forbidden_properties = forbidden_set_properties & properties
if forbidden_properties:
raise ConfigError(_('cannot add those properties: {0}').format(
@ -516,6 +531,8 @@ class Settings(object):
it is better (faster) to set the path parameter
instead of passing a :class:`tiramisu.option.Option()` object.
"""
if self._getcontext().cfgimpl_get_meta() is not None:
raise ConfigError(_('cannot change permissive with metaconfig'))
if not isinstance(permissives, frozenset):
raise TypeError(_('permissive must be a frozenset'))
forbidden_permissives = forbidden_set_permissives & permissives
@ -529,7 +546,12 @@ class Settings(object):
#____________________________________________________________
# reset methods
def reset(self, opt=None, _path=None, all_properties=False):
def reset(self,
opt=None,
_path=None,
all_properties=False):
if self._getcontext().cfgimpl_get_meta() is not None:
raise ConfigError(_('cannot change property with metaconfig'))
if all_properties and (_path or opt): # pragma: optional cover
raise ValueError(_('opt and all_properties must not be set '
'together in reset'))
@ -547,105 +569,63 @@ class Settings(object):
def validate_properties(self,
opt_or_descr,
is_descr,
check_frozen,
path,
value=None,
force_permissive=False,
setting_properties=undefined,
self_properties=undefined,
setting_properties,
index=None,
debug=False):
force_permissive=False):
"""
validation upon the properties related to `opt_or_descr`
:param opt_or_descr: an option or an option description object
:param force_permissive: behaves as if the permissive property
was present
:param is_descr: we have to know if we are in an option description,
just because the mandatory property
doesn't exist here
:param check_frozen: in the validation process, an option is to be modified,
the behavior can be different
(typically with the `frozen` property)
"""
# opt properties
if self_properties is not undefined:
if not isinstance(self_properties, frozenset):
raise Exception('pouet')
properties = self_properties
else:
properties = self.getproperties(opt_or_descr,
path,
setting_properties=setting_properties,
index=index)
properties = self.getproperties(opt_or_descr,
path,
setting_properties=setting_properties,
index=index)
# calc properties
properties &= setting_properties
if not is_descr:
properties &= setting_properties - set(['frozen'])
if not opt_or_descr.impl_is_optiondescription():
#mandatory
if 'mandatory' in properties and \
not self._getcontext().cfgimpl_get_values().isempty(opt_or_descr,
value,
index=index):
properties.remove('mandatory')
elif 'empty' in properties and \
'empty' in setting_properties and \
self._getcontext().cfgimpl_get_values().isempty(opt_or_descr,
value,
force_allow_empty_list=True,
index=index):
properties.add('mandatory')
# should return 'frozen' only when tried to modify a value
if check_frozen and 'everything_frozen' in setting_properties:
properties.add('frozen')
elif 'frozen' in properties and not check_frozen:
properties.remove('frozen')
if 'empty' in properties:
properties.remove('empty')
if 'mandatory' in properties or 'empty' in properties:
value = 'pouet'
if self.validate_mandatory(opt_or_descr, index, value, properties):
properties += set(['mandatory']) - set(['empty'])
else:
properties -= set(['mandatory', 'empty'])
opt_type = 'option'
else:
opt_type = 'optiondescription'
# remove permissive properties
if properties != frozenset() and (force_permissive is True or
'permissive' in setting_properties):
if force_permissive is True and properties:
# remove global permissive if need
properties -= self.get_context_permissive()
# at this point an option should not remain in properties
if properties != frozenset():
props = list(properties)
datas = {'opt': opt_or_descr,
'path': path,
'setting_properties': setting_properties,
'index': index,
'debug': True}
if is_descr:
opt_type = 'optiondescription'
else:
opt_type = 'option'
if 'frozen' in properties:
raise PropertiesOptionError(_('cannot change the value for '
'option "{0}" this option is'
' frozen').format(
opt_or_descr.impl_getname()),
props,
self,
datas,
opt_type)
else:
if len(props) == 1:
prop_msg = _('property')
else:
prop_msg = _('properties')
raise PropertiesOptionError(_('cannot access to {0} "{1}" '
'because has {2} {3}'
'').format(opt_type,
opt_or_descr.impl_get_display_name(),
prop_msg,
display_list(props)),
props,
self,
datas,
opt_type)
raise PropertiesOptionError(None,
properties,
self,
datas,
opt_type)
def validate_mandatory(self, opt, index, value, properties):
values = self._getcontext().cfgimpl_get_values()
return 'mandatory' in properties and values.isempty(opt,
value,
index=index) or \
'empty' in properties and values.isempty(opt,
value,
force_allow_empty_list=True,
index=index)
#____________________________________________________________
# read only/read write

View file

@ -44,7 +44,7 @@ class Storage(object):
def __init__(self, session_id, persistent, test=False):
if not test and session_id in _list_sessions: # pragma: optional cover
raise ConflictError(_('session already used'))
raise ConflictError(_('session "{}" already used').format(session_id))
if persistent: # pragma: optional cover
raise ValueError(_('a dictionary cannot be persistent'))
self.session_id = session_id

View file

@ -90,7 +90,14 @@ class Values(Cache):
"""if path has a value
return: boolean
"""
return path in self._values[0]
has_path = path in self._values[0]
if index is None:
return has_path
elif has_path:
path_idx = self._values[0].index(path)
indexes = self._values[1][path_idx]
return index in indexes
return False
def reduce_index(self, path, index):
"""
@ -199,29 +206,15 @@ class Values(Cache):
path,
default,
index=None,
only_default=False,
with_value=False):
"""get owner for a path
return: owner object
"""
if index is None:
if only_default:
if path in self._values[0]:
owner = undefined
else:
owner = default
else:
owner = self._getvalue(path,
3,
index)
if owner is undefined:
owner = default
else:
owner = self._getvalue(path,
3,
index)
if owner is undefined:
owner = default
owner = self._getvalue(path,
3,
index)
if owner is undefined:
owner = default
if with_value:
return owner, self._getvalue(path,
2,

View file

@ -38,7 +38,7 @@ class Cache(object):
if DEBUG:
global FIXME
FIXME += 1
print('ca set cache', path, val, POUET(self), FIXME)
print('ca set cache', path, val, POUET(self), FIXME, id(self))
#if path is not None and (path.startswith('od.st.') or path.startswith('od.dod.')):
# raise Exception('mais ... mais ... mais')
#if FIXME == 111:
@ -51,7 +51,7 @@ class Cache(object):
if DEBUG:
global FIXME
FIXME += 1
print('ca trouve dans le cache', path, value, POUET(self), FIXME)
print('ca trouve dans le cache', path, value, POUET(self), FIXME, id(self))
#if path is not None and (path.startswith('od.st.') or path.startswith('od.dod.')):
# raise Exception('mais ... mais ... mais')
#if FIXME == 45:
@ -65,7 +65,7 @@ class Cache(object):
if DEBUG:
global FIXME
FIXME += 1
print('ca del cache', path, POUET(self), FIXME)
print('ca del cache', path, POUET(self), FIXME, id(self))
#if path is not None and (path.startswith('od.st.') or path.startswith('od.dod.')):
# raise Exception('mais ... mais ... mais')
#if FIXME == 23:
@ -79,7 +79,7 @@ class Cache(object):
:param path: the path's option
"""
if DEBUG:
print('ca cherche dans le cache', path, POUET(self))
print('ca cherche dans le cache', path, POUET(self), id(self))
return path in self._cache and index in self._cache[path]
def reset_expired_cache(self, exp):
@ -96,7 +96,7 @@ class Cache(object):
def reset_all_cache(self):
"empty the cache"
if DEBUG:
print('bzzzzzzzzzzzz delete tout le cache', POUET(self))
print('bzzzzzzzzzzzz delete tout le cache', POUET(self), id(self))
self._cache.clear()
def get_cached(self):

View file

@ -19,7 +19,7 @@ from time import time
import sys
import weakref
from .error import ConfigError, SlaveError, PropertiesOptionError
from .setting import owners, expires_time, undefined
from .setting import owners, expires_time, undefined, forbidden_owners
from .autolib import carry_out_calculation
from .i18n import _
from .option import DynSymLinkOption, Option
@ -66,13 +66,10 @@ class Values(object):
validate=True,
force_permissive=False,
trusted_cached_properties=True,
validate_properties=True,
setting_properties=undefined,
self_properties=undefined,
index=None,
check_frozen=False,
display_warnings=True,
_orig_context=undefined):
display_warnings=True):
context = self._getcontext()
settings = context.cfgimpl_get_settings()
if path is None:
@ -83,8 +80,7 @@ class Values(object):
path,
setting_properties=setting_properties,
index=index)
if 'cache' in setting_properties and self._p_.hascache(path, index) and \
_orig_context is undefined:
if 'cache' in setting_properties and self._p_.hascache(path, index):
if 'expire' in setting_properties:
ntime = int(time())
is_cached, value = self._p_.getcache(path,
@ -93,36 +89,18 @@ class Values(object):
if index:
value = value[index]
if is_cached:
if not trusted_cached_properties:
# revalidate properties (because of not default properties)
settings.validate_properties(opt,
False,
False,
value=value,
path=path,
force_permissive=force_permissive,
setting_properties=setting_properties,
self_properties=self_properties,
index=index)
return value
if _orig_context is not undefined:
_context = _orig_context
else:
_context = context
val = self.get_validated_value(opt,
path,
validate,
force_permissive,
validate_properties,
setting_properties,
self_properties,
index=index,
check_frozen=check_frozen,
display_warnings=display_warnings,
_orig_context=_context)
force_permissive=force_permissive)
if index is None and 'cache' in setting_properties and \
validate and validate_properties and force_permissive is False \
and trusted_cached_properties is True and _orig_context is undefined:
validate and force_permissive is False \
and trusted_cached_properties is True:
if 'expire' in setting_properties:
if ntime is None:
ntime = int(time())
@ -134,27 +112,24 @@ class Values(object):
opt,
path,
validate,
force_permissive,
validate_properties,
setting_properties,
self_properties,
self_properties=None,
index=None,
check_frozen=False,
display_warnings=True,
_orig_context=undefined):
force_permissive=False):
"""same has getitem but don't touch the cache
index is None for slave value, if value returned is not a list, just return []
"""
context = self._getcontext()
setting = context.cfgimpl_get_settings()
config_error = None
try:
value = self.getvalue(opt,
path,
self_properties,
index,
setting_properties,
self_properties,
validate,
_orig_context)
force_permissive=force_permissive)
except ConfigError as value:
value_error = True
# For calculating properties, we need value (ie for mandatory
@ -181,23 +156,6 @@ class Values(object):
if err:
config_error = err
value = None
if validate_properties:
if config_error is not None:
# should not raise PropertiesOptionError if option is
# mandatory
val_props = undefined
else:
val_props = value
setting.validate_properties(opt,
False,
check_frozen,
value=val_props,
path=path,
force_permissive=force_permissive,
setting_properties=setting_properties,
self_properties=self_properties,
index=index)
if not value_error and validate and display_warnings:
opt.impl_validate(value,
context,
@ -213,10 +171,11 @@ class Values(object):
def getvalue(self,
opt,
path,
self_properties,
index,
setting_properties,
self_properties,
validate,
_orig_context):
force_permissive=False):
"""actually retrieves the value
:param opt: the `option.Option()` object
@ -231,7 +190,6 @@ class Values(object):
_index = index
owner, value = self._p_.getowner(path,
owners.default,
only_default=True,
index=_index,
with_value=True)
is_default = owner == owners.default
@ -247,11 +205,13 @@ class Values(object):
path,
index,
validate,
_orig_context)
setting_properties,
force_permissive=force_permissive)
def getdefaultvalue(self,
opt,
path,
setting_properties=undefined,
index=None):
"""get default value:
- get meta config value or
@ -267,43 +227,45 @@ class Values(object):
return self._getdefaultvalue(opt,
path,
index,
True,
self._getcontext())
True)
def _getdefaultvalue(self,
opt,
path,
index,
validate,
_orig_context):
setting_properties,
force_permissive=False):
context = self._getcontext()
def _reset_cache():
# calculated value could be a new value, so reset cache
_orig_context.cfgimpl_reset_cache(opt=opt,
path=path)
context.cfgimpl_reset_cache(opt=opt,
path=path)
#FIXME with_meta should be calculated here...
with_meta = True
if with_meta:
meta = self._getcontext().cfgimpl_get_meta()
if meta is not None:
# retrieved value from meta config
try:
value = meta.cfgimpl_get_values().get_cached_value(opt,
path,
index=index,
_orig_context=_orig_context)
except PropertiesOptionError:
# if properties error, return an other default value
# unexpected error, should not happened
pass
else:
return value
if self._is_meta(opt,
path,
index,
setting_properties,
force_permissive=force_permissive):
meta = context.cfgimpl_get_meta()
# retrieved value from meta config
try:
value = meta.getattr(path,
index=index,
setting_properties=setting_properties,
force_permissive=force_permissive)
except PropertiesOptionError:
# if properties error, return an other default value
# unexpected error, should not happened
pass
else:
return value
if opt.impl_has_callback():
# if value has callback, calculate value
callback, callback_params = opt.impl_get_callback()
value = carry_out_calculation(opt,
context=_orig_context,
context=context,
callback=callback,
callback_params=callback_params,
index=index,
@ -444,15 +406,37 @@ class Values(object):
index):
context = self._getcontext()
settings = context.cfgimpl_get_settings()
# First validate properties with this value
context.cfgimpl_get_settings().validate_properties(opt,
False,
True,
value=value,
path=path,
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index)
properties = settings.getproperties(opt,
path,
setting_properties=setting_properties,
index=index)
if 'everything_frozen' in setting_properties or 'frozen' in properties:
datas = {'opt': opt,
'path': path,
'setting_properties': setting_properties,
'index': index,
'debug': True}
raise PropertiesOptionError(None,
['frozen'],
settings,
datas,
'option')
if settings.validate_mandatory(opt,
index,
value,
properties):
datas = {'opt': opt,
'path': path,
'setting_properties': setting_properties,
'index': index,
'debug': True}
raise PropertiesOptionError(None,
['mandatory'],
settings,
datas,
'option')
# Value must be valid for option
opt.impl_validate(value,
context,
@ -488,17 +472,32 @@ class Values(object):
def _is_meta(self,
opt,
path,
index,
setting_properties,
force_permissive=False):
context = self._getcontext()
if context.cfgimpl_get_meta() is None:
force_permissive=False,
force_owner_is_default=False):
if not force_owner_is_default and self._p_.hasvalue(path,
index=index):
# has already a value, so not meta
return False
return self.is_default_owner(opt,
path,
setting_properties,
validate_meta=False,
index=None,
force_permissive=force_permissive)
context = self._getcontext()
meta = context.cfgimpl_get_meta()
if meta is None:
return False
if opt.impl_is_master_slaves('slave'):
master = opt.impl_get_master_slaves().getmaster(opt)
masterp = master.impl_getpath(context)
# slave could be a "meta" only if master hasn't value
if self._p_.hasvalue(masterp,
index=index):
return False
return not meta.cfgimpl_get_values().is_default_owner(opt,
path,
setting_properties,
index=index,
force_permissive=force_permissive)
#______________________________________________________________________
# owner
@ -517,9 +516,9 @@ class Values(object):
was present
:returns: a `setting.owners.Owner` object
"""
if opt._is_symlinkoption() and \
if opt.impl_is_symlinkoption() and \
not isinstance(opt, DynSymLinkOption):
opt = opt._impl_getopt()
opt = opt.impl_getopt()
return self._getowner(opt,
path,
setting_properties,
@ -537,6 +536,9 @@ class Values(object):
index=None):
"""get owner of an option
"""
#FIXME: validate_meta ne marche que si == False ou undefined !
if validate_meta is not False and validate_meta is not undefined:
raise Exception('poeut')
if not isinstance(opt, Option) and not isinstance(opt,
DynSymLinkOption):
raise ConfigError(_('owner only avalaible for an option'))
@ -547,30 +549,26 @@ class Values(object):
setting_properties)
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
return owners.default
owner = self._p_.getowner(path,
owners.default,
only_default=only_default,
index=index)
if validate_meta is undefined:
if opt.impl_is_master_slaves('slave'):
master = opt.impl_get_master_slaves().getmaster(opt)
masterp = master.impl_getpath(context)
validate_meta = self._is_meta(master,
masterp,
setting_properties,
force_permissive=force_permissive)
if only_default:
if self._p_.hasvalue(path,
index):
owner = undefined
else:
validate_meta = True
if validate_meta and owner is owners.default:
meta = context.cfgimpl_get_meta()
if meta is not None:
owner = meta.cfgimpl_get_values()._getowner(opt,
path,
setting_properties,
force_permissive=force_permissive,
self_properties=self_properties,
only_default=only_default,
index=index)
owner = owners.default
else:
owner = self._p_.getowner(path,
owners.default,
index=index)
if owner is owners.default and validate_meta is not False:
if validate_meta is undefined:
validate_meta = self._is_meta(opt,
path,
index,
setting_properties,
force_permissive=force_permissive,
force_owner_is_default=True)
if validate_meta:
owner = owners.meta
return owner
def setowner(self,
@ -584,7 +582,10 @@ class Values(object):
:param owner: a valid owner, that is a `setting.owners.Owner` object
"""
if not isinstance(owner, owners.Owner):
raise TypeError(_("invalid generic owner {0}").format(str(owner)))
raise TypeError(_("invalid owner {0}").format(str(owner)))
if owner in forbidden_owners:
raise ConfigError(_('set owner "{0}" is forbidden').format(str(owner)))
if not self._p_.hasvalue(path):
raise ConfigError(_('no value for {0} cannot change owner to {1}'
@ -595,7 +596,7 @@ class Values(object):
opt,
path,
setting_properties,
validate_meta=True,
validate_meta=undefined,
self_properties=undefined,
index=None,
force_permissive=False):
@ -631,13 +632,12 @@ class Values(object):
path,
setting_properties,
validate=False)
ret = fake_value.get_cached_value(opt,
path,
setting_properties=setting_properties,
check_frozen=True,
force_permissive=force_permissive)
if isinstance(ret, Exception):
raise ret
#FIXME ce n'est pas deja fait dans le reset ?
#sinon c'est un validate_properties qu'il faut faire ...
#fake_value.get_cached_value(opt,
# path,
# setting_properties=setting_properties,
# force_permissive=force_permissive)
if opt.impl_is_master_slaves('master'):
opt.impl_get_master_slaves().reset(opt,
self,
@ -653,7 +653,7 @@ class Values(object):
path,
None,
validate,
context)
setting_properties)
self._setvalue(opt,
path,
value,
@ -687,7 +687,6 @@ class Values(object):
path,
index=index,
setting_properties=setting_properties,
check_frozen=True,
force_permissive=force_permissive)
self._p_.resetvalue_index(path, index)
@ -702,7 +701,6 @@ class Values(object):
current_value = self.get_cached_value(opt,
path,
setting_properties=setting_properties,
check_frozen=True,
force_permissive=force_permissive)
current_value.pop(index)
self.setvalue(opt,
@ -772,13 +770,14 @@ class Values(object):
path = '.'.join(currpath + [name])
if opt.impl_is_optiondescription():
#FIXME ?
if not settings.validate_properties(opt, True, False, path=path,
force_permissive=True,
setting_properties=setting_properties):
for path in _mandatory_warnings(opt, currpath + [name]):
yield path
else:
if opt._is_symlinkoption() and \
if opt.impl_is_symlinkoption() and \
not isinstance(opt, DynSymLinkOption):
continue
self_properties = settings.getproperties(opt,