diff --git a/flask/app.py b/flask/app.py index fb791f33..9dfc3783 100644 --- a/flask/app.py +++ b/flask/app.py @@ -1484,8 +1484,10 @@ class Flask(_PackageBoundObject): Since a request context typically also manages an application context it would also be called when you pop a request context. - When a teardown function was called because of an exception it will - be passed an error object. + When a teardown function was called because of an unhandled exception + it will be passed an error object. If an :meth:`errorhandler` is + registered, it will handle the exception and the teardown will not + receive it. The return values of teardown functions are ignored. diff --git a/tests/test_appctx.py b/tests/test_appctx.py index 7ef7b479..fc2f6b13 100644 --- a/tests/test_appctx.py +++ b/tests/test_appctx.py @@ -81,7 +81,7 @@ def test_app_tearing_down_with_previous_exception(app): assert cleanup_stuff == [None] -def test_app_tearing_down_with_handled_exception(app): +def test_app_tearing_down_with_handled_exception_by_except_block(app): cleanup_stuff = [] @app.teardown_appcontext @@ -97,6 +97,49 @@ def test_app_tearing_down_with_handled_exception(app): assert cleanup_stuff == [None] +def test_app_tearing_down_with_handled_exception_by_app_handler(app, client): + app.config['PROPAGATE_EXCEPTIONS'] = True + cleanup_stuff = [] + + @app.teardown_appcontext + def cleanup(exception): + cleanup_stuff.append(exception) + + @app.route('/') + def index(): + raise Exception('dummy') + + @app.errorhandler(Exception) + def handler(f): + return flask.jsonify(str(f)) + + with app.app_context(): + client.get('/') + + assert cleanup_stuff == [None] + + +def test_app_tearing_down_with_unhandled_exception(app, client): + app.config['PROPAGATE_EXCEPTIONS'] = True + cleanup_stuff = [] + + @app.teardown_appcontext + def cleanup(exception): + cleanup_stuff.append(exception) + + @app.route('/') + def index(): + raise Exception('dummy') + + with pytest.raises(Exception): + with app.app_context(): + client.get('/') + + assert len(cleanup_stuff) == 1 + assert isinstance(cleanup_stuff[0], Exception) + assert str(cleanup_stuff[0]) == 'dummy' + + def test_app_ctx_globals_methods(app, app_ctx): # get assert flask.g.get('foo') is None