Commit 0e480ec9 authored by Tim Peters's avatar Tim Peters

Merge/port checkins to ZODB code made from Zope3.

This includes:

r26945 | jim | 2004-08-06 18:30:44 -0400 (Fri, 06 Aug 2004) | 6 lines
   M /Zope3/trunk/src/persistent/tests/test_persistent.py
   M /Zope3/trunk/src/zope/event/tests.py

Updated to work with the versions of doctest from Python with versions
  greater than or equal to 2.3.0 and less than 2.4.0.a2 and with
  versions greater than 2.4.0a2.

r26482 | srichter | 2004-07-13 13:07:03 -0400 (Tue, 13 Jul 2004) | 2 lines
   M /Zope3/trunk/src/transaction/__init__.py
   M /Zope3/trunk/src/transaction/_transaction.py
   M /Zope3/trunk/src/transaction/tests/test_transaction.py

Converted XXX to TODO.

r25953 | sidnei | 2004-06-23 13:14:20 -0400 (Wed, 23 Jun 2004) | 1 line
   M /Zope3/trunk/src/ZODB/interfaces.py
   M /Zope3/trunk/src/transaction/_transaction.py
   M /Zope3/trunk/src/zope/app/rdb/__init__.py
   M /Zope3/trunk/src/zope/app/rdb/tests/test_zopedbtransactionmanager.py

Add missing sortKey method to ZopeDBTransactionManager and DataManagerAdapter, and also add it to the interface.

r25330 | alga | 2004-06-10 10:07:45 -0400 (Thu, 10 Jun 2004) | 4 lines
   M /Zope3/trunk/src/ZODB/Connection.py
   M /Zope3/trunk/src/ZODB/interfaces.py
   M /Zope3/trunk/src/ZODB/tests/testConnection.py

Added an IConnection interface declaration on ZODB Connection.

Jim says Tim Peters will be mad at him, but that's the right way to go.

r25273 | philikon | 2004-06-06 04:43:57 -0400 (Sun, 06 Jun 2004) | 4 lines
Changed paths:
   M /Zope3/trunk/src/BTrees
   M /Zope3/trunk/src/ZODB
   M /Zope3/trunk/src/persistent

Ignore .so files.

