diff options
author | Jonathan LaCour <jonathan@cleverdevil.org> | 2013-04-23 22:25:06 -0700 |
---|---|---|
committer | Jonathan LaCour <jonathan@cleverdevil.org> | 2013-04-23 22:25:06 -0700 |
commit | acdca0b861e204b488e69129224f305d4cccd89c (patch) | |
tree | f51096ee21f63d38bff289dfe8ded52203a992ed | |
parent | 0f94eea7a301ae5493097145700aba98f932fa3e (diff) | |
parent | 2813782d1699e84096018ce01177af1c24cf2890 (diff) | |
download | pecan-acdca0b861e204b488e69129224f305d4cccd89c.tar.gz |
Merge pull request #207 from ryanpetrello/next
Resolve a bug in TransactionHook.
-rw-r--r-- | pecan/hooks.py | 5 | ||||
-rw-r--r-- | pecan/tests/test_hooks.py | 43 |
2 files changed, 46 insertions, 2 deletions
diff --git a/pecan/hooks.py b/pecan/hooks.py index 97dc416..f7422b8 100644 --- a/pecan/hooks.py +++ b/pecan/hooks.py @@ -144,7 +144,8 @@ class TransactionHook(PecanHook): self.start_ro() def before(self, state): - if self.is_transactional(state) and not state.request.transactional: + if self.is_transactional(state) \ + and not getattr(state.request, 'transactional', False): self.clear() state.request.transactional = True self.start() @@ -170,7 +171,7 @@ class TransactionHook(PecanHook): state.request.error = True def after(self, state): - if state.request.transactional: + if getattr(state.request, 'transactional', False): action_name = None if state.request.error: action_name = 'after_rollback' diff --git a/pecan/tests/test_hooks.py b/pecan/tests/test_hooks.py index 5ad4d46..8f6c55a 100644 --- a/pecan/tests/test_hooks.py +++ b/pecan/tests/test_hooks.py @@ -992,6 +992,49 @@ class TestTransactionHook(PecanTestCase): assert run_hook[2] == 'commit' assert run_hook[3] == 'clear' + def test_transaction_hook_with_broken_hook(self): + """ + In a scenario where a preceding hook throws an exception, + ensure that TransactionHook still rolls back properly. + """ + run_hook = [] + + class RootController(object): + @expose() + def index(self): + return 'Hello, World!' + + def gen(event): + return lambda: run_hook.append(event) + + class MyCustomException(Exception): + pass + + class MyHook(PecanHook): + + def on_route(self, state): + raise MyCustomException('BROKEN!') + + app = TestApp(make_app(RootController(), hooks=[ + MyHook(), + TransactionHook( + start=gen('start'), + start_ro=gen('start_ro'), + commit=gen('commit'), + rollback=gen('rollback'), + clear=gen('clear') + ) + ])) + + self.assertRaises( + MyCustomException, + app.get, + '/' + ) + + assert len(run_hook) == 1 + assert run_hook[0] == 'clear' + class TestRequestViewerHook(PecanTestCase): |