prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  remove request.exception if the excview tween fails to handle the exception
  Pyramid 1.9 makes `request.exception` and `request.exc_info` a little more important as I've moved the pyramid_tm tween over the excview and in general would advocate to move most tweens over the excview. With that in mind it's currently not possible to test `request.exception` to see if the response was rendered in relation to that exception - the excview tween sets the exception even if it failed to squash it (attempted to render an excview and couldn't find one). Ideally the exception would be related to the response that was generated when it was squashed. This would be more explicit if we used `response.exception` to indicate the response is from a squashed exception but I think that's a larger change.
  
  I'm proposing to remove `request.exception` and `request.exc_info` in the excview tween if it reraises the original exception. This makes introspection `request.exception` more reliable by upstream tweens that want to know what the squashed exception was... Of course any raised exception should be more interesting than the original `request.exception` but if the tween receives a response then they can see if it is a response generated by a squashed exception or if it is a "normal" response.
  
  </issue>
  <code>
  [start of pyramid/tweens.py]
  1 import sys
  2 
  3 from pyramid.compat import reraise
  4 from pyramid.exceptions import PredicateMismatch
  5 from pyramid.interfaces import (
  6     IExceptionViewClassifier,
  7     IRequest,
  8     )
  9 
  10 from zope.interface import providedBy
  11 from pyramid.view import _call_view
  12 
  13 def excview_tween_factory(handler, registry):
  14     """ A :term:`tween` factory which produces a tween that catches an
  15     exception raised by downstream tweens (or the main Pyramid request
  16     handler) and, if possible, converts it into a Response using an
  17     :term:`exception view`."""
  18 
  19     def excview_tween(request):
  20         attrs = request.__dict__
  21         try:
  22             response = handler(request)
  23         except Exception as exc:
  24             # WARNING: do not assign the result of sys.exc_info() to a local
  25             # var here, doing so will cause a leak.  We used to actually
  26             # explicitly delete both "exception" and "exc_info" from ``attrs``
  27             # in a ``finally:`` clause below, but now we do not because these
  28             # attributes are useful to upstream tweens.  This actually still
  29             # apparently causes a reference cycle, but it is broken
  30             # successfully by the garbage collector (see
  31             # https://github.com/Pylons/pyramid/issues/1223).
  32             attrs['exc_info'] = sys.exc_info()
  33             attrs['exception'] = exc
  34             # clear old generated request.response, if any; it may
  35             # have been mutated by the view, and its state is not
  36             # sane (e.g. caching headers)
  37             if 'response' in attrs:
  38                 del attrs['response']
  39             # we use .get instead of .__getitem__ below due to
  40             # https://github.com/Pylons/pyramid/issues/700
  41             request_iface = attrs.get('request_iface', IRequest)
  42             provides = providedBy(exc)
  43             try:
  44                 response = _call_view(
  45                     registry,
  46                     request,
  47                     exc,
  48                     provides,
  49                     '',
  50                     view_classifier=IExceptionViewClassifier,
  51                     request_iface=request_iface.combined
  52                     )
  53 
  54             # if views matched but did not pass predicates, squash the error
  55             # and re-raise the original exception
  56             except PredicateMismatch:
  57                 response = None
  58 
  59             # re-raise the original exception as no exception views were
  60             # able to handle the error
  61             if response is None:
  62                 reraise(*attrs['exc_info'])
  63 
  64         return response
  65 
  66     return excview_tween
  67 
  68 MAIN = 'MAIN'
  69 INGRESS = 'INGRESS'
  70 EXCVIEW = 'pyramid.tweens.excview_tween_factory'
  71
  [end of pyramid/tweens.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/pyramid/tweens.py b/pyramid/tweens.py
  --- a/pyramid/tweens.py
  +++ b/pyramid/tweens.py
  @@ -10,6 +10,50 @@
   from zope.interface import providedBy
   from pyramid.view import _call_view
   
  +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']
  +        reraise(*exc_info)
  +
  +    return response
  +
   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
  @@ -17,50 +61,10 @@
       :term:`exception view`."""
   
       def excview_tween(request):
  -        attrs = request.__dict__
           try:
               response = handler(request)
           except Exception as exc:
  -            # WARNING: do not assign the result of sys.exc_info() to a local
  -            # var here, doing so will cause a leak.  We used to actually
  -            # explicitly delete both "exception" and "exc_info" from ``attrs``
  -            # in a ``finally:`` clause below, but now we do not because these
  -            # attributes are useful to upstream tweens.  This actually still
  -            # apparently causes a reference cycle, but it is broken
  -            # successfully by the garbage collector (see
  -            # https://github.com/Pylons/pyramid/issues/1223).
  -            attrs['exc_info'] = sys.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(
  -                    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:
  -                reraise(*attrs['exc_info'])
  -
  +            response = _error_handler(request, exc)
           return response
   
       return excview_tween
  
verification_info: {"golden_diff": "diff --git a/pyramid/tweens.py b/pyramid/tweens.py\n--- a/pyramid/tweens.py\n+++ b/pyramid/tweens.py\n@@ -10,6 +10,50 @@\n from zope.interface import providedBy\n from pyramid.view import _call_view\n \n+def _error_handler(request, exc):\n+    # NOTE: we do not need to delete exc_info because this function\n+    # should never be in the call stack of the exception\n+    exc_info = sys.exc_info()\n+\n+    attrs = request.__dict__\n+    attrs['exc_info'] = exc_info\n+    attrs['exception'] = exc\n+    # clear old generated request.response, if any; it may\n+    # have been mutated by the view, and its state is not\n+    # sane (e.g. caching headers)\n+    if 'response' in attrs:\n+        del attrs['response']\n+    # we use .get instead of .__getitem__ below due to\n+    # https://github.com/Pylons/pyramid/issues/700\n+    request_iface = attrs.get('request_iface', IRequest)\n+    provides = providedBy(exc)\n+    try:\n+        response = _call_view(\n+            request.registry,\n+            request,\n+            exc,\n+            provides,\n+            '',\n+            view_classifier=IExceptionViewClassifier,\n+            request_iface=request_iface.combined\n+            )\n+\n+    # if views matched but did not pass predicates then treat the\n+    # same as not finding any matching views\n+    except PredicateMismatch:\n+        response = None\n+\n+    # re-raise the original exception as no exception views were\n+    # able to handle the error\n+    if response is None:\n+        if 'exception' in attrs:\n+            del attrs['exception']\n+        if 'exc_info' in attrs:\n+            del attrs['exc_info']\n+        reraise(*exc_info)\n+\n+    return response\n+\n def excview_tween_factory(handler, registry):\n     \"\"\" A :term:`tween` factory which produces a tween that catches an\n     exception raised by downstream tweens (or the main Pyramid request\n@@ -17,50 +61,10 @@\n     :term:`exception view`.\"\"\"\n \n     def excview_tween(request):\n-        attrs = request.__dict__\n         try:\n             response = handler(request)\n         except Exception as exc:\n-            # WARNING: do not assign the result of sys.exc_info() to a local\n-            # var here, doing so will cause a leak.  We used to actually\n-            # explicitly delete both \"exception\" and \"exc_info\" from ``attrs``\n-            # in a ``finally:`` clause below, but now we do not because these\n-            # attributes are useful to upstream tweens.  This actually still\n-            # apparently causes a reference cycle, but it is broken\n-            # successfully by the garbage collector (see\n-            # https://github.com/Pylons/pyramid/issues/1223).\n-            attrs['exc_info'] = sys.exc_info()\n-            attrs['exception'] = exc\n-            # clear old generated request.response, if any; it may\n-            # have been mutated by the view, and its state is not\n-            # sane (e.g. caching headers)\n-            if 'response' in attrs:\n-                del attrs['response']\n-            # we use .get instead of .__getitem__ below due to\n-            # https://github.com/Pylons/pyramid/issues/700\n-            request_iface = attrs.get('request_iface', IRequest)\n-            provides = providedBy(exc)\n-            try:\n-                response = _call_view(\n-                    registry,\n-                    request,\n-                    exc,\n-                    provides,\n-                    '',\n-                    view_classifier=IExceptionViewClassifier,\n-                    request_iface=request_iface.combined\n-                    )\n-\n-            # if views matched but did not pass predicates, squash the error\n-            # and re-raise the original exception\n-            except PredicateMismatch:\n-                response = None\n-\n-            # re-raise the original exception as no exception views were\n-            # able to handle the error\n-            if response is None:\n-                reraise(*attrs['exc_info'])\n-\n+            response = _error_handler(request, exc)\n         return response\n \n     return excview_tween\n", "issue": "remove request.exception if the excview tween fails to handle the exception\nPyramid 1.9 makes `request.exception` and `request.exc_info` a little more important as I've moved the pyramid_tm tween over the excview and in general would advocate to move most tweens over the excview. With that in mind it's currently not possible to test `request.exception` to see if the response was rendered in relation to that exception - the excview tween sets the exception even if it failed to squash it (attempted to render an excview and couldn't find one). Ideally the exception would be related to the response that was generated when it was squashed. This would be more explicit if we used `response.exception` to indicate the response is from a squashed exception but I think that's a larger change.\r\n\r\nI'm proposing to remove `request.exception` and `request.exc_info` in the excview tween if it reraises the original exception. This makes introspection `request.exception` more reliable by upstream tweens that want to know what the squashed exception was... Of course any raised exception should be more interesting than the original `request.exception` but if the tween receives a response then they can see if it is a response generated by a squashed exception or if it is a \"normal\" response.\n", "before_files": [{"content": "import sys\n\nfrom pyramid.compat import reraise\nfrom pyramid.exceptions import PredicateMismatch\nfrom pyramid.interfaces import (\n    IExceptionViewClassifier,\n    IRequest,\n    )\n\nfrom zope.interface import providedBy\nfrom pyramid.view import _call_view\n\ndef excview_tween_factory(handler, registry):\n    \"\"\" A :term:`tween` factory which produces a tween that catches an\n    exception raised by downstream tweens (or the main Pyramid request\n    handler) and, if possible, converts it into a Response using an\n    :term:`exception view`.\"\"\"\n\n    def excview_tween(request):\n        attrs = request.__dict__\n        try:\n            response = handler(request)\n        except Exception as exc:\n            # WARNING: do not assign the result of sys.exc_info() to a local\n            # var here, doing so will cause a leak.  We used to actually\n            # explicitly delete both \"exception\" and \"exc_info\" from ``attrs``\n            # in a ``finally:`` clause below, but now we do not because these\n            # attributes are useful to upstream tweens.  This actually still\n            # apparently causes a reference cycle, but it is broken\n            # successfully by the garbage collector (see\n            # https://github.com/Pylons/pyramid/issues/1223).\n            attrs['exc_info'] = sys.exc_info()\n            attrs['exception'] = exc\n            # clear old generated request.response, if any; it may\n            # have been mutated by the view, and its state is not\n            # sane (e.g. caching headers)\n            if 'response' in attrs:\n                del attrs['response']\n            # we use .get instead of .__getitem__ below due to\n            # https://github.com/Pylons/pyramid/issues/700\n            request_iface = attrs.get('request_iface', IRequest)\n            provides = providedBy(exc)\n            try:\n                response = _call_view(\n                    registry,\n                    request,\n                    exc,\n                    provides,\n                    '',\n                    view_classifier=IExceptionViewClassifier,\n                    request_iface=request_iface.combined\n                    )\n\n            # if views matched but did not pass predicates, squash the error\n            # and re-raise the original exception\n            except PredicateMismatch:\n                response = None\n\n            # re-raise the original exception as no exception views were\n            # able to handle the error\n            if response is None:\n                reraise(*attrs['exc_info'])\n\n        return response\n\n    return excview_tween\n\nMAIN = 'MAIN'\nINGRESS = 'INGRESS'\nEXCVIEW = 'pyramid.tweens.excview_tween_factory'\n", "path": "pyramid/tweens.py"}]}