Skip to content

Commit 575da96

Browse files
committed
Update errors and function signature of invoke
1 parent b60615d commit 575da96

File tree

7 files changed

+57
-48
lines changed

7 files changed

+57
-48
lines changed

supafunc/_async/functions_client.py

+20-12
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from httpx import HTTPError, Response
21
from typing import Any, Dict, Literal, Optional, Union
32

4-
from ..errors import FunctionsHttpError, FunctionsRelayError
3+
from httpx import HTTPError, Response
54

5+
from ..errors import FunctionsHttpError, FunctionsRelayError
66
from ..utils import AsyncClient, __version__
77

88

@@ -25,8 +25,11 @@ async def _request(
2525
response = await client.request(method, url, json=json, headers=headers)
2626
try:
2727
response.raise_for_status()
28-
except HTTPError:
29-
raise Exception({**response.json(), "statusCode": response.status_code})
28+
except HTTPError as exc:
29+
raise FunctionsHttpError(
30+
response.json().get("error")
31+
or f"An error occurred while requesting your edge function at {exc.request.url!r}."
32+
)
3033

3134
return response
3235

@@ -41,7 +44,9 @@ def set_auth(self, token: str) -> None:
4144

4245
self.headers["Authorization"] = f"Bearer {token}"
4346

44-
async def invoke(self, function_name: str, invoke_options: Dict = {}) -> Dict:
47+
async def invoke(
48+
self, function_name: str, invoke_options: Optional[Dict] = None
49+
) -> Dict:
4550
"""Invokes a function
4651
4752
Parameters
@@ -55,16 +60,22 @@ async def invoke(self, function_name: str, invoke_options: Dict = {}) -> Dict:
5560
Returns
5661
-------
5762
Dict
58-
Dictionary with data and/or error message
63+
Dictionary with data
5964
"""
60-
headers = {**self.headers, **invoke_options.get("headers", {})}
61-
body = invoke_options.get("body")
65+
headers = self.headers
66+
if invoke_options is not None:
67+
headers.update(invoke_options.get("headers", {}))
68+
69+
body = invoke_options.get("body") if invoke_options else None
70+
response_type = (
71+
invoke_options.get("responseType") if invoke_options else "text/plain"
72+
)
73+
6274
if type(body) == str:
6375
headers["Content-Type"] = "text/plain"
6476
elif type(body) == dict:
6577
headers["Content-Type"] = "application/json"
6678

67-
response_type = invoke_options.get("responseType")
6879
response = await self._request(
6980
"POST", f"{self.url}/{function_name}", headers=headers, json=body
7081
)
@@ -73,9 +84,6 @@ async def invoke(self, function_name: str, invoke_options: Dict = {}) -> Dict:
7384
if is_relay_error and is_relay_error == "true":
7485
raise FunctionsRelayError(response.json().get("error"))
7586

76-
if response.is_success is not True:
77-
raise FunctionsHttpError(response.json().get("error"))
78-
7987
if response_type == "json":
8088
data = response.json()
8189
else:

supafunc/_sync/functions_client.py

+19-13
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
from httpx import HTTPError, Response
21
from typing import Any, Dict, Literal, Optional, Union
32

4-
from ..errors import FunctionsHttpError, FunctionsRelayError
3+
from httpx import HTTPError, Response
54

5+
from ..errors import FunctionsHttpError, FunctionsRelayError
66
from ..utils import SyncClient, __version__
77

88

99
class SyncFunctionsClient:
1010
def __init__(self, url: str, headers: Dict):
1111
self.url = url
1212
self.headers = {
13-
"User-Agent": f"supabase-py/storage3 v{__version__}",
13+
"User-Agent": f"supabase-py/functions-py v{__version__}",
1414
**headers,
1515
}
1616

@@ -25,8 +25,11 @@ def _request(
2525
response = client.request(method, url, json=json, headers=headers)
2626
try:
2727
response.raise_for_status()
28-
except HTTPError:
29-
raise Exception({**response.json(), "statusCode": response.status_code})
28+
except HTTPError as exc:
29+
raise FunctionsHttpError(
30+
response.json().get("error")
31+
or f"An error occurred while requesting your edge function at {exc.request.url!r}."
32+
)
3033

3134
return response
3235

@@ -41,7 +44,7 @@ def set_auth(self, token: str) -> None:
4144

4245
self.headers["Authorization"] = f"Bearer {token}"
4346

44-
def invoke(self, function_name: str, invoke_options: Dict = {}) -> Dict:
47+
def invoke(self, function_name: str, invoke_options: Optional[Dict] = None) -> Dict:
4548
"""Invokes a function
4649
4750
Parameters
@@ -55,16 +58,22 @@ def invoke(self, function_name: str, invoke_options: Dict = {}) -> Dict:
5558
Returns
5659
-------
5760
Dict
58-
Dictionary with data and/or error message
61+
Dictionary with data
5962
"""
60-
headers = {**self.headers, **invoke_options.get("headers", {})}
61-
body = invoke_options.get("body")
63+
headers = self.headers
64+
if invoke_options is not None:
65+
headers.update(invoke_options.get("headers", {}))
66+
67+
body = invoke_options.get("body") if invoke_options else None
68+
response_type = (
69+
invoke_options.get("responseType") if invoke_options else "text/plain"
70+
)
71+
6272
if type(body) == str:
6373
headers["Content-Type"] = "text/plain"
6474
elif type(body) == dict:
6575
headers["Content-Type"] = "application/json"
6676

67-
response_type = invoke_options.get("responseType")
6877
response = self._request(
6978
"POST", f"{self.url}/{function_name}", headers=headers, json=body
7079
)
@@ -73,9 +82,6 @@ def invoke(self, function_name: str, invoke_options: Dict = {}) -> Dict:
7382
if is_relay_error and is_relay_error == "true":
7483
raise FunctionsRelayError(response.json().get("error"))
7584

76-
if response.is_success is not True:
77-
raise FunctionsHttpError(response.json().get("error"))
78-
7985
if response_type == "json":
8086
data = response.json()
8187
else:

supafunc/errors.py

+6-15
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,6 @@
11
from __future__ import annotations
22

3-
from typing_extensions import TypedDict
4-
5-
6-
class FunctionsError(Exception):
7-
def __init__(self, message: str) -> None:
8-
Exception.__init__(self, message)
9-
self.message = message
10-
self.name = "FunctionsError"
3+
from typing import TypedDict
114

125

136
class FunctionsApiErrorDict(TypedDict):
@@ -16,9 +9,9 @@ class FunctionsApiErrorDict(TypedDict):
169
status: int
1710

1811

19-
class CustomFunctionsError(FunctionsError):
12+
class FunctionsError(Exception):
2013
def __init__(self, message: str, name: str, status: int) -> None:
21-
FunctionsError.__init__(self, message)
14+
super().__init__(message)
2215
self.name = name
2316
self.status = status
2417

@@ -30,23 +23,21 @@ def to_dict(self) -> FunctionsApiErrorDict:
3023
}
3124

3225

33-
class FunctionsHttpError(CustomFunctionsError):
26+
class FunctionsHttpError(FunctionsError):
3427
def __init__(self, message: str) -> None:
3528
super().__init__(
36-
self,
3729
message,
3830
"FunctionsHttpError",
3931
400,
4032
)
4133

4234

43-
class FunctionsRelayError(CustomFunctionsError):
35+
class FunctionsRelayError(FunctionsError):
4436
"""Base exception for relay errors."""
4537

4638
def __init__(self, message: str) -> None:
4739
super().__init__(
48-
self,
4940
message,
50-
"FunctionsHttpError",
41+
"FunctionsRelayError",
5142
400,
5243
)

tests/_async/clients.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from supafunc import AsyncFunctionsClient
21
from jwt import encode
32

3+
from supafunc import AsyncFunctionsClient
4+
45
GOTRUE_JWT_SECRET = "37c304f8-51aa-419a-a1af-06154e63707a"
56
FUNCTIONS_URL = "http://localhost:54321/functions/v1"
67

tests/_async/test_function_client.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
from httpx import Response
2-
from jwt import encode
31
import pytest
42
import respx
3+
from httpx import Response
4+
from jwt import encode
55

66
from supafunc.errors import FunctionsHttpError, FunctionsRelayError
7+
78
from .clients import (
8-
GOTRUE_JWT_SECRET,
99
FUNCTIONS_URL,
10+
GOTRUE_JWT_SECRET,
1011
function_client,
1112
mock_access_token,
1213
)

tests/_sync/clients.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from supafunc import SyncFunctionsClient
21
from jwt import encode
32

3+
from supafunc import SyncFunctionsClient
4+
45
GOTRUE_JWT_SECRET = "37c304f8-51aa-419a-a1af-06154e63707a"
56
FUNCTIONS_URL = "http://localhost:54321/functions/v1"
67

tests/_sync/test_function_client.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
1-
from httpx import Response
2-
from jwt import encode
31
import pytest
42
import respx
3+
from httpx import Response
4+
from jwt import encode
55

66
from supafunc.errors import FunctionsHttpError, FunctionsRelayError
7+
78
from .clients import (
8-
GOTRUE_JWT_SECRET,
99
FUNCTIONS_URL,
10+
GOTRUE_JWT_SECRET,
1011
function_client,
1112
mock_access_token,
1213
)

0 commit comments

Comments
 (0)