diff options
| author | Steve Piercy <web@stevepiercy.com> | 2017-05-12 01:27:20 -0700 |
|---|---|---|
| committer | Steve Piercy <web@stevepiercy.com> | 2017-05-12 01:27:20 -0700 |
| commit | dede5366e8b2ce5982806f4306cdaaa6c8e178ca (patch) | |
| tree | 5a9d27d5f518d1abc5e89c5a5a00b6d409781671 | |
| parent | 0b92dfed800117595ef00fb2847c5db9970f4cac (diff) | |
| parent | 4e27dd4c452a67d38a07eb79939dcbfcc6e82ab0 (diff) | |
| download | pyramid-dede5366e8b2ce5982806f4306cdaaa6c8e178ca.tar.gz pyramid-dede5366e8b2ce5982806f4306cdaaa6c8e178ca.tar.bz2 pyramid-dede5366e8b2ce5982806f4306cdaaa6c8e178ca.zip | |
Merge remote-tracking branch 'upstream/master'
| -rw-r--r-- | CHANGES.txt | 42 | ||||
| -rw-r--r-- | docs/conf.py | 2 | ||||
| -rw-r--r-- | docs/whatsnew-1.9.rst | 9 | ||||
| -rw-r--r-- | pyramid/tests/test_view.py | 6 | ||||
| -rw-r--r-- | pyramid/tweens.py | 60 | ||||
| -rw-r--r-- | pyramid/view.py | 26 | ||||
| -rw-r--r-- | setup.py | 2 |
7 files changed, 77 insertions, 70 deletions
diff --git a/CHANGES.txt b/CHANGES.txt index b299ed6e9..51a1e457d 100644 --- a/CHANGES.txt +++ b/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) ================== @@ -114,23 +139,6 @@ Deprecations 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 --------------------- diff --git a/docs/conf.py b/docs/conf.py index f09ae325b..e63019c63 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -70,7 +70,7 @@ intersphinx_mapping = { '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), diff --git a/docs/whatsnew-1.9.rst b/docs/whatsnew-1.9.rst index b1a406a74..0ba29625c 100644 --- a/docs/whatsnew-1.9.rst +++ b/docs/whatsnew-1.9.rst @@ -46,6 +46,15 @@ Deprecations 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 -------------------------- diff --git a/pyramid/tests/test_view.py b/pyramid/tests/test_view.py index cab42cf48..2061515b3 100644 --- a/pyramid/tests/test_view.py +++ b/pyramid/tests/test_view.py @@ -778,11 +778,11 @@ class TestViewMethodsMixin(unittest.TestCase): 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() diff --git a/pyramid/tweens.py b/pyramid/tweens.py index 673429b06..740b6961c 100644 --- a/pyramid/tweens.py +++ b/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 @@ def excview_tween_factory(handler, registry): """ 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: diff --git a/pyramid/view.py b/pyramid/view.py index 498bdde45..0c1b8cd97 100644 --- a/pyramid/view.py +++ b/pyramid/view.py @@ -657,8 +657,19 @@ class ViewMethodsMixin(object): 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 @@ class ViewMethodsMixin(object): # 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 @@ class ViewMethodsMixin(object): 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 @@ -61,7 +61,7 @@ testing_extras = tests_require + [ ] setup(name='pyramid', - version='1.9a1', + version='1.9a2', description='The Pyramid Web Framework, a Pylons project', long_description=README + '\n\n' + CHANGES, classifiers=[ |
