Skip to content

Commit 45aed53

Browse files
feat: initial typing of the public API (#248)
* Initial typing of the public API This adds type annotations for the 2 main decorators of the library. Closes: #190 * fix typing * Remove zip_safe flag, as it's not needed anymore. * run black * fix import order --------- Co-authored-by: Gareth <garethgeorge@google.com>
1 parent 049e031 commit 45aed53

File tree

6 files changed

+30
-5
lines changed

6 files changed

+30
-5
lines changed

README.md

+4-2
Original file line numberDiff line numberDiff line change
@@ -59,10 +59,11 @@ functions-framework==3.*
5959
Create an `main.py` file with the following contents:
6060

6161
```python
62+
import flask
6263
import functions_framework
6364

6465
@functions_framework.http
65-
def hello(request):
66+
def hello(request: flask.Request) -> flask.typing.ResponseReturnValue:
6667
return "Hello world!"
6768
```
6869

@@ -98,9 +99,10 @@ Create an `main.py` file with the following contents:
9899

99100
```python
100101
import functions_framework
102+
from cloudevents.http.event import CloudEvent
101103

102104
@functions_framework.cloud_event
103-
def hello_cloud_event(cloud_event):
105+
def hello_cloud_event(cloud_event: CloudEvent) -> None:
104106
print(f"Received event with ID: {cloud_event['id']} and data {cloud_event.data}")
105107
```
106108

setup.py

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
],
4747
keywords="functions-framework",
4848
packages=find_packages(where="src"),
49+
package_data={"functions_framework": ["py.typed"]},
4950
namespace_packages=["google", "google.cloud"],
5051
package_dir={"": "src"},
5152
python_requires=">=3.5, <4",

src/functions_framework/__init__.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,14 @@
2323
import types
2424

2525
from inspect import signature
26-
from typing import Type
26+
from typing import Callable, Type
2727

2828
import cloudevents.exceptions as cloud_exceptions
2929
import flask
3030
import werkzeug
3131

3232
from cloudevents.http import from_http, is_binary
33+
from cloudevents.http.event import CloudEvent
3334

3435
from functions_framework import _function_registry, _typed_event, event_conversion
3536
from functions_framework.background_event import BackgroundEvent
@@ -45,6 +46,9 @@
4546

4647
_CLOUDEVENT_MIME_TYPE = "application/cloudevents+json"
4748

49+
CloudEventFunction = Callable[[CloudEvent], None]
50+
HTTPFunction = Callable[[flask.Request], flask.typing.ResponseReturnValue]
51+
4852

4953
class _LoggingHandler(io.TextIOWrapper):
5054
"""Logging replacement for stdout and stderr in GCF Python 3.7."""
@@ -59,7 +63,7 @@ def write(self, out):
5963
return self.stderr.write(json.dumps(payload) + "\n")
6064

6165

62-
def cloud_event(func):
66+
def cloud_event(func: CloudEventFunction) -> CloudEventFunction:
6367
"""Decorator that registers cloudevent as user function signature type."""
6468
_function_registry.REGISTRY_MAP[
6569
func.__name__
@@ -99,7 +103,7 @@ def wrapper(*args, **kwargs):
99103
return _typed
100104

101105

102-
def http(func):
106+
def http(func: HTTPFunction) -> HTTPFunction:
103107
"""Decorator that registers http as user function signature type."""
104108
_function_registry.REGISTRY_MAP[
105109
func.__name__

src/functions_framework/py.typed

Whitespace-only changes.

tests/test_typing.py

+16
Original file line numberDiff line numberDiff line change
@@ -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}")

tox.ini

+2
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,10 @@ deps =
1919
black
2020
twine
2121
isort
22+
mypy
2223
commands =
2324
black --check src tests setup.py conftest.py --exclude tests/test_functions/background_load_error/main.py
2425
isort -c src tests setup.py conftest.py
26+
mypy tests/test_typing.py
2527
python setup.py --quiet sdist bdist_wheel
2628
twine check dist/*

0 commit comments

Comments
 (0)