From ff15c4ce7f54d2f9f593d6058d22af4b96285981 Mon Sep 17 00:00:00 2001 From: niv-openerp Date: Mon, 6 May 2013 12:29:55 +0200 Subject: [PATCH] [IMP] Added new api to handle transactions in controllers bzr revid: nicolas.vanhoren@openerp.com-20130506102955-x28gmm3rx8i6j345 --- addons/web/com.py | 95 ++++++++++++++++++++++++++++++++++++++++++++++ addons/web/http.py | 9 ++++- 2 files changed, 102 insertions(+), 2 deletions(-) create mode 100644 addons/web/com.py diff --git a/addons/web/com.py b/addons/web/com.py new file mode 100644 index 00000000000..85a06b9d5ec --- /dev/null +++ b/addons/web/com.py @@ -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() \ No newline at end of file diff --git a/addons/web/http.py b/addons/web/http.py index e0bd34a1bd0..8d36536b2fa 100644 --- a/addons/web/http.py +++ b/addons/web/http.py @@ -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)