Skip to content

Commit

Permalink
feat: initial typing of the public API (#248)
Browse files Browse the repository at this point in the history
* 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>
  • Loading branch information
multani and garethgeorge authored Aug 28, 2023
1 parent 049e031 commit 45aed53
Show file tree
Hide file tree
Showing 6 changed files with 30 additions and 5 deletions.
6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,10 +59,11 @@ functions-framework==3.*
Create an `main.py` file with the following contents:

```python
import flask
import functions_framework

@functions_framework.http
def hello(request):
def hello(request: flask.Request) -> flask.typing.ResponseReturnValue:
return "Hello world!"
```

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

```python
import functions_framework
from cloudevents.http.event import CloudEvent

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

Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
],
keywords="functions-framework",
packages=find_packages(where="src"),
package_data={"functions_framework": ["py.typed"]},
namespace_packages=["google", "google.cloud"],
package_dir={"": "src"},
python_requires=">=3.5, <4",
Expand Down
10 changes: 7 additions & 3 deletions src/functions_framework/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,14 @@
import types

from inspect import signature
from typing import Type
from typing import Callable, Type

import cloudevents.exceptions as cloud_exceptions
import flask
import werkzeug

from cloudevents.http import from_http, is_binary
from cloudevents.http.event import CloudEvent

from functions_framework import _function_registry, _typed_event, event_conversion
from functions_framework.background_event import BackgroundEvent
Expand All @@ -45,6 +46,9 @@

_CLOUDEVENT_MIME_TYPE = "application/cloudevents+json"

CloudEventFunction = Callable[[CloudEvent], None]
HTTPFunction = Callable[[flask.Request], flask.typing.ResponseReturnValue]


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


def cloud_event(func):
def cloud_event(func: CloudEventFunction) -> CloudEventFunction:
"""Decorator that registers cloudevent as user function signature type."""
_function_registry.REGISTRY_MAP[
func.__name__
Expand Down Expand Up @@ -99,7 +103,7 @@ def wrapper(*args, **kwargs):
return _typed


def http(func):
def http(func: HTTPFunction) -> HTTPFunction:
"""Decorator that registers http as user function signature type."""
_function_registry.REGISTRY_MAP[
func.__name__
Expand Down
Empty file.
16 changes: 16 additions & 0 deletions tests/test_typing.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import typing

if typing.TYPE_CHECKING: # pragma: no cover
import flask

from cloudevents.http.event import CloudEvent

import functions_framework

@functions_framework.http
def hello(request: flask.Request) -> flask.typing.ResponseReturnValue:
return "Hello world!"

@functions_framework.cloud_event
def hello_cloud_event(cloud_event: CloudEvent) -> None:
print(f"Received event: id={cloud_event['id']} and data={cloud_event.data}")
2 changes: 2 additions & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,10 @@ deps =
black
twine
isort
mypy
commands =
black --check src tests setup.py conftest.py --exclude tests/test_functions/background_load_error/main.py
isort -c src tests setup.py conftest.py
mypy tests/test_typing.py
python setup.py --quiet sdist bdist_wheel
twine check dist/*

0 comments on commit 45aed53

Please sign in to comment.