librelist archives

« back to archive

How to not handle an error after you have looked at it. Reraise?

How to not handle an error after you have looked at it. Reraise?

From:
Adrian Ratnapala
Date:
2012-07-15 @ 10:47
If you have trapped an exception (an HTTP error in this case), but
your exception handler decides it is not interested, how can you make
the error handling proceed as if you never trapped the error at all?

flask/app.py makes me think you should just re-raise the exception -
flask seems careful not to trash sys.exc_info.  But this doesn't help
-- if you re-raise an http error it seems to get treated as if it were
an ordinary exception.  I don't know if this is a bug or if it is the
intended behaviour.  If it is the intended behaviour, then I don't
know how to ignore trapped HTTP errors. (All of this relates to flask
0.9, commit:ea2a062).

Below is a script that demonstrates the problem.  The behaviour that I
see is not surprising considering the implementation of
flask/app.py:handle_http_exception.  At the bottom of this email is a
patch that attempts to "fix" this bug (assuming it is a bug).   This
makes my demo program work as expected, but causes several flask unit
tests to fail.

If this is a bug, then if you like, I can make this a proper pull
request on github and begin whatever formal review process you guys
have.

Cheers.


reraise.py
----------------------------------------------------------------

import flask
from werkzeug.exceptions import Forbidden

def make_app() :
        app = flask.Flask(__name__)
        #app.config['TESTING']=True
        #app.config['TRAP_HTTP_EXCEPTIONS']=True

        @app.route("/")
        def page() :
                raise Forbidden

        return app

def test_no_handler() :
        app = make_app()
        with app.test_client() as c:
                resp = c.get('/')
                assert resp.status_code != 500
                assert resp.status_code == 403

def test_reraising_handler() :
        app = make_app()
        @app.errorhandler(403)
        def check_403(x=None) :
                raise

        with app.test_client() as c:
                resp = c.get('/')
                assert resp.status_code != 500
                assert resp.status_code == 403


if __name__ == "__main__" :
        test_no_handler() # works fine.
        test_reraising_handler() # produces 500 instead of 403

----------------------------------------------------------------


diff --git a/flask/app.py b/flask/app.py
index d30d380..c480814 100644
--- a/flask/app.py
+++ b/flask/app.py
@@ -1210,7 +1210,11 @@ class Flask(_PackageBoundObject):
             handler = self.error_handler_spec[None].get(e.code)
         if handler is None:
             return e
-        return handler(e)
+        try: handler(e)
+        except HTTPException, x:
+                if self.config.get('TRAP_HTTP_EXCEPTIONS') :
+                        raise
+                return x

     def trap_http_exception(self, e):
         """Checks if an HTTP exception should be trapped or not.  By default





-- 
Adrian Ratnapala
mobile: +49 1515 277 0000

NGBitS GmbH
Rainer Strasse 7
83104 Osterm√ľnchen

Web: www.ngbits.com