From 348bf52188b9f7bef1096d8fe70edf2e62ea04a8 Mon Sep 17 00:00:00 2001 From: Joshua Carp Date: Tue, 2 Jun 2015 16:13:30 -0400 Subject: [PATCH] Handle empty deque on errorhandler lookup. After registering a custom errorhandler by exception class, raising any unhandled exception in a view function swallows the error and instead throws an `IndexError` on trying to look up the appropriate handler. This patch avoids the uninformative `IndexError` and preserves the original exception by looping until the deque of classes is empty, not forever. --- flask/app.py | 2 +- tests/test_user_error_handler.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/flask/app.py b/flask/app.py index 293eb6e9..2a19d11b 100644 --- a/flask/app.py +++ b/flask/app.py @@ -1421,7 +1421,7 @@ class Flask(_PackageBoundObject): # __mro__ done = set() - while True: + while queue: cls = queue.popleft() if cls in done: continue diff --git a/tests/test_user_error_handler.py b/tests/test_user_error_handler.py index 33131f3e..11677433 100644 --- a/tests/test_user_error_handler.py +++ b/tests/test_user_error_handler.py @@ -3,6 +3,35 @@ from werkzeug.exceptions import Forbidden, InternalServerError import flask +def test_error_handler_no_match(): + app = flask.Flask(__name__) + + class CustomException(Exception): + pass + + @app.errorhandler(CustomException) + def custom_exception_handler(e): + assert isinstance(e, CustomException) + return 'custom' + + @app.errorhandler(500) + def handle_500(e): + return type(e).__name__ + + @app.route('/custom') + def custom_test(): + raise CustomException() + + @app.route('/keyerror') + def key_error(): + raise KeyError() + + c = app.test_client() + + assert c.get('/custom').data == b'custom' + assert c.get('/keyerror').data == b'KeyError' + + def test_error_handler_subclass(): app = flask.Flask(__name__)