From 8d0e2c8dcbb9a9e15e93818eba9a289a9fc86025 Mon Sep 17 00:00:00 2001 From: Arjun Srinivasan <69502+asriniva@users.noreply.github.com> Date: Mon, 17 Aug 2020 23:33:48 +0000 Subject: [PATCH] Add legacy GCF Python 3.7 behavior (#77) * Add legacy GCF Python 3.7 behavior * Add test * Modify tests --- src/functions_framework/__init__.py | 13 +++++++ tests/test_functions.py | 41 +++++++++++++++++++++++ tests/test_functions/returns_none/main.py | 27 +++++++++++++++ 3 files changed, 81 insertions(+) create mode 100644 tests/test_functions/returns_none/main.py diff --git a/src/functions_framework/__init__.py b/src/functions_framework/__init__.py index f89e05ee..575c93d9 100644 --- a/src/functions_framework/__init__.py +++ b/src/functions_framework/__init__.py @@ -233,6 +233,19 @@ def create_app(target=None, source=None, signature_type=None): with app.app_context(): spec.loader.exec_module(source_module) + # Handle legacy GCF Python 3.7 behavior + if os.environ.get("ENTRY_POINT"): + os.environ["FUNCTION_TRIGGER_TYPE"] = signature_type + os.environ["FUNCTION_NAME"] = os.environ.get("K_SERVICE", target) + app.make_response_original = app.make_response + + def handle_none(rv): + if rv is None: + rv = "OK" + return app.make_response_original(rv) + + app.make_response = handle_none + # Extract the target function from the source file try: function = getattr(source_module, target) diff --git a/tests/test_functions.py b/tests/test_functions.py index f03569b0..9f2686e4 100644 --- a/tests/test_functions.py +++ b/tests/test_functions.py @@ -11,6 +11,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. + +import os import pathlib import re import time @@ -318,3 +320,42 @@ def test_flask_current_app_is_available(): resp = client.get("/") assert resp.status_code == 200 + + +def test_function_returns_none(): + source = TEST_FUNCTIONS_DIR / "returns_none" / "main.py" + target = "function" + + client = create_app(target, source).test_client() + resp = client.get("/") + + assert resp.status_code == 500 + + +def test_legacy_function_check_env(monkeypatch): + source = TEST_FUNCTIONS_DIR / "http_check_env" / "main.py" + target = "function" + + monkeypatch.setenv("ENTRY_POINT", target) + + client = create_app(target, source).test_client() + resp = client.post("/", json={"mode": "FUNCTION_TRIGGER_TYPE"}) + assert resp.status_code == 200 + assert resp.data == b"http" + + resp = client.post("/", json={"mode": "FUNCTION_NAME"}) + assert resp.status_code == 200 + assert resp.data.decode("utf-8") == target + + +def test_legacy_function_returns_none(monkeypatch): + source = TEST_FUNCTIONS_DIR / "returns_none" / "main.py" + target = "function" + + monkeypatch.setenv("ENTRY_POINT", target) + + client = create_app(target, source).test_client() + resp = client.get("/") + + assert resp.status_code == 200 + assert resp.data == b"OK" diff --git a/tests/test_functions/returns_none/main.py b/tests/test_functions/returns_none/main.py new file mode 100644 index 00000000..f6a4acaa --- /dev/null +++ b/tests/test_functions/returns_none/main.py @@ -0,0 +1,27 @@ +# Copyright 2020 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + + +def function(request): + """Test HTTP function when using legacy GCF behavior. + + The function returns None, which should be a 200 response. + + Args: + request: The HTTP request which triggered this function. + + Returns: + None. + """ + return None