Merge branch 'master' into orm
Conflicts: test/test_dereference.py test/test_state.py tiramisu/config.py tiramisu/value.py
This commit is contained in:
@ -152,7 +152,10 @@ def carry_out_calculation(option, config, callback, callback_params,
|
||||
opt)
|
||||
# get value
|
||||
try:
|
||||
value = config._getattr(path, force_permissive=True)
|
||||
value = config._getattr(path, force_permissive=True, validate=False)
|
||||
# convert to list, not modifie this multi
|
||||
if value.__class__.__name__ == 'Multi':
|
||||
value = list(value)
|
||||
except PropertiesOptionError as err:
|
||||
if force_permissive:
|
||||
continue
|
||||
|
@ -48,7 +48,7 @@ class SubConfig(object):
|
||||
:type subpath: `str` with the path name
|
||||
"""
|
||||
# main option description
|
||||
if not isinstance(descr, OptionDescription):
|
||||
if descr is not None and not isinstance(descr, OptionDescription):
|
||||
raise TypeError(_('descr must be an optiondescription, not {0}'
|
||||
).format(type(descr)))
|
||||
self._impl_descr = descr
|
||||
@ -172,7 +172,7 @@ class SubConfig(object):
|
||||
def cfgimpl_get_description(self):
|
||||
if self._impl_descr is None:
|
||||
raise ConfigError(_('no option description found for this config'
|
||||
' (may be metaconfig without meta)'))
|
||||
' (may be GroupConfig)'))
|
||||
else:
|
||||
return self._impl_descr
|
||||
|
||||
@ -459,9 +459,9 @@ class SubConfig(object):
|
||||
return context_descr.impl_get_path_by_opt(descr)
|
||||
|
||||
|
||||
class CommonConfig(SubConfig):
|
||||
"abstract base class for the Config and the MetaConfig"
|
||||
__slots__ = ('_impl_values', '_impl_settings', '_impl_meta')
|
||||
class _CommonConfig(SubConfig):
|
||||
"abstract base class for the Config, GroupConfig and the MetaConfig"
|
||||
__slots__ = ('_impl_values', '_impl_settings', '_impl_meta', '_impl_test')
|
||||
|
||||
def _impl_build_all_caches(self):
|
||||
if not self.cfgimpl_get_description().impl_already_build_caches():
|
||||
@ -503,7 +503,8 @@ class CommonConfig(SubConfig):
|
||||
return None
|
||||
|
||||
def cfgimpl_get_meta(self):
|
||||
return self._impl_meta
|
||||
if self._impl_meta is not None:
|
||||
return self._impl_meta()
|
||||
|
||||
# information
|
||||
def impl_set_information(self, key, value):
|
||||
@ -521,42 +522,15 @@ class CommonConfig(SubConfig):
|
||||
"""
|
||||
return self._impl_values.get_information(key, default)
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
class Config(CommonConfig):
|
||||
"main configuration management entry"
|
||||
__slots__ = ('__weakref__', '_impl_test')
|
||||
|
||||
def __init__(self, descr, session_id=None, persistent=False):
|
||||
""" Configuration option management master class
|
||||
|
||||
:param descr: describes the configuration schema
|
||||
:type descr: an instance of ``option.OptionDescription``
|
||||
:param context: the current root config
|
||||
:type context: `Config`
|
||||
:param session_id: session ID is import with persistent Config to
|
||||
retrieve good session
|
||||
:type session_id: `str`
|
||||
:param persistent: if persistent, don't delete storage when leaving
|
||||
:type persistent: `boolean`
|
||||
"""
|
||||
settings, values = get_storages(self, session_id, persistent)
|
||||
self._impl_settings = Settings(self, settings)
|
||||
self._impl_values = Values(self, values)
|
||||
super(Config, self).__init__(descr, weakref.ref(self))
|
||||
self._impl_build_all_caches()
|
||||
self._impl_meta = None
|
||||
#undocumented option used only in test script
|
||||
self._impl_test = False
|
||||
|
||||
# ----- state
|
||||
def __getstate__(self):
|
||||
if self._impl_meta is not None:
|
||||
raise ConfigError('cannot serialize Config with meta')
|
||||
raise ConfigError('cannot serialize Config with MetaConfig')
|
||||
slots = set()
|
||||
for subclass in self.__class__.__mro__:
|
||||
if subclass is not object:
|
||||
slots.update(subclass.__slots__)
|
||||
slots -= frozenset(['_impl_context', '__weakref__'])
|
||||
slots -= frozenset(['_impl_context', '_impl_meta', '__weakref__'])
|
||||
state = {}
|
||||
for slot in slots:
|
||||
try:
|
||||
@ -583,6 +557,35 @@ class Config(CommonConfig):
|
||||
storage = get_storage(test=self._impl_test, **state['_storage'])
|
||||
self._impl_values._impl_setstate(storage)
|
||||
self._impl_settings._impl_setstate(storage)
|
||||
self._impl_meta = None
|
||||
|
||||
|
||||
# ____________________________________________________________
|
||||
class Config(_CommonConfig):
|
||||
"main configuration management entry"
|
||||
__slots__ = ('__weakref__', '_impl_test')
|
||||
|
||||
def __init__(self, descr, session_id=None, persistent=False):
|
||||
""" Configuration option management master class
|
||||
|
||||
:param descr: describes the configuration schema
|
||||
:type descr: an instance of ``option.OptionDescription``
|
||||
:param context: the current root config
|
||||
:type context: `Config`
|
||||
:param session_id: session ID is import with persistent Config to
|
||||
retrieve good session
|
||||
:type session_id: `str`
|
||||
:param persistent: if persistent, don't delete storage when leaving
|
||||
:type persistent: `boolean`
|
||||
"""
|
||||
settings, values = get_storages(self, session_id, persistent)
|
||||
self._impl_settings = Settings(self, settings)
|
||||
self._impl_values = Values(self, values)
|
||||
super(Config, self).__init__(descr, weakref.ref(self))
|
||||
self._impl_build_all_caches()
|
||||
self._impl_meta = None
|
||||
#undocumented option used only in test script
|
||||
self._impl_test = False
|
||||
|
||||
def cfgimpl_reset_cache(self,
|
||||
only_expired=False,
|
||||
@ -593,99 +596,119 @@ class Config(CommonConfig):
|
||||
self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
|
||||
|
||||
|
||||
#class MetaConfig(CommonConfig):
|
||||
# __slots__ = ('_impl_children',)
|
||||
class GroupConfig(_CommonConfig):
|
||||
__slots__ = ('_impl_children', '__weakref__')
|
||||
|
||||
# def __init__(self, children, meta=True, session_id=None, persistent=False):
|
||||
# if not isinstance(children, list):
|
||||
# raise ValueError(_("metaconfig's children must be a list"))
|
||||
# self._impl_descr = None
|
||||
# self._impl_path = None
|
||||
# if meta:
|
||||
# for child in children:
|
||||
# if not isinstance(child, CommonConfig):
|
||||
# raise TypeError(_("metaconfig's children "
|
||||
# "must be config, not {0}"
|
||||
# ).format(type(child)))
|
||||
# if self._impl_descr is None:
|
||||
# self._impl_descr = child.cfgimpl_get_description()
|
||||
# elif not self._impl_descr is child.cfgimpl_get_description():
|
||||
# raise ValueError(_('all config in metaconfig must '
|
||||
# 'have the same optiondescription'))
|
||||
# if child.cfgimpl_get_meta() is not None:
|
||||
# raise ValueError(_("child has already a metaconfig's"))
|
||||
# child._impl_meta = self
|
||||
def __init__(self, children, session_id=None, persistent=False,
|
||||
_descr=None):
|
||||
if not isinstance(children, list):
|
||||
raise ValueError(_("metaconfig's children must be a list"))
|
||||
self._impl_children = children
|
||||
settings, values = get_storages(self, session_id, persistent)
|
||||
self._impl_settings = Settings(self, settings)
|
||||
self._impl_values = Values(self, values)
|
||||
super(GroupConfig, self).__init__(_descr, weakref.ref(self))
|
||||
self._impl_meta = None
|
||||
#undocumented option used only in test script
|
||||
self._impl_test = False
|
||||
|
||||
# self._impl_children = children
|
||||
# settings, values = get_storages(self, session_id, persistent)
|
||||
# self._impl_settings = Settings(self, settings)
|
||||
# self._impl_values = Values(self, values)
|
||||
# self._impl_meta = None
|
||||
def cfgimpl_get_children(self):
|
||||
return self._impl_children
|
||||
|
||||
# def cfgimpl_get_children(self):
|
||||
# return self._impl_children
|
||||
#def cfgimpl_get_context(self):
|
||||
# "a meta config is a config which has a setting, that is itself"
|
||||
# return self
|
||||
#
|
||||
def cfgimpl_reset_cache(self,
|
||||
only_expired=False,
|
||||
only=('values', 'settings')):
|
||||
if 'values' in only:
|
||||
self.cfgimpl_get_values().reset_cache(only_expired=only_expired)
|
||||
if 'settings' in only:
|
||||
self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
|
||||
for child in self._impl_children:
|
||||
child.cfgimpl_reset_cache(only_expired=only_expired, only=only)
|
||||
|
||||
# def cfgimpl_get_context(self):
|
||||
# "a meta config is a config wich has a setting, that is itself"
|
||||
# return self
|
||||
def setattrs(self, path, value):
|
||||
"""Setattr not in current GroupConfig, but in each children
|
||||
"""
|
||||
for child in self._impl_children:
|
||||
try:
|
||||
if not isinstance(child, GroupConfig):
|
||||
setattr(child, path, value)
|
||||
else:
|
||||
child.setattrs(path, value)
|
||||
except PropertiesOptionError:
|
||||
pass
|
||||
|
||||
# def cfgimpl_reset_cache(self,
|
||||
# only_expired=False,
|
||||
# only=('values', 'settings')):
|
||||
# if 'values' in only:
|
||||
# self.cfgimpl_get_values().reset_cache(only_expired=only_expired)
|
||||
# if 'settings' in only:
|
||||
# self.cfgimpl_get_settings().reset_cache(only_expired=only_expired)
|
||||
# for child in self._impl_children:
|
||||
# child.cfgimpl_reset_cache(only_expired=only_expired, only=only)
|
||||
def find_firsts(self, byname=None, bypath=None, byvalue=None,
|
||||
type_='path', display_error=True):
|
||||
"""Find first not in current GroupConfig, but in each children
|
||||
"""
|
||||
ret = []
|
||||
#if MetaConfig, all children have same OptionDescription as context
|
||||
#so search only one time for all children
|
||||
try:
|
||||
if bypath is None and byname is not None and \
|
||||
isinstance(self, MetaConfig):
|
||||
bypath = self._find(bytype=None, byvalue=None, byname=byname,
|
||||
first=True, type_='path',
|
||||
check_properties=False,
|
||||
display_error=display_error)
|
||||
byname = None
|
||||
except AttributeError:
|
||||
pass
|
||||
for child in self._impl_children:
|
||||
try:
|
||||
if not isinstance(child, MetaConfig):
|
||||
if bypath is not None:
|
||||
#if byvalue is None, try if not raise
|
||||
value = getattr(child, bypath)
|
||||
if byvalue is not None:
|
||||
if isinstance(value, Multi):
|
||||
if byvalue in value:
|
||||
ret.append(child)
|
||||
else:
|
||||
if value == byvalue:
|
||||
ret.append(child)
|
||||
else:
|
||||
ret.append(child)
|
||||
else:
|
||||
ret.append(child.find_first(byname=byname,
|
||||
byvalue=byvalue,
|
||||
type_=type_,
|
||||
display_error=False))
|
||||
else:
|
||||
ret.extend(child.find_firsts(byname=byname,
|
||||
bypath=bypath,
|
||||
byvalue=byvalue,
|
||||
type_=type_,
|
||||
display_error=False))
|
||||
except AttributeError:
|
||||
pass
|
||||
return self._find_return_results(ret, display_error)
|
||||
|
||||
# def set_contexts(self, path, value):
|
||||
# for child in self._impl_children:
|
||||
# try:
|
||||
# if not isinstance(child, MetaConfig):
|
||||
# setattr(child, path, value)
|
||||
# else:
|
||||
# child.set_contexts(path, value)
|
||||
# except PropertiesOptionError:
|
||||
# pass
|
||||
|
||||
# def find_first_contexts(self, byname=None, bypath=None, byvalue=None,
|
||||
# type_='path', display_error=True):
|
||||
# ret = []
|
||||
# try:
|
||||
# if bypath is None and byname is not None and \
|
||||
# self.cfgimpl_get_description() is not None:
|
||||
# bypath = self._find(bytype=None, byvalue=None, byname=byname,
|
||||
# first=True, type_='path',
|
||||
# check_properties=False,
|
||||
# display_error=display_error)
|
||||
# except ConfigError:
|
||||
# pass
|
||||
# for child in self._impl_children:
|
||||
# try:
|
||||
# if not isinstance(child, MetaConfig):
|
||||
# if bypath is not None:
|
||||
# if byvalue is not None:
|
||||
# if getattr(child, bypath) == byvalue:
|
||||
# ret.append(child)
|
||||
# else:
|
||||
# #not raise
|
||||
# getattr(child, bypath)
|
||||
# ret.append(child)
|
||||
# else:
|
||||
# ret.append(child.find_first(byname=byname,
|
||||
# byvalue=byvalue,
|
||||
# type_=type_,
|
||||
# display_error=False))
|
||||
# else:
|
||||
# ret.extend(child.find_first_contexts(byname=byname,
|
||||
# bypath=bypath,
|
||||
# byvalue=byvalue,
|
||||
# type_=type_,
|
||||
# display_error=False))
|
||||
# except AttributeError:
|
||||
# pass
|
||||
# return self._find_return_results(ret, display_error)
|
||||
class MetaConfig(GroupConfig):
|
||||
__slots__ = tuple()
|
||||
|
||||
def __init__(self, children, session_id=None, persistent=False):
|
||||
descr = None
|
||||
for child in children:
|
||||
if not isinstance(child, _CommonConfig):
|
||||
raise TypeError(_("metaconfig's children "
|
||||
"should be config, not {0}"
|
||||
).format(type(child)))
|
||||
if child.cfgimpl_get_meta() is not None:
|
||||
raise ValueError(_("child has already a metaconfig's"))
|
||||
if descr is None:
|
||||
descr = child.cfgimpl_get_description()
|
||||
elif not descr is child.cfgimpl_get_description():
|
||||
raise ValueError(_('all config in metaconfig must '
|
||||
'have the same optiondescription'))
|
||||
child._impl_meta = weakref.ref(self)
|
||||
|
||||
super(MetaConfig, self).__init__(children, session_id, persistent, descr)
|
||||
|
||||
|
||||
def mandatory_warnings(config):
|
||||
|
@ -73,7 +73,7 @@ class Values(object):
|
||||
else:
|
||||
return value
|
||||
|
||||
def _getvalue(self, opt, path, validate=True):
|
||||
def _getvalue(self, opt, path):
|
||||
"""actually retrieves the value
|
||||
|
||||
:param opt: the `option.Option()` object
|
||||
@ -82,14 +82,9 @@ class Values(object):
|
||||
if not self._p_.hasvalue(path):
|
||||
# if there is no value
|
||||
value = self._getdefault(opt)
|
||||
if opt.impl_is_multi():
|
||||
value = Multi(value, self.context, opt, path, validate)
|
||||
else:
|
||||
# if there is a value
|
||||
value = self._p_.getvalue(path)
|
||||
if opt.impl_is_multi() and not isinstance(value, Multi):
|
||||
# load value so don't need to validate if is not a Multi
|
||||
value = Multi(value, self.context, opt, path, validate=False)
|
||||
return value
|
||||
|
||||
def get_modified_values(self):
|
||||
@ -198,7 +193,7 @@ class Values(object):
|
||||
# ConfigError if properties did not raise.
|
||||
config_error = None
|
||||
force_permissives = None
|
||||
# if value is callback and is not set
|
||||
# if value has callback and is not set
|
||||
# or frozen with force_default_on_freeze
|
||||
if opt.impl_has_callback() and (
|
||||
self._is_default_owner(path) or
|
||||
@ -208,7 +203,7 @@ class Values(object):
|
||||
if (opt.impl_is_multi() and
|
||||
opt.impl_get_multitype() == multitypes.slave):
|
||||
masterp = self._get_opt_path(opt.impl_get_master_slaves())
|
||||
mastervalue = getattr(context, masterp)
|
||||
mastervalue = context._getattr(masterp, validate=validate)
|
||||
lenmaster = len(mastervalue)
|
||||
if lenmaster == 0:
|
||||
value = []
|
||||
@ -240,7 +235,10 @@ class Values(object):
|
||||
if opt.impl_is_multi():
|
||||
value = Multi(value, self.context, opt, path, validate)
|
||||
else:
|
||||
value = self._getvalue(opt, path, validate)
|
||||
value = self._getvalue(opt, path)
|
||||
if opt.impl_is_multi():
|
||||
# load value so don't need to validate if is not a Multi
|
||||
value = Multi(value, self.context, opt, path, validate=validate)
|
||||
if config_error is None and validate:
|
||||
opt.impl_validate(value, context, 'validator' in setting)
|
||||
if config_error is None and self._is_default_owner(path) and \
|
||||
@ -266,10 +264,27 @@ class Values(object):
|
||||
context = self._getcontext()
|
||||
opt.impl_validate(value, context,
|
||||
'validator' in context.cfgimpl_get_settings())
|
||||
if opt.impl_is_multi() and not isinstance(value, Multi):
|
||||
if opt.impl_is_multi():
|
||||
value = Multi(value, self.context, opt, path, setitem=True)
|
||||
# Save old value
|
||||
if opt.impl_get_multitype() == multitypes.master and \
|
||||
self._p_.hasvalue(path):
|
||||
old_value = self._p_.getvalue(path)
|
||||
old_owner = self._p_.getowner(path, None)
|
||||
else:
|
||||
old_value = undefined
|
||||
old_owner = undefined
|
||||
self._setvalue(opt, path, value, force_permissive=force_permissive,
|
||||
is_write=is_write)
|
||||
if opt.impl_is_multi() and opt.impl_get_multitype() == multitypes.master:
|
||||
try:
|
||||
value._valid_master()
|
||||
except Exception, err:
|
||||
if old_value is not undefined:
|
||||
self._p_.setvalue(path, old_value, old_owner)
|
||||
else:
|
||||
self._p_.resetvalue(path)
|
||||
raise err
|
||||
|
||||
def _setvalue(self, opt, path, value, force_permissive=False,
|
||||
force_properties=None,
|
||||
@ -283,6 +298,8 @@ class Values(object):
|
||||
force_permissive=force_permissive,
|
||||
force_properties=force_properties)
|
||||
owner = context.cfgimpl_get_settings().getowner()
|
||||
if isinstance(value, Multi):
|
||||
value = list(value)
|
||||
self._p_.setvalue(path, value, owner)
|
||||
|
||||
def getowner(self, opt):
|
||||
@ -403,6 +420,8 @@ class Multi(list):
|
||||
:param opt: the option object that have this Multi value
|
||||
:param setitem: only if set a value
|
||||
"""
|
||||
if isinstance(value, Multi):
|
||||
raise ValueError(_('{0} is already a Multi ').format(opt._name))
|
||||
self.opt = opt
|
||||
self.path = path
|
||||
if not isinstance(context, weakref.ReferenceType):
|
||||
@ -412,8 +431,9 @@ class Multi(list):
|
||||
value = [value]
|
||||
if validate and self.opt.impl_get_multitype() == multitypes.slave:
|
||||
value = self._valid_slave(value, setitem)
|
||||
elif validate and self.opt.impl_get_multitype() == multitypes.master:
|
||||
self._valid_master(value)
|
||||
elif not setitem and validate and \
|
||||
self.opt.impl_get_multitype() == multitypes.master:
|
||||
self._valid_master()
|
||||
super(Multi, self).__init__(value)
|
||||
|
||||
def _getcontext(self):
|
||||
@ -433,12 +453,10 @@ class Multi(list):
|
||||
values = context.cfgimpl_get_values()
|
||||
masterp = context.cfgimpl_get_description().impl_get_path_by_opt(
|
||||
self.opt.impl_get_master_slaves())
|
||||
mastervalue = getattr(context, masterp)
|
||||
mastervalue = context._getattr(masterp, validate=False)
|
||||
masterlen = len(mastervalue)
|
||||
valuelen = len(value)
|
||||
is_default_owner = not values._is_default_owner(self.path) or setitem
|
||||
if valuelen > masterlen or (valuelen < masterlen and
|
||||
is_default_owner):
|
||||
if valuelen > masterlen or (valuelen < masterlen and setitem):
|
||||
raise SlaveError(_("invalid len for the slave: {0}"
|
||||
" which has {1} as master").format(
|
||||
self.opt.impl_getname(), masterp))
|
||||
@ -455,30 +473,12 @@ class Multi(list):
|
||||
#else: same len so do nothing
|
||||
return value
|
||||
|
||||
def _valid_master(self, value):
|
||||
masterlen = len(value)
|
||||
def _valid_master(self):
|
||||
#masterlen = len(value)
|
||||
values = self._getcontext().cfgimpl_get_values()
|
||||
for slave in self.opt._master_slaves:
|
||||
path = values._get_opt_path(slave)
|
||||
if not values._is_default_owner(path):
|
||||
value_slave = values._getvalue(slave, path)
|
||||
if len(value_slave) > masterlen:
|
||||
raise SlaveError(_("invalid len for the master: {0}"
|
||||
" which has {1} as slave with"
|
||||
" greater len").format(
|
||||
self.opt.impl_getname(), slave.impl_getname()))
|
||||
elif len(value_slave) < masterlen:
|
||||
for num in range(0, masterlen - len(value_slave)):
|
||||
if slave.impl_has_callback():
|
||||
# if callback add a value, but this value will not
|
||||
# change anymore automaticly (because this value
|
||||
# has owner)
|
||||
index = value_slave.__len__()
|
||||
value_slave.append(
|
||||
values._getcallback_value(slave, index=index),
|
||||
force=True)
|
||||
else:
|
||||
value_slave.append(undefined, force=True)
|
||||
Multi(values._getvalue(slave, path), self.context, slave, path)
|
||||
|
||||
def __setitem__(self, index, value):
|
||||
self._validate(value, index)
|
||||
@ -518,16 +518,15 @@ class Multi(list):
|
||||
dvalue = values._getcallback_value(slave, index=index)
|
||||
else:
|
||||
dvalue = slave.impl_getdefault_multi()
|
||||
old_value = values.getitem(slave, path,
|
||||
old_value = values.getitem(slave, path, validate=False,
|
||||
validate_properties=False)
|
||||
if len(old_value) < self.__len__():
|
||||
values.getitem(slave, path,
|
||||
validate_properties=False).append(
|
||||
dvalue, force=True)
|
||||
else:
|
||||
values.getitem(slave, path,
|
||||
validate_properties=False)[
|
||||
index] = dvalue
|
||||
if len(old_value) + 1 != self.__len__():
|
||||
raise SlaveError(_("invalid len for the slave: {0}"
|
||||
" which has {1} as master").format(
|
||||
self.opt._name, self.__len__()))
|
||||
values.getitem(slave, path, validate=False,
|
||||
validate_properties=False).append(
|
||||
dvalue, force=True)
|
||||
|
||||
def sort(self, cmp=None, key=None, reverse=False):
|
||||
if self.opt.impl_get_multitype() in [multitypes.slave,
|
||||
@ -597,7 +596,7 @@ class Multi(list):
|
||||
values = context.cfgimpl_get_values()
|
||||
if not values.is_default_owner(slave):
|
||||
#get multi without valid properties
|
||||
values.getitem(slave,
|
||||
values.getitem(slave, validate=False,
|
||||
validate_properties=False
|
||||
).pop(index, force=True)
|
||||
#set value without valid properties
|
||||
|
Reference in New Issue
Block a user