Skip to content

Commit

Permalink
feat: rewrite region enumerated literals as Enums (#164)
Browse files Browse the repository at this point in the history
  • Loading branch information
juancarlospaco authored Nov 28, 2024
1 parent 46cadae commit 3ca78fa
Show file tree
Hide file tree
Showing 8 changed files with 101 additions and 8 deletions.
20 changes: 18 additions & 2 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ repository = "https://github.com/supabase/functions-py"
[tool.poetry.dependencies]
python = "^3.9"
httpx = {version = ">=0.26,<0.28", extras = ["http2"]}
strenum = "^0.4.15"

[tool.poetry.group.dev.dependencies]
black = ">=23.9.1,<25.0.0"
Expand Down
1 change: 1 addition & 0 deletions supabase_functions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from ._async.functions_client import AsyncFunctionsClient
from ._sync.functions_client import SyncFunctionsClient
from .utils import FunctionRegion

__all__ = ["create_client"]

Expand Down
18 changes: 15 additions & 3 deletions supabase_functions/_async/functions_client.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
from typing import Any, Dict, Literal, Optional, Union
from warnings import warn

from httpx import HTTPError, Response

from ..errors import FunctionsHttpError, FunctionsRelayError
from ..utils import AsyncClient, is_http_url, is_valid_jwt, is_valid_str_arg
from ..utils import (
AsyncClient,
FunctionRegion,
is_http_url,
is_valid_jwt,
is_valid_str_arg,
)
from ..version import __version__


Expand Down Expand Up @@ -88,8 +95,13 @@ async def invoke(
response_type = invoke_options.get("responseType", "text/plain")

region = invoke_options.get("region")
if region and isinstance(region, str) and region != "any":
headers["x-region"] = region.lower().strip()
if region:
if not isinstance(region, FunctionRegion):
warn(f"Use FunctionRegion({region})")
region = FunctionRegion(region)

if region.value != "any":
headers["x-region"] = region.value

body = invoke_options.get("body")
if isinstance(body, str):
Expand Down
18 changes: 15 additions & 3 deletions supabase_functions/_sync/functions_client.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,16 @@
from typing import Any, Dict, Literal, Optional, Union
from warnings import warn

from httpx import HTTPError, Response

from ..errors import FunctionsHttpError, FunctionsRelayError
from ..utils import SyncClient, is_http_url, is_valid_jwt, is_valid_str_arg
from ..utils import (
FunctionRegion,
SyncClient,
is_http_url,
is_valid_jwt,
is_valid_str_arg,
)
from ..version import __version__


Expand Down Expand Up @@ -88,8 +95,13 @@ def invoke(
response_type = invoke_options.get("responseType", "text/plain")

region = invoke_options.get("region")
if region and isinstance(region, str) and region != "any":
headers["x-region"] = region.lower().strip()
if region:
if not isinstance(region, FunctionRegion):
warn(f"Use FunctionRegion({region})")
region = FunctionRegion(region)

if region.value != "any":
headers["x-region"] = region.value

body = invoke_options.get("body")
if isinstance(body, str):
Expand Down
25 changes: 25 additions & 0 deletions supabase_functions/utils.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,38 @@
import re
import sys
from urllib.parse import urlparse

from httpx import AsyncClient as AsyncClient # noqa: F401
from httpx import Client as BaseClient

if sys.version_info >= (3, 11):
from enum import StrEnum
else:
from strenum import StrEnum


DEFAULT_FUNCTION_CLIENT_TIMEOUT = 5
BASE64URL_REGEX = r"^([a-z0-9_-]{4})*($|[a-z0-9_-]{3}$|[a-z0-9_-]{2}$)$"


class FunctionRegion(StrEnum):
Any = "any"
ApNortheast1 = "ap-northeast-1"
ApNortheast2 = "ap-northeast-2"
ApSouth1 = "ap-south-1"
ApSoutheast1 = "ap-southeast-1"
ApSoutheast2 = "ap-southeast-2"
CaCentral1 = "ca-central-1"
EuCentral1 = "eu-central-1"
EuWest1 = "eu-west-1"
EuWest2 = "eu-west-2"
EuWest3 = "eu-west-3"
SaEast1 = "sa-east-1"
UsEast1 = "us-east-1"
UsWest1 = "us-west-1"
UsWest2 = "us-west-2"


class SyncClient(BaseClient):
def aclose(self) -> None:
self.close()
Expand Down
13 changes: 13 additions & 0 deletions tests/_async/test_function_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from httpx import Response
from jwt import encode

from supabase_functions import FunctionRegion
from supabase_functions.errors import FunctionsHttpError, FunctionsRelayError

from .clients import (
Expand Down Expand Up @@ -40,6 +41,18 @@ async def test_invoke():
assert route.called


async def test_invoke_region():
with respx.mock:
route = respx.post(f"{FUNCTIONS_URL}/hello-world").mock(
return_value=Response(200)
)
await function_client().invoke(
function_name="hello-world",
invoke_options={"region": FunctionRegion("us-west-2")},
)
assert route.called


async def test_invoke_with_json_response():
async with respx.mock:
route = respx.post(f"{FUNCTIONS_URL}/hello-world").mock(
Expand Down
13 changes: 13 additions & 0 deletions tests/_sync/test_function_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from httpx import Response
from jwt import encode

from supabase_functions import FunctionRegion
from supabase_functions.errors import FunctionsHttpError, FunctionsRelayError

from .clients import (
Expand Down Expand Up @@ -40,6 +41,18 @@ def test_invoke():
assert route.called


def test_invoke_region():
with respx.mock:
route = respx.post(f"{FUNCTIONS_URL}/hello-world").mock(
return_value=Response(200)
)
function_client().invoke(
function_name="hello-world",
invoke_options={"region": FunctionRegion("us-west-2")},
)
assert route.called


def test_invoke_with_json_response():
with respx.mock:
route = respx.post(f"{FUNCTIONS_URL}/hello-world").mock(
Expand Down

0 comments on commit 3ca78fa

Please sign in to comment.