1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2026-06-22 09:30:48 +02:00

EmComponent: get rid of database functions

This commit is contained in:
ArnAud 2015-07-16 11:27:19 +02:00
commit 1d2c069fb8

View file

@ -6,8 +6,6 @@
import datetime import datetime
import logging import logging
import sqlalchemy as sql
from Database import sqlutils
import EditorialModel.fieldtypes as ftypes import EditorialModel.fieldtypes as ftypes
from collections import OrderedDict from collections import OrderedDict
@ -21,12 +19,6 @@ logger = logging.getLogger('Lodel2.EditorialModel')
# @pure # @pure
class EmComponent(object): class EmComponent(object):
## The name of the engine configuration
# @todo Not a good idea to store it here
dbconf = 'default'
## The table in wich we store data for this object
# None for EmComponent
table = None
## Used by EmComponent::modify_rank ## Used by EmComponent::modify_rank
ranked_in = None ranked_in = None
@ -53,14 +45,7 @@ class EmComponent(object):
# @param id_or_name int|str: name or id of the object # @param id_or_name int|str: name or id of the object
# @throw TypeError if id_or_name is not an integer nor a string # @throw TypeError if id_or_name is not an integer nor a string
# @throw NotImplementedError if called with EmComponent # @throw NotImplementedError if called with EmComponent
def __init__(self, id_or_name, dbconf = 'default'): def __init__(self, id_or_name):
self.dbconf = dbconf
if self.dbconf:
self.db_engine = sqlutils.get_engine(dbconf)
else:
self.db_engine = False
if type(self) == EmComponent: if type(self) == EmComponent:
raise NotImplementedError('Abstract class') raise NotImplementedError('Abstract class')
@ -77,7 +62,6 @@ class EmComponent(object):
self.name = id_or_name self.name = id_or_name
else: else:
raise TypeError('Bad argument: expecting <int> or <str> but got : ' + str(type(id_or_name))) raise TypeError('Bad argument: expecting <int> or <str> but got : ' + str(type(id_or_name)))
self.table = self.__class__.table
self.populate() self.populate()
## @brief Access an attribute of an EmComponent ## @brief Access an attribute of an EmComponent
@ -124,10 +108,9 @@ class EmComponent(object):
def __eq__(self, other): def __eq__(self, other):
return self.__class__ == other.__class__ and self.uid == other.uid return self.__class__ == other.__class__ and self.uid == other.uid
## Lookup in the database properties of the object to populate the properties ## Set all fields
# @throw EmComponentNotExistError if the instance is not anymore stored in database
def populate(self): def populate(self):
records = self._populate_db() # Db query records = [] # TODO
for record in records: for record in records:
for keys in self._fields.keys(): for keys in self._fields.keys():
@ -136,34 +119,7 @@ class EmComponent(object):
super(EmComponent, self).__setattr__('deleted', False) super(EmComponent, self).__setattr__('deleted', False)
#@classmethod ## Insert a new component
## Shortcut that return the sqlAlchemy engine
#def db_engine(cls):
# return sqlutils.get_engine(cls.dbconf)
## Do the query on the database for EmComponent::populate()
# @throw EmComponentNotExistError if the instance is not anymore stored in database
def _populate_db(self):
dbe = self.db_engine
component = sql.Table(self.table, sqlutils.meta(dbe))
req = sql.sql.select([component])
if self.uid is None:
req = req.where(component.c.name == self.name)
else:
req = req.where(component.c.uid == self.uid)
conn = dbe.connect()
res = conn.execute(req)
res = res.fetchall()
conn.close()
if not res or len(res) == 0:
raise EmComponentNotExistError("No " + self.__class__.__name__ + " found with " + ('name ' + self.name if self.uid is None else 'uid ' + str(self.uid)))
return res
## Insert a new component in the database
# #
# This function create and assign a new UID and handle the date_create and date_update values # This function create and assign a new UID and handle the date_create and date_update values
# @warning There is a mandatory argument dbconf that indicate wich database configuration to use # @warning There is a mandatory argument dbconf that indicate wich database configuration to use
@ -182,118 +138,45 @@ class EmComponent(object):
if argname in ['date_update', 'date_create', 'rank', 'uid']: # Automatic properties if argname in ['date_update', 'date_create', 'rank', 'uid']: # Automatic properties
raise TypeError("Invalid argument : " + argname) raise TypeError("Invalid argument : " + argname)
elif argname not in valid_args: elif argname not in valid_args:
raise TypeError("Unexcepted keyword argument '"+argname+"' for "+cls.__name__+" creation") raise TypeError("Unexcepted keyword argument '" + argname + "' for " + cls.__name__ + " creation")
#Check uniq names constraint #Check uniq names constraint
try: try:
name = kwargs['name'] name = kwargs['name']
exist = cls(name) exist = cls(name)
for kname in kwargs: for kname in kwargs:
if not (getattr(exist, kname) == kwargs[kname]): if not (getattr(exist, kname) == kwargs[kname]):
raise EmComponentExistError("An "+cls.__name__+" named "+name+" allready exists with a different "+kname) raise EmComponentExistError("An " + cls.__name__ + " named " + name + " allready exists with a different " + kname)
logger.info("Trying to create an "+cls.__name__+" that allready exist with same attribute. Returning the existing one") logger.info("Trying to create an " + cls.__name__ + " that allready exist with same attribute. Returning the existing one")
return exist return exist
except EmComponentNotExistError: except EmComponentNotExistError:
pass pass
# Mandatory fields check (actual fieldtypes don't allow this check
#for name in cls._fields:
# if cls._fields[name].notNull and cls._fields[name].default == None:
# raise TypeError("Missing argument : "+name)
if 'dbconf' in kwargs: kwargs['uid'] = cls.new_uid()
if not kwargs['db_engine']:
raise NotImplementedError("Its a nonsense to call create with no database")
dbconf = kwargs['dbconf']
else:
dbconf = 'default'
dbe = sqlutils.get_engine(dbconf)
kwargs['uid'] = cls.new_uid(dbe)
kwargs['date_update'] = kwargs['date_create'] = datetime.datetime.utcnow() kwargs['date_update'] = kwargs['date_create'] = datetime.datetime.utcnow()
conn = dbe.connect()
kwargs['rank'] = cls._get_max_rank( kwargs[cls.ranked_in], dbe )+1 kwargs['rank'] = cls._get_max_rank( kwargs[cls.ranked_in], dbe )+1
table = sql.Table(cls.table, sqlutils.meta(dbe))
req = table.insert(kwargs)
if not conn.execute(req):
raise RuntimeError("Unable to create the "+cls.__class__.__name__+" EmComponent ")
conn.close()
return cls(kwargs['name'], dbconf) return cls(kwargs['name'], dbconf)
## Write the representation of the component in the database ## Delete this component
# @return bool
# @todo stop using datetime.datetime.utcnow() for date_update update
def save(self):
values = {}
for name, field in self._fields.items():
values[name] = field.to_sql()
# Don't allow creation date overwritting
#if 'date_create' in values:
#del values['date_create']
#logger.warning("date_create supplied for save, but overwritting of date_create not allowed, the date will not be changed")
values['date_update'] = datetime.datetime.utcnow()
self._save_db(values)
## Do the query in the datbase for EmComponent::save()
# @param values dict: A dictionnary of the values to insert
# @throw RunTimeError if it was unable to do the Db update
def _save_db(self, values):
""" Do the query on the db """
dbe = self.db_engine
component = sql.Table(self.table, sqlutils.meta(dbe))
req = sql.update(component, values=values).where(component.c.uid == self.uid)
conn = dbe.connect()
res = conn.execute(req)
conn.close()
if not res:
raise RuntimeError("Unable to save the component in the database")
## Delete this component data in the database
# @return bool : True if deleted False if deletion aborded # @return bool : True if deleted False if deletion aborded
# @throw RunTimeError if it was unable to do the deletion # @throw RunTimeError if it was unable to do the deletion
def delete(self): def delete(self):
#<SQL> pass
dbe = self.db_engine
component = sql.Table(self.table, sqlutils.meta(dbe))
req = component.delete().where(component.c.uid == self.uid)
conn = dbe.connect()
res = conn.execute(req)
conn.close()
if not res:
raise RuntimeError("Unable to delete the component in the database")
#</SQL>
super(EmComponent, self).__setattr__('deleted', True)
return True
## @brief Get the maximum rank given an EmComponent child class and a ranked_in filter ## @brief Get the maximum rank given an EmComponent child class and a ranked_in filter
# @param ranked_in_value mixed: The rank "family" # @param ranked_in_value mixed: The rank "family"
# @return -1 if no EmComponent found else return an integer >= 0 # @return -1 if no EmComponent found else return an integer >= 0
@classmethod @classmethod
def _get_max_rank(cls, ranked_in_value, dbe): def _get_max_rank(cls, ranked_in_value):
component = sql.Table(cls.table, sqlutils.meta(dbe)) pass
req = sql.sql.select([component.c.rank]).where(getattr(component.c, cls.ranked_in) == ranked_in_value).order_by(component.c.rank.desc())
c = dbe.connect()
res = c.execute(req)
res = res.fetchone()
c.close()
if res != None:
return res['rank']
else:
return -1
## Only make a call to the class method ## Only make a call to the class method
# @return A positive integer or -1 if no components # @return A positive integer or -1 if no components
# @see EmComponent::_get_max_rank() # @see EmComponent::_get_max_rank()
def get_max_rank(self, ranked_in_value): def get_max_rank(self, ranked_in_value):
return self.__class__._get_max_rank(ranked_in_value, self.db_engine) return self.__class__._get_max_rank(ranked_in_value)
## Set a new rank for this component ## Set a new rank for this component
# @note This function assume that ranks are properly set from 1 to x with no gap # @note This function assume that ranks are properly set from 1 to x with no gap
@ -334,12 +217,12 @@ class EmComponent(object):
req = table.update().where(table.c.uid == sql.bindparam('b_uid')).values(rank=sql.bindparam('b_rank')) req = table.update().where(table.c.uid == sql.bindparam('b_uid')).values(rank=sql.bindparam('b_rank'))
res = conn.execute(req, updated_ranks) res = conn.execute(req, updated_ranks)
conn.close() conn.close()
if res: if res:
#Instance rank update #Instance rank update
self._fields['rank'].value = new_rank self._fields['rank'].value = new_rank
return bool(res) return bool(res)
## @brief Modify a rank given a sign and a new_rank ## @brief Modify a rank given a sign and a new_rank
# - If sign is '=' set the rank to new_rank # - If sign is '=' set the rank to new_rank
# - If sign is '-' set the rank to cur_rank - new_rank # - If sign is '-' set the rank to cur_rank - new_rank