[IMP] Added new api to handle transactions in controllers

bzr revid: nicolas.vanhoren@openerp.com-20130506102955-x28gmm3rx8i6j345
This commit is contained in:
niv-openerp 2013-05-06 12:29:55 +02:00
parent 8088c205ed
commit ff15c4ce7f
2 changed files with 102 additions and 2 deletions

95
addons/web/com.py Normal file
View File

@ -0,0 +1,95 @@
import openerp.service.security as security
import openerp.service.model as model
import openerp
def _sessions():
if getattr(_thread_data, "sessions", None) is None:
_thread_data.sessions = []
return _thread_data.sessions
class Session(object):
def __init__(self, db, uid, password):
self.db = db
self.uid = uid
self.password = password
self.cr = None
def model(self, model_name):
return Model(self, model_name)
def _execute(self, model_name, method, args, kwargs):
self.ensure_transation()
return model.execute_cr(self.cr, self.uid, model_name, method, *args, **kwargs)
def ensure_transation(self):
if self.cr is None:
security.check(self.db, self.uid, self.password)
threading.currentThread().dbname = self.db
self.cr = openerp.registry(self.db).db.cursor()
def close_transaction(self, has_exception=False):
if self.cr is None:
return
if has_exception:
try:
self.cr.rollback()
except:
pass # nothing
else:
try:
self.cr.commit()
except:
pass # nothing
try:
self.cr.close()
except:
pass # nothing
self.cr = None
class Model(object):
def __init__(self, session, name):
self.session = session
self.name = name
def __getattr__(self, method):
def proxy(*args, **kw):
result = self.session._execute(self.name, method, args, kw)
# reorder read
if method == "read":
if isinstance(result, list) and len(result) > 0 and "id" in result[0]:
index = {}
for r in result:
index[r['id']] = r
result = [index[x] for x in args[0] if x in index]
return result
return proxy
def search_read(self, domain=None, fields=None, offset=0, limit=None, order=None, context=None):
record_ids = self.search(domain or [], offset, limit or False, order or False, context or {})
if not record_ids: return []
records = self.read(record_ids, fields or [], context or {})
return records
import threading
_thread_data = threading.local()
class _ThreadSession:
def __getattr__(self, name):
if len(_sessions()) == 0:
raise Exception("Session not initialized")
return getattr(_sessions()[-1], name)
def __setattr__(self, name, value):
if len(_sessions()) == 0:
raise Exception("Session not initialized")
return setattr(_sessions()[-1], name, value)
def init(self, db, uid, password):
ses = self
class with_obj:
def __enter__(self):
_sessions().append(Session(db, uid, password))
def __exit__(self, type, value, traceback):
_sessions().pop().close_transaction(type is not None)
return with_obj()
transaction = _ThreadSession()

View File

@ -118,6 +118,11 @@ class WebRequest(object):
# we use _ as seprator where RFC2616 uses '-'
self.lang = lang.replace('-', '_')
def wrap_transaction(self, fct):
from openerp.addons.web.com import transaction
with transaction.init(self.session._db, self.session._uid, self.session._password):
return fct()
def reject_nonliteral(dct):
if '__ref' in dct:
raise ValueError(
@ -200,7 +205,7 @@ class JsonRequest(WebRequest):
if _logger.isEnabledFor(logging.DEBUG):
_logger.debug("--> %s.%s\n%s", method.im_class.__name__, method.__name__, pprint.pformat(self.jsonrequest))
response['id'] = self.jsonrequest.get('id')
response["result"] = method(self, **self.params)
response["result"] = self.wrap_transaction(lambda: method(self, **self.params))
except session.AuthenticationError, e:
se = serialize_exception(e)
error = {
@ -294,7 +299,7 @@ class HttpRequest(WebRequest):
akw[key] = type(value)
_logger.debug("%s --> %s.%s %r", self.httprequest.method, method.im_class.__name__, method.__name__, akw)
try:
r = method(self, **self.params)
r = self.wrap_transaction(lambda: method(self, **self.params))
except Exception, e:
_logger.exception("An exception occured during an http request")
se = serialize_exception(e)