functions-framework 3.4.0__tar.gz → 3.6.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {functions-framework-3.4.0 → functions_framework-3.6.0}/PKG-INFO +17 -11
- {functions-framework-3.4.0 → functions_framework-3.6.0}/README.md +8 -6
- {functions-framework-3.4.0 → functions_framework-3.6.0}/setup.py +7 -7
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/__init__.py +34 -11
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/_http/gunicorn.py +6 -3
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/_typed_event.py +3 -3
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/event_conversion.py +1 -1
- functions_framework-3.6.0/src/functions_framework/py.typed +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework.egg-info/PKG-INFO +17 -11
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework.egg-info/SOURCES.txt +2 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework.egg-info/requires.txt +2 -2
- {functions-framework-3.4.0 → functions_framework-3.6.0}/tests/test_functions.py +13 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/tests/test_http.py +7 -6
- {functions-framework-3.4.0 → functions_framework-3.6.0}/tests/test_samples.py +1 -1
- functions_framework-3.6.0/tests/test_typing.py +16 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/LICENSE +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/setup.cfg +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/__main__.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/_cli.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/_function_registry.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/_http/__init__.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/_http/flask.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/background_event.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/exceptions.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework.egg-info/dependency_links.txt +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework.egg-info/entry_points.txt +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework.egg-info/namespace_packages.txt +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework.egg-info/top_level.txt +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/google/__init__.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/google/cloud/__init__.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/google/cloud/functions/__init__.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/google/cloud/functions/context.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/google/cloud/functions_v1/__init__.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/google/cloud/functions_v1/context.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/google/cloud/functions_v1beta2/__init__.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/src/google/cloud/functions_v1beta2/context.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/tests/test_cli.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/tests/test_cloud_event_functions.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/tests/test_convert.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/tests/test_decorator_functions.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/tests/test_function_registry.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/tests/test_main.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/tests/test_typed_event_functions.py +0 -0
- {functions-framework-3.4.0 → functions_framework-3.6.0}/tests/test_view_functions.py +0 -0
|
@@ -1,30 +1,34 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: functions-framework
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.6.0
|
|
4
4
|
Summary: An open source FaaS (Function as a service) framework for writing portable Python functions -- brought to you by the Google Cloud Functions team.
|
|
5
5
|
Home-page: https://github.com/googlecloudplatform/functions-framework-python
|
|
6
6
|
Author: Google LLC
|
|
7
7
|
Author-email: googleapis-packages@google.com
|
|
8
8
|
Keywords: functions-framework
|
|
9
|
-
Classifier: Development Status ::
|
|
9
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
10
|
Classifier: Intended Audience :: Developers
|
|
11
11
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.5
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
15
12
|
Classifier: Programming Language :: Python :: 3.7
|
|
16
13
|
Classifier: Programming Language :: Python :: 3.8
|
|
17
14
|
Classifier: Programming Language :: Python :: 3.9
|
|
18
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
18
|
Requires-Python: >=3.5, <4
|
|
20
19
|
Description-Content-Type: text/markdown
|
|
21
20
|
License-File: LICENSE
|
|
21
|
+
Requires-Dist: flask<4.0,>=1.0
|
|
22
|
+
Requires-Dist: click<9.0,>=7.0
|
|
23
|
+
Requires-Dist: watchdog>=1.0.0
|
|
24
|
+
Requires-Dist: gunicorn>=19.2.0; platform_system != "Windows"
|
|
25
|
+
Requires-Dist: cloudevents<2.0.0,>=1.2.0
|
|
22
26
|
|
|
23
27
|
# Functions Framework for Python
|
|
24
28
|
|
|
25
29
|
[](https://badge.fury.io/py/functions-framework)
|
|
26
30
|
|
|
27
|
-
[![Python unit CI][ff_python_unit_img]][ff_python_unit_link] [![Python lint CI][ff_python_lint_img]][ff_python_lint_link] [![Python conformace CI][ff_python_conformance_img]][ff_python_conformance_link]
|
|
31
|
+
[![Python unit CI][ff_python_unit_img]][ff_python_unit_link] [![Python lint CI][ff_python_lint_img]][ff_python_lint_link] [![Python conformace CI][ff_python_conformance_img]][ff_python_conformance_link] 
|
|
28
32
|
|
|
29
33
|
An open source FaaS (Function as a service) framework for writing portable
|
|
30
34
|
Python functions -- brought to you by the Google Cloud Functions team.
|
|
@@ -81,14 +85,15 @@ functions-framework==3.*
|
|
|
81
85
|
Create an `main.py` file with the following contents:
|
|
82
86
|
|
|
83
87
|
```python
|
|
88
|
+
import flask
|
|
84
89
|
import functions_framework
|
|
85
90
|
|
|
86
91
|
@functions_framework.http
|
|
87
|
-
def hello(request):
|
|
92
|
+
def hello(request: flask.Request) -> flask.typing.ResponseReturnValue:
|
|
88
93
|
return "Hello world!"
|
|
89
94
|
```
|
|
90
95
|
|
|
91
|
-
> Your function is passed a single parameter, `(request)`, which is a Flask [`Request`](
|
|
96
|
+
> Your function is passed a single parameter, `(request)`, which is a Flask [`Request`](https://flask.palletsprojects.com/en/3.0.x/api/#flask.Request) object.
|
|
92
97
|
|
|
93
98
|
Run the following command:
|
|
94
99
|
|
|
@@ -120,13 +125,14 @@ Create an `main.py` file with the following contents:
|
|
|
120
125
|
|
|
121
126
|
```python
|
|
122
127
|
import functions_framework
|
|
128
|
+
from cloudevents.http.event import CloudEvent
|
|
123
129
|
|
|
124
130
|
@functions_framework.cloud_event
|
|
125
|
-
def hello_cloud_event(cloud_event):
|
|
131
|
+
def hello_cloud_event(cloud_event: CloudEvent) -> None:
|
|
126
132
|
print(f"Received event with ID: {cloud_event['id']} and data {cloud_event.data}")
|
|
127
133
|
```
|
|
128
134
|
|
|
129
|
-
> Your function is passed a single [CloudEvent](https://github.com/cloudevents/sdk-python/blob/
|
|
135
|
+
> Your function is passed a single [CloudEvent](https://github.com/cloudevents/sdk-python/blob/main/cloudevents/sdk/event/v1.py) parameter.
|
|
130
136
|
|
|
131
137
|
Run the following command to run `hello_cloud_event` target locally:
|
|
132
138
|
|
|
@@ -324,7 +330,7 @@ After you've written your function, you can simply deploy it from your local mac
|
|
|
324
330
|
|
|
325
331
|
### Cloud Run/Cloud Run on GKE
|
|
326
332
|
|
|
327
|
-
Once you've written your function and added the Functions Framework to your `requirements.txt` file, all that's left is to create a container image. [Check out the Cloud Run quickstart](https://cloud.google.com/run/docs/quickstarts/build-and-deploy) for Python to create a container image and deploy it to Cloud Run. You'll write a `Dockerfile` when you build your container. This `Dockerfile` allows you to specify exactly what goes into your container (including custom binaries, a specific operating system, and more). [Here is an example `Dockerfile` that calls Functions Framework.](https://github.com/GoogleCloudPlatform/functions-framework-python/blob/
|
|
333
|
+
Once you've written your function and added the Functions Framework to your `requirements.txt` file, all that's left is to create a container image. [Check out the Cloud Run quickstart](https://cloud.google.com/run/docs/quickstarts/build-and-deploy) for Python to create a container image and deploy it to Cloud Run. You'll write a `Dockerfile` when you build your container. This `Dockerfile` allows you to specify exactly what goes into your container (including custom binaries, a specific operating system, and more). [Here is an example `Dockerfile` that calls Functions Framework.](https://github.com/GoogleCloudPlatform/functions-framework-python/blob/main/examples/cloud_run_http)
|
|
328
334
|
|
|
329
335
|
If you want even more control over the environment, you can [deploy your container image to Cloud Run on GKE](https://cloud.google.com/run/docs/quickstarts/prebuilt-deploy-gke). With Cloud Run on GKE, you can run your function on a GKE cluster, which gives you additional control over the environment (including use of GPU-based instances, longer timeouts and more).
|
|
330
336
|
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
[](https://badge.fury.io/py/functions-framework)
|
|
4
4
|
|
|
5
|
-
[![Python unit CI][ff_python_unit_img]][ff_python_unit_link] [![Python lint CI][ff_python_lint_img]][ff_python_lint_link] [![Python conformace CI][ff_python_conformance_img]][ff_python_conformance_link]
|
|
5
|
+
[![Python unit CI][ff_python_unit_img]][ff_python_unit_link] [![Python lint CI][ff_python_lint_img]][ff_python_lint_link] [![Python conformace CI][ff_python_conformance_img]][ff_python_conformance_link] 
|
|
6
6
|
|
|
7
7
|
An open source FaaS (Function as a service) framework for writing portable
|
|
8
8
|
Python functions -- brought to you by the Google Cloud Functions team.
|
|
@@ -59,14 +59,15 @@ functions-framework==3.*
|
|
|
59
59
|
Create an `main.py` file with the following contents:
|
|
60
60
|
|
|
61
61
|
```python
|
|
62
|
+
import flask
|
|
62
63
|
import functions_framework
|
|
63
64
|
|
|
64
65
|
@functions_framework.http
|
|
65
|
-
def hello(request):
|
|
66
|
+
def hello(request: flask.Request) -> flask.typing.ResponseReturnValue:
|
|
66
67
|
return "Hello world!"
|
|
67
68
|
```
|
|
68
69
|
|
|
69
|
-
> Your function is passed a single parameter, `(request)`, which is a Flask [`Request`](
|
|
70
|
+
> Your function is passed a single parameter, `(request)`, which is a Flask [`Request`](https://flask.palletsprojects.com/en/3.0.x/api/#flask.Request) object.
|
|
70
71
|
|
|
71
72
|
Run the following command:
|
|
72
73
|
|
|
@@ -98,13 +99,14 @@ Create an `main.py` file with the following contents:
|
|
|
98
99
|
|
|
99
100
|
```python
|
|
100
101
|
import functions_framework
|
|
102
|
+
from cloudevents.http.event import CloudEvent
|
|
101
103
|
|
|
102
104
|
@functions_framework.cloud_event
|
|
103
|
-
def hello_cloud_event(cloud_event):
|
|
105
|
+
def hello_cloud_event(cloud_event: CloudEvent) -> None:
|
|
104
106
|
print(f"Received event with ID: {cloud_event['id']} and data {cloud_event.data}")
|
|
105
107
|
```
|
|
106
108
|
|
|
107
|
-
> Your function is passed a single [CloudEvent](https://github.com/cloudevents/sdk-python/blob/
|
|
109
|
+
> Your function is passed a single [CloudEvent](https://github.com/cloudevents/sdk-python/blob/main/cloudevents/sdk/event/v1.py) parameter.
|
|
108
110
|
|
|
109
111
|
Run the following command to run `hello_cloud_event` target locally:
|
|
110
112
|
|
|
@@ -302,7 +304,7 @@ After you've written your function, you can simply deploy it from your local mac
|
|
|
302
304
|
|
|
303
305
|
### Cloud Run/Cloud Run on GKE
|
|
304
306
|
|
|
305
|
-
Once you've written your function and added the Functions Framework to your `requirements.txt` file, all that's left is to create a container image. [Check out the Cloud Run quickstart](https://cloud.google.com/run/docs/quickstarts/build-and-deploy) for Python to create a container image and deploy it to Cloud Run. You'll write a `Dockerfile` when you build your container. This `Dockerfile` allows you to specify exactly what goes into your container (including custom binaries, a specific operating system, and more). [Here is an example `Dockerfile` that calls Functions Framework.](https://github.com/GoogleCloudPlatform/functions-framework-python/blob/
|
|
307
|
+
Once you've written your function and added the Functions Framework to your `requirements.txt` file, all that's left is to create a container image. [Check out the Cloud Run quickstart](https://cloud.google.com/run/docs/quickstarts/build-and-deploy) for Python to create a container image and deploy it to Cloud Run. You'll write a `Dockerfile` when you build your container. This `Dockerfile` allows you to specify exactly what goes into your container (including custom binaries, a specific operating system, and more). [Here is an example `Dockerfile` that calls Functions Framework.](https://github.com/GoogleCloudPlatform/functions-framework-python/blob/main/examples/cloud_run_http)
|
|
306
308
|
|
|
307
309
|
If you want even more control over the environment, you can [deploy your container image to Cloud Run on GKE](https://cloud.google.com/run/docs/quickstarts/prebuilt-deploy-gke). With Cloud Run on GKE, you can run your function on a GKE cluster, which gives you additional control over the environment (including use of GPU-based instances, longer timeouts and more).
|
|
308
310
|
|
|
@@ -25,7 +25,7 @@ with open(path.join(here, "README.md"), encoding="utf-8") as f:
|
|
|
25
25
|
|
|
26
26
|
setup(
|
|
27
27
|
name="functions-framework",
|
|
28
|
-
version="3.
|
|
28
|
+
version="3.6.0",
|
|
29
29
|
description="An open source FaaS (Function as a service) framework for writing portable Python functions -- brought to you by the Google Cloud Functions team.",
|
|
30
30
|
long_description=long_description,
|
|
31
31
|
long_description_content_type="text/markdown",
|
|
@@ -33,27 +33,27 @@ setup(
|
|
|
33
33
|
author="Google LLC",
|
|
34
34
|
author_email="googleapis-packages@google.com",
|
|
35
35
|
classifiers=[
|
|
36
|
-
"Development Status ::
|
|
36
|
+
"Development Status :: 5 - Production/Stable ",
|
|
37
37
|
"Intended Audience :: Developers",
|
|
38
38
|
"License :: OSI Approved :: Apache Software License",
|
|
39
|
-
"Programming Language :: Python :: 3",
|
|
40
|
-
"Programming Language :: Python :: 3.5",
|
|
41
|
-
"Programming Language :: Python :: 3.6",
|
|
42
39
|
"Programming Language :: Python :: 3.7",
|
|
43
40
|
"Programming Language :: Python :: 3.8",
|
|
44
41
|
"Programming Language :: Python :: 3.9",
|
|
45
42
|
"Programming Language :: Python :: 3.10",
|
|
43
|
+
"Programming Language :: Python :: 3.11",
|
|
44
|
+
"Programming Language :: Python :: 3.12",
|
|
46
45
|
],
|
|
47
46
|
keywords="functions-framework",
|
|
48
47
|
packages=find_packages(where="src"),
|
|
48
|
+
package_data={"functions_framework": ["py.typed"]},
|
|
49
49
|
namespace_packages=["google", "google.cloud"],
|
|
50
50
|
package_dir={"": "src"},
|
|
51
51
|
python_requires=">=3.5, <4",
|
|
52
52
|
install_requires=[
|
|
53
|
-
"flask>=1.0,<
|
|
53
|
+
"flask>=1.0,<4.0",
|
|
54
54
|
"click>=7.0,<9.0",
|
|
55
55
|
"watchdog>=1.0.0",
|
|
56
|
-
"gunicorn>=19.2.0
|
|
56
|
+
"gunicorn>=19.2.0; platform_system!='Windows'",
|
|
57
57
|
"cloudevents>=1.2.0,<2.0.0",
|
|
58
58
|
],
|
|
59
59
|
entry_points={
|
|
@@ -23,13 +23,14 @@ import sys
|
|
|
23
23
|
import types
|
|
24
24
|
|
|
25
25
|
from inspect import signature
|
|
26
|
-
from typing import Type
|
|
26
|
+
from typing import Callable, Type
|
|
27
27
|
|
|
28
28
|
import cloudevents.exceptions as cloud_exceptions
|
|
29
29
|
import flask
|
|
30
30
|
import werkzeug
|
|
31
31
|
|
|
32
32
|
from cloudevents.http import from_http, is_binary
|
|
33
|
+
from cloudevents.http.event import CloudEvent
|
|
33
34
|
|
|
34
35
|
from functions_framework import _function_registry, _typed_event, event_conversion
|
|
35
36
|
from functions_framework.background_event import BackgroundEvent
|
|
@@ -45,6 +46,9 @@ _CRASH = "crash"
|
|
|
45
46
|
|
|
46
47
|
_CLOUDEVENT_MIME_TYPE = "application/cloudevents+json"
|
|
47
48
|
|
|
49
|
+
CloudEventFunction = Callable[[CloudEvent], None]
|
|
50
|
+
HTTPFunction = Callable[[flask.Request], flask.typing.ResponseReturnValue]
|
|
51
|
+
|
|
48
52
|
|
|
49
53
|
class _LoggingHandler(io.TextIOWrapper):
|
|
50
54
|
"""Logging replacement for stdout and stderr in GCF Python 3.7."""
|
|
@@ -59,11 +63,11 @@ class _LoggingHandler(io.TextIOWrapper):
|
|
|
59
63
|
return self.stderr.write(json.dumps(payload) + "\n")
|
|
60
64
|
|
|
61
65
|
|
|
62
|
-
def cloud_event(func):
|
|
66
|
+
def cloud_event(func: CloudEventFunction) -> CloudEventFunction:
|
|
63
67
|
"""Decorator that registers cloudevent as user function signature type."""
|
|
64
|
-
_function_registry.REGISTRY_MAP[
|
|
65
|
-
|
|
66
|
-
|
|
68
|
+
_function_registry.REGISTRY_MAP[func.__name__] = (
|
|
69
|
+
_function_registry.CLOUDEVENT_SIGNATURE_TYPE
|
|
70
|
+
)
|
|
67
71
|
|
|
68
72
|
@functools.wraps(func)
|
|
69
73
|
def wrapper(*args, **kwargs):
|
|
@@ -99,11 +103,11 @@ def typed(*args):
|
|
|
99
103
|
return _typed
|
|
100
104
|
|
|
101
105
|
|
|
102
|
-
def http(func):
|
|
106
|
+
def http(func: HTTPFunction) -> HTTPFunction:
|
|
103
107
|
"""Decorator that registers http as user function signature type."""
|
|
104
|
-
_function_registry.REGISTRY_MAP[
|
|
105
|
-
|
|
106
|
-
|
|
108
|
+
_function_registry.REGISTRY_MAP[func.__name__] = (
|
|
109
|
+
_function_registry.HTTP_SIGNATURE_TYPE
|
|
110
|
+
)
|
|
107
111
|
|
|
108
112
|
@functools.wraps(func)
|
|
109
113
|
def wrapper(*args, **kwargs):
|
|
@@ -353,11 +357,30 @@ def create_app(target=None, source=None, signature_type=None):
|
|
|
353
357
|
|
|
354
358
|
# Execute the module, within the application context
|
|
355
359
|
with _app.app_context():
|
|
356
|
-
|
|
360
|
+
try:
|
|
361
|
+
spec.loader.exec_module(source_module)
|
|
362
|
+
function = _function_registry.get_user_function(
|
|
363
|
+
source, source_module, target
|
|
364
|
+
)
|
|
365
|
+
except Exception as e:
|
|
366
|
+
if werkzeug.serving.is_running_from_reloader():
|
|
367
|
+
# When reloading, print out the error immediately, but raise
|
|
368
|
+
# it later so the debugger or server can handle it.
|
|
369
|
+
import traceback
|
|
370
|
+
|
|
371
|
+
traceback.print_exc()
|
|
372
|
+
err = e
|
|
373
|
+
|
|
374
|
+
def function(*_args, **_kwargs):
|
|
375
|
+
raise err from None
|
|
376
|
+
|
|
377
|
+
else:
|
|
378
|
+
# When not reloading, raise the error immediately so the
|
|
379
|
+
# command fails.
|
|
380
|
+
raise e from None
|
|
357
381
|
|
|
358
382
|
# Get the configured function signature type
|
|
359
383
|
signature_type = _function_registry.get_func_signature_type(target, signature_type)
|
|
360
|
-
function = _function_registry.get_user_function(source, source_module, target)
|
|
361
384
|
|
|
362
385
|
_configure_app(_app, function, signature_type)
|
|
363
386
|
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/_http/gunicorn.py
RENAMED
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
import os
|
|
16
|
+
|
|
15
17
|
import gunicorn.app.base
|
|
16
18
|
|
|
17
19
|
|
|
@@ -19,14 +21,15 @@ class GunicornApplication(gunicorn.app.base.BaseApplication):
|
|
|
19
21
|
def __init__(self, app, host, port, debug, **options):
|
|
20
22
|
self.options = {
|
|
21
23
|
"bind": "%s:%s" % (host, port),
|
|
22
|
-
"workers": 1,
|
|
23
|
-
"threads":
|
|
24
|
-
"timeout":
|
|
24
|
+
"workers": os.environ.get("WORKERS", (os.cpu_count() or 1) * 4),
|
|
25
|
+
"threads": os.environ.get("THREADS", 1),
|
|
26
|
+
"timeout": os.environ.get("CLOUD_RUN_TIMEOUT_SECONDS", 300),
|
|
25
27
|
"loglevel": "error",
|
|
26
28
|
"limit_request_line": 0,
|
|
27
29
|
}
|
|
28
30
|
self.options.update(options)
|
|
29
31
|
self.app = app
|
|
32
|
+
|
|
30
33
|
super().__init__()
|
|
31
34
|
|
|
32
35
|
def load_config(self):
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/_typed_event.py
RENAMED
|
@@ -48,9 +48,9 @@ def register_typed_event(decorator_type, func):
|
|
|
48
48
|
)
|
|
49
49
|
|
|
50
50
|
_function_registry.INPUT_TYPE_MAP[func.__name__] = input_type
|
|
51
|
-
_function_registry.REGISTRY_MAP[
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
_function_registry.REGISTRY_MAP[func.__name__] = (
|
|
52
|
+
_function_registry.TYPED_SIGNATURE_TYPE
|
|
53
|
+
)
|
|
54
54
|
|
|
55
55
|
|
|
56
56
|
""" Checks whether the response type of the typed function has a to_dict method"""
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/event_conversion.py
RENAMED
|
@@ -27,7 +27,7 @@ _CLOUD_EVENT_SPEC_VERSION = "1.0"
|
|
|
27
27
|
|
|
28
28
|
# Maps background/legacy event types to their equivalent CloudEvent types.
|
|
29
29
|
# For more info on event mappings see
|
|
30
|
-
# https://github.com/GoogleCloudPlatform/functions-framework-conformance/blob/
|
|
30
|
+
# https://github.com/GoogleCloudPlatform/functions-framework-conformance/blob/main/docs/mapping.md
|
|
31
31
|
_BACKGROUND_TO_CE_TYPE = {
|
|
32
32
|
"google.pubsub.topic.publish": "google.cloud.pubsub.topic.v1.messagePublished",
|
|
33
33
|
"providers/cloud.pubsub/eventTypes/topic.publish": "google.cloud.pubsub.topic.v1.messagePublished",
|
|
File without changes
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework.egg-info/PKG-INFO
RENAMED
|
@@ -1,30 +1,34 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: functions-framework
|
|
3
|
-
Version: 3.
|
|
3
|
+
Version: 3.6.0
|
|
4
4
|
Summary: An open source FaaS (Function as a service) framework for writing portable Python functions -- brought to you by the Google Cloud Functions team.
|
|
5
5
|
Home-page: https://github.com/googlecloudplatform/functions-framework-python
|
|
6
6
|
Author: Google LLC
|
|
7
7
|
Author-email: googleapis-packages@google.com
|
|
8
8
|
Keywords: functions-framework
|
|
9
|
-
Classifier: Development Status ::
|
|
9
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
10
10
|
Classifier: Intended Audience :: Developers
|
|
11
11
|
Classifier: License :: OSI Approved :: Apache Software License
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.5
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.6
|
|
15
12
|
Classifier: Programming Language :: Python :: 3.7
|
|
16
13
|
Classifier: Programming Language :: Python :: 3.8
|
|
17
14
|
Classifier: Programming Language :: Python :: 3.9
|
|
18
15
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
19
18
|
Requires-Python: >=3.5, <4
|
|
20
19
|
Description-Content-Type: text/markdown
|
|
21
20
|
License-File: LICENSE
|
|
21
|
+
Requires-Dist: flask<4.0,>=1.0
|
|
22
|
+
Requires-Dist: click<9.0,>=7.0
|
|
23
|
+
Requires-Dist: watchdog>=1.0.0
|
|
24
|
+
Requires-Dist: gunicorn>=19.2.0; platform_system != "Windows"
|
|
25
|
+
Requires-Dist: cloudevents<2.0.0,>=1.2.0
|
|
22
26
|
|
|
23
27
|
# Functions Framework for Python
|
|
24
28
|
|
|
25
29
|
[](https://badge.fury.io/py/functions-framework)
|
|
26
30
|
|
|
27
|
-
[![Python unit CI][ff_python_unit_img]][ff_python_unit_link] [![Python lint CI][ff_python_lint_img]][ff_python_lint_link] [![Python conformace CI][ff_python_conformance_img]][ff_python_conformance_link]
|
|
31
|
+
[![Python unit CI][ff_python_unit_img]][ff_python_unit_link] [![Python lint CI][ff_python_lint_img]][ff_python_lint_link] [![Python conformace CI][ff_python_conformance_img]][ff_python_conformance_link] 
|
|
28
32
|
|
|
29
33
|
An open source FaaS (Function as a service) framework for writing portable
|
|
30
34
|
Python functions -- brought to you by the Google Cloud Functions team.
|
|
@@ -81,14 +85,15 @@ functions-framework==3.*
|
|
|
81
85
|
Create an `main.py` file with the following contents:
|
|
82
86
|
|
|
83
87
|
```python
|
|
88
|
+
import flask
|
|
84
89
|
import functions_framework
|
|
85
90
|
|
|
86
91
|
@functions_framework.http
|
|
87
|
-
def hello(request):
|
|
92
|
+
def hello(request: flask.Request) -> flask.typing.ResponseReturnValue:
|
|
88
93
|
return "Hello world!"
|
|
89
94
|
```
|
|
90
95
|
|
|
91
|
-
> Your function is passed a single parameter, `(request)`, which is a Flask [`Request`](
|
|
96
|
+
> Your function is passed a single parameter, `(request)`, which is a Flask [`Request`](https://flask.palletsprojects.com/en/3.0.x/api/#flask.Request) object.
|
|
92
97
|
|
|
93
98
|
Run the following command:
|
|
94
99
|
|
|
@@ -120,13 +125,14 @@ Create an `main.py` file with the following contents:
|
|
|
120
125
|
|
|
121
126
|
```python
|
|
122
127
|
import functions_framework
|
|
128
|
+
from cloudevents.http.event import CloudEvent
|
|
123
129
|
|
|
124
130
|
@functions_framework.cloud_event
|
|
125
|
-
def hello_cloud_event(cloud_event):
|
|
131
|
+
def hello_cloud_event(cloud_event: CloudEvent) -> None:
|
|
126
132
|
print(f"Received event with ID: {cloud_event['id']} and data {cloud_event.data}")
|
|
127
133
|
```
|
|
128
134
|
|
|
129
|
-
> Your function is passed a single [CloudEvent](https://github.com/cloudevents/sdk-python/blob/
|
|
135
|
+
> Your function is passed a single [CloudEvent](https://github.com/cloudevents/sdk-python/blob/main/cloudevents/sdk/event/v1.py) parameter.
|
|
130
136
|
|
|
131
137
|
Run the following command to run `hello_cloud_event` target locally:
|
|
132
138
|
|
|
@@ -324,7 +330,7 @@ After you've written your function, you can simply deploy it from your local mac
|
|
|
324
330
|
|
|
325
331
|
### Cloud Run/Cloud Run on GKE
|
|
326
332
|
|
|
327
|
-
Once you've written your function and added the Functions Framework to your `requirements.txt` file, all that's left is to create a container image. [Check out the Cloud Run quickstart](https://cloud.google.com/run/docs/quickstarts/build-and-deploy) for Python to create a container image and deploy it to Cloud Run. You'll write a `Dockerfile` when you build your container. This `Dockerfile` allows you to specify exactly what goes into your container (including custom binaries, a specific operating system, and more). [Here is an example `Dockerfile` that calls Functions Framework.](https://github.com/GoogleCloudPlatform/functions-framework-python/blob/
|
|
333
|
+
Once you've written your function and added the Functions Framework to your `requirements.txt` file, all that's left is to create a container image. [Check out the Cloud Run quickstart](https://cloud.google.com/run/docs/quickstarts/build-and-deploy) for Python to create a container image and deploy it to Cloud Run. You'll write a `Dockerfile` when you build your container. This `Dockerfile` allows you to specify exactly what goes into your container (including custom binaries, a specific operating system, and more). [Here is an example `Dockerfile` that calls Functions Framework.](https://github.com/GoogleCloudPlatform/functions-framework-python/blob/main/examples/cloud_run_http)
|
|
328
334
|
|
|
329
335
|
If you want even more control over the environment, you can [deploy your container image to Cloud Run on GKE](https://cloud.google.com/run/docs/quickstarts/prebuilt-deploy-gke). With Cloud Run on GKE, you can run your function on a GKE cluster, which gives you additional control over the environment (including use of GPU-based instances, longer timeouts and more).
|
|
330
336
|
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework.egg-info/SOURCES.txt
RENAMED
|
@@ -10,6 +10,7 @@ src/functions_framework/_typed_event.py
|
|
|
10
10
|
src/functions_framework/background_event.py
|
|
11
11
|
src/functions_framework/event_conversion.py
|
|
12
12
|
src/functions_framework/exceptions.py
|
|
13
|
+
src/functions_framework/py.typed
|
|
13
14
|
src/functions_framework.egg-info/PKG-INFO
|
|
14
15
|
src/functions_framework.egg-info/SOURCES.txt
|
|
15
16
|
src/functions_framework.egg-info/dependency_links.txt
|
|
@@ -38,4 +39,5 @@ tests/test_http.py
|
|
|
38
39
|
tests/test_main.py
|
|
39
40
|
tests/test_samples.py
|
|
40
41
|
tests/test_typed_event_functions.py
|
|
42
|
+
tests/test_typing.py
|
|
41
43
|
tests/test_view_functions.py
|
|
@@ -323,6 +323,19 @@ def test_invalid_function_definition_function_syntax_error():
|
|
|
323
323
|
)
|
|
324
324
|
|
|
325
325
|
|
|
326
|
+
def test_invalid_function_definition_function_syntax_robustness_with_debug(monkeypatch):
|
|
327
|
+
monkeypatch.setattr(
|
|
328
|
+
functions_framework.werkzeug.serving, "is_running_from_reloader", lambda: True
|
|
329
|
+
)
|
|
330
|
+
source = TEST_FUNCTIONS_DIR / "background_load_error" / "main.py"
|
|
331
|
+
target = "function"
|
|
332
|
+
|
|
333
|
+
client = create_app(target, source).test_client()
|
|
334
|
+
|
|
335
|
+
resp = client.get("/")
|
|
336
|
+
assert resp.status_code == 500
|
|
337
|
+
|
|
338
|
+
|
|
326
339
|
def test_invalid_function_definition_missing_dependency():
|
|
327
340
|
source = TEST_FUNCTIONS_DIR / "background_missing_dependency" / "main.py"
|
|
328
341
|
target = "function"
|
|
@@ -12,6 +12,7 @@
|
|
|
12
12
|
# See the License for the specific language governing permissions and
|
|
13
13
|
# limitations under the License.
|
|
14
14
|
|
|
15
|
+
import os
|
|
15
16
|
import platform
|
|
16
17
|
import sys
|
|
17
18
|
|
|
@@ -96,17 +97,17 @@ def test_gunicorn_application(debug):
|
|
|
96
97
|
assert gunicorn_app.app == app
|
|
97
98
|
assert gunicorn_app.options == {
|
|
98
99
|
"bind": "%s:%s" % (host, port),
|
|
99
|
-
"workers":
|
|
100
|
-
"threads":
|
|
101
|
-
"timeout":
|
|
100
|
+
"workers": os.cpu_count() * 4,
|
|
101
|
+
"threads": 1,
|
|
102
|
+
"timeout": 300,
|
|
102
103
|
"loglevel": "error",
|
|
103
104
|
"limit_request_line": 0,
|
|
104
105
|
}
|
|
105
106
|
|
|
106
107
|
assert gunicorn_app.cfg.bind == ["1.2.3.4:1234"]
|
|
107
|
-
assert gunicorn_app.cfg.workers ==
|
|
108
|
-
assert gunicorn_app.cfg.threads ==
|
|
109
|
-
assert gunicorn_app.cfg.timeout ==
|
|
108
|
+
assert gunicorn_app.cfg.workers == os.cpu_count() * 4
|
|
109
|
+
assert gunicorn_app.cfg.threads == 1
|
|
110
|
+
assert gunicorn_app.cfg.timeout == 300
|
|
110
111
|
assert gunicorn_app.load() == app
|
|
111
112
|
|
|
112
113
|
|
|
@@ -24,7 +24,7 @@ class TestSamples:
|
|
|
24
24
|
self.stop_all_containers(client)
|
|
25
25
|
|
|
26
26
|
TAG = "cloud_run_http"
|
|
27
|
-
client.images.build(path=str(EXAMPLES_DIR / "cloud_run_http"), tag=
|
|
27
|
+
client.images.build(path=str(EXAMPLES_DIR / "cloud_run_http"), tag=TAG)
|
|
28
28
|
container = client.containers.run(image=TAG, detach=True, ports={8080: 8080})
|
|
29
29
|
timeout = 10
|
|
30
30
|
success = False
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
|
|
3
|
+
if typing.TYPE_CHECKING: # pragma: no cover
|
|
4
|
+
import flask
|
|
5
|
+
|
|
6
|
+
from cloudevents.http.event import CloudEvent
|
|
7
|
+
|
|
8
|
+
import functions_framework
|
|
9
|
+
|
|
10
|
+
@functions_framework.http
|
|
11
|
+
def hello(request: flask.Request) -> flask.typing.ResponseReturnValue:
|
|
12
|
+
return "Hello world!"
|
|
13
|
+
|
|
14
|
+
@functions_framework.cloud_event
|
|
15
|
+
def hello_cloud_event(cloud_event: CloudEvent) -> None:
|
|
16
|
+
print(f"Received event: id={cloud_event['id']} and data={cloud_event.data}")
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/_http/__init__.py
RENAMED
|
File without changes
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/_http/flask.py
RENAMED
|
File without changes
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/background_event.py
RENAMED
|
File without changes
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/functions_framework/exceptions.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/google/cloud/functions/__init__.py
RENAMED
|
File without changes
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/google/cloud/functions/context.py
RENAMED
|
File without changes
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/google/cloud/functions_v1/__init__.py
RENAMED
|
File without changes
|
{functions-framework-3.4.0 → functions_framework-3.6.0}/src/google/cloud/functions_v1/context.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|