adding after_rollback functionality
This commit is contained in:
@@ -2,7 +2,7 @@ from inspect import getargspec, getmembers, isclass, ismethod
|
||||
from util import _cfg
|
||||
|
||||
__all__ = [
|
||||
'expose', 'transactional', 'accept_noncanonical', 'after_commit'
|
||||
'expose', 'transactional', 'accept_noncanonical', 'after_commit', 'after_rollback'
|
||||
]
|
||||
|
||||
|
||||
@@ -105,6 +105,24 @@ def transactional(ignore_redirects=True):
|
||||
return deco
|
||||
|
||||
|
||||
def after_action(action_type, action):
|
||||
'''
|
||||
If utilizing the :mod:`pecan.hooks` ``TransactionHook``, allows you
|
||||
to flag a controller method to perform a callable action after the
|
||||
action_type is successfully issued.
|
||||
|
||||
:param action: The callable to call after the commit is successfully issued.
|
||||
'''
|
||||
|
||||
if action_type not in ('commit', 'rollback'):
|
||||
raise Exception, 'action_type (%s) is not valid' % action_type
|
||||
|
||||
|
||||
def deco(func):
|
||||
_cfg(func).setdefault('after_%s' % action_type, []).append(action)
|
||||
return func
|
||||
return deco
|
||||
|
||||
def after_commit(action):
|
||||
'''
|
||||
If utilizing the :mod:`pecan.hooks` ``TransactionHook``, allows you
|
||||
@@ -113,10 +131,18 @@ def after_commit(action):
|
||||
|
||||
:param action: The callable to call after the commit is successfully issued.
|
||||
'''
|
||||
def deco(func):
|
||||
_cfg(func).setdefault('after_commit', []).append(action)
|
||||
return func
|
||||
return deco
|
||||
return after_action('commit', action)
|
||||
|
||||
|
||||
def after_rollback(action):
|
||||
'''
|
||||
If utilizing the :mod:`pecan.hooks` ``TransactionHook``, allows you
|
||||
to flag a controller method to perform a callable action after the
|
||||
rollback is successfully issued.
|
||||
|
||||
:param action: The callable to call after the rollback is successfully issued.
|
||||
'''
|
||||
return after_action('rollback', action)
|
||||
|
||||
|
||||
def accept_noncanonical(func):
|
||||
|
||||
@@ -156,19 +156,23 @@ class TransactionHook(PecanHook):
|
||||
|
||||
def after(self, state):
|
||||
if state.request.transactional:
|
||||
action_name = None
|
||||
if state.request.error:
|
||||
action_name = 'after_rollback'
|
||||
self.rollback()
|
||||
else:
|
||||
action_name = 'after_commit'
|
||||
self.commit()
|
||||
|
||||
#
|
||||
# If a controller was routed to, find any
|
||||
# after_commit actions it may have registered, and perform
|
||||
# them.
|
||||
#
|
||||
#
|
||||
# If a controller was routed to, find any
|
||||
# after_* actions it may have registered, and perform
|
||||
# them.
|
||||
#
|
||||
if action_name:
|
||||
controller = getattr(state, 'controller', None)
|
||||
if controller is not None:
|
||||
actions = _cfg(controller).get('after_commit', [])
|
||||
actions = _cfg(controller).get(action_name, [])
|
||||
for action in actions:
|
||||
action()
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
from cStringIO import StringIO
|
||||
from pecan import make_app, expose, request, redirect
|
||||
from pecan import make_app, expose, request, redirect, abort
|
||||
from pecan.core import state
|
||||
from pecan.hooks import PecanHook, TransactionHook, HookController, RequestViewerHook
|
||||
from pecan.configuration import Config
|
||||
from pecan.decorators import transactional, after_commit
|
||||
from pecan.decorators import transactional, after_commit, after_rollback
|
||||
from copy import copy
|
||||
from formencode import Schema, validators
|
||||
from webtest import TestApp
|
||||
@@ -559,6 +559,17 @@ class TestTransactionHook(object):
|
||||
def decorated(self):
|
||||
run_hook.append('inside')
|
||||
return 'Decorated Method!'
|
||||
|
||||
@expose()
|
||||
@after_rollback(action('action-three'))
|
||||
def rollback(self):
|
||||
abort(500)
|
||||
|
||||
@expose()
|
||||
@transactional()
|
||||
@after_rollback(action('action-four'))
|
||||
def rollback_decorated(self):
|
||||
abort(500)
|
||||
|
||||
def gen(event):
|
||||
return lambda: run_hook.append(event)
|
||||
@@ -612,6 +623,39 @@ class TestTransactionHook(object):
|
||||
|
||||
run_hook = []
|
||||
|
||||
response = app.get('/rollback', expect_errors=True)
|
||||
assert response.status_int == 500
|
||||
|
||||
assert len(run_hook) == 2
|
||||
assert run_hook[0] == 'start_ro'
|
||||
assert run_hook[1] == 'clear'
|
||||
|
||||
run_hook = []
|
||||
|
||||
response = app.post('/rollback', expect_errors=True)
|
||||
assert response.status_int == 500
|
||||
|
||||
assert len(run_hook) == 4
|
||||
assert run_hook[0] == 'start'
|
||||
assert run_hook[1] == 'rollback'
|
||||
assert run_hook[2] == 'action-three'
|
||||
assert run_hook[3] == 'clear'
|
||||
|
||||
run_hook = []
|
||||
|
||||
response = app.get('/rollback_decorated', expect_errors=True)
|
||||
assert response.status_int == 500
|
||||
|
||||
assert len(run_hook) == 6
|
||||
assert run_hook[0] == 'start_ro'
|
||||
assert run_hook[1] == 'clear'
|
||||
assert run_hook[2] == 'start'
|
||||
assert run_hook[3] == 'rollback'
|
||||
assert run_hook[4] == 'action-four'
|
||||
assert run_hook[5] == 'clear'
|
||||
|
||||
run_hook = []
|
||||
|
||||
response = app.get('/fourohfour', status=404)
|
||||
assert response.status_int == 404
|
||||
|
||||
|
||||
Reference in New Issue
Block a user