From fa02fabacc421e94d1effb249ca3f0ff8cf226ac Mon Sep 17 00:00:00 2001 From: Tiago Nobrega Date: Mon, 24 Jun 2024 15:07:38 -0300 Subject: [PATCH 1/2] fix(flask): handle SyntaxErrors when parsing app.py --- rockcraft/extensions/gunicorn.py | 7 ++++++- tests/unit/extensions/test_gunicorn.py | 29 ++++++++++++++++++++++++++ 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/rockcraft/extensions/gunicorn.py b/rockcraft/extensions/gunicorn.py index 9fed53284..90acf5c73 100644 --- a/rockcraft/extensions/gunicorn.py +++ b/rockcraft/extensions/gunicorn.py @@ -259,7 +259,12 @@ def _wsgi_path_error_messages(self): return [ "flask application can not be imported from app:app, no app.py file found in the project root." ] - if not self.has_global_variable(app_file, "app"): + try: + has_app = self.has_global_variable(app_file, "app") + except SyntaxError as err: + return [f"error parsing app.py: {err.msg}"] + + if not has_app: return [ "flask application can not be imported from app:app in file app.py file in the project root." ] diff --git a/tests/unit/extensions/test_gunicorn.py b/tests/unit/extensions/test_gunicorn.py index ba6153fb0..7af0d6b05 100644 --- a/tests/unit/extensions/test_gunicorn.py +++ b/tests/unit/extensions/test_gunicorn.py @@ -13,6 +13,7 @@ # # You should have received a copy of the GNU General Public License # along with this program. If not, see . +import textwrap import pytest from rockcraft import extensions @@ -333,6 +334,34 @@ def test_flask_extension_requirements_txt_no_flask_error(tmp_path): ) +@pytest.mark.usefixtures("flask_extension") +def test_flask_extension_bad_app_py(tmp_path): + bad_code = textwrap.dedent( + """ + import flask + + app = flask.Flask() + + bad = "my value + """ + ).strip() + (tmp_path / "app.py").write_text(bad_code) + (tmp_path / "requirements.txt").write_text("flask") + flask_input_yaml = { + "extensions": ["flask-framework"], + "base": "bare", + "build-base": "ubuntu@22.04", + "platforms": {"amd64": {}}, + } + with pytest.raises(ExtensionError) as exc: + extensions.apply_extensions(tmp_path, flask_input_yaml) + + expected = ( + "- error parsing app.py: unterminated string literal (detected at line 5)" + ) + assert str(exc.value) == expected + + @pytest.mark.usefixtures("flask_extension") def test_flask_extension_no_requirements_txt_no_app_py_error(tmp_path): flask_input_yaml = { From 2f6c4bc8834f38d4c635650a59356c9dee70ff54 Mon Sep 17 00:00:00 2001 From: Tiago Nobrega Date: Mon, 24 Jun 2024 15:09:11 -0300 Subject: [PATCH 2/2] chore: fix typo in error message --- rockcraft/extensions/gunicorn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rockcraft/extensions/gunicorn.py b/rockcraft/extensions/gunicorn.py index 90acf5c73..60ae5b5ee 100644 --- a/rockcraft/extensions/gunicorn.py +++ b/rockcraft/extensions/gunicorn.py @@ -266,7 +266,7 @@ def _wsgi_path_error_messages(self): if not has_app: return [ - "flask application can not be imported from app:app in file app.py file in the project root." + "flask application can not be imported from app:app in app.py in the project root." ] return []