Steve Piercy
2017-05-12 dede5366e8b2ce5982806f4306cdaaa6c8e178ca
Merge remote-tracking branch 'upstream/master'
7 files modified
147 ■■■■ changed files
CHANGES.txt 42 ●●●●● patch | view | raw | blame | history
docs/conf.py 2 ●●● patch | view | raw | blame | history
docs/whatsnew-1.9.rst 9 ●●●●● patch | view | raw | blame | history
pyramid/tests/test_view.py 6 ●●●● patch | view | raw | blame | history
pyramid/tweens.py 60 ●●●● patch | view | raw | blame | history
pyramid/view.py 26 ●●●● patch | view | raw | blame | history
setup.py 2 ●●● patch | view | raw | blame | history
CHANGES.txt
@@ -1,3 +1,28 @@
1.9a2 (2017-05-09)
==================
Backward Incompatibilities
--------------------------
- ``request.exception`` and ``request.exc_info`` will only be set if the
  response was generated by the EXCVIEW tween. This is to avoid any confusion
  where a response was generated elsewhere in the pipeline and not in
  direct relation to the original exception. If anyone upstream wants to
  catch and render responses for exceptions they should set
  ``request.exception`` and ``request.exc_info`` themselves to indicate
  the exception that was squashed when generating the response.
  Similar behavior occurs with ``request.invoke_exception_view`` in which
  the exception properties are set to reflect the exception if a response
  is successfully generated by the method.
  This is a very minor incompatibility. Most tweens right now would give
  priority to the raised exception and ignore ``request.exception``. This
  change just improves and clarifies that bookkeeping by trying to be
  more clear about the relationship between the response and its squashed
  exception. See https://github.com/Pylons/pyramid/pull/3029 and
  https://github.com/Pylons/pyramid/pull/3031
1.9a1 (2017-05-01)
==================
@@ -113,23 +138,6 @@
  See https://github.com/Pylons/pyramid/pull/2854 and
  https://github.com/Pylons/pyramid/pull/3019
Backward Incompatibilities
--------------------------
- ``request.exception`` and ``request.exc_info`` will only be set if the
  response was generated by the EXCVIEW tween. This is to avoid any confusion
  where a response was generated elsewhere in the pipeline and not in
  direct relation to the original exception. If anyone upstream wants to
  catch and render responses for exceptions they should set
  ``request.exception`` and ``request.exc_info`` themselves to indicate
  the exception that was squashed when generating the response.
  This is a very minor incompatibility. Most tweens right now would give
  priority to the raised exception and ignore ``request.exception``. This
  change just improves and clarifies that bookkeeping by trying to be
  more clear about the relationship between the response and its squashed
  exception. See https://github.com/Pylons/pyramid/pull/3029
Documentation Changes
---------------------
docs/conf.py
@@ -70,7 +70,7 @@
    'plaster': ('http://docs.pylonsproject.org/projects/plaster/en/latest/', None),
    'pylonswebframework': ('http://docs.pylonsproject.org/projects/pylons-webframework/en/latest/', None),
    'python': ('https://docs.python.org/3', None),
    'pytest': ('http://pytest.org/latest/', None),
    'pytest': ('https://pytest.org/en/latest/', None),
    'sphinx': ('http://www.sphinx-doc.org/en/latest', None),
    'sqla': ('http://docs.sqlalchemy.org/en/latest', None),
    'tm': ('http://docs.pylonsproject.org/projects/pyramid-tm/en/latest/', None),
docs/whatsnew-1.9.rst
@@ -46,6 +46,15 @@
  See https://github.com/Pylons/pyramid/pull/2854 and https://github.com/Pylons/pyramid/pull/3019
Backward Incompatibilities
--------------------------
- ``request.exception`` and ``request.exc_info`` will only be set if the response was generated by the EXCVIEW tween. This is to avoid any confusion where a response was generated elsewhere in the pipeline and not in direct relation to the original exception. If anyone upstream wants to catch and render responses for exceptions they should set ``request.exception`` and ``request.exc_info`` themselves to indicate the exception that was squashed when generating the response.
  Similar behavior occurs with :meth:`pyramid.request.Request.invoke_exception_view` in which the exception properties are set to reflect the exception if a response is successfully generated by the method.
  This is a very minor incompatibility. Most tweens right now would give priority to the raised exception and ignore ``request.exception``. This change just improves and clarifies that bookkeeping by trying to be more clear about the relationship between the response and its squashed exception. See https://github.com/Pylons/pyramid/pull/3029 and https://github.com/Pylons/pyramid/pull/3031