This fix should probably be merged to the original ZODB tree.
parent 151db346
......@@ -28,7 +28,7 @@ ZoneAlarm. Many particularly slow tests are skipped unless you pass
Compatibility
-------------
ZODB 3.3 is requires Python 2.3.4 or later.
ZODB 3.3 requires Python 2.3.4 or later.
The Zope 2.8 release should be compatible with this version of ZODB.
Note that Zope 2.7 and higher includes ZEO, so this package should
......
......@@ -35,6 +35,8 @@ from ZODB.POSException \
from ZODB.TmpStore import TmpStore
from ZODB.utils import oid_repr, z64, positive_id
from ZODB.serialize import ObjectWriter, ConnectionObjectReader, myhasattr
from ZODB.interfaces import IConnection
from ZODB.interfaces import implements
global_reset_counter = 0
......@@ -147,6 +149,7 @@ class Connection(ExportImport, object):
getTransferCounts
"""
implements(IConnection)
_tmp = None
_code_timestamp = 0
......
......@@ -17,7 +17,8 @@ $Id$
"""
try:
from zope.interface import Interface, Attribute
from zope.interface import Interface, Attribute, implements
from zope.interface.verify import verifyObject
except ImportError:
class Interface:
pass
......@@ -27,6 +28,11 @@ except ImportError:
self.__name__ = __name__
self.__doc__ = __doc__
def implements(*args):
pass
def verifyObject(*args):
pass
class IDataManager(Interface):
"""Objects that manage transactional storage.
......@@ -144,6 +150,16 @@ class IDataManager(Interface):
"""
def sortKey():
"""
Return a key to use for ordering registered DataManagers
ZODB uses a global sort order to prevent deadlock when it commits
transactions involving multiple resource managers. The resource
manager must define a sortKey() method that provides a global ordering
for resource managers.
"""
class ITransaction(Interface):
"""Object representing a running transaction.
......@@ -224,3 +240,26 @@ class ITransaction(Interface):
"""
# XXX is this this allowed to cause an exception here, during
# the two-phase commit, or can it toss data silently?
class IConnection(Interface):
"""ZODB connection.
XXX: This interface is incomplete.
"""
def add(ob):
"""Add a new object 'obj' to the database and assign it an oid.
A persistent object is normally added to the database and
assigned an oid when it becomes reachable to an object already in
the database. In some cases, it is useful to create a new
object and use its oid (_p_oid) in a single transaction.
This method assigns a new oid regardless of whether the object
is reachable.
The object is added when the transaction commits. The object
must implement the IPersistent interface and must not
already be associated with a Connection.
"""
......@@ -22,6 +22,7 @@ import transaction
from ZODB.config import databaseFromString
from ZODB.utils import p64, u64
from ZODB.tests.warnhook import WarningsHook
from ZODB.interfaces import verifyObject
class ConnectionDotAdd(unittest.TestCase):
......@@ -595,6 +596,15 @@ class StubStorage:
return None
class TestConnectionInterface(unittest.TestCase):
def test(self):
from ZODB.interfaces import IConnection
db = databaseFromString("<zodb>\n<mappingstorage/>\n</zodb>")
cn = db.open()
verifyObject(IConnection, cn)
class StubDatabase:
def __init__(self):
......@@ -608,4 +618,5 @@ class StubDatabase:
def test_suite():
s = unittest.makeSuite(ConnectionDotAdd, 'check')
s.addTest(doctest.DocTestSuite())
s.addTest(unittest.makeSuite(TestConnectionInterface))
return s
......@@ -25,23 +25,30 @@ class P(Persistent):
def inc(self):
self.x += 1
def DocFileSuite(path, globs=None):
# It's not entirely obvious how to connection this single string
# with unittest. For now, re-use the _utest() function that comes
# standard with doctest in Python 2.3. One problem is that the
# error indicator doesn't point to the line of the doctest file
# that failed.
source = open(path).read()
if globs is None:
globs = sys._getframe(1).f_globals
t = doctest.Tester(globs=globs)
def runit():
doctest._utest(t, path, source, path, 0)
f = unittest.FunctionTestCase(runit, description="doctest from %s" % path)
suite = unittest.TestSuite()
suite.addTest(f)
return suite
try:
DocFileSuite = doctest.DocFileSuite # >= Python 2.4.0a2
except AttributeError:
# <= Python 2.4.0a1
def DocFileSuite(path, globs=None):
# It's not entirely obvious how to connection this single string
# with unittest. For now, re-use the _utest() function that comes
# standard with doctest in Python 2.3. One problem is that the
# error indicator doesn't point to the line of the doctest file
# that failed.
path = os.path.join(persistent.tests.__path__[0], path)
source = open(path).read()
if globs is None:
globs = sys._getframe(1).f_globals
t = doctest.Tester(globs=globs)
def runit():
doctest._utest(t, path, source, path, 0)
f = unittest.FunctionTestCase(runit,
description="doctest from %s" % path)
suite = unittest.TestSuite()
suite.addTest(f)
return suite
def test_suite():
path = os.path.join(persistent.tests.__path__[0], "persistent.txt")
return DocFileSuite(path, {"P": P})
return DocFileSuite("persistent.txt", globs={"P": P})
......@@ -11,6 +11,10 @@
# FOR A PARTICULAR PURPOSE.
#
############################################################################
"""Exported transaction functions.
$Id$
"""
from transaction._transaction import Transaction
from transaction._manager import TransactionManager, ThreadTransactionManager
......@@ -29,5 +33,5 @@ def commit(sub=False):
def abort(sub=False):
manager.get().abort(sub)
# XXX Issue deprecation warning if this variant is used?
# TODO: Issue deprecation warning if this variant is used?
get_transaction = get
......@@ -25,7 +25,7 @@ Transaction has two methods for a resource manager to call to
participate in a transaction -- register() and join(). join() takes a
resource manager and adds it to the list of resources. register() is
for backwards compatibility. It takes a persistent object and
registers its _p_jar attribute. XXX explain adapter
registers its _p_jar attribute. TODO: explain adapter
Subtransactions
---------------
......@@ -54,7 +54,7 @@ methods and support a second argument to tpc_begin().
The second argument to tpc_begin() indicates that a subtransaction
commit is beginning (if it is true). In a subtransaction, there is no
tpc_vote() call. (XXX I don't have any idea why.) The tpc_finish()
tpc_vote() call. (XXX: I don't have any idea why.) The tpc_finish()
or tpc_abort() call applies just to that subtransaction.
Once a resource manager is involved in a subtransaction, all
......@@ -187,11 +187,11 @@ class Transaction(object):
def join(self, resource):
if self.status != Status.ACTIVE:
# XXX Should it be possible to join a committing transaction?
# TODO: Should it be possible to join a committing transaction?
# I think some users want it.
raise ValueError("expected txn status %r, but it's %r" % (
Status.ACTIVE, self.status))
# XXX the prepare check is a bit of a hack, perhaps it would
# TODO: the prepare check is a bit of a hack, perhaps it would
# be better to use interfaces. If this is a ZODB4-style
# resource manager, it needs to be adapted, too.
if myhasattr(resource, "prepare"):
......@@ -219,7 +219,7 @@ class Transaction(object):
self._adapters[manager] = adapter
self.join(adapter)
else:
# XXX comment out this expensive assert later
# TODO: comment out this expensive assert later
# Use id() to guard against proxies.
assert id(obj) not in map(id, adapter.objects)
adapter.objects.append(obj)
......@@ -230,7 +230,7 @@ class Transaction(object):
self._resources.append(adapter)
def begin(self):
# XXX I'm not sure how this should be implemented. Not doing
# TODO: I'm not sure how this should be implemented. Not doing
# anything now, but my best guess is: If nothing has happened
# yet, it's fine. Otherwise, abort this transaction and let
# the txn manager create a new one.
......@@ -293,8 +293,8 @@ class Transaction(object):
for rm in L:
rm.tpc_finish(self)
except:
# XXX do we need to make this warning stronger?
# XXX It would be nice if the system could be configured
# TODO: do we need to make this warning stronger?
# TODO: It would be nice if the system could be configured
# to stop committing transactions at this point.
self.log.critical("A storage error occured during the second "
"phase of the two-phase commit. Resources "
......@@ -365,8 +365,8 @@ class Transaction(object):
# Merge all of _sub, _nonsub, and _resources.
d = dict(self._sub)
d.update(self._nonsub)
# XXX I think _sub and _nonsub are disjoint, and that
# XXX _resources is empty. If so, we can simplify this code.
# TODO: I think _sub and _nonsub are disjoint, and that
# _resources is empty. If so, we can simplify this code.
assert len(d) == len(self._sub) + len(self._nonsub)
assert not self._resources
for rm in self._resources:
......@@ -430,7 +430,7 @@ class Transaction(object):
def setExtendedInfo(self, name, value):
self._extension[name] = value
# XXX We need a better name for the adapters.
# TODO: We need a better name for the adapters.
class MultiObjectResourceAdapter(object):
"""Adapt the old-style register() call to the new-style join().
......@@ -538,7 +538,7 @@ class DataManagerAdapter(object):
self._datamanager = datamanager
self._rollback = None
# XXX I'm not sure why commit() doesn't do anything
# TODO: I'm not sure why commit() doesn't do anything
def commit(self, transaction):
pass
......@@ -580,3 +580,7 @@ class DataManagerAdapter(object):
def tpc_vote(self, transaction):
if not self._sub:
self._datamanager.prepare(transaction)
def sortKey(self):
return self._datamanager.sortKey()
......@@ -203,7 +203,7 @@ class TransactionTests(unittest.TestCase):
assert self.nosub1._p_jar.ctpc_finish == 0
assert self.nosub1._p_jar.cabort == 1
# XXX
# XXX:
def BUGtestNSJSubTransactionCommitAbort(self):
"""
this reveals a bug in transaction.py
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment