Exemple #1
0
    def invoke_exception_view(self,
                              exc_info=None,
                              request=None,
                              secure=True,
                              reraise=False):
        """ Executes an exception view related to the request it's called upon.
        The arguments it takes are these:

        ``exc_info``

            If provided, should be a 3-tuple in the form provided by
            ``sys.exc_info()``.  If not provided,
            ``sys.exc_info()`` will be called to obtain the current
            interpreter exception information.  Default: ``None``.

        ``request``

            If the request to be used is not the same one as the instance that
            this method is called upon, it may be passed here.  Default:
            ``None``.

        ``secure``

            If the exception view should not be rendered if the current user
            does not have the appropriate permission, this should be ``True``.
            Default: ``True``.

        ``reraise``

            A boolean indicating whether the original error should be reraised
            if a :term:`response` object could not be created. If ``False``
            then an :class:`pyramid.httpexceptions.HTTPNotFound`` exception
            will be raised. Default: ``False``.

        If a response is generated then ``request.exception`` and
        ``request.exc_info`` will be left at the values used to render the
        response. Otherwise the previous values for ``request.exception`` and
        ``request.exc_info`` will be restored.

        .. versionadded:: 1.7

        .. versionchanged:: 1.9
           The ``request.exception`` and ``request.exc_info`` properties will
           reflect the exception used to render the response where previously
           they were reset to the values prior to invoking the method.

           Also added the ``reraise`` argument.

        """
        if request is None:
            request = self
        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)

        # clear old generated request.response, if any; it may
        # have been mutated by the view, and its state is not
        # sane (e.g. caching headers)
        with hide_attrs(request, 'response', 'exc_info', 'exception'):
            attrs['exception'] = exc
            attrs['exc_info'] = exc_info
            # we use .get instead of .__getitem__ below due to
            # https://github.com/Pylons/pyramid/issues/700
            request_iface = attrs.get('request_iface', IRequest)

            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,
                )
            except Exception:
                if reraise:
                    reraise_(*exc_info)
                raise
            finally:
                manager.pop()

        if response is None:
            if reraise:
                reraise_(*exc_info)
            raise HTTPNotFound

        # successful response, overwrite exception/exc_info
        attrs['exception'] = exc
        attrs['exc_info'] = exc_info
        return response
Exemple #2
0
    def invoke_exception_view(
        self, exc_info=None, request=None, secure=True, reraise=False
    ):
        """ Executes an exception view related to the request it's called upon.
        The arguments it takes are these:

        ``exc_info``

            If provided, should be a 3-tuple in the form provided by
            ``sys.exc_info()``.  If not provided,
            ``sys.exc_info()`` will be called to obtain the current
            interpreter exception information.  Default: ``None``.

        ``request``

            If the request to be used is not the same one as the instance that
            this method is called upon, it may be passed here.  Default:
            ``None``.

        ``secure``

            If the exception view should not be rendered if the current user
            does not have the appropriate permission, this should be ``True``.
            Default: ``True``.

        ``reraise``

            A boolean indicating whether the original error should be reraised
            if a :term:`response` object could not be created. If ``False``
            then an :class:`pyramid.httpexceptions.HTTPNotFound`` exception
            will be raised. Default: ``False``.

        If a response is generated then ``request.exception`` and
        ``request.exc_info`` will be left at the values used to render the
        response. Otherwise the previous values for ``request.exception`` and
        ``request.exc_info`` will be restored.

        .. versionadded:: 1.7

        .. versionchanged:: 1.9
           The ``request.exception`` and ``request.exc_info`` properties will
           reflect the exception used to render the response where previously
           they were reset to the values prior to invoking the method.

           Also added the ``reraise`` argument.

        """
        if request is None:
            request = self
        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)

        # clear old generated request.response, if any; it may
        # have been mutated by the view, and its state is not
        # sane (e.g. caching headers)
        with hide_attrs(request, 'response', 'exc_info', 'exception'):
            attrs['exception'] = exc
            attrs['exc_info'] = exc_info
            # we use .get instead of .__getitem__ below due to
            # https://github.com/Pylons/pyramid/issues/700
            request_iface = attrs.get('request_iface', IRequest)

            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,
                )
            except Exception:
                if reraise:
                    reraise_(*exc_info)
                raise
            finally:
                manager.pop()

        if response is None:
            if reraise:
                reraise_(*exc_info)
            raise HTTPNotFound

        # successful response, overwrite exception/exc_info
        attrs['exception'] = exc
        attrs['exc_info'] = exc_info
        return response