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 logging
import sqlalchemy as sql
from Database import sqlutils
import EditorialModel.fieldtypes as ftypes
from collections import OrderedDict
@ -21,12 +19,6 @@ logger = logging.getLogger('Lodel2.EditorialModel')
# @pure
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
ranked_in = None
@ -53,14 +45,7 @@ class EmComponent(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 NotImplementedError if called with EmComponent
def __init__(self, id_or_name, dbconf = 'default'):
self.dbconf = dbconf
if self.dbconf:
self.db_engine = sqlutils.get_engine(dbconf)
else:
self.db_engine = False
def __init__(self, id_or_name):
if type(self) == EmComponent:
raise NotImplementedError('Abstract class')
@ -77,7 +62,6 @@ class EmComponent(object):
self.name = id_or_name
else:
raise TypeError('Bad argument: expecting <int> or <str> but got : ' + str(type(id_or_name)))
self.table = self.__class__.table
self.populate()
## @brief Access an attribute of an EmComponent
@ -124,10 +108,9 @@ class EmComponent(object):
def __eq__(self, other):
return self.__class__ == other.__class__ and self.uid == other.uid
## Lookup in the database properties of the object to populate the properties
# @throw EmComponentNotExistError if the instance is not anymore stored in database
## Set all fields
def populate(self):
records = self._populate_db() # Db query
records = [] # TODO
for record in records:
for keys in self._fields.keys():
@ -136,34 +119,7 @@ class EmComponent(object):
super(EmComponent, self).__setattr__('deleted', False)
#@classmethod
## 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
## Insert a new component
#
# 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
@ -182,118 +138,45 @@ class EmComponent(object):
if argname in ['date_update', 'date_create', 'rank', 'uid']: # Automatic properties
raise TypeError("Invalid argument : " + argname)
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
try:
name = kwargs['name']
exist = cls(name)
for kname in kwargs:
if not (getattr(exist, kname) == kwargs[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")
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")
return exist
except EmComponentNotExistError:
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:
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['uid'] = cls.new_uid()
kwargs['date_update'] = kwargs['date_create'] = datetime.datetime.utcnow()
conn = dbe.connect()
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)
## Write the representation of the component in the database
# @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
## Delete this component
# @return bool : True if deleted False if deletion aborded
# @throw RunTimeError if it was unable to do the deletion
def delete(self):
#<SQL>
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
pass
## @brief Get the maximum rank given an EmComponent child class and a ranked_in filter
# @param ranked_in_value mixed: The rank "family"
# @return -1 if no EmComponent found else return an integer >= 0
@classmethod
def _get_max_rank(cls, ranked_in_value, dbe):
component = sql.Table(cls.table, sqlutils.meta(dbe))
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
def _get_max_rank(cls, ranked_in_value):
pass
## Only make a call to the class method
# @return A positive integer or -1 if no components
# @see EmComponent::_get_max_rank()
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
# @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'))
res = conn.execute(req, updated_ranks)
conn.close()
if res:
#Instance rank update
self._fields['rank'].value = new_rank
return bool(res)
## @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 cur_rank - new_rank