Documentation Enhancements
--------------------------
pyramid/tests/test_view.py
@@ -778,11 +778,11 @@
        orig_response = request.response = DummyResponse(b'foo')
        try:
            raise RuntimeError
        except RuntimeError:
        except RuntimeError as ex:
            response = request.invoke_exception_view()
            self.assertEqual(response.app_iter, [b'bar'])
            self.assertTrue(request.exception is orig_exc)
            self.assertTrue(request.exc_info is orig_exc_info)
            self.assertTrue(request.exception is ex)
            self.assertTrue(request.exc_info[1] is ex)
            self.assertTrue(request.response is orig_response)
        else: # pragma: no cover
            self.fail()
pyramid/tweens.py
@@ -1,55 +1,18 @@
import sys
from pyramid.compat import reraise
from pyramid.exceptions import PredicateMismatch
from pyramid.interfaces import (
    IExceptionViewClassifier,
    IRequest,
    )
from zope.interface import providedBy
from pyramid.view import _call_view
from pyramid.httpexceptions import HTTPNotFound
def _error_handler(request, exc):
    # NOTE: we do not need to delete exc_info because this function
    # should never be in the call stack of the exception
    exc_info = sys.exc_info()
    attrs = request.__dict__
    attrs['exc_info'] = exc_info
    attrs['exception'] = 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)
    if 'response' in attrs:
        del attrs['response']
    # we use .get instead of .__getitem__ below due to
    # https://github.com/Pylons/pyramid/issues/700
    request_iface = attrs.get('request_iface', IRequest)
    provides = providedBy(exc)
    try:
        response = _call_view(
            request.registry,
            request,
            exc,
            provides,
            '',
            view_classifier=IExceptionViewClassifier,
            request_iface=request_iface.combined
            )
    # if views matched but did not pass predicates then treat the
    # same as not finding any matching views
    except PredicateMismatch:
        response = None
    # re-raise the original exception as no exception views were
    # able to handle the error
    if response is None:
        if 'exception' in attrs:
            del attrs['exception']
        if 'exc_info' in attrs:
            del attrs['exc_info']
        response = request.invoke_exception_view(exc_info)
    except HTTPNotFound:
        # re-raise the original exception as no exception views were
        # able to handle the error
        reraise(*exc_info)
    return response
@@ -58,7 +21,18 @@
    """ A :term:`tween` factory which produces a tween that catches an
    exception raised by downstream tweens (or the main Pyramid request
    handler) and, if possible, converts it into a Response using an
    :term:`exception view`."""
    :term:`exception view`.
    .. versionchanged:: 1.9
       The ``request.response`` will be remain unchanged even if the tween
       handles an exception. Previously it was deleted after handling an
       exception.
       Also, ``request.exception`` and ``request.exc_info`` are only set if
       the tween handles an exception and returns a response otherwise they
       are left at their original values.
    """
    def excview_tween(request):
        try:
pyramid/view.py
@@ -657,8 +657,19 @@
        This method returns a :term:`response` object or raises
        :class:`pyramid.httpexceptions.HTTPNotFound` if a matching view cannot
        be found."""
        be found.
        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.
        .. 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.
        """
        if request is None:
            request = self
        registry = getattr(request, 'registry', None)
@@ -673,7 +684,7 @@
        # 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, 'exception', 'exc_info', 'response'):
        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
@@ -690,6 +701,11 @@
                secure=secure,
                request_iface=request_iface.combined,
                )
            if response is None:
                raise HTTPNotFound
            return response
        if response is None:
            raise HTTPNotFound
        # successful response, overwrite exception/exc_info
        attrs['exception'] = exc
        attrs['exc_info'] = exc_info
        return response
setup.py
@@ -61,7 +61,7 @@
    ]
setup(name='pyramid',
      version='1.9a1',
      version='1.9a2',
      description='The Pyramid Web Framework, a Pylons project',
      long_description=README + '\n\n' + CHANGES,
      classifiers=[