Commit 92a97b25 authored by Jim Fulton's avatar Jim Fulton

Grand renaming:

- Renamed most files (especially python modules) to lower case.

- Moved views and interfaces into separate hierarchies within each
  project, where each top-level directory under the zope package
  is a separate project.

- Moved everything to src from lib/python.

  lib/python will eventually go away. I need access to the cvs
  repository to make this happen, however.

There are probably some bits that are broken. All tests pass
and zope runs, but I haven't tried everything. There are a number
of cleanups I'll work on tomorrow.
parent e2ab28a3
This diff is collapsed.
This diff is collapsed.
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from transaction.manager import ThreadedTransactionManager
_manager = ThreadedTransactionManager()
get_transaction = _manager.new
def set_factory(factory):
_manager.txn_factory = factory
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from zope.interface import Interface
class TransactionError(StandardError):
"""An error occured due to normal transaction processing."""
class ConflictError(TransactionError):
"""Two transactions tried to modify the same object at once
This transaction should be resubmitted.
"""
class RollbackError(TransactionError):
"""An error occurred rolling back a savepoint."""
class IDataManager(Interface):
"""Data management interface for storing objects transactionally
This is currently implemented by ZODB database connections.
"""
def prepare(transaction):
"""Begin two-phase commit of a transaction.
DataManager should return True or False.
"""
def abort(transaction):
"""Abort changes made by transaction."""
def commit(transaction):
"""Commit changes made by transaction."""
def savepoint(transaction):
"""Do tentative commit of changes to this point.
Should return an object implementing IRollback
"""
class IRollback(Interface):
def rollback():
"""Rollback changes since savepoint."""
class ITransaction(Interface):
"""Transaction objects
Application code typically gets these by calling
get_transaction().
"""
def abort():
"""Abort the current transaction."""
def begin():
"""Begin a transaction."""
def commit():
"""Commit a transaction."""
def join(resource):
"""Join a resource manager to the current transaction."""
def status():
"""Return status of the current transaction."""
import logging
from transaction.interfaces import IRollback
from transaction.txn import Transaction, Status
# XXX need to change asserts of transaction status into explicit checks
# that raise some exception
# XXX need lots of error checking
class TransactionManager(object):
txn_factory = Transaction
def __init__(self):
self.logger = logging.getLogger("txn")
def new(self):
txn = self.txn_factory(self)
self.logger.debug("%s: begin", txn)
return txn
def commit(self, txn):
assert txn._status is Status.ACTIVE
txn._status = Status.PREPARING
prepare_ok = True
self.logger.debug("%s: prepare", txn)
try:
for r in txn._resources:
if prepare_ok and not r.prepare(txn):
prepare_ok = False
except:
txn._status = Status.FAILED
raise
txn._status = Status.PREPARED
# XXX An error below is intolerable. What state to use?
if prepare_ok:
self._commit(txn)
else:
self.abort(txn)
def _commit(self, txn):
self.logger.debug("%s: commit", txn)
# finish the two-phase commit
for r in txn._resources:
r.commit(txn)
txn._status = Status.COMMITTED
def abort(self, txn):
self.logger.debug("%s: abort", txn)
assert txn._status in (Status.ACTIVE, Status.PREPARED, Status.FAILED)
txn._status = Status.PREPARING
for r in txn._resources:
r.abort(txn)
txn._status = Status.ABORTED
def savepoint(self, txn):
self.logger.debug("%s: savepoint", txn)
return Rollback([r.savepoint(txn) for r in txn._resources])
class Rollback(object):
__implements__ = IRollback
def __init__(self, resources):
self._resources = resources
def rollback(self):
for r in self._resources:
r.rollback()
# make the transaction manager visible to client code
import thread
class ThreadedTransactionManager(TransactionManager):
def __init__(self):
TransactionManager.__init__(self)
self._pool = {}
def new(self):
tid = thread.get_ident()
txn = self._pool.get(tid)
if txn is None:
txn = super(ThreadedTransactionManager, self).new()
self._pool[tid] = txn
return txn
def _commit(self, txn):
tid = thread.get_ident()
assert self._pool[tid] is txn
super(ThreadedTransactionManager, self)._commit(txn)
del self._pool[tid]
def abort(self, txn):
tid = thread.get_ident()
assert self._pool[tid] is txn
super(ThreadedTransactionManager, self).abort(txn)
del self._pool[tid]
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
# Make this directory a package
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
"""Test cases for objects implementing IDataManager.
This is a combo test between Connection and DB, since the two are
rather incestuous and the DB Interface is not defined that I was
able to find.
To do a full test suite one would probably want to write a dummy
storage that will raise errors as needed for testing.
I started this test suite to reproduce a very simple error (tpc_abort
had an error and wouldn't even run if called). So it is *very*
incomplete, and even the tests that exist do not make sure that
the data actually gets written/not written to the storge.
Obviously this test suite should be expanded.
$Id: abstestIDataManager.py,v 1.2 2002/12/25 14:12:15 jim Exp $
"""
import os
from unittest import TestCase
from transaction.txn import Transaction
class IDataManagerTests(TestCase, object):
def setUp(self):
self.datamgr = None # subclass should override
self.obj = None # subclass should define Persistent object
self.txn_factory = None
def get_transaction(self):
return self.txn_factory()
################################
# IDataManager interface tests #
################################
def testCommitObj(self):
tran = self.get_transaction()
self.datamgr.prepare(tran)
self.datamgr.commit(tran)
def testAbortTran(self):
tran = self.get_transaction()
self.datamgr.prepare(tran)
self.datamgr.abort(tran)
def testRollback(self):
tran = self.get_transaction()
rb = self.datamgr.savepoint(tran)
if rb is not None:
rb.rollback()
# XXX The fact that this module has the same name as the package makes
# explicit imports impossible elsewhere. Pick a new name?
__metaclass__ = type
from transaction.interfaces import ITransaction, TransactionError
class Set(dict):
def add(self, k):
self[k] = 1
class Status:
ACTIVE = "Active"
PREPARING = "Preparing"
PREPARED = "Prepared"
FAILED = "Failed"
COMMITTED = "Committed"
ABORTING = "Aborting"
ABORTED = "Aborted"
class Transaction:
__implements__ = ITransaction
def __init__(self, manager=None, parent=None):
self._manager = manager
self._parent = parent
self._status = Status.ACTIVE
self._resources = Set()
def __repr__(self):
return "<%s %X %s>" % (self.__class__.__name__, id(self), self._status)
def begin(self, parent=None):
"""Begin a transaction.
If parent is not None, it is the parent transaction for this one.
"""
assert self._manager is not None
if parent is not None:
t = Transaction(self._manager, self)
return t
def commit(self):
"""Commit a transaction."""
assert self._manager is not None
self._manager.commit(self)
def abort(self):
"""Rollback to initial state."""
assert self._manager is not None
self._manager.abort(self)
def savepoint(self):
"""Save current progress and return a savepoint."""
assert self._manager is not None
return self._manager.savepoint(self)
def join(self, resource):
"""resource is participating in the transaction."""
assert self._manager is not None
if self._status != Status.ACTIVE:
raise TransactionError("Can't join transaction. Status=%s" %
self._status)
self._resources.add(resource)
def status(self):
"""Return the status of the transaction."""
return self._status
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