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

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}$")