This commit is contained in:
2017-11-12 14:33:05 +01:00
parent ee445aee85
commit 7ab7b810dc
13 changed files with 1439 additions and 1420 deletions

View File

@ -35,6 +35,7 @@ class CommonTiramisu(object):
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
self.opt = opt
@ -43,6 +44,7 @@ class CommonTiramisu(object):
if self.slave_need_index:
self._test_slave_index()
self.config = config
self.setting_properties = setting_properties
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
if not self.allow_unrestraint:
@ -81,11 +83,19 @@ class TiramisuOptionOption(CommonTiramisu):
allow_unrestraint = True
slave_need_index = False
def __init__(self, opt, path, index, config, force_permissive, force_unrestraint):
def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionOption, self).__init__(opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
if config:
@ -117,11 +127,19 @@ class TiramisuOptionOption(CommonTiramisu):
class TiramisuOptionOwner(CommonTiramisu):
"""manager option's owner"""
def __init__(self, opt, path, index, config, force_permissive, force_unrestraint):
def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionOwner, self).__init__(opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
if config:
@ -135,9 +153,8 @@ class TiramisuOptionOwner(CommonTiramisu):
def isdefault(self):
"""is option has defaut value"""
#FIXME isdefault for slave should have index!
#FIXME should not be here, just for check property
return self.values.is_default_owner(self.opt,
index=self.index,
force_permissive=self.force_permissive)
def set(self, owner):
@ -158,11 +175,19 @@ class TiramisuOptionProperty(CommonTiramisu):
#allow_unrestraint = True
slave_need_index = False
def __init__(self, opt, path, index, config, force_permissive, force_unrestraint):
def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionProperty, self).__init__(opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
if config:
@ -170,7 +195,10 @@ class TiramisuOptionProperty(CommonTiramisu):
def get(self):
self._test_slave_index()
return self.settings.getproperties(self.opt, self.path, index=self.index, obj=False)
return self.settings.getproperties(self.opt,
self.path,
index=self.index,
obj=False)
def set(self, properties):
"""set properties for a specified option"""
@ -189,11 +217,19 @@ class TiramisuOptionPermissive(CommonTiramisu):
allow_unrestraint = True
slave_need_index = False
def __init__(self, opt, path, index, config, force_permissive, force_unrestraint):
def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionPermissive, self).__init__(opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
if config:
@ -201,8 +237,7 @@ class TiramisuOptionPermissive(CommonTiramisu):
def get(self):
"""get permissive value for a specified path"""
setting_properties = self.settings.getproperties(None, None, obj=False)
return self.settings.getpermissive(setting_properties, self.path)
return self.settings.getpermissive(self.setting_properties, self.path)
def set(self, permissive):
self.settings.setpermissive(permissive, opt=self.opt, path=self.path)
@ -217,25 +252,28 @@ class TiramisuOptionPermissive(CommonTiramisu):
class TiramisuOptionValue(CommonTiramisu):
"""manager option's value"""
def __init__(self, opt, path, index, config, force_permissive, force_unrestraint):
def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
super(TiramisuOptionValue, self).__init__(opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint)
def append(self, value=undefined):
if not self.opt.impl_is_master_slaves('master'):
raise APIError('append is only allowed for a master')
multi = self.config.getattr(self.path,
force_permissive=self.force_permissive)
multi.append(value)
self.set(multi)
def get(self):
settings = self.config.cfgimpl_get_settings()
value = self.config.getattr(self.path,
index=self.index,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive)
if isinstance(value, Multi):
value = list(value)
@ -247,45 +285,53 @@ class TiramisuOptionValue(CommonTiramisu):
if isinstance(value, list):
while undefined in value:
idx = value.index(undefined)
value[idx] = values._getdefaultvalue(self.opt,
self.path,
True,
idx,
undefined,
True)
value[idx] = values.getdefaultvalue(self.opt,
self.path,
idx)
else:
if value == undefined:
value = values._getdefaultvalue(self.opt,
self.path,
True,
self.index,
undefined,
True)
value = values.getdefaultvalue(self.opt,
self.path,
self.index)
self.config.setattr(self.path,
value,
index=self.index,
force_permissive=self.force_permissive)
def pop(self, index):
"""pop value for a specified master values
"""
self.config.delattr(self.path,
index=index,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive)
def reset(self):
"""reset value for a value"""
if self.index is None:
self.config.cfgimpl_get_values().reset(self.opt,
path=self.path,
force_permissive=self.force_permissive)
else:
#FIXME ... _p_ ...
self.config.cfgimpl_get_values()._p_.resetvalue_index(self.path, self.index)
self.config.delattr(self.path,
index=self.index,
setting_properties=self.setting_properties,
force_permissive=self.force_permissive)
class TiramisuOption(object):
icon = '\u2937'
tmpl_help = ' {} {}: {}'
def __init__(self, opt, path, index, config, force_permissive=False, force_unrestraint=False):
def __init__(self,
opt,
path,
index,
config,
setting_properties,
force_permissive,
force_unrestraint):
self.opt = opt
self.path = path
self.index = index
self.config = config
self.setting_properties = setting_properties
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
self.registers = {}
@ -310,6 +356,7 @@ class TiramisuOption(object):
self.path,
self.index,
self.config,
self.setting_properties,
self.force_permissive,
self.force_unrestraint)
elif subfunc == 'help':
@ -322,18 +369,25 @@ class TiramisuAPI(object):
icon = '\u2937'
tmpl_help = ' {} {}: {}'
def __init__(self, config, force_permissive=False, force_unrestraint=False):
def __init__(self,
config,
force_permissive=False,
force_unrestraint=False):
self.config = config
self.force_permissive = force_permissive
self.force_unrestraint = force_unrestraint
settings = self.config.cfgimpl_get_settings()
#FIXME ?
self.config.read_write()
self.config.cfgimpl_get_settings().setpermissive(('hidden',))
settings.setpermissive(('hidden',))
#/FIXME ?
def option(self, path, index=None):
validate = not self.force_unrestraint
settings = self.config.cfgimpl_get_settings()
setting_properties = settings.getcontextproperties()
opt = self.config.unwrap_from_path(path,
setting_properties=setting_properties,
validate=validate,
validate_properties=validate,
force_permissive=self.force_permissive,
@ -344,14 +398,19 @@ class TiramisuAPI(object):
path,
index,
self.config,
force_permissive=self.force_permissive,
force_unrestraint=self.force_unrestraint)
setting_properties,
self.force_permissive,
self.force_unrestraint)
def __getattr__(self, subfunc):
if subfunc == 'forcepermissive':
return TiramisuAPI(self.config, force_permissive=True, force_unrestraint=self.force_unrestraint)
return TiramisuAPI(self.config,
force_permissive=True,
force_unrestraint=self.force_unrestraint)
elif subfunc == 'unrestraint':
return TiramisuAPI(self.config, force_permissive=self.force_permissive, force_unrestraint=True)
return TiramisuAPI(self.config,
force_permissive=self.force_permissive,
force_unrestraint=True)
elif subfunc == 'help':
return self._help()
else:

View File

