From e5e00e4c0af8a8c9eb1eb57c0985509ddc36032c Mon Sep 17 00:00:00 2001 From: Raphael Collet Date: Wed, 9 Apr 2014 11:56:04 +0200 Subject: [PATCH] [IMP] registry: now cursor() simply returns a cursor, which may itself be used as a context manager bzr revid: rco@openerp.com-20140409095604-joh9dt0qkma12ykm --- openerp/addons/base/res/res_users.py | 6 ++-- openerp/addons/base/tests/test_db_cursor.py | 5 +++- openerp/addons/base/tests/test_ir_sequence.py | 2 +- openerp/addons/base/tests/test_uninstall.py | 2 +- openerp/cli/server.py | 4 +-- openerp/http.py | 2 +- openerp/modules/registry.py | 29 +++++++------------ openerp/service/report.py | 4 +-- openerp/sql_db.py | 17 +++++++++++ openerp/tests/common.py | 4 +-- openerp/tools/mail.py | 2 +- 11 files changed, 44 insertions(+), 33 deletions(-) diff --git a/openerp/addons/base/res/res_users.py b/openerp/addons/base/res/res_users.py index 0ad1d1276f6..9ce0efd2eb8 100644 --- a/openerp/addons/base/res/res_users.py +++ b/openerp/addons/base/res/res_users.py @@ -388,7 +388,7 @@ class res_users(osv.osv): if not password: return False user_id = False - cr = self.pool.get_cursor() + cr = self.pool.cursor() try: # autocommit: our single update request will be performed atomically. # (In this way, there is no opportunity to have two transactions @@ -440,7 +440,7 @@ class res_users(osv.osv): # Successfully logged in as admin! # Attempt to guess the web base url... if user_agent_env and user_agent_env.get('base_location'): - cr = self.pool.get_cursor() + cr = self.pool.cursor() try: base = user_agent_env['base_location'] ICP = self.pool['ir.config_parameter'] @@ -461,7 +461,7 @@ class res_users(osv.osv): raise openerp.exceptions.AccessDenied() if self._uid_cache.get(db, {}).get(uid) == passwd: return - cr = self.pool.get_cursor() + cr = self.pool.cursor() try: self.check_credentials(cr, uid, passwd) if self._uid_cache.has_key(db): diff --git a/openerp/addons/base/tests/test_db_cursor.py b/openerp/addons/base/tests/test_db_cursor.py index b3ce36467bb..abf8ceb91eb 100644 --- a/openerp/addons/base/tests/test_db_cursor.py +++ b/openerp/addons/base/tests/test_db_cursor.py @@ -21,12 +21,15 @@ class test_cr_execute(unittest2.TestCase): """ Try to use iterable but non-list or int params in query parameters. """ - with registry().cursor(auto_commit=False) as cr: + cr = registry().cursor() + try: with self.assertRaises(ValueError): cr.execute("SELECT id FROM res_users WHERE login=%s", 'admin') with self.assertRaises(ValueError): cr.execute("SELECT id FROM res_users WHERE id=%s", 1) with self.assertRaises(ValueError): cr.execute("SELECT id FROM res_users WHERE id=%s", '1') + finally: + cr.close() # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/openerp/addons/base/tests/test_ir_sequence.py b/openerp/addons/base/tests/test_ir_sequence.py index 5bb64720336..18b56daa58c 100644 --- a/openerp/addons/base/tests/test_ir_sequence.py +++ b/openerp/addons/base/tests/test_ir_sequence.py @@ -21,7 +21,7 @@ def registry(model): return openerp.modules.registry.RegistryManager.get(DB)[model] def cursor(): - return openerp.modules.registry.RegistryManager.get(DB).get_cursor() + return openerp.modules.registry.RegistryManager.get(DB).cursor() def drop_sequence(code): diff --git a/openerp/addons/base/tests/test_uninstall.py b/openerp/addons/base/tests/test_uninstall.py index 7c88196fbf6..b5c51c81405 100644 --- a/openerp/addons/base/tests/test_uninstall.py +++ b/openerp/addons/base/tests/test_uninstall.py @@ -13,7 +13,7 @@ def registry(model): return openerp.modules.registry.RegistryManager.get(DB)[model] def cursor(): - return openerp.modules.registry.RegistryManager.get(DB).get_cursor() + return openerp.modules.registry.RegistryManager.get(DB).cursor() def get_module(module_name): registry = openerp.modules.registry.RegistryManager.get(DB) diff --git a/openerp/cli/server.py b/openerp/cli/server.py index a808511ab8a..ff60674b890 100644 --- a/openerp/cli/server.py +++ b/openerp/cli/server.py @@ -103,7 +103,7 @@ def export_translation(): fileformat = os.path.splitext(config["translate_out"])[-1][1:].lower() buf = file(config["translate_out"], "w") registry = openerp.modules.registry.RegistryManager.new(dbname) - cr = registry.get_cursor() + cr = registry.cursor() openerp.tools.trans_export(config["language"], config["translate_modules"] or ["all"], buf, fileformat, cr) cr.close() @@ -117,7 +117,7 @@ def import_translation(): dbname = config['db_name'] registry = openerp.modules.registry.RegistryManager.new(dbname) - cr = registry.get_cursor() + cr = registry.cursor() openerp.tools.trans_load( cr, config["translate_in"], config["language"], context=context) cr.commit() diff --git a/openerp/http.py b/openerp/http.py index ab2c8852ac7..370d8ca7f30 100644 --- a/openerp/http.py +++ b/openerp/http.py @@ -235,7 +235,7 @@ class WebRequest(object): """ # some magic to lazy create the cr if not self._cr: - self._cr = self.registry.get_cursor() + self._cr = self.registry.cursor() return self._cr def __enter__(self): diff --git a/openerp/modules/registry.py b/openerp/modules/registry.py index 4d0b4f5e15f..ce76f8e86c9 100644 --- a/openerp/modules/registry.py +++ b/openerp/modules/registry.py @@ -78,7 +78,7 @@ class Registry(Mapping): # Useful only in a multi-process context. self._any_cache_cleared = False - cr = self.get_cursor() + cr = self.cursor() has_unaccent = openerp.modules.db.has_unaccent(cr) if openerp.tools.config['unaccent'] and not has_unaccent: _logger.warning("The option --unaccent was given but no unaccent() function was found in database.") @@ -203,28 +203,19 @@ class Registry(Mapping): self.test_cr = None RegistryManager.leave_test_mode() - def get_cursor(self): - """ Return a new cursor for the database. """ + def cursor(self): + """ Return a new cursor for the database. The cursor itself may be used + as a context manager to commit/rollback and close automatically. + """ if self.test_cr is not None: # While in test mode, we use one special cursor across requests. The # test cursor uses a reentrant lock to serialize accesses. The lock - # is granted here by get_cursor(), and automatically released by the + # is granted here by cursor(), and automatically released by the # cursor itself in its method close(). self.test_cr.acquire() return self.test_cr return self.db.cursor() - @contextmanager - def cursor(self, auto_commit=True): - """ Manage a new cursor; commit, rollback and closing are automatic. """ - cr = self.get_cursor() - try: - yield cr - if auto_commit: - cr.commit() - finally: - cr.close() - class DummyRLock(object): """ Dummy reentrant lock, to be used while running rpc and js tests """ def acquire(self): @@ -314,7 +305,7 @@ class RegistryManager(object): # Yeah, crazy. registry = cls.registries[db_name] - cr = registry.get_cursor() + cr = registry.cursor() try: registry.do_parent_store(cr) cr.commit() @@ -370,7 +361,7 @@ class RegistryManager(object): changed = False if openerp.multi_process and db_name in cls.registries: registry = cls.get(db_name) - cr = registry.get_cursor() + cr = registry.cursor() try: cr.execute(""" SELECT base_registry_signaling.last_value, @@ -416,7 +407,7 @@ class RegistryManager(object): registry = cls.get(db_name) if registry.any_cache_cleared(): _logger.info("At least one model cache has been cleared, signaling through the database.") - cr = registry.get_cursor() + cr = registry.cursor() r = 1 try: cr.execute("select nextval('base_cache_signaling')") @@ -431,7 +422,7 @@ class RegistryManager(object): if openerp.multi_process and db_name in cls.registries: _logger.info("Registry changed, signaling through the database") registry = cls.get(db_name) - cr = registry.get_cursor() + cr = registry.cursor() r = 1 try: cr.execute("select nextval('base_registry_signaling')") diff --git a/openerp/service/report.py b/openerp/service/report.py index 30e043c2977..0c2f720f4cb 100644 --- a/openerp/service/report.py +++ b/openerp/service/report.py @@ -49,7 +49,7 @@ def exp_render_report(db, uid, object, ids, datas=None, context=None): self_reports[id] = {'uid': uid, 'result': False, 'state': False, 'exception': None} - cr = openerp.registry(db).get_cursor() + cr = openerp.registry(db).cursor() try: result, format = openerp.report.render_report(cr, uid, ids, object, datas, context) if not result: @@ -87,7 +87,7 @@ def exp_report(db, uid, object, ids, datas=None, context=None): self_reports[id] = {'uid': uid, 'result': False, 'state': False, 'exception': None} def go(id, uid, ids, datas, context): - cr = openerp.registry(db).get_cursor() + cr = openerp.registry(db).cursor() try: result, format = openerp.report.render_report(cr, uid, ids, object, datas, context) if not result: diff --git a/openerp/sql_db.py b/openerp/sql_db.py index be20af40367..c93f4fbb92f 100644 --- a/openerp/sql_db.py +++ b/openerp/sql_db.py @@ -347,6 +347,23 @@ class Cursor(object): """ return self._cnx.rollback() + def __enter__(self): + """ Using the cursor as a contextmanager automatically commits and + closes it:: + + with cr: + cr.execute(...) + + # cr is committed if no failure occurred + # cr is closed in any case + """ + return self + + def __exit__(self, exc_type, exc_value, traceback): + if exc_type is None: + self.commit() + self.close() + @contextmanager @check def savepoint(self): diff --git a/openerp/tests/common.py b/openerp/tests/common.py index f9a267837d9..9f3684fa6df 100644 --- a/openerp/tests/common.py +++ b/openerp/tests/common.py @@ -71,7 +71,7 @@ class BaseCase(unittest2.TestCase): """ def cursor(self): - return self.registry.get_cursor() + return self.registry.cursor() def ref(self, xid): """ Returns database ID corresponding to a given identifier. @@ -120,7 +120,7 @@ class SingleTransactionCase(BaseCase): @classmethod def setUpClass(cls): cls.registry = RegistryManager.get(DB) - cls.cr = cls.registry.get_cursor() + cls.cr = cls.registry.cursor() cls.uid = openerp.SUPERUSER_ID @classmethod diff --git a/openerp/tools/mail.py b/openerp/tools/mail.py index 3da075fda6e..de6cd173521 100644 --- a/openerp/tools/mail.py +++ b/openerp/tools/mail.py @@ -625,7 +625,7 @@ def email_send(email_from, email_to, subject, body, email_cc=None, email_bcc=Non if not cr: db_name = getattr(threading.currentThread(), 'dbname', None) if db_name: - local_cr = cr = openerp.registry(db_name).get_cursor() + local_cr = cr = openerp.registry(db_name).cursor() else: raise Exception("No database cursor found, please pass one explicitly")