sqlalchemy has a storage
This commit is contained in:
0
tiramisu/storage/sqlalchemy/__init__.py
Normal file
0
tiramisu/storage/sqlalchemy/__init__.py
Normal file
284
tiramisu/storage/sqlalchemy/option.py
Normal file
284
tiramisu/storage/sqlalchemy/option.py
Normal file
@ -0,0 +1,284 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
""
|
||||
# Copyright (C) 2014 Team tiramisu (see AUTHORS for all contributors)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation; either version 2 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# This program is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#
|
||||
# ____________________________________________________________
|
||||
from tiramisu.setting import multitypes
|
||||
|
||||
|
||||
from sqlalchemy.ext.declarative import declarative_base, declared_attr
|
||||
from sqlalchemy import create_engine, Column, Integer, String, Boolean, \
|
||||
PickleType, ForeignKey, Table
|
||||
from sqlalchemy.orm import relationship, backref
|
||||
from sqlalchemy.orm import sessionmaker
|
||||
|
||||
|
||||
#FIXME
|
||||
engine = create_engine('sqlite:///:memory:')
|
||||
SqlAlchemyBase = declarative_base()
|
||||
#____________________________________________________________
|
||||
#
|
||||
# require
|
||||
require_table = Table('require', SqlAlchemyBase.metadata,
|
||||
Column('left_id', Integer, ForeignKey('requireoption.id')),
|
||||
Column('right_id', Integer, ForeignKey('baseoption.id'))
|
||||
)
|
||||
|
||||
class _RequireExpected(SqlAlchemyBase):
|
||||
__tablename__ = 'expected'
|
||||
id = Column(Integer, primary_key=True)
|
||||
expected = Column(PickleType)
|
||||
require = Column(Integer, ForeignKey('requireoption.id'))
|
||||
|
||||
def __init__(self, expected):
|
||||
self.expected = expected
|
||||
|
||||
|
||||
class _RequireOption(SqlAlchemyBase):
|
||||
__tablename__ = 'requireoption'
|
||||
id = Column(Integer, primary_key=True)
|
||||
r_opt = Column(Integer)
|
||||
expected = relationship("_RequireExpected")
|
||||
action = Column(String, nullable=False)
|
||||
inverse = Column(Boolean, default=False)
|
||||
transitive = Column(Boolean, default=True)
|
||||
same_action = Column(Boolean, default=True)
|
||||
|
||||
def __init__(self, option, expected, action, inverse, transitive,
|
||||
same_action):
|
||||
self.r_opt = option.id
|
||||
for expect in expected:
|
||||
self.expected.append(_RequireExpected(expect))
|
||||
self.action = action
|
||||
self.inverse = inverse
|
||||
self.transitive = transitive
|
||||
self.same_action = same_action
|
||||
|
||||
def get_expected(self):
|
||||
for expected in self.expected:
|
||||
yield(expected.expected)
|
||||
|
||||
#def get_option(self, config):
|
||||
# return config.cfgimpl_get_description().impl_get_opt_by_id(self.r_opt)
|
||||
|
||||
|
||||
#____________________________________________________________
|
||||
#
|
||||
# properties
|
||||
property_table = Table('property', SqlAlchemyBase.metadata,
|
||||
Column('left_id', Integer, ForeignKey('propertyoption.name')),
|
||||
Column('right_id', Integer, ForeignKey('baseoption.id'))
|
||||
)
|
||||
|
||||
|
||||
class _PropertyOption(SqlAlchemyBase):
|
||||
__tablename__ = 'propertyoption'
|
||||
name = Column(String, primary_key=True)
|
||||
|
||||
def __init__(self, name):
|
||||
self.name = name
|
||||
|
||||
|
||||
#____________________________________________________________
|
||||
#
|
||||
# information
|
||||
class _Information(SqlAlchemyBase):
|
||||
__tablename__ = 'information'
|
||||
id = Column(Integer, primary_key=True)
|
||||
option = Column(Integer, ForeignKey('baseoption.id'))
|
||||
key = Column(String)
|
||||
value = Column(PickleType)
|
||||
|
||||
def __init__(self, key, value):
|
||||
self.key = key
|
||||
self.value = value
|
||||
|
||||
|
||||
#____________________________________________________________
|
||||
#
|
||||
# callback
|
||||
class _CallbackParamOption(SqlAlchemyBase):
|
||||
__tablename__ = 'callback_param_option'
|
||||
id = Column(Integer, primary_key=True)
|
||||
callback_param = Column(Integer, ForeignKey('callback_param.id'))
|
||||
option = Column(Integer)
|
||||
force_permissive = Column(Boolean)
|
||||
value = Column(PickleType)
|
||||
|
||||
def __init__(self, option=None, force_permissive=None, value=None):
|
||||
if value is not None:
|
||||
self.value = value
|
||||
else:
|
||||
self.option = option.id
|
||||
self.force_permissive = force_permissive
|
||||
|
||||
|
||||
class _CallbackParam(SqlAlchemyBase):
|
||||
__tablename__ = 'callback_param'
|
||||
id = Column(Integer, primary_key=True)
|
||||
callback = Column(Integer, ForeignKey('baseoption.id'))
|
||||
name = Column(String)
|
||||
params = relationship('_CallbackParamOption')
|
||||
|
||||
def __init__(self, name, params):
|
||||
self.name = name
|
||||
for param in params:
|
||||
if isinstance(param, tuple):
|
||||
self.params.append(_CallbackParamOption(option=param[0],
|
||||
force_permissive=param[1]))
|
||||
else:
|
||||
self.params.append(_CallbackParamOption(value=param))
|
||||
|
||||
|
||||
#____________________________________________________________
|
||||
#
|
||||
# consistency
|
||||
consistency_table = Table('consistencyopt', SqlAlchemyBase.metadata,
|
||||
Column('left_id', Integer, ForeignKey('consistency.id')),
|
||||
Column('right_id', Integer, ForeignKey('baseoption.id'))
|
||||
)
|
||||
|
||||
|
||||
class _Consistency(SqlAlchemyBase):
|
||||
__tablename__ = 'consistency'
|
||||
id = Column(Integer, primary_key=True)
|
||||
func = Column(PickleType)
|
||||
|
||||
def __init__(self, func, all_cons_opts):
|
||||
self.func = func
|
||||
for option in all_cons_opts:
|
||||
option._consistencies.append(self)
|
||||
|
||||
|
||||
#____________________________________________________________
|
||||
#
|
||||
# Base
|
||||
class _Base(SqlAlchemyBase):
|
||||
__tablename__ = 'baseoption'
|
||||
id = Column(Integer, primary_key=True)
|
||||
_name = Column(String)
|
||||
_informations = relationship('_Information')
|
||||
_default = Column(PickleType)
|
||||
_default_multi = Column(PickleType)
|
||||
_requires = relationship('_RequireOption', secondary=require_table,
|
||||
backref=backref('option', enable_typechecks=False))
|
||||
_multi = Column(Boolean)
|
||||
_multitype = Column(String)
|
||||
_callback = Column(PickleType)
|
||||
_callback_params = relationship('_CallbackParam')
|
||||
_validator = Column(PickleType)
|
||||
_validator_params = relationship('_CallbackParam')
|
||||
_parent = Column(Integer, ForeignKey('baseoption.id'))
|
||||
_children = relationship('BaseOption', enable_typechecks=False)
|
||||
_properties = relationship('_PropertyOption', secondary=property_table,
|
||||
backref=backref('options', enable_typechecks=False))
|
||||
_warnings_only = Column(Boolean)
|
||||
_readonly = Column(Boolean, default=False)
|
||||
_consistencies = relationship('_Consistency', secondary=consistency_table,
|
||||
backref=backref('options', enable_typechecks=False))
|
||||
_choice_values = Column(PickleType)
|
||||
_choice_open_values = Column(Boolean)
|
||||
_type = Column(String(50))
|
||||
__mapper_args__ = {
|
||||
'polymorphic_identity': 'option',
|
||||
'polymorphic_on': _type
|
||||
}
|
||||
#FIXME devrait etre une table
|
||||
_optiondescription_group_type = Column(String)
|
||||
|
||||
def __init__(self):
|
||||
self.commit()
|
||||
|
||||
def commit(self):
|
||||
session.add(self)
|
||||
session.commit()
|
||||
|
||||
def _get_property_object(self, propname):
|
||||
prop_obj = session.query(_PropertyOption).filter(_PropertyOption.name == propname).first()
|
||||
if prop_obj is None:
|
||||
prop_obj = _PropertyOption(propname)
|
||||
return prop_obj
|
||||
|
||||
def _add_require(self, require):
|
||||
self._requires.append(_RequireOption(*require))
|
||||
|
||||
def _add_callback(self, key, values):
|
||||
self._callback_params.append(_CallbackParam(key, values))
|
||||
|
||||
def _add_validator(self, key, values):
|
||||
self._validator_params.append(_CallbackParam(key, values))
|
||||
|
||||
def _add_consistency(self, func, all_cons_opts):
|
||||
_Consistency(func, all_cons_opts)
|
||||
# ____________________________________________________________
|
||||
# information
|
||||
def impl_set_information(self, key, value):
|
||||
"""updates the information's attribute
|
||||
(which is a dictionary)
|
||||
|
||||
:param key: information's key (ex: "help", "doc"
|
||||
:param value: information's value (ex: "the help string")
|
||||
"""
|
||||
info = session.query(_Information).filter_by(option=self.id, key=key).first()
|
||||
#FIXME pas append ! remplacer !
|
||||
if info is None:
|
||||
self._informations.append(_Information(key, value))
|
||||
else:
|
||||
info.value = value
|
||||
|
||||
def impl_get_information(self, key, default=None):
|
||||
"""retrieves one information's item
|
||||
|
||||
:param key: the item string (ex: "help")
|
||||
"""
|
||||
info = session.query(_Information).filter_by(option=self.id, key=key).first()
|
||||
if info is not None:
|
||||
return info.value
|
||||
elif default is not None:
|
||||
return default
|
||||
else:
|
||||
raise ValueError(_("information's item not found: {0}").format(
|
||||
key))
|
||||
|
||||
|
||||
class StorageOptionDescription(object):
|
||||
def impl_get_opt_by_path(self, path):
|
||||
try:
|
||||
#FIXME
|
||||
idx = self._cache_paths[1].index(path)
|
||||
opt_id = self._cache_paths[0][idx]
|
||||
return session.query(_Base).filter_by(id=opt_id).first()
|
||||
except ValueError:
|
||||
raise AttributeError(_('no option for path {0}').format(path))
|
||||
|
||||
def impl_get_path_by_opt(self, opt):
|
||||
try:
|
||||
return self._cache_paths[1][self._cache_paths[0].index(opt)]
|
||||
except ValueError:
|
||||
raise AttributeError(_('no option {0} found').format(opt))
|
||||
|
||||
|
||||
class StorageBase(_Base):
|
||||
@declared_attr
|
||||
def __mapper_args__(self):
|
||||
return {'polymorphic_identity': self.__name__.lower()}
|
||||
|
||||
|
||||
#FIXME
|
||||
SqlAlchemyBase.metadata.create_all(engine)
|
||||
Session = sessionmaker(bind=engine)
|
||||
session = Session()
|
@ -1,5 +1,5 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
"default plugin for cache: set it in a simple dictionary"
|
||||
"utils used by storage"
|
||||
# Copyright (C) 2013 Team tiramisu (see AUTHORS for all contributors)
|
||||
#
|
||||
# This program is free software; you can redistribute it and/or modify
|
||||
|
Reference in New Issue
Block a user