Michael Merickel
2017-06-05 22215dfabb3e8b2b2ca494299766d4703c75f268
Merge pull request #3060 from Pylons/push_threadlocals_exception_view

When invoking an exception view, push the new threadlocals
3 files modified
60 ■■■■ changed files
pyramid/tests/test_view.py 19 ●●●●● patch | view | raw | blame | history
pyramid/threadlocal.py 2 ●●● patch | view | raw | blame | history
pyramid/view.py 39 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_view.py
@@ -790,6 +790,8 @@
    def test_it_supports_alternate_requests(self):
        def exc_view(exc, request):
            self.assertTrue(request is other_req)
            from pyramid.threadlocal import get_current_request
            self.assertTrue(get_current_request() is other_req)
            return DummyResponse(b'foo')
        self.config.add_view(exc_view, context=RuntimeError)
        request = self._makeOne()
@@ -816,6 +818,23 @@
        else: # pragma: no cover
            self.fail()
    def test_it_raises_if_no_registry(self):
        request = self._makeOne()
        del request.registry
        from pyramid.threadlocal import manager
        manager.push({'registry': None, 'request': request})
        try:
            raise RuntimeError
        except RuntimeError:
            try:
                request.invoke_exception_view()
            except RuntimeError as e:
                self.assertEqual(e.args[0], "Unable to retrieve registry")
        else: # pragma: no cover
            self.fail()
        finally:
            manager.pop()
    def test_it_supports_alternate_exc_info(self):
        def exc_view(exc, request):
            self.assertTrue(request.exc_info is exc_info)
pyramid/threadlocal.py
@@ -31,7 +31,7 @@
        self.stack[:] = []
def defaults():
    return {'request':None, 'registry':global_registry}
    return {'request': None, 'registry': global_registry}
manager = ThreadLocalManager(default=defaults)
pyramid/view.py
@@ -28,7 +28,11 @@
    default_exceptionresponse_view,
    )
from pyramid.threadlocal import get_current_registry
from pyramid.threadlocal import (
    get_current_registry,
    manager,
    )
from pyramid.util import hide_attrs
_marker = object()
@@ -675,8 +679,13 @@
        registry = getattr(request, 'registry', None)
        if registry is None:
            registry = get_current_registry()
        if registry is None:
            raise RuntimeError("Unable to retrieve registry")
        if exc_info is None:
            exc_info = sys.exc_info()
        exc = exc_info[1]
        attrs = request.__dict__
        context_iface = providedBy(exc)
@@ -690,17 +699,23 @@
            # we use .get instead of .__getitem__ below due to
            # https://github.com/Pylons/pyramid/issues/700
            request_iface = attrs.get('request_iface', IRequest)
            response = _call_view(
                registry,
                request,
                exc,
                context_iface,
                '',
                view_types=None,
                view_classifier=IExceptionViewClassifier,
                secure=secure,
                request_iface=request_iface.combined,
                )
            manager.push({'request': request, 'registry': registry})
            try:
                response = _call_view(
                    registry,
                    request,
                    exc,
                    context_iface,
                    '',
                    view_types=None,
                    view_classifier=IExceptionViewClassifier,
                    secure=secure,
                    request_iface=request_iface.combined,
                    )
            finally:
                manager.pop()
        if response is None:
            raise HTTPNotFound