better sqlalchemy integration

This commit is contained in:
2016-10-01 20:15:08 +02:00
parent d545c6883c
commit c81a2bcdbf
7 changed files with 297 additions and 50 deletions

View File

@ -36,7 +36,7 @@ class ChoiceOption(Option):
The option can also have the value ``None``
"""
__slots__ = tuple()
__slots__ = tuple('_init')
display_name = _('choice')
def __init__(self, name, doc, values, default=None,
@ -55,8 +55,10 @@ class ChoiceOption(Option):
if not isinstance(values, tuple): # pragma: optional cover
raise TypeError(_('values must be a tuple or a function for {0}'
).format(name))
self.impl_set_choice_values_params(values, values_params)
session = self.getsession()
#cannot add values and values_params in database before add option
#set in _init temporary
self._init = (values, values_params)
super(ChoiceOption, self).__init__(name, doc, default=default,
default_multi=default_multi,
callback=callback,
@ -66,19 +68,30 @@ class ChoiceOption(Option):
validator=validator,
validator_params=validator_params,
properties=properties,
warnings_only=warnings_only)
warnings_only=warnings_only,
session=session)
self.impl_set_choice_values_params(values, values_params, session)
session.commit()
del(self._init)
def impl_get_values(self, context, current_opt=undefined,
returns_raise=False):
if current_opt is undefined:
current_opt = self
params = undefined
#FIXME cache? but in context...
values = self._choice_values
if '_init' in dir(self):
values, params = self._init
else:
values = self._choice_values
if isinstance(values, FunctionType):
if context is None:
values = []
else:
values_params = self.impl_get_choice_values_params()
if params is not undefined:
values_params = params
else:
values_params = self.impl_get_choice_values_params()
values = carry_out_calculation(current_opt, context=context,
callback=values,
callback_params=values_params,

View File

@ -420,7 +420,7 @@ class StorageOptionDescription(StorageBase):
def impl_build_cache_option(self, _currpath=None, cache_path=None,
cache_option=None):
if _currpath is None and getattr(self, '_cache_paths', None) is not None:
if self.impl_is_readonly() or (_currpath is None and getattr(self, '_cache_paths', None) is not None):
# cache already set
return
if _currpath is None:

View File

@ -198,6 +198,152 @@ class _CallbackParam(SqlAlchemyBase):
self.params.append(_CallbackParamOption(value=param))
#____________________________________________________________
#
# choice
class _ChoiceParamOption(SqlAlchemyBase):
__tablename__ = 'choice_param_option'
id = Column(Integer, primary_key=True)
choice = Column(Integer, index=True)
option = Column(Integer)
force_permissive = Column(Boolean)
value = Column(PickleType)
def __init__(self, choice, option=undefined, force_permissive=undefined, value=undefined):
self.choice = choice.id
if value is not undefined:
self.value = value
elif option is not undefined:
self.option = option.id
self.force_permissive = force_permissive
class _ChoiceParam(SqlAlchemyBase):
__tablename__ = 'choice_param'
id = Column(Integer, primary_key=True)
option = Column(Integer, index=True)
key = Column(String)
def __init__(self, option, key):
self.option = option.id
self.key = key
#def load_choice_parm(collection_type, proxy):
# def getter(obj):
# if obj is None:
# return None
# ret = []
# requires = getattr(obj, proxy.value_attr)
# session = util.Session()
# for require in requires:
# if require.value is not None:
# ret.append(require.value)
# else:
# option = session.query(_Base).filter_by(id=require.option).first()
# ret.append((option, require.force_permissive))
# return tuple(ret)
#
# def setter(obj, value):
# setattr(obj, proxy.value_attr, value)
# return getter, setter
#
#
#class _ChoiceParamOption(SqlAlchemyBase):
# __tablename__ = 'choice_param_option'
# id = Column(Integer, primary_key=True)
# valid_param = Column(Integer, ForeignKey('choice_param.id'))
# option = Column(Integer)
# force_permissive = Column(Boolean)
# value = Column(PickleType)
#
# def __init__(self, option=undefined, force_permissive=undefined, value=undefined):
# if value is not undefined:
# self.value = value
# elif option is not undefined:
# self.option = option.id
# self.force_permissive = force_permissive
#
#
#class _ChoiceParam(SqlAlchemyBase):
# __tablename__ = 'choice_param'
# id = Column(Integer, primary_key=True)
# choice = Column(Integer, ForeignKey('baseoption.id'))
# key = Column(String)
# params = relationship('_ChoiceParamOption')
#
# def __init__(self, key, params):
# self.key = key
# for param in params:
# if isinstance(param, tuple):
# if param == (None,):
# self.params.append(_ChoiceParamOption())
# else:
# self.params.append(_ChoiceParamOption(option=param[0],
# force_permissive=param[1]))
# else:
# self.params.append(_ChoiceParamOption(value=param))
#____________________________________________________________
#
# validator
def load_validator_parm(collection_type, proxy):
def getter(obj):
if obj is None:
return None
ret = []
requires = getattr(obj, proxy.value_attr)
session = util.Session()
for require in requires:
if require.value is not None:
ret.append(require.value)
else:
option = session.query(_Base).filter_by(id=require.option).first()
ret.append((option, require.force_permissive))
return tuple(ret)
def setter(obj, value):
setattr(obj, proxy.value_attr, value)
return getter, setter
class _ValidatorParamOption(SqlAlchemyBase):
__tablename__ = 'validator_param_option'
id = Column(Integer, primary_key=True)
validator_param = Column(Integer, ForeignKey('validator_param.id'))
option = Column(Integer)
force_permissive = Column(Boolean)
value = Column(PickleType)
def __init__(self, option=undefined, force_permissive=undefined, value=undefined):
if value is not undefined:
self.value = value
elif option is not undefined:
self.option = option.id
self.force_permissive = force_permissive
class _ValidatorParam(SqlAlchemyBase):
__tablename__ = 'validator_param'
id = Column(Integer, primary_key=True)
validator = Column(Integer, ForeignKey('baseoption.id'))
key = Column(String)
params = relationship('_ValidatorParamOption')
def __init__(self, key, params):
self.key = key
for param in params:
if isinstance(param, tuple):
if param == (None,):
self.params.append(_ValidatorParamOption())
else:
self.params.append(_ValidatorParamOption(option=param[0],
force_permissive=param[1]))
else:
self.params.append(_ValidatorParamOption(value=param))
#____________________________________________________________
#
# consistency
@ -253,10 +399,10 @@ class _Base(SqlAlchemyBase):
_opt = Column(Integer)
_master_slaves = Column(Integer)
_choice_values = Column(PickleType)
_cho_params = relationship('_CallbackParam',
collection_class=attribute_mapped_collection('key'))
_choice_values_params = association_proxy("_cho_params", "params",
getset_factory=load_callback_parm)
#_cho_params = relationship('_ChoiceParam',
# collection_class=attribute_mapped_collection('key'))
#_choice_values_params = association_proxy("_cho_params", "params",
# getset_factory=load_choice_parm)
_reqs = relationship("_Require", collection_class=list)
_requires = association_proxy("_reqs", "requires", getset_factory=load_requires)
_multi = Column(Integer)
@ -267,10 +413,10 @@ class _Base(SqlAlchemyBase):
_callback_params = association_proxy("_call_params", "params",
getset_factory=load_callback_parm)
_validator = Column(PickleType)
_val_params = relationship('_CallbackParam',
_val_params = relationship('_ValidatorParam',
collection_class=attribute_mapped_collection('key'))
_validator_params = association_proxy("_val_params", "params",
getset_factory=load_callback_parm)
getset_factory=load_validator_parm)
######
#FIXME not autoload
_props = relationship("_PropertyOption", collection_class=set)
@ -348,9 +494,6 @@ class _Base(SqlAlchemyBase):
return (None, {})
return ret, self._callback_params
def impl_get_choice_values_params(self):
return self._choice_values_params
def impl_get_validator(self):
ret = self._validator
if ret is None:
@ -407,6 +550,10 @@ class _Base(SqlAlchemyBase):
self.commit(session)
def _set_readonly(self, has_extra):
session = self.getsession()
opt = session.query(_Base).filter_by(id=self.id).first()
opt._readonly = True
session.commit()
self._readonly = True
def _set_callback(self, callback, callback_params):
@ -414,10 +561,38 @@ class _Base(SqlAlchemyBase):
if callback_params is not None:
self._callback_params = callback_params
def impl_set_choice_values_params(self, values, values_params):
def impl_set_choice_values_params(self, values, values_params, session):
self._choice_values = values
if values_params is not None:
self._choice_values_params = values_params
for key, params in values_params.items():
choice = _ChoiceParam(self, key)
session.add(choice)
session.commit()
for param in params:
if isinstance(param, tuple):
if param == (None,):
session.add(_ChoiceParamOption(choice))
else:
session.add(_ChoiceParamOption(choice, option=param[0], force_permissive=param[1]))
else:
session.add(_ChoiceParamOption(choice, value=param))
session.commit()
def impl_get_choice_values_params(self):
session = self.getsession()
params = {}
for param in session.query(_ChoiceParam).filter_by(option=self.id).all():
_params = []
for _param in session.query(_ChoiceParamOption).filter_by(choice=param.id).all():
if _param.value:
_params.append(_param.value)
elif _param.option:
_params.append((session.query(_Base).filter_by(id=_param.option).first(),
_param.force_permissive))
else:
_params.append((None,))
params[param.key] = _params
return params
def _set_validator(self, validator, validator_params):
self._validator = validator
@ -425,10 +600,11 @@ class _Base(SqlAlchemyBase):
self._validator_params = validator_params
def impl_is_readonly(self):
try:
return self._readonly
except AttributeError:
session = self.getsession()
opt = session.query(_Base).filter_by(id=self.id).first()
if opt is None or opt._readonly is None:
return False
return opt._readonly
def impl_is_multi(self):
return self._multi == 0 or self._multi == 2
@ -559,6 +735,9 @@ class StorageOptionDescription(object):
def impl_build_cache_option(self, descr=None, _currpath=None,
subdyn_path=None, session=None):
if self.impl_is_readonly() or (_currpath is None and getattr(self, '_cache_paths', None) is not None):
# cache already set
return
if descr is None:
save = True
descr = self