From aa6dd09c2cab5eb15a45d73b5ade24b7b4131c5a Mon Sep 17 00:00:00 2001 From: Rohan salwan Date: Wed, 23 Jun 2021 05:06:03 +0530 Subject: [PATCH 1/2] correctly handle raising deferred errors in cli lazy loading --- CHANGES.rst | 2 ++ src/flask/cli.py | 17 +++++++++-------- tests/test_cli.py | 5 +++++ 3 files changed, 16 insertions(+), 8 deletions(-) diff --git a/CHANGES.rst b/CHANGES.rst index 44512451..dc3f5cbf 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -17,6 +17,8 @@ Unreleased :issue:`4150` - ``jsonify`` handles ``decimal.Decimal`` by encoding to ``str``. :issue:`4157` +- Correctly handle raising deferred errors in CLI lazy loading. + :issue:`4096` Version 2.0.1 diff --git a/src/flask/cli.py b/src/flask/cli.py index d9e810da..81191a1a 100644 --- a/src/flask/cli.py +++ b/src/flask/cli.py @@ -312,7 +312,7 @@ class DispatchingApp: self.loader = loader self._app = None self._lock = Lock() - self._bg_loading_exc_info = None + self._bg_loading_exc = None if use_eager_loading is None: use_eager_loading = os.environ.get("WERKZEUG_RUN_MAIN") != "true" @@ -328,23 +328,24 @@ class DispatchingApp: with self._lock: try: self._load_unlocked() - except Exception: - self._bg_loading_exc_info = sys.exc_info() + except Exception as e: + self._bg_loading_exc = e t = Thread(target=_load_app, args=()) t.start() def _flush_bg_loading_exception(self): __traceback_hide__ = True # noqa: F841 - exc_info = self._bg_loading_exc_info - if exc_info is not None: - self._bg_loading_exc_info = None - raise exc_info + exc = self._bg_loading_exc + + if exc is not None: + self._bg_loading_exc = None + raise exc def _load_unlocked(self): __traceback_hide__ = True # noqa: F841 self._app = rv = self.loader() - self._bg_loading_exc_info = None + self._bg_loading_exc = None return rv def __call__(self, environ, start_response): diff --git a/tests/test_cli.py b/tests/test_cli.py index ebf8d1f5..2edb0bdd 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -17,6 +17,7 @@ from flask import Blueprint from flask import current_app from flask import Flask from flask.cli import AppGroup +from flask.cli import DispatchingApp from flask.cli import dotenv from flask.cli import find_best_app from flask.cli import FlaskGroup @@ -659,3 +660,7 @@ def test_click_7_deprecated(): pytest.deprecated_call(cli_main, match=".* Click 7 is deprecated") else: cli_main() + + +def test_load_in_background(): + pytest.raises(Exception, DispatchingApp, "appname123") From 2305b056c3a3161c92ea61e6fceb67262766bc40 Mon Sep 17 00:00:00 2001 From: David Lord Date: Thu, 5 Aug 2021 19:15:31 -0700 Subject: [PATCH 2/2] add test for lazy loading error --- tests/test_cli.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/tests/test_cli.py b/tests/test_cli.py index 2edb0bdd..5a666d8a 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -311,6 +311,23 @@ def test_scriptinfo(test_apps, monkeypatch): assert app.name == "testapp" +def test_lazy_load_error(monkeypatch): + """When using lazy loading, the correct exception should be + re-raised. + """ + + class BadExc(Exception): + pass + + def bad_load(): + raise BadExc + + lazy = DispatchingApp(bad_load, use_eager_loading=False) + + with pytest.raises(BadExc): + lazy._flush_bg_loading_exception() + + def test_with_appcontext(runner): @click.command() @with_appcontext @@ -660,7 +677,3 @@ def test_click_7_deprecated(): pytest.deprecated_call(cli_main, match=".* Click 7 is deprecated") else: cli_main() - - -def test_load_in_background(): - pytest.raises(Exception, DispatchingApp, "appname123")