better support for sqlalchemy storage

This commit is contained in:
2014-07-06 15:31:57 +02:00
parent 3cc2d9ca3d
commit 71f8926fca
16 changed files with 369 additions and 241 deletions

View File

@ -33,11 +33,7 @@ from tiramisu.storage import get_storages_option
StorageBase = get_storages_option('base')
class SubMulti(object):
pass
submulti = SubMulti()
submulti = 2
allowed_character = '[a-z\d\-_]'
@ -115,7 +111,10 @@ class Base(StorageBase):
if callback is not None:
validate_callback(callback, callback_params, 'callback')
self._callback = callback
self._callback_params = callback_params
if callback_params is None:
self._callback_params = {}
else:
self._callback_params = callback_params
def __init__(self, name, doc, default=None, default_multi=None,
requires=None, multi=False, callback=None,
@ -143,8 +142,13 @@ class Base(StorageBase):
raise ValueError(_("invalid default_multi value {0} "
"for option {1}: {2}").format(
str(default_multi), name, err))
self._multi = multi
if self._multi is not False:
if multi is True:
self._multi = 0
elif multi is False:
self._multi = 1
elif multi is submulti:
self._multi = submulti
if self._multi != 1:
if default is None:
default = []
self._default_multi = default_multi
@ -260,10 +264,10 @@ class BaseOption(Base):
return
if not load and self._callback is None:
self._state_callback = None
self._state_callback_params = None
self._state_callback_params = {}
elif load and self._state_callback is None:
self._callback = None
self._callback_params = None
self._callback_params = {}
del(self._state_callback)
del(self._state_callback_params)
else:
@ -273,7 +277,7 @@ class BaseOption(Base):
else:
callback = self._callback
callback_params = self._callback_params
self._state_callback_params = None
self._state_callback_params = {}
if callback_params is not None:
cllbck_prms = {}
for key, values in callback_params.items():
@ -429,6 +433,19 @@ class BaseOption(Base):
def impl_get_callback(self):
return self._callback, self._callback_params
def impl_has_callback(self):
"to know if a callback has been defined or not"
return self._callback is not None
def _is_subdyn(self):
try:
return self._subdyn is not None
except AttributeError:
return False
def impl_getproperties(self):
return self._properties
class OnlyOption(BaseOption):
__slots__ = tuple()
@ -713,18 +730,11 @@ class Option(OnlyOption):
"accesses the Option's doc"
return self.impl_get_information('doc')
def impl_has_callback(self):
"to know if a callback has been defined or not"
if self._callback is None:
return False
else:
return True
#def impl_getkey(self, value):
# return value
def impl_is_multi(self):
return self._multi is True or self._multi is submulti
return self._multi == 0 or self._multi is submulti
def impl_is_submulti(self):
return self._multi is submulti
@ -746,7 +756,7 @@ class Option(OnlyOption):
self._name))
warnings_only = params.get('warnings_only', False)
if self._is_subdyn():
dynod = self._subdyn
dynod = self._impl_getsubdyn()
else:
dynod = None
for opt in other_opts:
@ -756,10 +766,10 @@ class Option(OnlyOption):
if dynod is None:
raise ConfigError(_('almost one option in consistency is '
'in a dynoptiondescription but not all'))
if dynod != opt._subdyn:
if dynod != opt._impl_getsubdyn():
raise ConfigError(_('option in consistency must be in same'
' dynoptiondescription'))
dynod = opt._subdyn
dynod = opt._impl_getsubdyn()
elif dynod is not None:
raise ConfigError(_('almost one option in consistency is in a '
'dynoptiondescription but not all'))
@ -847,10 +857,10 @@ class Option(OnlyOption):
default_multi = self._default_multi
except AttributeError:
default_multi = None
if callback is not None and ((not self._multi and
if callback is not None and ((self._multi == 1 and
(self._default is not None or
default_multi is not None))
or (self._multi and
or (self._multi != 1 and
(self._default != [] or
default_multi is not None))
): # pragma: optional cover
@ -983,6 +993,23 @@ class SymLinkOption(OnlyOption):
def impl_get_information(self, key, default=undefined):
return self._opt.impl_get_information(key, default)
#FIXME utile tout ca ? c'est un peu de la duplication ...
def impl_getproperties(self):
return self._opt._properties
def impl_get_callback(self):
return self._opt._callback, self._opt._callback_params
def impl_has_callback(self):
"to know if a callback has been defined or not"
return self._opt._callback is not None
def _is_subdyn(self):
try:
return self._opt._subdyn is not None
except AttributeError:
return False
class DynSymLinkOption(SymLinkOption):
__slots__ = ('_dyn',)

View File

@ -55,7 +55,7 @@ class MasterSlaves(object):
).format(name))
if validate:
callback, callback_params = self.master.impl_get_callback()
if callback is not None and callback_params is not None: # pragma: optional cover
if callback is not None and callback_params != {}: # pragma: optional cover
for key, callbacks in callback_params.items():
for callbk in callbacks:
if isinstance(callbk, tuple):

View File

@ -48,11 +48,14 @@ class ChoiceOption(Option):
"""
if isinstance(values, FunctionType):
validate_callback(values, values_params, 'values')
elif not isinstance(values, tuple): # pragma: optional cover
raise TypeError(_('values must be a tuple or a function for {0}'
).format(name))
self._extra = {'_choice_values': values,
'_choice_values_params': values_params}
else:
if values_params is not None:
raise ValueError(_('values is not a function, so values_params must be None'))
if not isinstance(values, tuple): # pragma: optional cover
raise TypeError(_('values must be a tuple or a function for {0}'
).format(name))
self._choice_values = values
self._choice_values_params = values_params
super(ChoiceOption, self).__init__(name, doc, default=default,
default_multi=default_multi,
callback=callback,
@ -66,9 +69,9 @@ class ChoiceOption(Option):
def impl_get_values(self, context):
#FIXME cache? but in context...
values = self._extra['_choice_values']
values = self._choice_values
if isinstance(values, FunctionType):
values_params = self._extra['_choice_values_params']
values_params = self._choice_values_params
if values_params is None:
values_params = {}
values = carry_out_calculation(self, config=context,

View File

@ -74,7 +74,6 @@ class OptionDescription(BaseOption, StorageOptionDescription):
'dynoptiondescription'))
old = child
self._add_children(child_names, children)
self._cache_paths = None
self._cache_consistencies = None
# the group_type is useful for filtering OptionDescriptions in a config
self._group_type = groups.default
@ -167,9 +166,6 @@ class OptionDescription(BaseOption, StorageOptionDescription):
raise ValueError(_('group_type: {0}'
' not allowed').format(group_type))
def impl_get_group_type(self):
return self._group_type
def _valid_consistency(self, option, value, context, index, submulti_idx):
if self._cache_consistencies is None:
return True
@ -239,7 +235,6 @@ class OptionDescription(BaseOption, StorageOptionDescription):
:param descr: parent :class:`tiramisu.option.OptionDescription`
"""
if descr is None:
self._cache_paths = None
self._cache_consistencies = None
self.impl_build_cache_option()
descr = self
@ -261,8 +256,6 @@ class OptionDescription(BaseOption, StorageOptionDescription):
def _impl_get_suffixes(self, context):
callback, callback_params = self.impl_get_callback()
if callback_params is None:
callback_params = {}
values = carry_out_calculation(self, config=context,
callback=callback,
callback_params=callback_params)
@ -275,10 +268,9 @@ class OptionDescription(BaseOption, StorageOptionDescription):
def _impl_search_dynchild(self, name=undefined, context=undefined):
ret = []
for child in self._impl_st_getchildren():
for child in self._impl_st_getchildren(context, only_dyn=True):
cname = child.impl_getname()
if isinstance(child, DynOptionDescription) and \
(name is undefined or name.startswith(cname)):
if name is undefined or name.startswith(cname):
path = cname
for value in child._impl_get_suffixes(context):
if name is undefined:
@ -296,7 +288,7 @@ class OptionDescription(BaseOption, StorageOptionDescription):
return child._impl_to_dyn(name, path)
def _impl_getchildren(self, dyn=True, context=undefined):
for child in self._impl_st_getchildren():
for child in self._impl_st_getchildren(context):
cname = child._name
if dyn and child.impl_is_dynoptiondescription():
path = cname
@ -310,24 +302,30 @@ class OptionDescription(BaseOption, StorageOptionDescription):
def impl_getchildren(self):
return list(self._impl_getchildren())
def __getattr__(self, name, context=undefined):
if name.startswith('_'): # or name.startswith('impl_'):
return object.__getattribute__(self, name)
return self._getattr(name, context=context)
class DynOptionDescription(OptionDescription):
def __init__(self, name, doc, children, requires=None, properties=None,
callback=None, callback_params=None):
super(DynOptionDescription, self).__init__(name, doc, children,
requires, properties)
for child in children:
if isinstance(child, OptionDescription):
if child.impl_get_group_type() != groups.master:
raise ConfigError(_('cannot set optiondescription in an '
'dynoptiondescription'))
for chld in child._impl_getchildren():
chld._subdyn = self
chld._impl_setsubdyn(self)
if isinstance(child, SymLinkOption):
raise ConfigError(_('cannot set symlinkoption in an '
'dynoptiondescription'))
child._subdyn = self
super(DynOptionDescription, self).__init__(name, doc, children,
requires, properties)
child._impl_setsubdyn(self)
self.impl_set_callback(callback, callback_params)
self.commit()
def _validate_callback(self, callback, callback_params):
if callback is None:
@ -346,7 +344,7 @@ class SynDynOptionDescription(object):
def __getattr__(self, name, context=undefined):
if name in dir(self._opt):
return getattr(self._opt, name)
return self._opt._getattr(name, self._name, self._suffix, context)
return self._opt._getattr(name, suffix=self._suffix, context=context)
def impl_getname(self):
return self._name