[z3-checkins] r18249 - in z3/sqlos/branch/jinty-3.0-fix_the_tests:
. transaction
jinty at codespeak.net
jinty at codespeak.net
Fri Oct 7 10:02:52 CEST 2005
Author: jinty
Date: Fri Oct 7 10:02:49 2005
New Revision: 18249
Modified:
z3/sqlos/branch/jinty-3.0-fix_the_tests/adapter.py
z3/sqlos/branch/jinty-3.0-fix_the_tests/connection.py
z3/sqlos/branch/jinty-3.0-fix_the_tests/transaction/__init__.py
Log:
Rather than joining only the first transaction, join as objects become dirty.
This is paricularly tricky because the ZopeDatabaseAdapter (ZDA) joins when it
sees a SQL activity.
Sometimes we generate SQL activity only in the prepare phase of a transaction
causing the ZDA to try and join the transaction then. This fails.
The implemented solution is to force the ZDA to join when we join, which is a
little hackish (the interfaces state specifically that we should not be calling
this method).
Some other solutions would be:
* change the ZDA code to join every transaction
* change the transaction code to allow joins during the prepare phase
Also update to a non-depreciated version of the transaction interface.
(130:135)
Modified: z3/sqlos/branch/jinty-3.0-fix_the_tests/adapter.py
==============================================================================
--- z3/sqlos/branch/jinty-3.0-fix_the_tests/adapter.py (original)
+++ z3/sqlos/branch/jinty-3.0-fix_the_tests/adapter.py Fri Oct 7 10:02:49 2005
@@ -12,8 +12,6 @@
__metaclass__ = type
-from transaction import get_transaction
-
from sqlobject.dbconnection import DBAPI
from sqlobject import _mysql, _postgres, _sybase, _sqlite
from sqlos.interfaces import ISQLObject
@@ -46,7 +44,6 @@
self.debug = 0
self.supportTransactions = False
self._dm = SQLObjectTransactionManager(connection)
- get_transaction().join(self._dm)
def makeConnection(self):
return self._connection
Modified: z3/sqlos/branch/jinty-3.0-fix_the_tests/connection.py
==============================================================================
--- z3/sqlos/branch/jinty-3.0-fix_the_tests/connection.py (original)
+++ z3/sqlos/branch/jinty-3.0-fix_the_tests/connection.py Fri Oct 7 10:02:49 2005
@@ -11,7 +11,6 @@
"""
__metaclass__ = type
-from transaction import get_transaction
from zope.interface import implements
from zope.component import ComponentLookupError
from zope.app import zapi
Modified: z3/sqlos/branch/jinty-3.0-fix_the_tests/transaction/__init__.py
==============================================================================
--- z3/sqlos/branch/jinty-3.0-fix_the_tests/transaction/__init__.py (original)
+++ z3/sqlos/branch/jinty-3.0-fix_the_tests/transaction/__init__.py Fri Oct 7 10:02:49 2005
@@ -15,7 +15,7 @@
# The next import is needed so we don't shadow
# the global 'transaction' module from zope3.
-from transaction import get_transaction
+from transaction import get
from transaction.interfaces import IDataManager, IRollback
from transaction.util import NoSavepointSupportRollback
@@ -45,7 +45,7 @@
>>> import tempfile
>>> import urllib
>>> fh, testdb_file = tempfile.mkstemp()
- >>> testdb_url = 'sqlite://' + urllib.pathname2url(testdb_file)
+ >>> testdb_dbi = 'dbi://' + urllib.pathname2url(testdb_file)
First, register the subscribers:
@@ -63,15 +63,19 @@
Then, create a connection:
- >>> from sqlobject.dbconnection import connectionForURI
- >>> from sqlos.tests.sampleperson import SamplePerson
+ >>> import sqlite
>>> from sqlos.adapter import SQLiteAdapter
- >>> connection = connectionForURI(testdb_url)
- >>> adapter = SQLiteAdapter(connection.makeConnection())
+ >>> from zope.app.rdb import ZopeDatabaseAdapter
+ >>> class SQLiteda(ZopeDatabaseAdapter):
+ ... def _connection_factory(self):
+ ... return sqlite.connect(testdb_file)
+ >>> zda = SQLiteda(testdb_dbi)
+ >>> adapter = SQLiteAdapter(zda())
Stuff the connection into the test class and initialize the table
if it doesn't exists yet:
+ >>> from sqlos.tests.sampleperson import SamplePerson
>>> SamplePerson._connection = adapter
>>> SamplePerson.createTable(ifNotExists=True)
@@ -125,7 +129,7 @@
False
>>> person._expire_called
False
-
+
Prepare the transaction, make sure we get the expected values:
>>> t1 = '1'
@@ -191,12 +195,47 @@
>>> person.dirty, person._expired
(False, False)
+ Lets abort the current transaction to cleanup:
+
+ >>> from transaction import get
+ >>> get().abort()
+
+ Now lets test the integration with the zope transaction machinery, to make
+ sure that the Zope DA is registered for committing and that our transaction
+ manager is also called:
+
+ >>> oldcommit = SQLObjectTransactionManager.commit
+ >>> def commit(self, txn):
+ ... print 'committing'
+ ... oldcommit(self, txn)
+ >>> SQLObjectTransactionManager.commit = commit
+ >>> from zope.app.rdb import ZopeConnection
+ >>> oldregister = ZopeConnection.registerForTxn
+ >>> def register(self):
+ ... if not self._txn_registered:
+ ... print 'registering zope da for txn'
+ ... oldregister(self)
+ >>> ZopeConnection.registerForTxn = register
+
+ change the sample person and try another commit
+ (regression test for http://codespeak.net/issues/z3/issue9):
+
+ >>> people = list(SamplePerson.select(SamplePerson.q.username=='sidnei'))
+ registering zope da for txn
+ >>> assert len(people) == 1
+ >>> people[0].username = 'alan'
+ >>> from transaction import get
+ >>> get().commit()
+ committing
+
And then cleanup the monkeypatched method:
>>> SamplePerson.syncUpdate = oldsync
>>> del SamplePerson._sync_called
>>> SamplePerson.expire = oldexpire
>>> del SamplePerson._expire_called
+ >>> SQLObjectTransactionManager.commit = oldcommit
+ >>> ZopeConnection.registerForTxn = oldregister
And finally call tearDown and cleanup:
@@ -212,6 +251,7 @@
self.sqlconnection = sqlconnection
self.state = 0
self.prepared = False
+ self._joined_txn = False
self.delta = 0
self.transaction = None
@@ -246,8 +286,9 @@
self.delta = 0
for obj in self.objects:
expired(obj)
- self.sqlconnection.rollback()
+ self.sqlconnection.rollback()# Doesn't the Zope DA take care of this?
self.objects.clear()
+ self._joined_txn = False
def commit(self, txn):
if not self.prepared:
@@ -261,8 +302,9 @@
# XXX Can't know if modified has been fired yet. Maybe we
# should *not* fire a modified event here?
modified(obj)
- self.sqlconnection.commit()
+ self.sqlconnection.commit() # Doesn't the Zope DA take care of this?
self.objects.clear()
+ self._joined_txn = False
def register(self, obj):
if not ISQLObject.providedBy(obj):
@@ -271,6 +313,13 @@
"manager")
self.objects.add(obj)
self.delta += 1
+ if not self._joined_txn:
+ # register the Zope DA connection as well, becuse when we prepare,
+ # and cause DB activity, it might try to register as well. which
+ # fails. not very nice at all.
+ self.sqlconnection.registerForTxn()
+ get().join(self)
+ self._joined_txn = True
def savepoint(self, txn):
"""Create a savepoint that can not be rolled back"""
More information about the z3-checkins
mailing list