@ -31,7 +31,7 @@ from .option import OptionDescription, Option, SymLinkOption, \
from .option.baseoption import valid_name
from .setting import groups, Settings, default_encoding, undefined
from .storage import get_storages, set_storage, get_default_values_storages
from .value import Values, Multi
from .value import Values # , Multi
from .i18n import _
@ -45,9 +45,19 @@ class SubConfig(object):
on-demand. A Config is also a SubConfig.
Root Config is call context below
"""
__slots__ = ('_impl_context', '_impl_descr', '_impl_path')
__slots__ = ('_impl_context',
'_impl_descr',
'_impl_path',
'_impl_setting_properties',
'_impl_length')
def __init__(self, descr, context, subpath=None):
def __init__(self,
descr,
context,
setting_properties,
validate,
force_permissive,
subpath=None):
""" Configuration option management master class
:param descr: describes the configuration schema
@ -63,13 +73,19 @@ class SubConfig(object):
error = True
if error:
raise TypeError(_('descr must be an optiondescription, not {0}'
).format(type(descr)))
).format(type(descr)))
self._impl_descr = descr
# sub option descriptions
if not isinstance(context, weakref.ReferenceType): # pragma: optional cover
raise ValueError('context must be a Weakref')
self._impl_context = context
self._impl_path = subpath
if setting_properties is not undefined:
self._impl_setting_properties = setting_properties
if descr.impl_get_group_type() == groups.master:
self._impl_length = descr.get_length(context().cfgimpl_get_values(),
validate=validate,
force_permissive=force_permissive)
def cfgimpl_reset_cache(self,
only_expired=False,
@ -144,17 +160,20 @@ class SubConfig(object):
else:
reset_all_cache()
def cfgimpl_get_home_by_path(self, path, force_permissive=False,
returns_raise=False, _setting_properties=undefined,
validate_properties=True):
def cfgimpl_get_home_by_path(self,
path,
setting_properties,
validate_properties=True,
force_permissive=False,
returns_raise=False):
""":returns: tuple (config, name)"""
path = path.split('.')
for step in path[:-1]:
self = self.getattr(step,
force_permissive=force_permissive,
returns_raise=returns_raise,
validate_properties=validate_properties,
_setting_properties=_setting_properties)
returns_raise=returns_raise,
setting_properties=setting_properties)
if isinstance(self, Exception):
return self, None
return self, path[-1]
@ -269,62 +288,111 @@ class SubConfig(object):
# attribute methods
def __setattr__(self, name, value):
"attribute notation mechanism for the setting of the value of an option"
self.setattr(name, value)
self.setattr(name,
value)
def _setattr(self, name, value, force_permissive=False, not_raises=False):
"""use setattr instead of _setattr
"""
self.setattr(name, value, force_permissive=force_permissive,
not_raises=not_raises)
def setattr(self,
name,
value,
force_permissive=False,
not_raises=False,
index=None,
setting_properties=undefined,
_commit=True):
def setattr(self, name, value, force_permissive=False, not_raises=False, index=None,
_setting_properties=undefined, _commit=True):
if name.startswith('_impl_'):
return object.__setattr__(self, name, value)
return object.__setattr__(self,
name,
value)
context = self._cfgimpl_get_context()
if _setting_properties is undefined:
_setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
if setting_properties is undefined:
setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
if '.' in name: # pragma: optional cover
homeconfig, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive,
_setting_properties=_setting_properties)
return homeconfig.setattr(name, value, force_permissive,
not_raises, index=index,
_setting_properties=_setting_properties,
_commit=_commit)
self, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive,
setting_properties=setting_properties)
child = self.cfgimpl_get_description().__getattr__(name,
context=context)
if isinstance(child, OptionDescription) or isinstance(child, SynDynOptionDescription):
if isinstance(child, (OptionDescription, SynDynOptionDescription)):
raise TypeError(_("can't assign to an OptionDescription")) # pragma: optional cover
elif child._is_symlinkoption() and \
not isinstance(child, DynSymLinkOption): # pragma: no dynoptiondescription cover
path = context.cfgimpl_get_description().impl_get_path_by_opt(
child._impl_getopt())
context.setattr(path, value, force_permissive, not_raises, index=index,
_setting_properties=_setting_properties,
_commit=_commit)
raise TypeError(_("can't assign to a SymlinkOption"))
else:
msg = self.cfgimpl_get_description().impl_validate_value(child, value, self)
if msg is not None:
if not_raises:
return msg
else:
raise msg
subpath = self._get_subpath(name)
ret = self.cfgimpl_get_values().setitem(child, value, subpath,
force_permissive=force_permissive,
not_raises=not_raises, index=index,
_setting_properties=_setting_properties,
_commit=_commit)
if ret is not None:
return ret
return self.cfgimpl_get_values().setitem(child,
value,
subpath,
force_permissive,
not_raises,
index,
setting_properties,
_commit)
def __delattr__(self, name):
self.delattr(name)
def delattr(self,
name,
index=None,
force_permissive=False,
setting_properties=undefined,
validate=True,
not_raises=False):
context = self._cfgimpl_get_context()
child = self.cfgimpl_get_description().__getattr__(name, context)
self.cfgimpl_get_values().__delitem__(child)
if setting_properties is undefined:
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,
force_permissive=force_permissive,
setting_properties=setting_properties)
child = self.cfgimpl_get_description().__getattr__(name,
context=context)
if isinstance(child, (OptionDescription, SynDynOptionDescription)):
raise TypeError(_("can't delete an OptionDescription")) # pragma: optional cover
elif child._is_symlinkoption() and \
not isinstance(child, DynSymLinkOption): # pragma: no dynoptiondescription cover
raise TypeError(_("can't delete a SymlinkOption"))
else:
subpath = self._get_subpath(name)
values = self.cfgimpl_get_values()
if index is not None:
if child.impl_is_master_slaves('master'):
ret = values.reset_master(self,
child,
subpath,
index,
force_permissive,
setting_properties)
elif child.impl_is_master_slaves('slave'):
ret = values.reset_slave(child,
subpath,
index,
setting_properties,
force_permissive=force_permissive,
validate=validate)
else:
raise ValueError(_("can delete value with index only with a master or a slave"))
else:
ret = values.reset(child,
subpath,
setting_properties,
force_permissive=force_permissive,
validate=validate)
if ret:
if not_raises:
return ret
raise ret
def __getattr__(self, name):
return self.getattr(name)
def _getattr(self, name, force_permissive=False, validate=True): # pragma: optional cover
"""use getattr instead of _getattr
"""
return self.getattr(name, force_permissive, validate)
setting_properties = self.cfgimpl_get_context().cfgimpl_get_settings().getcontextproperties()
return self.getattr(name, setting_properties)
def _get_subpath(self, name):
if self._impl_path is None:
@ -333,10 +401,15 @@ class SubConfig(object):
subpath = self._impl_path + '.' + name
return subpath
def getattr(self, name, force_permissive=False, validate=True,
_setting_properties=undefined, _self_properties=undefined, index=None,
returns_raise=False, returns_option=False,
validate_properties=True):
def getattr(self,
name,
setting_properties,
force_permissive=False,
validate=True,
validate_properties=True,
index=None,
returns_raise=False,
returns_option=False):
"""
attribute notation mechanism for accessing the value of an option
:param name: attribute name
@ -346,51 +419,51 @@ class SubConfig(object):
# attribute access by passing a path,
# for instance getattr(self, "creole.general.family.adresse_ip_eth0")
context = self._cfgimpl_get_context()
if _setting_properties is undefined:
_setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
if '.' in name:
homeconfig, name = self.cfgimpl_get_home_by_path(
name, force_permissive=force_permissive,
validate_properties=validate_properties,
returns_raise=returns_raise, _setting_properties=_setting_properties)
homeconfig, name = self.cfgimpl_get_home_by_path(name,
force_permissive=force_permissive,
validate_properties=validate_properties,
returns_raise=returns_raise,
setting_properties=setting_properties)
if isinstance(homeconfig, Exception):
cfg = homeconfig
else:
cfg = homeconfig.getattr(name, force_permissive=force_permissive,
cfg = homeconfig.getattr(name,
force_permissive=force_permissive,
validate=validate,
_setting_properties=_setting_properties,
_self_properties=_self_properties,
index=index, returns_raise=returns_raise,
validate_properties=validate_properties)
validate_properties=validate_properties,
setting_properties=setting_properties,
index=index,
returns_raise=returns_raise)
else:
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,
force_permissive=force_permissive,
setting_properties=_setting_properties,
self_properties=_self_properties,
validate_properties=validate_properties,
index=index)
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())
cfg = context.getattr(path, validate=validate,
force_permissive=force_permissive,
_setting_properties=_setting_properties,
_self_properties=_self_properties,
path = context.cfgimpl_get_description().impl_get_path_by_opt(option._impl_getopt())
cfg = context.getattr(path,
validate=validate,
validate_properties=validate_properties,
index=index, returns_raise=True)
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index,
returns_raise=True)
elif option.impl_is_optiondescription():
if validate_properties:
props = self.cfgimpl_get_settings().validate_properties(
option, True, False, path=subpath,
force_permissive=force_permissive,
self_properties=_self_properties,
setting_properties=_setting_properties)
if setting_properties:
props = self.cfgimpl_get_settings().validate_properties(option,
True,
False,
path=subpath,
force_permissive=force_permissive,
setting_properties=setting_properties)
if props:
if returns_raise:
return props
@ -398,25 +471,29 @@ class SubConfig(object):
raise props
if returns_option is True:
return option
return SubConfig(option, self._impl_context, subpath)
return SubConfig(option,
self._impl_context,
setting_properties,
validate,
force_permissive,
subpath)
else:
if validate:
ret = self.cfgimpl_get_description().impl_validate(context,
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, path=subpath,
validate=validate,
force_permissive=force_permissive,
setting_properties=_setting_properties,
self_properties=_self_properties,
validate_properties=validate_properties,
index=index)
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 not returns_raise and isinstance(cfg, Exception):
raise cfg
if returns_option is True:
@ -473,13 +550,13 @@ class SubConfig(object):
if byvalue is undefined:
return True
value = self.getattr(path, force_permissive=force_permissive,
_setting_properties=setting_properties,
setting_properties=setting_properties,
returns_raise=True)
if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError):
return False
raise value # pragma: no cover
elif isinstance(value, Multi):
elif isinstance(value, list):
return byvalue in value
else:
return value == byvalue
@ -506,7 +583,7 @@ class SubConfig(object):
if byvalue is undefined and check_properties:
value = self.getattr(path,
force_permissive=force_permissive,
_setting_properties=setting_properties,
setting_properties=setting_properties,
returns_raise=True)
if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError):
@ -533,9 +610,14 @@ class SubConfig(object):
else:
return find_results
def make_dict(self, flatten=False, _currpath=None, withoption=None,
withvalue=undefined, force_permissive=False,
setting_properties=undefined, fullpath=False):
def make_dict(self,
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:
>>> print cfg.make_dict()
@ -579,17 +661,20 @@ class SubConfig(object):
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)
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, byname=withoption,
byvalue=withvalue, first=False,
type_='path', _subpath=self.cfgimpl_get_path(False),
for path in context._find(bytype=None,
byname=withoption,
byvalue=withvalue,
first=False,
type_='path',
_subpath=self.cfgimpl_get_path(False),
force_permissive=force_permissive,
setting_properties=setting_properties):
path = '.'.join(path.split('.')[:-1])
opt = context.unwrap_from_path(path, force_permissive=True)
opt = context.unwrap_from_path(path,
orce_permissive=True)
mypath = self.cfgimpl_get_path()
if mypath is not None:
if mypath == path:
@ -624,7 +709,7 @@ class SubConfig(object):
setting_properties, force_permissive=False, fullpath=False):
value = self.getattr(path,
force_permissive=force_permissive,
_setting_properties=setting_properties,
setting_properties=setting_properties,
returns_raise=True)
if isinstance(value, Exception):
if not isinstance(value, PropertiesOptionError): # pragma: no cover
@ -689,30 +774,52 @@ class _CommonConfig(SubConfig):
return self.cfgimpl_get_values().getowner(opt, index=index,
force_permissive=force_permissive)
def unwrap_from_path(self, path, force_permissive=False, index=None,
validate_properties=True, validate=True,
_setting_properties=undefined):
def unwrap_from_path(self,
path,
setting_properties=undefined,
force_permissive=False,
index=None,
validate=True,
validate_properties=True):
"""convenience method to extract and Option() object from the Config()
and it is **fast**: finds the option directly in the appropriate
namespace
:returns: Option()
"""
if _setting_properties is undefined:
context = self._cfgimpl_get_context()
_setting_properties = context.cfgimpl_get_settings()._getproperties(read_write=True)
if '.' in path:
self, path = self.cfgimpl_get_home_by_path(path,
validate_properties=validate_properties,
force_permissive=force_permissive,
_setting_properties=_setting_properties)
return self.getattr(path,
validate_properties=validate_properties,
validate=validate,
force_permissive=force_permissive,
index=index,
_setting_properties=_setting_properties,
returns_option=True)
validate_properties=validate_properties,
setting_properties=setting_properties)
if not validate_properties:
return self.cfgimpl_get_description().__getattr__(path,
context=self._cfgimpl_get_context())
else:
option = self.cfgimpl_get_description().__getattr__(path,
context=self._cfgimpl_get_context())
if not validate_properties:
return option
else:
if index is None and option.impl_is_master_slaves('slave'):
subpath = self._get_subpath(path)
props = self.cfgimpl_get_settings().validate_properties(option,
True,
False,
path=subpath,
force_permissive=force_permissive,
setting_properties=setting_properties)
if props:
raise props
return option
else:
return self.getattr(path,
validate=validate,
force_permissive=force_permissive,
index=index,
setting_properties=setting_properties,
validate_properties=validate_properties,
returns_option=True)
def cfgimpl_get_path(self, dyn=True):
return None
@ -743,19 +850,17 @@ class _CommonConfig(SubConfig):
def __getstate__(self):
raise NotImplementedError()
def _gen_fake_values(self, session):
def _gen_fake_values(self):
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(session, fake=True))
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,
force_settings=force_settings)
session = self.cfgimpl_get_values()._p_.getsession()
config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation(
session))
config.cfgimpl_get_values()._p_.importation(self.cfgimpl_get_values()._p_.exportation())
config.cfgimpl_get_settings()._p_.set_modified_properties(self.cfgimpl_get_settings(
)._p_.get_modified_properties())
config.cfgimpl_get_settings()._pp_.set_modified_permissives(self.cfgimpl_get_settings(
@ -795,7 +900,7 @@ class Config(_CommonConfig):
raise ValueError(_("invalid session ID: {0} for config").format(session_id))
self._impl_settings = Settings(self, properties, permissives)
self._impl_values = Values(self, values)
super(Config, self).__init__(descr, weakref.ref(self))
super(Config, self).__init__(descr, weakref.ref(self), undefined, True, False)
self._impl_meta = None
#undocumented option used only in test script
self._impl_test = False
@ -926,21 +1031,25 @@ class GroupConfig(_CommonConfig):
__repr__ = __str__
def getattr(self, name, force_permissive=False, validate=True,
_setting_properties=undefined, _self_properties=undefined, index=None,
returns_raise=False, returns_option=False,
validate_properties=True):
def getattr(self,
name,
setting_properties,
force_permissive=False,
validate=True,
index=None,
returns_raise=False,
validate_properties=True,
returns_option=False):
for child in self._impl_children:
if name == child._impl_name:
return child
return super(GroupConfig, self).getattr(name, force_permissive,
validate,
_self_properties=_self_properties,
index=index,
_setting_properties=_setting_properties,
setting_properties=setting_properties,
returns_raise=returns_raise,
returns_option=False,
validate_properties=validate_properties)
validate_properties=validate_properties,
returns_option=False)
class MetaConfig(GroupConfig):
@ -1000,22 +1109,30 @@ class MetaConfig(GroupConfig):
else:
child_value = child.getattr(path)
if force_default or value == child_value:
child.cfgimpl_get_values().reset(opt, path=path,
child.cfgimpl_get_values().reset(opt,
path,
setting_properties,
validate=False,
_setting_properties=setting_properties,
_commit=False)
continue
if force_dont_change_value:
child_value = child.getattr(path, _setting_properties=setting_properties,
child_value = child.getattr(path,
setting_properties=setting_properties,
returns_raise=True)
if isinstance(child_value, Exception):
ret.append(child_value)
elif value != child_value:
childret = child.setattr(path, child_value, _commit=False, not_raises=True)
childret = child.setattr(path,
child_value,
_commit=False,
not_raises=True)
if childret is not None: # pragma: no cover
ret.append(childret)
setret = self.setattr(path, value, _commit=_commit, not_raises=True)
setret = self.setattr(path,
value,
_commit=_commit,
not_raises=True)
if setret is not None:
ret.append(setret)
return ret
@ -1024,13 +1141,15 @@ class MetaConfig(GroupConfig):
opt = self.cfgimpl_get_description().impl_get_opt_by_path(path)
setting_properties = self.cfgimpl_get_settings()._getproperties(read_write=False)
for child in self._impl_children:
child.cfgimpl_get_values().reset(opt, path=path,
child.cfgimpl_get_values().reset(opt,
path,
setting_properties,
validate=False,
_setting_properties=setting_properties,
_commit=False)
self.cfgimpl_get_values().reset(opt, path=path,
validate=False,
_setting_properties=setting_properties)
self.cfgimpl_get_values().reset(opt,
path,
setting_properties,
validate=False)
def new_config(self, session_id, persistent=False):
config = Config(self._impl_descr, session_id=session_id,

View File

@ -135,7 +135,7 @@ class Base(object):
def __init__(self, name, doc, requires=None, properties=None, is_multi=False):
if not valid_name(name):
raise ValueError(_("invalid name: {0} for option").format(name))
raise ValueError(_('invalid name: "{0}" for option').format(name))
if requires is not None:
calc_properties, requires = validate_requires_arg(self, is_multi,
requires, name)
@ -654,13 +654,18 @@ class DynSymLinkOption(object):
else:
return base_path + '.' + self._dyn
def impl_validate(self, value, context=undefined, validate=True,
force_index=None, force_submulti_index=None, is_multi=None,
display_error=True, display_warnings=True, multi=None,
def impl_validate(self,
value,
context=undefined,
validate=True,
force_index=None,
is_multi=None,
display_error=True,
display_warnings=True,
multi=None,
setting_properties=undefined):
return self._impl_getopt().impl_validate(value, context, validate,
force_index,
force_submulti_index,
current_opt=self,
is_multi=is_multi,
display_error=display_error,

View File

@ -112,12 +112,23 @@ class Option(OnlyOption):
super(Option, self).__init__(name, doc, requires=requires,
properties=properties, is_multi=is_multi)
if is_multi and default_multi is not None:
err = self._validate(default_multi)
if err:
raise ValueError(_("invalid default_multi value {0} "
"for option {1}: {2}").format(
str(default_multi),
self.impl_getname(), str(err)))
def test_multi_value(value):
err = self._validate(value)
if err:
raise ValueError(_("invalid default_multi value {0} "
"for option {1}: {2}").format(
str(value),
self.impl_getname(), str(err)))
if _multi is submulti:
if not isinstance(default_multi, list):
raise ValueError(_("invalid default_multi value {0} "
"for option {1}: must be a list for a submulti").format(
str(default_multi),
self.impl_getname()))
for value in default_multi:
test_multi_value(value)
else:
test_multi_value(default_multi)
_setattr(self, '_default_multi', default_multi)
if unique is not undefined:
_setattr(self, '_unique', unique)
@ -239,10 +250,17 @@ class Option(OnlyOption):
ret_val = val
return ret_val
def impl_validate(self, value, context=undefined, validate=True,
force_index=None, force_submulti_index=None,
current_opt=undefined, is_multi=None,
display_error=True, display_warnings=True, multi=None,
def impl_validate(self,
value,
context=undefined,
validate=True,
force_index=None,
force_submulti_index=None,
current_opt=undefined,
is_multi=None,
display_error=True,
display_warnings=True,
multi=None,
setting_properties=undefined):
"""
:param value: the option's value
@ -290,7 +308,8 @@ class Option(OnlyOption):
else:
validator_params_ = {'': (val,)}
# Raise ValueError if not valid
value = carry_out_calculation(current_opt, context=context,
value = carry_out_calculation(current_opt,
context=context,
callback=validator,
callback_params=validator_params_,
index=_index,
@ -304,11 +323,14 @@ class Option(OnlyOption):
else:
if display_error:
# option validation
err = self._validate(_value, context, current_opt)
err = self._validate(_value,
context,
current_opt)
if err:
if debug: # pragma: no cover
log.debug('do_validation: value: {0}, index: {1}, '
'submulti_index: {2}'.format(_value, _index,
'submulti_index: {2}'.format(_value,
_index,
submulti_index),
exc_info=True)
err_msg = '{0}'.format(err)
@ -342,8 +364,12 @@ class Option(OnlyOption):
if error is None:
# if context launch consistency validation
#if context is not undefined:
ret = self._valid_consistency(current_opt, _value, context,
_index, submulti_index, display_warnings,
ret = self._valid_consistency(current_opt,
_value,
context,
_index,
submulti_index,
display_warnings,
display_error)
if isinstance(ret, ValueError):
error = ret
@ -421,8 +447,13 @@ class Option(OnlyOption):
err = do_validation(val, idx, force_submulti_index)
if err:
return err
return self._valid_consistency(current_opt, None, context,
None, None, display_warnings, display_error)
return self._valid_consistency(current_opt,
None,
context,
None,
None,
display_warnings,
display_error)
def impl_is_dynsymlinkoption(self):
return False
@ -596,7 +627,11 @@ class Option(OnlyOption):
def impl_getdefault_multi(self):
"accessing the default value for a multi"
return getattr(self, '_default_multi', None)
if self.impl_is_submulti():
default_value = []
else:
default_value = None
return getattr(self, '_default_multi', default_value)
def _validate_callback(self, callback, callback_params):
"""callback_params:
@ -605,7 +640,7 @@ class Option(OnlyOption):
"""
if callback is None:
return
default_multi = self.impl_getdefault_multi()
default_multi = getattr(self, '_default_multi', None)
is_multi = self.impl_is_multi()
default = self.impl_getdefault()
if (not is_multi and (default is not None or default_multi is not None)) or \

View File

@ -163,11 +163,11 @@ class CacheOptionDescription(BaseOption):
raise ConfigError(_('a dynoption ({0}) cannot have '
'force_store_value property').format(subpath))
if force_store_values and not config._impl_values._p_.hasvalue(subpath, session):
value = config.cfgimpl_get_values()._get_cached_value(option,
path=subpath,
validate=False,
trusted_cached_properties=False,
validate_properties=True)
value = config.cfgimpl_get_values().get_cached_value(option,
path=subpath,
validate=False,
trusted_cached_properties=False,
validate_properties=True)
value_set = True
config._impl_values._p_.setvalue(subpath, value,
owners.forced, None, session, False)
@ -497,6 +497,9 @@ class OptionDescription(OptionDescriptionWalk):
raise ValueError(_("invalid suffix: {0} for option").format(val))
return values
def impl_validate_value(self, option, value, context):
pass
class DynOptionDescription(OptionDescription):
def __init__(self, name, doc, children, requires=None, properties=None,
@ -561,9 +564,13 @@ class SynDynOptionDescription(object):
class MasterSlaves(OptionDescription):
__slots__ = ('master', 'slaves')
def __init__(self, name, doc, children, requires=None, properties=None):
#if master (same name has group) is set
#for collect all slaves
def __init__(self,
name,
doc,
children,
requires=None,
properties=None):
super(MasterSlaves, self).__init__(name,
doc,
children,
@ -572,10 +579,6 @@ class MasterSlaves(OptionDescription):
self._group_type = groups.master
slaves = []
master = children[0]
if master.impl_getname() != name:
raise ValueError(_('master group with wrong'
' master name for {0}'
).format(name))
for child in children[1:]:
if child.impl_getdefault() != []:
raise ValueError(_("not allowed default value for option {0} "
@ -604,8 +607,6 @@ class MasterSlaves(OptionDescription):
raise ValueError(_("callback of master's option shall "
"not refered a slave's ones"))
#everything is ok, store references
#self.master = master
#self.slaves = tuple(slaves)
for child in children:
child._master_slaves = self
master._add_dependency(self)
@ -644,41 +645,74 @@ class MasterSlaves(OptionDescription):
c_opt = opt
return c_opt in self._children[1]
def reset(self, opt, values, setting_properties, _commit=True, force_permissive=False):
for slave in self.getslaves(opt):
values.reset(slave, validate=False, _setting_properties=setting_properties,
_commit=_commit, force_permissive=force_permissive)
def reset(self,
opt,
values,
setting_properties,
_commit=True,
force_permissive=False):
def pop(self, opt, values, index):
for slave in self.getslaves(opt):
slave_path = slave.impl_getpath(values._getcontext())
slavelen = values._p_.get_max_length(slave_path, None)
# just for raise if needed
if not values.is_default_owner(slave, validate_properties=False,
validate_meta=False, index=index):
multi = values._get_cached_value(slave, validate=False,
validate_properties=False,
)
if isinstance(multi, Exception):
raise multi
values.reset(slave,
slave_path,
setting_properties,
validate=False,
_commit=_commit,
force_permissive=force_permissive)
def pop(self,
opt,
path,
values,
index):
for slave in self.getslaves(opt):
slave_path = slave.impl_getpath(values._getcontext())
slavelen = values._p_.get_max_length(slave_path)
if not values.is_default_owner(slave,
validate_properties=False,
validate_meta=False,
index=index):
#FIXME # just for raise if needed
#multi = values.get_cached_value(slave,
# validate=False,
# validate_properties=False,
# )
#if isinstance(multi, Exception):
# raise multi
if slavelen > index:
values._p_.resetvalue_index(slave_path, index)
values._p_.resetvalue_index(slave_path,
index)
if slavelen > index + 1:
for idx in xrange(index + 1, slavelen):
values._p_.reduce_index(slave_path, idx)
values._p_.reduce_index(slave_path,
idx)
def getitem(self, values, opt, path, validate, force_permissive,
trusted_cached_properties, validate_properties,
slave_path=undefined, slave_value=undefined,
setting_properties=undefined, self_properties=undefined, index=None,
def getitem(self,
values,
opt,
path,
validate,
force_permissive,
trusted_cached_properties,
validate_properties,
setting_properties=undefined,
self_properties=undefined,
index=None,
check_frozen=False):
if self.is_master(opt):
return self._getmaster(values, opt, path, validate,
return self._getmaster(values,
opt,
path,
validate,
force_permissive,
validate_properties, slave_path,
slave_value, self_properties, index,
setting_properties, check_frozen)
validate_properties,
self_properties,
index,
setting_properties,
check_frozen)
else:
return self._getslave(values, opt, path, validate,
force_permissive, trusted_cached_properties,
@ -686,17 +720,26 @@ class MasterSlaves(OptionDescription):
self_properties, index,
check_frozen)
def _getmaster(self, values, opt, path, validate, force_permissive,
validate_properties, c_slave_path,
c_slave_value, self_properties, index,
setting_properties, check_frozen):
return values._get_cached_value(opt, path=path, validate=validate,
force_permissive=force_permissive,
validate_properties=validate_properties,
self_properties=self_properties,
from_masterslave=True, index=index,
setting_properties=setting_properties,
check_frozen=check_frozen)
def _getmaster(self,
values,
opt,
path,
validate,
force_permissive,
validate_properties,
self_properties,
index,
setting_properties,
check_frozen):
return values.get_cached_value(opt,
path=path,
validate=validate,
force_permissive=force_permissive,
validate_properties=validate_properties,
self_properties=self_properties,
index=index,
setting_properties=setting_properties,
check_frozen=check_frozen)
def _getslave(self, values, opt, path, validate, force_permissive,
trusted_cached_properties, validate_properties, setting_properties,
@ -725,20 +768,20 @@ class MasterSlaves(OptionDescription):
master = self.getmaster(opt)
context = values._getcontext()
masterp = master.impl_getpath(context)
mastervalue = values._get_cached_value(master, path=masterp, validate=validate,
force_permissive=force_permissive,
validate_properties=validate_properties,
self_properties=self_properties,
from_masterslave=True,
setting_properties=setting_properties,
check_frozen=check_frozen)
mastervalue = values.get_cached_value(master, path=masterp, validate=validate,
force_permissive=force_permissive,
validate_properties=validate_properties,
self_properties=self_properties,
from_masterslave=True,
setting_properties=setting_properties,
check_frozen=check_frozen)
if isinstance(mastervalue, Exception):
if isinstance(mastervalue, PropertiesOptionError):
mastervalue.set_orig_opt(opt)
return mastervalue
masterlen = len(mastervalue)
master_is_meta = values._is_meta(master, masterp, force_permissive=force_permissive)
multi = values._get_multi(opt, path)
#self._master_is_meta = values._is_meta(master, masterp, force_permissive=force_permissive)
multi = list() # values._get_multi(opt, path)
if validate_properties:
props = context.cfgimpl_get_settings().validate_properties(opt, False,
check_frozen,
@ -748,68 +791,84 @@ class MasterSlaves(OptionDescription):
setting_properties=setting_properties)
if props:
return props
#FIXME shouldn't have index!!!
if index is None:
indexes = xrange(0, masterlen)
else:
indexes = [index]
for idx in indexes:
value = values._get_cached_value(opt, path, validate,
force_permissive,
trusted_cached_properties,
validate_properties,
with_meta=master_is_meta,
index=idx,
# not self_properties,
# depends to index
#self_properties=self_properties,
setting_properties=setting_properties,
masterlen=masterlen,
from_masterslave=True,
check_frozen=check_frozen)
value = values.get_cached_value(opt, path, validate,
force_permissive,
trusted_cached_properties,
validate_properties,
index=idx,
# not self_properties,
# depends to index
#self_properties=self_properties,
setting_properties=setting_properties,
from_masterslave=True,
check_frozen=check_frozen)
if isinstance(value, Exception):
if isinstance(value, PropertiesOptionError):
err = value
if index is None:
multi.append_properties_error(value)
multi.append(value)
else:
multi = value
else:
return value
elif index is None:
multi.append(value, setitem=False, force=True, validate=False,
force_permissive=force_permissive)
multi.append(value)
else:
multi = value
return multi
def validate(self, values, opt, index, path, setitem):
def validate(self,
values,
opt,
index,
path,
setitem):
if self.is_master(opt):
#for regen slave path
base_path = '.'.join(path.split('.')[:-1]) + '.'
for slave in self.getslaves(opt):
slave_path = base_path + slave.impl_getname()
slavelen = values._p_.get_max_length(slave_path)
self.validate_slave_length(index, slavelen, slave.impl_getname(), opt)
self.validate_slave_length(index,
slavelen,
slave.impl_getname(),
opt)
else:
val_len = self.get_length(values, opt, slave_path=path)
val_len = self.get_length(values)
if isinstance(val_len, Exception):
return val_len
self.validate_slave_length(val_len, index,
opt.impl_getname(), opt, setitem=setitem)
self.validate_slave_length(val_len,
index,
opt.impl_getname(),
opt,
setitem=setitem)
def get_length(self, values, opt, validate=True, slave_path=undefined,
slave_value=undefined, force_permissive=False, master=None,
masterp=None, setting_properties=undefined):
def get_length(self,
values,
validate=True,
force_permissive=False,
master=None,
masterp=None,
setting_properties=undefined):
"""get master len with slave option"""
if master is None:
master = self.getmaster(None)
if masterp is None:
masterp = master.impl_getpath(self._getcontext())
if slave_value is undefined:
slave_path = undefined
value = self.getitem(values, master, masterp, validate,
force_permissive, None, True, slave_path=slave_path,
slave_value=slave_value, setting_properties=setting_properties)
masterp = master.impl_getpath(values._getcontext())
value = self.getitem(values,
master,
masterp,
validate,
force_permissive,
None,
True,
setting_properties=setting_properties)
if isinstance(value, Exception):
return value
return len(value)
@ -843,10 +902,9 @@ class MasterSlaves(OptionDescription):
master = self.getmaster(opt)
masterp = master.impl_getpath(context)
mastervalue = values._get_cached_value(master, path=masterp,
force_permissive=force_permissive,
from_masterslave=True,
setting_properties=setting_properties)
mastervalue = values.get_cached_value(master, path=masterp,
force_permissive=force_permissive,
setting_properties=setting_properties)
if isinstance(mastervalue, Exception):
return mastervalue
masterlen = len(mastervalue)
@ -857,9 +915,15 @@ class MasterSlaves(OptionDescription):
else:
for slave in self.getslaves(master):
slave_path = slave.impl_getpath(context)
slavelen = values._p_.get_max_length(slave_path, None)
slavelen = values._p_.get_max_length(slave_path)
self.validate_slave_length(masterlen, slavelen, slave.impl_getname(), master)
def impl_validate_value(self, option, value, context):
if option.impl_is_master_slaves('master') and isinstance(value, list):
if len(value) < context._impl_length:
return ValueError(_('cannot reduce length of master "{}"'
'').format(option.impl_get_display_name()))
def _impl_getpaths(klass, include_groups, _currpath):
"""returns a list of all paths in klass, recursively

View File

@ -353,15 +353,25 @@ class Settings(object):
path = opt.impl_getpath(self._getcontext())
return self.getproperties(opt, path)
def getproperties(self, opt, path, setting_properties=undefined, index=None, obj=True):
def getproperties(self,
opt,
path,
setting_properties=undefined,
index=None,
obj=True):
"""get properties for a specified option
"""
properties = self._getproperties(opt, path, index=index,
properties = self._getproperties(opt,
path,
index=index,
setting_properties=setting_properties)
if obj:
return Property(self, properties, opt, path)
return properties
def getcontextproperties(self):
return self._getproperties()
def __setitem__(self, opt, value): # pragma: optional cover
raise ValueError(_('you should only append/remove properties'))
@ -377,9 +387,13 @@ class Settings(object):
self._p_.delproperties(_path)
self._getcontext().cfgimpl_reset_cache(opt=opt, path=_path, only=('settings', 'values'))
def _getproperties(self, opt=None, path=None,
setting_properties=undefined, read_write=True,
apply_requires=True, index=None):
def _getproperties(self,
opt=None,
path=None,
setting_properties=undefined,
read_write=True,
apply_requires=True,
index=None):
"""
"""
if opt is None:

View File

@ -67,7 +67,7 @@ class Values(Cache):
return vidx
# value
def setvalue(self, path, value, owner, index, session, commit):
def setvalue(self, path, value, owner, index, commit):
"""set value for a path
a specified value must be associated to an owner
"""
@ -137,7 +137,7 @@ class Values(Cache):
_resetvalue_index(3)
self._values = tuple(values)
def resetvalue(self, path, session, commit):
def resetvalue(self, path, commit):
"""remove value means delete value in storage
"""
def _resetvalue(nb):
@ -174,7 +174,7 @@ class Values(Cache):
return values
# owner
def setowner(self, path, owner, session, index=None):
def setowner(self, path, owner, index=None):
"""change owner for a path
"""
idx = self._values[0].index(path)
@ -188,14 +188,14 @@ class Values(Cache):
lst[3] = tuple(values[0])
self._values = tuple(lst)
def get_max_length(self, path, session):
def get_max_length(self, path):
if path in self._values[0]:
idx = self._values[0].index(path)
else:
return 0
return max(self._values[1][idx]) + 1
def getowner(self, path, default, session, index=None, only_default=False,
def getowner(self, path, default, index=None, only_default=False,
with_value=False):
"""get owner for a path
return: owner object
@ -271,11 +271,11 @@ class Values(Cache):
if raises:
raise ValueError(_("information's item not found {0}").format(key))
def exportation(self, session, fake=False):
def exportation(self, fake=False):
return self._values
def importation(self, export):
self._values = export
def delete_session(session_id, session):
def delete_session(session_id):
raise ValueError(_('a dictionary cannot be persistent'))

View File

@ -15,6 +15,12 @@
# You should have received a copy of the GNU Lesser General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
# ____________________________________________________________
FIXME = 0
def POUET(obj):
return(obj.__class__.__name__.lower())
DEBUG = False
#DEBUG = True
class Cache(object):
@ -29,17 +35,41 @@ class Cache(object):
"""add val in cache for a specified path
if slave, add index
"""
if DEBUG:
global FIXME
FIXME += 1
print('ca set cache', path, val, POUET(self), FIXME)
#if path is not None and (path.startswith('od.st.') or path.startswith('od.dod.')):
# raise Exception('mais ... mais ... mais')
#if FIXME == 111:
# raise Exception('rah')
self._cache.setdefault(path, {})[index] = (val, time)
def getcache(self, path, exp, index):
value, created = self._cache[path][index]
if created is None or exp <= created:
if DEBUG:
global FIXME
FIXME += 1
print('ca trouve dans le cache', path, value, POUET(self), FIXME)
#if path is not None and (path.startswith('od.st.') or path.startswith('od.dod.')):
# raise Exception('mais ... mais ... mais')
#if FIXME == 45:
# raise Exception('rah')
return True, value
return False, None # pragma: no cover
def delcache(self, path):
"""remove cache for a specified path
"""
if DEBUG:
global FIXME
FIXME += 1
print('ca del cache', path, POUET(self), FIXME)
#if path is not None and (path.startswith('od.st.') or path.startswith('od.dod.')):
# raise Exception('mais ... mais ... mais')
#if FIXME == 23:
# raise Exception('rah')
if path in self._cache:
del self._cache[path]
@ -48,6 +78,8 @@ class Cache(object):
:param path: the path's option
"""
if DEBUG:
print('ca cherche dans le cache', path, POUET(self))
return path in self._cache and index in self._cache[path]
def reset_expired_cache(self, exp):
@ -63,6 +95,8 @@ class Cache(object):
def reset_all_cache(self):
"empty the cache"
if DEBUG:
print('bzzzzzzzzzzzz delete tout le cache', POUET(self))
self._cache.clear()
def get_cached(self):

View File

@ -54,76 +54,129 @@ class Values(object):
raise ConfigError(_('the context does not exist anymore'))
return context
def _get_multi(self, opt, path):
return Multi([], self.context, opt, path)
def getdefaultvalue(self,
opt,
path,
index=None):
"""get default value:
- get meta config value or
- get calculated value or
- get default value
:param opt: the `option.Option()` object
:param path: path for `option.Option()` object
:type path: str
:param index: index of a multi/submulti
:type index: int
:returns: default value
"""
return self._getdefaultvalue(opt,
path,
index,
True,
self._getcontext())
def _getdefaultvalue(self, opt, path, with_meta, index, submulti_index, validate,
_orig_context=undefined):
if _orig_context is undefined:
_orig_context = self._getcontext()
def _getdefaultvalue(self,
opt,
path,
index,
validate,
_orig_context):
def _reset_cache():
# calculated value could be a new value, so reset cache
_orig_context.cfgimpl_reset_cache(opt=opt,
path=path,
only=('values', 'properties'))
#FIXME with_meta should be calculated here...
with_meta = True
if with_meta:
meta = self._getcontext().cfgimpl_get_meta()
if meta is not None:
value = meta.cfgimpl_get_values(
)._get_cached_value(opt, path, index=index, submulti_index=submulti_index,
from_masterslave=True, _orig_context=_orig_context)
# retrieved value from meta config
value = meta.cfgimpl_get_values().get_cached_value(opt,
path,
index=index,
_orig_context=_orig_context)
if isinstance(value, Exception):
# if properties error, return an other default value
if not isinstance(value, PropertiesOptionError): # pragma: no cover
# unexpected error, should not happened
raise value
else:
if isinstance(value, Multi):
new_value = []
for val in value:
if isinstance(val, SubMulti):
val = list(val)
new_value.append(val)
value = new_value
del new_value
return value
# if value has callback and is not set
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,
value = carry_out_calculation(opt,
context=_orig_context,
callback=callback,
callback_params=callback_params,
index=index, validate=validate)
_orig_context.cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties'))
index=index,
validate=validate)
if isinstance(value, list) and index is not None:
#if return a list and index is set, return value only if
#it's a submulti without submulti_index and without list of list
if opt.impl_is_submulti() and submulti_index is undefined and \
(len(value) == 0 or not isinstance(value[0], list)):
# if value is a list and index is set
if opt.impl_is_submulti() and (value == [] or not isinstance(value[0], list)):
# return value only if it's a submulti and not a list of list
_reset_cache()
return value
if not opt.impl_is_submulti() and len(value) > index:
if len(value) > index:
# return the value for specified index if found
_reset_cache()
return value[index]
else:
# there is no calculate value for this index,
# so return an other default value
elif isinstance(value, list):
# value is a list, but no index specified
_reset_cache()
if opt.impl_is_submulti() and (value == [] or not isinstance(value[0], list)):
# if submulti, return a list of value
return [value]
# otherwise just return the value
return value
# now try to get default value
elif index is not None:
# if not list but with index
_reset_cache()
if opt.impl_is_submulti():
# if submulti, return a list of value
return [value]
# otherwise just return the value
return value
else:
_reset_cache()
# not a list or index is None
if opt.impl_is_submulti():
# return a list of list for a submulti
return [[value]]
elif opt.impl_is_multi():
# return a list for a multi
return [value]
# not a list, return value
return value
# now try to get default value:
# - if opt is a submulti, return a list a list
# - if opt is a multi, return a list
# - default value
value = opt.impl_getdefault()
if opt.impl_is_multi() and index is not None:
if value == []:
value = opt.impl_getdefault_multi()
if submulti_index is undefined and opt.impl_is_submulti():
if value is None:
value = []
elif not isinstance(value, list):
value = [value]
# if index, must return good value for this index
if len(value) > index:
value = value[index]
else:
if len(value) > index:
value = value[index]
else:
value = opt.impl_getdefault_multi()
if submulti_index is undefined and opt.impl_is_submulti():
if value is None:
value = []
elif not isinstance(value, list):
value = [value]
if opt.impl_is_submulti() and not isinstance(value, list) and submulti_index is undefined:
value = [value]
# no value for this index, retrieve default multi value
# default_multi is already a list for submulti
value = opt.impl_getdefault_multi()
return value
def _getvalue(self, opt, path, self_properties, index, submulti_index,
with_meta, masterlen, session, validate, _orig_context):
def _getvalue(self,
opt,
path,
self_properties,
index,
validate,
_orig_context):
"""actually retrieves the value
:param opt: the `option.Option()` object
@ -136,8 +189,11 @@ class Values(object):
_index = None
else:
_index = index
owner, value = self._p_.getowner(path, owners.default, session, only_default=True,
index=_index, with_value=True)
owner, value = self._p_.getowner(path,
owners.default,
only_default=True,
index=_index,
with_value=True)
is_default = owner == owners.default
if not is_default and not force_default:
if index is not None and not opt.impl_is_master_slaves('slave'):
@ -147,8 +203,11 @@ class Values(object):
#so return default value
else:
return value
return self._getdefaultvalue(opt, path, with_meta, index,
submulti_index, validate, _orig_context)
return self._getdefaultvalue(opt,
path,
index,
validate,
_orig_context)
def get_modified_values(self):
return self._p_.get_modified_values()
@ -163,55 +222,129 @@ class Values(object):
path = opt.impl_getpath(self._getcontext())
return self._contains(path)
def _contains(self, path, session=None):
if session is None:
session = self._p_.getsession()
return self._p_.hasvalue(path, session)
def _contains(self, path):
return self._p_.hasvalue(path)
def __delitem__(self, opt):
"""overrides the builtins `del()` instructions"""
self.reset(opt)
def reset(self, opt, path=None, validate=True, _setting_properties=None, _commit=True,
def reset(self,
opt,
path,
setting_properties,
validate=True,
_commit=True,
force_permissive=False):
context = self._getcontext()
setting = context.cfgimpl_get_settings()
if path is None:
path = opt.impl_getpath(context)
if _setting_properties is None:
_setting_properties = setting._getproperties(read_write=False)
session = self._p_.getsession()
hasvalue = self._contains(path, session)
hasvalue = self._contains(path)
if validate and hasvalue and 'validator' in _setting_properties:
session = context.cfgimpl_get_values()._p_.getsession()
fake_context = context._gen_fake_values(session)
if validate and hasvalue and 'validator' in setting_properties:
fake_context = context._gen_fake_values()
fake_value = fake_context.cfgimpl_get_values()
fake_value.reset(opt, path, validate=False)
ret = fake_value._get_cached_value(opt, path,
setting_properties=_setting_properties,
check_frozen=True,
force_permissive=force_permissive)
fake_value.reset(opt,
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
if opt.impl_is_master_slaves('master'):
opt.impl_get_master_slaves().reset(opt, self, _setting_properties, _commit=_commit,
opt.impl_get_master_slaves().reset(opt,
self,
setting_properties,
_commit=_commit,
force_permissive=force_permissive)
if hasvalue:
if 'force_store_value' in setting._getproperties(opt=opt,
path=path,
setting_properties=_setting_properties,
setting_properties=setting_properties,
read_write=False,
apply_requires=False):
value = self._getdefaultvalue(opt, path, True, undefined, undefined, validate)
value = self._getdefaultvalue(opt,
path,
True,
undefined,
validate,
context)
if isinstance(value, Exception): # pragma: no cover
raise value
self._setvalue(opt, path, value, force_owner=owners.forced, commit=_commit)
self._setvalue(opt,
path,
value,
owners.forced,
None,
commit=_commit)
else:
self._p_.resetvalue(path, session, _commit)
context.cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties'))
self._p_.resetvalue(path,
_commit)
context.cfgimpl_reset_cache(opt=opt,
path=path,
only=('values', 'properties'))
def _isempty(self, opt, value, force_allow_empty_list=False, index=None):
def reset_slave(self,
opt,
path,
index,
setting_properties,
validate=True,
force_permissive=False):
context = self._getcontext()
if validate and 'validator' in setting_properties:
fake_context = context._gen_fake_values()
fake_value = fake_context.cfgimpl_get_values()
fake_value.reset_slave(opt,
path,
index,
setting_properties,
validate=False)
ret = fake_value.get_cached_value(opt,
path,
index=index,
setting_properties=setting_properties,
check_frozen=True,
force_permissive=force_permissive)
if isinstance(ret, Exception):
raise ret
self._p_.resetvalue_index(path, index)
def reset_master(self,
subconfig,
opt,
path,
index,
force_permissive,
setting_properties):
current_value = self.get_cached_value(opt,
path,
setting_properties=setting_properties,
check_frozen=True,
force_permissive=force_permissive)
current_value.pop(index)
ret = self.setitem(opt,
current_value,
path,
force_permissive=force_permissive,
not_raises=True,
index=None,
setting_properties=setting_properties,
_commit=True)
if ret:
return ret
subconfig.cfgimpl_get_description().pop(opt,
path,
self,
index)
def _isempty(self,
opt,
value,
force_allow_empty_list=False,
index=None):
"convenience method to know if an option is empty"
if value is undefined:
return False
@ -235,15 +368,21 @@ class Values(object):
def __getitem__(self, opt):
"enables us to use the pythonic dictionary-like access to values"
return self._get_cached_value(opt)
return self.get_cached_value(opt)
def _get_cached_value(self, opt, path=None, validate=True,
force_permissive=False, trusted_cached_properties=True,
validate_properties=True,
setting_properties=undefined, self_properties=undefined,
index=None, submulti_index=undefined, from_masterslave=False,
with_meta=True, masterlen=undefined, check_frozen=False,
session=None, display_warnings=True, _orig_context=undefined):
def get_cached_value(self,
opt,
path=None,
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):
context = self._getcontext()
settings = context.cfgimpl_get_settings()
if path is None:
@ -252,7 +391,8 @@ class Values(object):
if setting_properties is undefined:
setting_properties = settings._getproperties(read_write=False)
if self_properties is undefined:
self_properties = settings._getproperties(opt, path,
self_properties = settings._getproperties(opt,
path,
read_write=False,
setting_properties=setting_properties,
index=index)
@ -264,11 +404,14 @@ class Values(object):
if index:
value = value[index]
if is_cached:
if opt.impl_is_multi() and not isinstance(value, Multi) and index is None:
value = Multi(value, self.context, opt, path)
#if opt.impl_is_multi() and not isinstance(value, Multi) and index is None:
# value = Multi(value, self.context, opt, path)
if not trusted_cached_properties:
# revalidate properties (because of not default properties)
props = settings.validate_properties(opt, False, False, value=value,
props = settings.validate_properties(opt,
False,
False,
value=value,
path=path,
force_permissive=force_permissive,
setting_properties=setting_properties,
@ -277,38 +420,35 @@ class Values(object):
if props:
return props
return value
if session is None:
session = self._p_.getsession()
if not from_masterslave and opt.impl_is_master_slaves():
val = opt.impl_get_master_slaves().getitem(self, opt, path,
validate,
force_permissive,
trusted_cached_properties,
validate_properties,
session,
setting_properties=setting_properties,
index=index,
self_properties=self_properties,
check_frozen=check_frozen)
#if not from_masterslave and opt.impl_is_master_slaves():
# val = opt.impl_get_master_slaves().getitem(self, opt, path,
# validate,
# force_permissive,
# trusted_cached_properties,
# validate_properties,
# setting_properties=setting_properties,
# index=index,
# self_properties=self_properties,
# check_frozen=check_frozen)
#else:
if _orig_context is not undefined:
_context = _orig_context
else:
val = self._get_validated_value(opt, path, validate,
force_permissive,
validate_properties,
setting_properties,
self_properties,
with_meta=with_meta,
masterlen=masterlen,
index=index,
submulti_index=submulti_index,
check_frozen=check_frozen,
session=session,
display_warnings=display_warnings,
_orig_context=_orig_context)
_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)
if isinstance(val, Exception):
return val
# cache doesn't work with SubMulti yet
if not from_masterslave and index is None and not isinstance(val, SubMulti) and \
'cache' in setting_properties and \
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:
if 'expire' in setting_properties:
@ -318,14 +458,17 @@ class Values(object):
self._p_.setcache(path, val, ntime, None)
return val
def _get_validated_value(self, opt, path, validate, force_permissive,
validate_properties, setting_properties,
def _get_validated_value(self,
opt,
path,
validate,
force_permissive,
validate_properties,
setting_properties,
self_properties,
index=None, submulti_index=undefined,
with_meta=True,
masterlen=undefined,
index=None,
check_frozen=False,
session=None, display_warnings=True,
display_warnings=True,
_orig_context=undefined):
"""same has getitem but don't touch the cache
index is None for slave value, if value returned is not a list, just return []
@ -333,10 +476,12 @@ class Values(object):
context = self._getcontext()
setting = context.cfgimpl_get_settings()
config_error = None
if session is None:
session = self._p_.getsession()
value = self._getvalue(opt, path, self_properties, index, submulti_index,
with_meta, masterlen, session, validate, _orig_context)
value = self._getvalue(opt,
path,
self_properties,
index,
validate,
_orig_context)
if isinstance(value, Exception):
value_error = True
if isinstance(value, ConfigError):
@ -355,22 +500,11 @@ class Values(object):
raise value
else:
value_error = False
if opt.impl_is_multi():
if index is None:
value = Multi(value, self.context, opt, path)
elif opt.impl_is_submulti() and submulti_index is undefined:
value = SubMulti(value, self.context, opt, path,
index)
if validate:
if submulti_index is undefined:
force_submulti_index = None
else:
force_submulti_index = submulti_index
err = opt.impl_validate(value, context,
err = opt.impl_validate(value,
context,
'validator' in setting_properties,
force_index=index,
force_submulti_index=force_submulti_index,
display_error=True,
display_warnings=False,
setting_properties=setting_properties)
@ -385,7 +519,10 @@ class Values(object):
val_props = undefined
else:
val_props = value
props = setting.validate_properties(opt, False, check_frozen, value=val_props,
props = setting.validate_properties(opt,
False,
check_frozen,
value=val_props,
path=path,
force_permissive=force_permissive,
setting_properties=setting_properties,
@ -394,10 +531,10 @@ class Values(object):
if props:
return props
if not value_error and validate and display_warnings:
opt.impl_validate(value, context,
opt.impl_validate(value,
context,
'validator' in setting_properties,
force_index=index,
force_submulti_index=force_submulti_index,
display_error=False,
display_warnings=display_warnings,
setting_properties=setting_properties)
@ -405,122 +542,116 @@ class Values(object):
return config_error
return value
def __setitem__(self, opt, value):
raise ConfigError(_('you should only set value with config'))
def setitem(self,
opt,
value,
path,
force_permissive,
not_raises,
index,
setting_properties,
_commit):
def setitem(self, opt, value, path, force_permissive=False,
check_frozen=True, not_raises=False, index=None,
_setting_properties=undefined, _commit=True):
# check_frozen is, for example, used with "force_store_value"
# user didn't change value, so not write
# valid opt
context = self._getcontext()
if 'validator' in _setting_properties:
session = context.cfgimpl_get_values()._p_.getsession()
owner = context.cfgimpl_get_settings().getowner()
if 'validator' in setting_properties:
if opt._has_consistencies():
fake_context = context._gen_fake_values(session)
fake_values = fake_context.cfgimpl_get_values()
fake_values._setvalue(opt, path, value, index=index)
# set value to a fake config when option has dependency
# validation will be complet in this case (consistency, ...)
tested_context = context._gen_fake_values()
tested_values = tested_context.cfgimpl_get_values()
tested_values._setvalue(opt,
path,
value,
index=index,
owner=owner)
else:
fake_context = context
fake_values = self
props = fake_values.validate(opt, value, path,
check_frozen=check_frozen,
force_permissive=force_permissive,
setting_properties=_setting_properties,
session=session, not_raises=not_raises,
index=index, setitem=True)
if props and not_raises:
tested_context = context
tested_values = self
props = tested_values.validate_setitem(opt,
value,
path,
force_permissive,
setting_properties,
index)
if props:
if not not_raises:
raise props
return props
err = opt.impl_validate(value, fake_context, display_warnings=False, force_index=index,
setting_properties=_setting_properties)
if err:
if not_raises:
return err
raise err
opt.impl_validate(value, fake_context, display_error=False,
setting_properties=_setting_properties)
self._setvalue(opt, path, value, index=index, commit=_commit)
def _setvalue(self, opt, path, value, force_owner=undefined, index=None, commit=True):
self._setvalue(opt,
path,
value,
owner,
index=index,
commit=_commit)
def validate_setitem(self,
opt,
value,
path,
force_permissive,
setting_properties,
index):
context = self._getcontext()
context.cfgimpl_reset_cache(opt=opt, path=path, only=('values', 'properties'))
if force_owner is undefined:
owner = context.cfgimpl_get_settings().getowner()
else:
owner = force_owner
# in storage, value must not be a multi
if isinstance(value, Multi):
if not opt.impl_is_master_slaves('slave') or index is None:
value = list(value)
if opt.impl_is_submulti():
for idx, val in enumerate(value):
if isinstance(val, SubMulti):
value[idx] = list(val)
else:
value = value[index]
session = self._p_.getsession()
#FIXME pourquoi là et pas dans masterslaves ??
if opt.impl_is_master_slaves('slave'):
if index is not None:
self._p_.setvalue(path, value, owner, index, session, commit)
else:
self._p_.resetvalue(path, session, commit)
for idx, val in enumerate(value):
self._p_.setvalue(path, val, owner, idx, session, commit)
else:
self._p_.setvalue(path, value, owner, None, session, commit)
del(session)
def validate(self, opt, value, path, check_frozen=True, force_permissive=False,
setting_properties=undefined, valid_masterslave=True,
not_raises=False, session=None, index=None, setitem=False):
if valid_masterslave and opt.impl_is_master_slaves():
if session is None:
session = self._p_.getsession()
setitem = True
if opt.impl_is_master_slaves('master'):
masterlen = len(value)
slavelen = None
elif index is not None:
masterlen = None
slavelen = index
setitem = False
else:
masterlen = None
slavelen = len(value)
opt.impl_get_master_slaves().impl_validate(self._getcontext(), force_permissive,
setting_properties, masterlen=masterlen,
slavelen=slavelen, opt=opt, setitem=setitem)
#val = opt.impl_get_master_slaves().impl_validate(self, opt, len_value, path, session, setitem=setitem)
#if isinstance(val, Exception):
# return val
props = self._getcontext().cfgimpl_get_settings().validate_properties(opt,
False,
check_frozen,
value=value,
path=path,
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index)
# First validate properties with this value
props = context.cfgimpl_get_settings().validate_properties(opt,
False,
True,
value=value,
path=path,
force_permissive=force_permissive,
setting_properties=setting_properties,
index=index)
if props:
if not_raises:
return props
raise props
return props
# Value must be valid for option
err = opt.impl_validate(value,
context,
display_warnings=False,
force_index=index,
setting_properties=setting_properties)
if err:
return err
# No error found so emit warnings
opt.impl_validate(value,
context,
display_error=False,
force_index=index,
setting_properties=setting_properties)
def _is_meta(self, opt, path, session=None, force_permissive=False):
def _setvalue(self,
opt,
path,
value,
owner,
index=None,
commit=True):
self._getcontext().cfgimpl_reset_cache(opt=opt,
path=path,
only=('values', 'properties'))
if isinstance(value, list):
# copy
value = list(value)
self._p_.setvalue(path,
value,
owner,
index,
commit)
def _is_meta(self, opt, path, force_permissive=False):
context = self._getcontext()
if context.cfgimpl_get_meta() is None:
return False
setting = context.cfgimpl_get_settings()
self_properties = setting._getproperties(opt, path, read_write=False)
if session is None:
session = self._p_.getsession()
return self.is_default_owner(opt, path=path, validate_properties=True,
validate_meta=False, index=None,
force_permissive=force_permissive)
def getowner(self, opt, index=None, force_permissive=False, session=None):
def getowner(self, opt, index=None, force_permissive=False):
"""
retrieves the option's owner
@ -533,16 +664,22 @@ class Values(object):
not isinstance(opt, DynSymLinkOption):
opt = opt._impl_getopt()
path = opt.impl_getpath(self._getcontext())
return self._getowner(opt, path, session, index=index, force_permissive=force_permissive)
return self._getowner(opt,
path,
index=index,
force_permissive=force_permissive)
def _getowner(self, opt, path, session, validate_properties=True,
force_permissive=False, validate_meta=undefined,
self_properties=undefined, only_default=False,
def _getowner(self,
opt,
path,
validate_properties=True,
force_permissive=False,
validate_meta=undefined,
self_properties=undefined,
only_default=False,
index=None):
"""get owner of an option
"""
if session is None:
session = self._p_.getsession()
if not isinstance(opt, Option) and not isinstance(opt,
DynSymLinkOption):
raise ConfigError(_('owner only avalaible for an option'))
@ -553,28 +690,32 @@ class Values(object):
if 'frozen' in self_properties and 'force_default_on_freeze' in self_properties:
return owners.default
if validate_properties:
value = self._get_cached_value(opt, path=path, force_permissive=force_permissive,
self_properties=self_properties, session=session,
index=index)
value = self.get_cached_value(opt,
path=path,
force_permissive=force_permissive,
self_properties=self_properties,
index=index)
if isinstance(value, Exception):
raise value
owner = self._p_.getowner(path, owners.default, session, only_default=only_default, index=index)
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, session)
validate_meta = self._is_meta(master, masterp)
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, session,
owner = meta.cfgimpl_get_values()._getowner(opt,
path,
validate_properties=validate_properties,
force_permissive=force_permissive,
self_properties=self_properties,
only_default=only_default, index=index)
only_default=only_default,
index=index)
return owner
def setowner(self, opt, owner, index=None, force_permissive=False):
@ -588,7 +729,6 @@ class Values(object):
raise TypeError(_("invalid generic owner {0}").format(str(owner)))
path = opt.impl_getpath(self._getcontext())
session = self._p_.getsession()
props = self._getcontext().cfgimpl_get_settings().validate_properties(opt,
False,
True,
@ -597,10 +737,10 @@ class Values(object):
force_permissive=force_permissive)
if props:
raise props
if not self._p_.hasvalue(path, session):
if not self._p_.hasvalue(path):
raise ConfigError(_('no value for {0} cannot change owner to {1}'
'').format(path, owner))
self._p_.setowner(path, owner, session, index=index)
self._p_.setowner(path, owner, index=index)
def is_default_owner(self, opt, path=None, validate_properties=True,
validate_meta=True, index=None,
@ -612,19 +752,30 @@ class Values(object):
"""
if path is None:
path = opt.impl_getpath(self._getcontext())
return self._is_default_owner(opt, path, session=None,
return self._is_default_owner(opt,
path,
validate_properties=validate_properties,
validate_meta=validate_meta, index=index,
validate_meta=validate_meta,
index=index,
force_permissive=force_permissive)
def _is_default_owner(self, opt, path, session, validate_properties=True,
validate_meta=True, self_properties=undefined,
index=None, force_permissive=False):
d = self._getowner(opt, path, session, validate_properties=validate_properties,
validate_meta=validate_meta,
self_properties=self_properties, only_default=True,
index=index, force_permissive=force_permissive)
return d == owners.default
def _is_default_owner(self,
opt,
path,
validate_properties=True,
validate_meta=True,
self_properties=undefined,
index=None,
force_permissive=False):
owner = self._getowner(opt,
path,
validate_properties=validate_properties,
validate_meta=validate_meta,
self_properties=self_properties,
only_default=True,
index=index,
force_permissive=force_permissive)
return owner == owners.default
# information
def set_information(self, key, value):
@ -688,13 +839,13 @@ class Values(object):
read_write=False,
setting_properties=setting_properties)
if 'mandatory' in self_properties or 'empty' in self_properties:
err = self._get_cached_value(opt, path=path,
trusted_cached_properties=False,
force_permissive=True,
setting_properties=setting_properties,
self_properties=self_properties,
validate=True,
display_warnings=False)
err = self.get_cached_value(opt, path=path,
trusted_cached_properties=False,
force_permissive=True,
setting_properties=setting_properties,
self_properties=self_properties,
validate=True,
display_warnings=False)
if opt.impl_is_master_slaves('slave') and isinstance(err, list):
for val in err:
ret = _is_properties_option(val, path)
@ -723,277 +874,3 @@ class Values(object):
err = context.getattr(path, returns_raise=True)
if isinstance(err, Exception) and not isinstance(err, PropertiesOptionError): # pragma: no cover
raise err
# ____________________________________________________________
# multi types
class Multi(list):
"""multi options values container
that support item notation for the values of multi options"""
__slots__ = ('opt', 'path', 'context', '__weakref__')
def __init__(self, value, context, opt, path):
"""
:param value: the Multi wraps a list value
:param context: the home config that has the values
:param opt: the option object that have this Multi value
:param path: path of the option
"""
if value is None:
value = []
if not opt.impl_is_submulti() and isinstance(value, Multi):
raise ValueError(_('{0} is already a Multi ').format(
opt.impl_getname()))
self.opt = opt
self.path = path
if not isinstance(context, weakref.ReferenceType):
raise ValueError('context must be a Weakref')
self.context = context
if not isinstance(value, list):
if not '_index' in self.__slots__ and opt.impl_is_submulti():
value = [[value]]
else:
value = [value]
elif value != [] and not '_index' in self.__slots__ and \
opt.impl_is_submulti() and not isinstance(value[0], list):
value = [value]
super(Multi, self).__init__(value)
if opt.impl_is_submulti():
if not '_index' in self.__slots__:
for idx, val in enumerate(self):
if not isinstance(val, SubMulti):
super(Multi, self).__setitem__(idx, SubMulti(val,
context,
opt, path,
idx))
self[idx].refmulti = weakref.ref(self)
def _getcontext(self):
"""context could be None, we need to test it
context is None only if all reference to `Config` object is deleted
(for example we delete a `Config` and we manipulate a reference to
old `SubConfig`, `Values`, `Multi` or `Settings`)
"""
context = self.context()
if context is None:
raise ConfigError(_('the context does not exist anymore'))
return context
def __setitem__(self, index, value):
self._setitem(index, value)
def _setitem(self, index, value, validate=True):
context = self._getcontext()
setting = context.cfgimpl_get_settings()
setting_properties = setting._getproperties(read_write=False)
if index < 0:
index = self.__len__() + index
if 'validator' in setting_properties and validate:
session = context.cfgimpl_get_values()._p_.getsession()
fake_context = context._gen_fake_values(session)
fake_multi = Multi(list(self), weakref.ref(fake_context), self.opt, self.path)
fake_multi._setitem(index, value, validate=False)
self._validate(value, fake_context, index, True)
#assume not checking mandatory property
super(Multi, self).__setitem__(index, value)
self._store(index=index)
#def __repr__(self, *args, **kwargs):
# return super(Multi, self).__repr__(*args, **kwargs)
def __getitem__(self, index):
value = super(Multi, self).__getitem__(index)
if isinstance(value, PropertiesOptionError):
raise value
return value
def __delitem__(self, index):
return self.pop(index)
def _getdefaultvalue(self, index):
values = self._getcontext().cfgimpl_get_values()
value = values._getdefaultvalue(self.opt, self.path, True, index,
undefined, True)
if self.opt.impl_is_submulti():
value = SubMulti(value, self.context, self.opt, self.path, index)
return value
def append(self, value=undefined, force=False, setitem=True, validate=True,
force_permissive=False):
"""the list value can be updated (appened)
only if the option is a master
"""
if not force and self.opt.impl_is_master_slaves('slave'):
raise SlaveError(_("cannot append a value on a multi option {0}"
" which is a slave").format(self.opt.impl_getname()))
index = self.__len__()
if value is undefined:
value = self._getdefaultvalue(index)
if validate and value not in [None, undefined]:
context = self._getcontext()
setting = context.cfgimpl_get_settings()
setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties:
session = context.cfgimpl_get_values()._p_.getsession()
fake_context = context._gen_fake_values(session)
fake_multi = Multi(list(self), weakref.ref(fake_context), self.opt, self.path)
fake_multi.append(value, validate=False, force=True,
setitem=setitem)
self._validate(value, fake_context, index, True)
if not '_index' in self.__slots__ and self.opt.impl_is_submulti():
if not isinstance(value, SubMulti):
value = SubMulti(value, self.context, self.opt, self.path, index)
value.refmulti = weakref.ref(self)
super(Multi, self).append(value)
if setitem:
self._store(force=force)
def append_properties_error(self, err):
super(Multi, self).append(err)
def sort(self, cmp=None, key=None, reverse=False):
if self.opt.impl_is_master_slaves():
raise SlaveError(_("cannot sort multi option {0} if master or slave"
"").format(self.opt.impl_getname()))
if sys.version_info[0] >= 3: # pragma: no cover
if cmp is not None:
raise ValueError(_('cmp is not permitted in python v3 or '
'greater'))
super(Multi, self).sort(key=key, reverse=reverse)
else:
super(Multi, self).sort(cmp=cmp, key=key, reverse=reverse)
self._store()
def reverse(self):
if self.opt.impl_is_master_slaves():
raise SlaveError(_("cannot reverse multi option {0} if master or "
"slave").format(self.opt.impl_getname()))
super(Multi, self).reverse()
self._store()
def insert(self, index, value, validate=True):
if self.opt.impl_is_master_slaves():
raise SlaveError(_("cannot insert multi option {0} if master or "
"slave").format(self.opt.impl_getname()))
context = self._getcontext()
setting = setting = context.cfgimpl_get_settings()
setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties and validate and value is not None:
session = context.cfgimpl_get_values()._p_.getsession()
fake_context = context._gen_fake_values(session)
fake_multi = Multi(list(self), weakref.ref(fake_context), self.opt, self.path)
fake_multi.insert(index, value, validate=False)
self._validate(value, fake_context, index, True)
super(Multi, self).insert(index, value)
self._store()
def extend(self, iterable, validate=True):
if self.opt.impl_is_master_slaves():
raise SlaveError(_("cannot extend multi option {0} if master or "
"slave").format(self.opt.impl_getname()))
index = getattr(self, '_index', None)
context = self._getcontext()
setting = context.cfgimpl_get_settings()
setting_properties = setting._getproperties(read_write=False)
if 'validator' in setting_properties and validate:
session = context.cfgimpl_get_values()._p_.getsession()
fake_context = context._gen_fake_values(session)
fake_multi = Multi(list(self), weakref.ref(fake_context), self.opt, self.path)
if index is None:
fake_multi.extend(iterable, validate=False)
self._validate(fake_multi, fake_context, index)
else:
fake_multi[index].extend(iterable, validate=False)
self._validate(fake_multi[index], fake_context, index)
super(Multi, self).extend(iterable)
self._store()
def _validate(self, value, fake_context, force_index, submulti=False):
err = self.opt.impl_validate(value, context=fake_context,
force_index=force_index,
multi=self)
if err:
raise err
def pop(self, index, force=False):
"""the list value can be updated (poped)
only if the option is a master
:param index: remove item a index
:type index: int
:param force: force pop item (without check master/slave)
:type force: boolean
:returns: item at index
"""
context = self._getcontext()
if not force:
if self.opt.impl_is_master_slaves('slave'):
raise SlaveError(_("cannot pop a value on a multi option {0}"
" which is a slave").format(self.opt.impl_getname()))
if self.opt.impl_is_master_slaves('master'):
self.opt.impl_get_master_slaves().pop(self.opt,
context.cfgimpl_get_values(), index)
#set value without valid properties
ret = super(Multi, self).pop(index)
self._store(force=force)
return ret
def remove(self, value):
idx = self.index(value)
return self.pop(idx)
def _store(self, force=False, index=None):
values = self._getcontext().cfgimpl_get_values()
if not force:
#FIXME could get properties an pass it
values.validate(self.opt, self, self.path, valid_masterslave=False)
values._setvalue(self.opt, self.path, self, index=index)
class SubMulti(Multi):
__slots__ = ('_index', 'refmulti')
def __init__(self, value, context, opt, path, index):
"""
:param index: index (only for slave with submulti)
:type index: `int`
"""
self._index = index
super(SubMulti, self).__init__(value, context, opt, path)
def append(self, value=undefined):
super(SubMulti, self).append(value, force=True)
def pop(self, index):
return super(SubMulti, self).pop(index, force=True)
def __setitem__(self, index, value):
self._setitem(index, value)
def _store(self, force=False, index=None):
#force is unused here
values = self._getcontext().cfgimpl_get_values()
values.validate(self.opt, self, self.path, valid_masterslave=False)
multi = self.refmulti()
if multi is None:
multi = values._get_cached_value(self.opt, path=self.path)
multi[self._index] = self
values._setvalue(self.opt, self.path, multi)
def _validate(self, value, fake_context, force_index, submulti=False):
if value is not None:
if submulti is False:
super(SubMulti, self)._validate(value, fake_context,
force_index, submulti)
else:
err = self.opt.impl_validate(value, context=fake_context,
force_index=self._index,
force_submulti_index=force_index,
multi=self)
if err:
raise err
def _getdefaultvalue(self, index):
values = self._getcontext().cfgimpl_get_values()
return values._getdefaultvalue(self.opt, self.path, True, index,
self._index, True)