better sqlalchemy integration
This commit is contained in:
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
Reference in New Issue
Block a user