diff options
| author | Raphael Collet <rco@openerp.com> | 2014-04-09 16:58:30 +0200 |
|---|---|---|
| committer | Raphael Collet <rco@openerp.com> | 2014-04-09 16:58:30 +0200 |
| commit | 5640f3076a98bf8c72a5319abaf4ceb77caa2ffc (patch) | |
| tree | e7ddbaa8d59dbe337f15c3a3d6bbc7ae273578f8 /openerp/sql_db.py | |
| parent | f090689984bcb46f47eab3fdfc5e9a10a21722ab (diff) | |
| parent | be0096c4a753d9eed336f899c18c92f1aaf0223b (diff) | |
[MERGE] test_cursor: implement a cursor mockup that never commits to database, and use it for http tests
bzr revid: rco@openerp.com-20140409145830-rop8esgic2y435kf
Diffstat (limited to 'openerp/sql_db.py')
| -rw-r--r-- | openerp/sql_db.py | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/openerp/sql_db.py b/openerp/sql_db.py index 59841656d8c..ee58503c40b 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): @@ -364,6 +381,42 @@ class Cursor(object): def __getattr__(self, name): return getattr(self._obj, name) +class TestCursor(Cursor): + """ A cursor to be used for tests. It keeps the transaction open across + several requests, and simulates committing, rolling back, and closing. + """ + def __init__(self, *args, **kwargs): + super(TestCursor, self).__init__(*args, **kwargs) + # in order to simulate commit and rollback, the cursor maintains a + # savepoint at its last commit + self.execute("SAVEPOINT test_cursor") + # we use a lock to serialize concurrent requests + self._lock = threading.RLock() + + def acquire(self): + self._lock.acquire() + + def release(self): + self._lock.release() + + def close(self, force=False): + if force: + super(TestCursor, self).close() + elif not self._closed: + self.rollback() # for stuff that has not been committed + self.release() + + def autocommit(self, on): + _logger.debug("TestCursor.autocommit(%r) does nothing", on) + + def commit(self): + self.execute("RELEASE SAVEPOINT test_cursor") + self.execute("SAVEPOINT test_cursor") + + def rollback(self): + self.execute("ROLLBACK TO SAVEPOINT test_cursor") + self.execute("SAVEPOINT test_cursor") + class PsycoConnection(psycopg2.extensions.connection): pass @@ -491,6 +544,11 @@ class Connection(object): _logger.debug('create %scursor to %r', cursor_type, self.dbname) return Cursor(self._pool, self.dbname, serialized=serialized) + def test_cursor(self, serialized=True): + cursor_type = serialized and 'serialized ' or '' + _logger.debug('create test %scursor to %r', cursor_type, self.dbname) + return TestCursor(self._pool, self.dbname, serialized=serialized) + # serialized_cursor is deprecated - cursors are serialized by default serialized_cursor = cursor |
