[Zodb-checkins] SVN: ZODB/trunk/ Merge from 3.3 branch.
Tim Peters
tim.one at comcast.net
Thu Sep 9 23:27:32 EDT 2004
Log message for revision 27489:
Merge from 3.3 branch.
Officially deprecate Transaction.begin().
Changed:
U ZODB/trunk/NEWS.txt
U ZODB/trunk/src/ZODB/tests/testZODB.py
U ZODB/trunk/src/transaction/_transaction.py
-=-
Modified: ZODB/trunk/NEWS.txt
===================================================================
--- ZODB/trunk/NEWS.txt 2004-09-10 03:25:47 UTC (rev 27488)
+++ ZODB/trunk/NEWS.txt 2004-09-10 03:27:31 UTC (rev 27489)
@@ -20,12 +20,12 @@
Connection
----------
-ZODB intends to raise ConnnectionStateError if an attempt is made to
-close a connection while modifications are pending (the connection is
-involved in a transaction that hasn't been abort()'ed or commit()'ed).
-It was missing the case where the only pending modifications were made
-in subtransactions. This has been fixed. If an attempt to close a
-connection with pending subtransactions is made now,
+ZODB intends to raise ConnnectionStateError if an attempt is made to close
+a connection while modifications are pending (the connection is involved in
+a transaction that hasn't been ``abort()``'ed or ``commit()``'ed). It was
+missing the case where the only pending modifications were made in
+subtransactions. This has been fixed. If an attempt to close a connection
+with pending subtransactions is made now::
ConnnectionStateError: Cannot close a connection with a pending subtransaction
@@ -34,28 +34,49 @@
transaction
-----------
-If ReadConflictError was raised by an attempt to load an object with a
-_p_independent() method that returned false, attempting to commit the
-transaction failed to (re)raise ReadConflictError for that object. Note
-that ZODB intends to prevent committing a transaction in which a
-ReadConflictError occurred; this was an obscure case it missed.
+- Some explanations of new transaction features in the 3.3a3 news
+ were incorrect, and this news file has been retroactively edited to
+ repair that. See news for 3.3a3 below.
-Growing pains: ZODB 3.1 and 3.2 had a bug wherein Transaction.begin()
-didn't abort the current transaction if the only pending changes were in a
-subtransaction. In ZODB 3.3, it's intended that transaction managers be
-used instead of invoking methods directly on Transaction objects, and
-calling begin() on a transaction manager didn't have this old bug. However,
-Transaction.begin() still exists in 3.3, and it had a worse bug: it never
-aborted the transaction (not even if changes were pending outside of
-subtransactions). Transaction.begin() has been changed to abort the
-transaction, although it's still strongly recommended to invoke begin() on
-the relevant transaction manager instead. For example,
+- If ReadConflictError was raised by an attempt to load an object with a
+ ``_p_independent()`` method that returned false, attempting to commit the
+ transaction failed to (re)raise ReadConflictError for that object. Note
+ that ZODB intends to prevent committing a transaction in which a
+ ReadConflictError occurred; this was an obscure case it missed.
- import transaction
- transaction.begin()
+- Growing pains: ZODB 3.2 had a bug wherein ``Transaction.begin()`` didn't
+ abort the current transaction if the only pending changes were in a
+ subtransaction. In ZODB 3.3, it's intended that a transaction manager be
+ used to effect ``begin()`` (instead of invoking ``Transaction.begin()``),
+ and calling ``begin()`` on a transaction manager didn't have this old
+ bug. However, ``Transaction.begin()`` still exists in 3.3, and it had a
+ worse bug: it never aborted the transaction (not even if changes were
+ pending outside of subtransactions). ``Transaction.begin()`` has been
+ changed to abort the transaction. ``Transaction.begin()`` is also
+ deprecated. Don't use it. Use ``begin()`` on the relevant transaction
+ manager instead. For example,
-if using the default ThreadTransactionManager (see news for 3.3a3 below).
+ >>> import transaction
+ >>> txn = transaction.begin() # start a txn using the default TM
+ if using the default ThreadTransactionManager (see news for 3.3a3 below).
+ In 3.3, it's intended that a single Transaction object is used for exactly
+ one transaction. So, unlike as in 3.2, when somtimes Transaction objects
+ were reused across transactions, but sometimes weren't, when you do
+ ``Transaction.begin()`` in 3.3 a brand new transaction object is
+ created. That's why this use is deprecated. Code of the form:
+
+ >>> txn = transaction.get()
+ >>> ...
+ >>> txn.begin()
+ >>> ...
+ >>> txn.commit()
+
+ can't work as intended is 3.3, because ``txn`` is no longer the current
+ Transaction object the instant ``txn.begin()`` returns.
+
+
+
BTrees
------
@@ -270,9 +291,9 @@
application code and for the interaction between transactions and
resource managers.
-The top-level transaction package has functions commit(), abort(),
-get(), and begin(). They should be used instead of the magic
-get_transaction() builtin, which will be deprecated. For example:
+The top-level transaction package has functions ``commit()``, ``abort()``,
+``get()``, and ``begin()``. They should be used instead of the magic
+``get_transaction()`` builtin, which will be deprecated. For example:
>>> get_transaction().commit()
@@ -281,38 +302,38 @@
>>> import transaction
>>> transaction.commit()
-The new API provides explicit transaction manager objects. The
-transaction manager (TM) is responsible for associating resource
-managers with a "current" transaction. It is available as
-`transaction.manager`. The default TM, implemented by
-ThreadedTransactionManager, assigns each thread its own current
-transaction. The TransactionManager class assigns all threads to the
-same transaction.
+The new API provides explicit transaction manager objects. A transaction
+manager (TM) is responsible for associating resource managers with a
+"current" transaction. The default TM, implemented by class
+``ThreadedTransactionManager``, assigns each thread its own current
+transaction. This default TM is available as ``transaction.manager``. The
+``TransactionManager`` class assigns all threads to the same transaction,
+and is an explicit replacement for the ``Connection.setLocalTransaction()``
+method:
-A transaction manager instance can be passed as the txn_mgr argument
-to DB.open(). If you do, the connection will use the specified
-transaction manager instead of the default transaction manager. You
-will need to call commit() and abort() on the transaction manager
-explicitly. For example:
+A transaction manager instance can be passed as the txn_mgr argument to
+``DB.open()``. If you do, the connection will use the specified
+transaction manager instead of the default TM. The current transaction is
+obtained by calling ``get()`` on a TM. For example:
>>> tm = transaction.TransactionManager()
>>> cn = db.open(txn_mgr=tm)
[...]
- >>> tm.commit()
+ >>> tm.get().commit()
-The setLocalTransaction() and getTransaction() methods of Connection
-are deprecated. Use an explicit TM passed via txn_mgr instead. The
-setLocalTransaction() manager functions still works, but it returns a
-TM instead of a Transaction.
+The ``setLocalTransaction()`` and ``getTransaction()`` methods of
+Connection are deprecated. Use an explicit TM passed via ``txn_mgr=`` to
+``DB.open()`` instead. The ``setLocalTransaction()`` method still works,
+but it returns a TM instead of a Transaction.
-The TM creates Transaction objects, which are used for exactly one
-transaction. They have a status() method that returns their current
-state.
+A TM creates Transaction objects, which are used for exactly one
+transaction. Transaction objects still have ``commit()``, ``abort()``,
+``note()``, ``setUser()``, and ``setExtendedInfo()`` methods.
-Resource managers, e.g. Connection or RDB adapter, should use join()
-instead of register(). An object that calls join() manages its own
-resources. An object that calls register() expects the TM to manage
-the objects.
+Resource managers, e.g. Connection or RDB adapter, should use a
+Transaction's ``join()`` method instead of its ``register()`` method. An
+object that calls ``join()`` manages its own resources. An object that
+calls ``register()`` expects the TM to manage the objects.
Data managers written against the ZODB 4 transaction API are now
supported in ZODB 3.
Modified: ZODB/trunk/src/ZODB/tests/testZODB.py
===================================================================
--- ZODB/trunk/src/ZODB/tests/testZODB.py 2004-09-10 03:25:47 UTC (rev 27488)
+++ ZODB/trunk/src/ZODB/tests/testZODB.py 2004-09-10 03:27:31 UTC (rev 27489)
@@ -386,39 +386,58 @@
# transaction, and, in fact, when this test was written,
# Transaction.begin() didn't do anything (everything from here
# down failed).
- cn = self._db.open()
- rt = cn.root()
- rt['a'] = 1
- transaction.get().begin() # should abort adding 'a' to the root
- rt = cn.root()
- self.assertRaises(KeyError, rt.__getitem__, 'a')
+ # Oh, bleech. Since Transaction.begin is also deprecated, we have
+ # to goof around suppressing the deprecation warning.
+ import warnings
- # A longstanding bug: this didn't work if changes were only in
- # subtransactions.
- transaction.get().begin()
- rt = cn.root()
- rt['a'] = 2
- transaction.get().commit(1)
+ # First verify that Transaction.begin *is* deprecated, by turning
+ # the warning into an error.
+ warnings.filterwarnings("error", category=DeprecationWarning)
+ self.assertRaises(DeprecationWarning, transaction.get().begin)
+ del warnings.filters[0]
- transaction.get().begin()
- rt = cn.root()
- self.assertRaises(KeyError, rt.__getitem__, 'a')
+ # Now ignore DeprecationWarnings for the duration. Use a
+ # try/finally block to ensure we reenable DeprecationWarnings
+ # no matter what.
+ warnings.filterwarnings("ignore", category=DeprecationWarning)
+ try:
+ cn = self._db.open()
+ rt = cn.root()
+ rt['a'] = 1
- # One more time, mixing "top level" and subtransaction changes.
- transaction.get().begin()
- rt = cn.root()
- rt['a'] = 3
- transaction.get().commit(1)
- rt['b'] = 4
+ transaction.get().begin() # should abort adding 'a' to the root
+ rt = cn.root()
+ self.assertRaises(KeyError, rt.__getitem__, 'a')
- transaction.get().begin()
- rt = cn.root()
- self.assertRaises(KeyError, rt.__getitem__, 'a')
- self.assertRaises(KeyError, rt.__getitem__, 'b')
+ # A longstanding bug: this didn't work if changes were only in
+ # subtransactions.
+ transaction.get().begin()
+ rt = cn.root()
+ rt['a'] = 2
+ transaction.get().commit(1)
- cn.close()
+ transaction.get().begin()
+ rt = cn.root()
+ self.assertRaises(KeyError, rt.__getitem__, 'a')
+ # One more time, mixing "top level" and subtransaction changes.
+ transaction.get().begin()
+ rt = cn.root()
+ rt['a'] = 3
+ transaction.get().commit(1)
+ rt['b'] = 4
+
+ transaction.get().begin()
+ rt = cn.root()
+ self.assertRaises(KeyError, rt.__getitem__, 'a')
+ self.assertRaises(KeyError, rt.__getitem__, 'b')
+
+ cn.close()
+
+ finally:
+ del warnings.filters[0]
+
def test_suite():
return unittest.makeSuite(ZODBTests, 'check')
Modified: ZODB/trunk/src/transaction/_transaction.py
===================================================================
--- ZODB/trunk/src/transaction/_transaction.py 2004-09-10 03:25:47 UTC (rev 27488)
+++ ZODB/trunk/src/transaction/_transaction.py 2004-09-10 03:27:31 UTC (rev 27489)
@@ -136,6 +136,7 @@
import logging
import sys
import thread
+import warnings
_marker = object()
@@ -230,6 +231,9 @@
self._resources.append(adapter)
def begin(self):
+ warnings.warn("Transaction.begin() should no longer be used; use "
+ "the begin() method of a transaction manager.",
+ DeprecationWarning)
if (self._resources or
self._sub or
self._nonsub or
More information about the Zodb-checkins
mailing list