adding after_rollback functionality
This commit is contained in:
		@@ -2,7 +2,7 @@ from inspect import getargspec, getmembers, isclass, ismethod
 | 
				
			|||||||
from util import _cfg
 | 
					from util import _cfg
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__all__ = [
 | 
					__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
 | 
					    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):
 | 
					def after_commit(action):
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
    If utilizing the :mod:`pecan.hooks` ``TransactionHook``, allows you
 | 
					    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.
 | 
					    :param action: The callable to call after the commit is successfully issued.
 | 
				
			||||||
    '''
 | 
					    '''
 | 
				
			||||||
    def deco(func):
 | 
					    return  after_action('commit', action)
 | 
				
			||||||
        _cfg(func).setdefault('after_commit', []).append(action)
 | 
					
 | 
				
			||||||
        return func
 | 
					
 | 
				
			||||||
    return deco
 | 
					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):
 | 
					def accept_noncanonical(func):
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -156,19 +156,23 @@ class TransactionHook(PecanHook):
 | 
				
			|||||||
    
 | 
					    
 | 
				
			||||||
    def after(self, state):
 | 
					    def after(self, state):
 | 
				
			||||||
        if state.request.transactional:
 | 
					        if state.request.transactional:
 | 
				
			||||||
 | 
					            action_name = None
 | 
				
			||||||
            if state.request.error:
 | 
					            if state.request.error:
 | 
				
			||||||
 | 
					                action_name = 'after_rollback'
 | 
				
			||||||
                self.rollback()
 | 
					                self.rollback()
 | 
				
			||||||
            else:
 | 
					            else:
 | 
				
			||||||
 | 
					                action_name = 'after_commit'
 | 
				
			||||||
                self.commit()
 | 
					                self.commit()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                #
 | 
					            #
 | 
				
			||||||
                # If a controller was routed to, find any
 | 
					            # If a controller was routed to, find any
 | 
				
			||||||
                # after_commit actions it may have registered, and perform
 | 
					            # after_* actions it may have registered, and perform
 | 
				
			||||||
                # them.
 | 
					            # them.
 | 
				
			||||||
                #
 | 
					            #
 | 
				
			||||||
 | 
					            if action_name:
 | 
				
			||||||
                controller = getattr(state, 'controller', None)
 | 
					                controller = getattr(state, 'controller', None)
 | 
				
			||||||
                if controller is not None:
 | 
					                if controller is not None:
 | 
				
			||||||
                    actions = _cfg(controller).get('after_commit', [])
 | 
					                    actions = _cfg(controller).get(action_name, [])
 | 
				
			||||||
                    for action in actions:
 | 
					                    for action in actions:
 | 
				
			||||||
                        action()
 | 
					                        action()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,9 +1,9 @@
 | 
				
			|||||||
from cStringIO           import StringIO
 | 
					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.core          import state
 | 
				
			||||||
from pecan.hooks         import PecanHook, TransactionHook, HookController, RequestViewerHook
 | 
					from pecan.hooks         import PecanHook, TransactionHook, HookController, RequestViewerHook
 | 
				
			||||||
from pecan.configuration import Config
 | 
					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 copy                import copy
 | 
				
			||||||
from formencode          import Schema, validators
 | 
					from formencode          import Schema, validators
 | 
				
			||||||
from webtest             import TestApp
 | 
					from webtest             import TestApp
 | 
				
			||||||
@@ -560,6 +560,17 @@ class TestTransactionHook(object):
 | 
				
			|||||||
                run_hook.append('inside')
 | 
					                run_hook.append('inside')
 | 
				
			||||||
                return 'Decorated Method!'
 | 
					                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):
 | 
					        def gen(event):
 | 
				
			||||||
            return lambda: run_hook.append(event)
 | 
					            return lambda: run_hook.append(event)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -612,6 +623,39 @@ class TestTransactionHook(object):
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        run_hook = []
 | 
					        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)
 | 
					        response = app.get('/fourohfour', status=404)
 | 
				
			||||||
        assert response.status_int == 404
 | 
					        assert response.status_int == 404
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user