Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix excview tween to reraise the original exception if left unhandled… #2567

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/api/interfaces.rst
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ Other Interfaces
.. autointerface:: IRenderer
:members:

.. autointerface:: IRequestFactory
:members:

.. autointerface:: IResponseFactory
:members:

Expand Down
73 changes: 73 additions & 0 deletions pyramid/tests/test_tweens.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import unittest
from pyramid import testing

class Test_excview_tween_factory(unittest.TestCase):
def setUp(self):
self.config = testing.setUp()

def tearDown(self):
testing.tearDown()

def _makeOne(self, handler, registry=None):
from pyramid.tweens import excview_tween_factory
if registry is None:
registry = self.config.registry
return excview_tween_factory(handler, registry)

def test_it_passthrough_no_exception(self):
dummy_response = DummyResponse()
def handler(request):
return dummy_response
tween = self._makeOne(handler)
request = DummyRequest()
result = tween(request)
self.assertTrue(result is dummy_response)

def test_it_catches_notfound(self):
from pyramid.request import Request
from pyramid.httpexceptions import HTTPNotFound
self.config.add_notfound_view(lambda exc, request: exc)
def handler(request):
raise HTTPNotFound
tween = self._makeOne(handler)
request = Request.blank('/')
result = tween(request)
self.assertEqual(result.status, '404 Not Found')

def test_it_catches_with_predicate(self):
from pyramid.request import Request
from pyramid.response import Response
def excview(request):
return Response('foo')
self.config.add_view(excview, context=ValueError, request_method='GET')
def handler(request):
raise ValueError
tween = self._makeOne(handler)
request = Request.blank('/')
result = tween(request)
self.assertTrue(b'foo' in result.body)

def test_it_reraises_on_mismatch(self):
from pyramid.request import Request
def excview(request): pass
self.config.add_view(excview, context=ValueError, request_method='GET')
def handler(request):
raise ValueError
tween = self._makeOne(handler)
request = Request.blank('/')
request.method = 'POST'
self.assertRaises(ValueError, lambda: tween(request))

def test_it_reraises_on_no_match(self):
from pyramid.request import Request
def handler(request):
raise ValueError
tween = self._makeOne(handler)
request = Request.blank('/')
self.assertRaises(ValueError, lambda: tween(request))

class DummyRequest:
pass

class DummyResponse:
pass
31 changes: 21 additions & 10 deletions pyramid/tweens.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import sys

from pyramid.compat import reraise
from pyramid.exceptions import PredicateMismatch
from pyramid.interfaces import (
IExceptionViewClassifier,
IRequest,
Expand Down Expand Up @@ -38,17 +40,26 @@ def excview_tween(request):
# https://github.com/Pylons/pyramid/issues/700
request_iface = attrs.get('request_iface', IRequest)
provides = providedBy(exc)
response = _call_view(
registry,
request,
exc,
provides,
'',
view_classifier=IExceptionViewClassifier,
request_iface=request_iface.combined
)
try:
response = _call_view(
registry,
request,
exc,
provides,
'',
view_classifier=IExceptionViewClassifier,
request_iface=request_iface.combined
)

# if views matched but did not pass predicates, squash the error
# and re-raise the original exception
except PredicateMismatch:
response = None

# re-raise the original exception as no exception views were
# able to handle the error
if response is None:
raise
reraise(*attrs['exc_info'])

return response

Expand Down