Skip to content

Commit

Permalink
- Replace ZODB.POSException.ConflictError with
Browse files Browse the repository at this point in the history
  transaction.interfaces.TransientError. The latter should be a more generic
  signal to retry a transaction/request.
- Get rid of ZODB dependency.
  • Loading branch information
Adam Groszer committed Mar 9, 2012
1 parent 24af2a3 commit 31660ee
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 8 deletions.
6 changes: 5 additions & 1 deletion CHANGES.txt
Expand Up @@ -5,7 +5,11 @@ CHANGES
3.14 (unreleased)
-----------------

- Nothing changed yet.
- Replace ZODB.POSException.ConflictError with
transaction.interfaces.TransientError. The latter should be a more generic
signal to retry a transaction/request.

- Get rid of ZODB dependency.


3.13.2 (2011-08-04)
Expand Down
5 changes: 3 additions & 2 deletions setup.py
Expand Up @@ -64,16 +64,17 @@ def read(*rnames):
'zope.security',
'zope.securitypolicy',
'zope.site',
'zope.testing']),
'zope.testing',
'ZODB3']),
install_requires=['zope.interface',
'ZODB3',
'zope.authentication',
'zope.component',
'zope.error',
'zope.browser>=1.2',
'zope.location',
'zope.publisher>=3.12.4',
'zope.traversing>=3.9.0',
'transaction >=1.1.0',
'setuptools',
],
include_package_data = True,
Expand Down
43 changes: 41 additions & 2 deletions src/zope/app/publication/tests/test_zopepublication.py
Expand Up @@ -172,8 +172,18 @@ def testInterfacesVerify(self):
verifyClass(interface, TestPublication)

def testRetryAllowed(self):
from ZODB.POSException import ConflictError
from zope.publisher.interfaces import Retry

# a more generic version of ConflictError, but is the better thing
from transaction.interfaces import TransientError
try:
raise TransientError
except:
self.assertRaises(Retry, self.publication.handleException,
self.object, self.request, sys.exc_info(), retry_allowed=True)

# be nice and check ZODB's ConflictError
from ZODB.POSException import ConflictError
try:
raise ConflictError
except:
Expand All @@ -187,8 +197,20 @@ def testRetryAllowed(self):
self.object, self.request, sys.exc_info(), retry_allowed=True)

def testRetryNotAllowed(self):
from transaction.interfaces import TransientError
try:
raise TransientError
except:
self.publication.handleException(
self.object, self.request, sys.exc_info(), retry_allowed=False)
value = ''.join(self.request.response._result).split()
self.assertEqual(' '.join(value[:6]),
'Traceback (most recent call last): File')
self.assertEqual(' '.join(value[-5:]),
'in testRetryNotAllowed raise TransientError'
' TransientError')

from ZODB.POSException import ConflictError
from zope.publisher.interfaces import Retry
try:
raise ConflictError
except:
Expand All @@ -201,6 +223,7 @@ def testRetryNotAllowed(self):
'in testRetryNotAllowed raise ConflictError'
' ConflictError: database conflict error')

from zope.publisher.interfaces import Retry
try:
raise Retry(sys.exc_info())
except:
Expand Down Expand Up @@ -380,6 +403,22 @@ class IConflictError(Interface):
self.assertEqual(self.object, adapter.obj)
self.assertEqual(self.request, adapter.request)

def testExceptionResetsResponseTransientError(self):
from zope.publisher.browser import TestRequest
request = TestRequest()
request.response.setHeader('Content-Type', 'application/pdf')
request.response.setCookie('spam', 'eggs')
from transaction.interfaces import TransientError
try:
raise TransientError
except:
pass
self.publication.handleException(
self.object, request, sys.exc_info(), retry_allowed=False)
self.assertEqual(request.response.getHeader('Content-Type'),
'text/html;charset=utf-8')
self.assertEqual(request.response._cookies, {})

def testExceptionResetsResponse(self):
from zope.publisher.browser import TestRequest
request = TestRequest()
Expand Down
6 changes: 3 additions & 3 deletions src/zope/app/publication/zopepublication.py
Expand Up @@ -17,14 +17,12 @@
import logging
from new import instancemethod

from ZODB.POSException import ConflictError
import transaction

import zope.component
import zope.component.interfaces
from zope.component import queryMultiAdapter
from zope.event import notify
from zope.security.interfaces import Unauthorized
from zope.interface import implements, providedBy
from zope.publisher.publish import mapply
from zope.publisher.interfaces import IExceptionSideEffects, IHeld
Expand Down Expand Up @@ -300,7 +298,9 @@ def handleException(self, object, request, exc_info, retry_allowed=True):
raise

# Convert ConflictErrors to Retry exceptions.
if retry_allowed and isinstance(exc_info[1], ConflictError):
# where transaction.interfaces.TransientError is a more generic exception
if retry_allowed and isinstance(exc_info[1],
transaction.interfaces.TransientError):
tryToLogWarning(
'ZopePublication',
'Competing writes/reads at %s: %s'
Expand Down

0 comments on commit 31660ee

Please sign in to comment.