From 37f3caded618b48aad03e50cd34647a51bf24cdc Mon Sep 17 00:00:00 2001 From: David Laban Date: Wed, 21 Dec 2022 15:33:52 +0000 Subject: [PATCH 1/3] fix: don't exit on reload if there is a syntax error (#213) --- src/functions_framework/__init__.py | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/src/functions_framework/__init__.py b/src/functions_framework/__init__.py index 8d47670c..10994d04 100644 --- a/src/functions_framework/__init__.py +++ b/src/functions_framework/__init__.py @@ -357,11 +357,27 @@ def handle_none(rv): # Execute the module, within the application context with _app.app_context(): - spec.loader.exec_module(source_module) + try: + spec.loader.exec_module(source_module) + function = _function_registry.get_user_function(source, source_module, target) + except Exception as e: + if werkzeug.serving.is_running_from_reloader(): + # When reloading, print out the error immediately, but raise + # it later so the debugger or server can handle it. + import traceback + traceback.print_exc() + err = e + + def function(*_args, **_kwargs): + raise err from None + + else: + # When not reloading, raise the error immediately so the + # command fails. + raise e from None # Get the configured function signature type signature_type = _function_registry.get_func_signature_type(target, signature_type) - function = _function_registry.get_user_function(source, source_module, target) _configure_app(_app, function, signature_type) From c20387f7a6ded099901f30b0aa66b1255b71488e Mon Sep 17 00:00:00 2001 From: David Laban Date: Wed, 6 Sep 2023 08:54:58 +0100 Subject: [PATCH 2/3] style: reformat using black --- src/functions_framework/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/functions_framework/__init__.py b/src/functions_framework/__init__.py index 10994d04..ece4f446 100644 --- a/src/functions_framework/__init__.py +++ b/src/functions_framework/__init__.py @@ -359,12 +359,15 @@ def handle_none(rv): with _app.app_context(): try: spec.loader.exec_module(source_module) - function = _function_registry.get_user_function(source, source_module, target) + function = _function_registry.get_user_function( + source, source_module, target + ) except Exception as e: if werkzeug.serving.is_running_from_reloader(): # When reloading, print out the error immediately, but raise # it later so the debugger or server can handle it. import traceback + traceback.print_exc() err = e From 00ba2cd85db1517d9add0c5db220a97b097b95bb Mon Sep 17 00:00:00 2001 From: David Laban Date: Wed, 6 Sep 2023 09:29:18 +0100 Subject: [PATCH 3/3] test: robustness to syntax error in debug mode startup --- tests/test_functions.py | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/test_functions.py b/tests/test_functions.py index 81860cae..f0bd7793 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -323,6 +323,19 @@ def test_invalid_function_definition_function_syntax_error(): ) +def test_invalid_function_definition_function_syntax_robustness_with_debug(monkeypatch): + monkeypatch.setattr( + functions_framework.werkzeug.serving, "is_running_from_reloader", lambda: True + ) + source = TEST_FUNCTIONS_DIR / "background_load_error" / "main.py" + target = "function" + + client = create_app(target, source).test_client() + + resp = client.get("/") + assert resp.status_code == 500 + + def test_invalid_function_definition_missing_dependency(): source = TEST_FUNCTIONS_DIR / "background_missing_dependency" / "main.py" target = "function"