Skip to content

Commit b5f7316

Browse files
committed
chore: type the module
1 parent 4d68841 commit b5f7316

File tree

1 file changed

+85
-21
lines changed

1 file changed

+85
-21
lines changed

Diff for: supabase/lib/storage/storage_bucket_api.py

+85-21
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,43 @@
11
from __future__ import annotations
22

33
from collections.abc import Awaitable
4-
from typing import Any, Literal, Optional, Union
4+
from dataclasses import dataclass
5+
from datetime import datetime
6+
from typing import Any, Literal, Optional, Type, Union
57

68
from httpx import AsyncClient, Client
79

8-
RequestMethod = Literal["GET", "POST", "PUT", "DELETE", "PATCH"]
9-
# dict is returned when the request was synchronous, awaitable when async, None if there was an error
10-
_SyncOrAsyncResponse = Union[dict[str, Any], Awaitable, None]
10+
__all__ = ["Bucket", "StorageBucketAPI"]
11+
12+
_RequestMethod = Literal["GET", "POST", "PUT", "DELETE", "PATCH"]
13+
14+
15+
@dataclass
16+
class Bucket:
17+
id: str
18+
name: str
19+
owner: str
20+
public: bool
21+
created_at: datetime
22+
updated_at: datetime
23+
24+
def __post_init__(self) -> None:
25+
# created_at and updated_at are returned by the API as ISO timestamps
26+
# so we convert them to datetime objects
27+
self.created_at = datetime.fromisoformat(self.created_at) # type: ignore
28+
self.updated_at = datetime.fromisoformat(self.updated_at) # type: ignore
29+
30+
31+
ResponseType = Union[
32+
dict[
33+
str, str
34+
], # response from an endpoint without a custom response_class, example: create_bucket
35+
list[
36+
Bucket
37+
], # response from an endpoint which returns a list of objects, example: list_buckets
38+
Bucket, # response from an endpoint which returns a single object, example: get_bucket
39+
None,
40+
]
1141

1242

1343
class StorageBucketAPI:
@@ -27,50 +57,82 @@ def __init__(
2757
self._client = Client(headers=self.headers)
2858

2959
def _request(
30-
self, method: RequestMethod, url: str, json: Optional[dict[Any, Any]] = None
31-
) -> Union[dict[Any, Any], Awaitable, None]:
60+
self,
61+
method: _RequestMethod,
62+
url: str,
63+
json: Optional[dict[Any, Any]] = None,
64+
response_class: Optional[Type] = None,
65+
) -> Any:
3266
if self._is_async:
33-
return self._async_request(method, url, json)
67+
return self._async_request(method, url, json, response_class)
3468
else:
35-
return self._sync_request(method, url, json)
69+
return self._sync_request(method, url, json, response_class)
3670

3771
def _sync_request(
38-
self, method: RequestMethod, url: str, json: Optional[dict[Any, Any]] = None
39-
) -> Optional[dict[Any, Any]]:
72+
self,
73+
method: _RequestMethod,
74+
url: str,
75+
json: Optional[dict[Any, Any]] = None,
76+
response_class: Optional[Type] = None,
77+
) -> ResponseType:
4078
if isinstance(self._client, AsyncClient): # only to appease the type checker
4179
return
4280

4381
response = self._client.request(method, url, json=json)
4482
response.raise_for_status()
45-
return response.json()
83+
84+
response_data = response.json()
85+
86+
if not response_class:
87+
# if no response_class is specified, return the raw response
88+
return response_data
89+
90+
if isinstance(response_data, list):
91+
# if a list of objects are returned, convert each member to response_class
92+
return [response_class(**item) for item in response_data]
93+
else:
94+
return response_class(**response_data)
4695

4796
async def _async_request(
48-
self, method: RequestMethod, url: str, json: Optional[dict[Any, Any]] = None
49-
) -> Optional[dict[Any, Any]]:
97+
self,
98+
method: _RequestMethod,
99+
url: str,
100+
json: Optional[dict[Any, Any]] = None,
101+
response_class: Optional[Type] = None,
102+
) -> ResponseType:
50103
if isinstance(self._client, Client): # only to appease the type checker
51104
return
52105

53106
response = await self._client.request(method, url, json=json)
54107
response.raise_for_status()
55-
return response.json()
56108

57-
def list_buckets(self) -> _SyncOrAsyncResponse:
109+
response_data = response.json()
110+
111+
if not response_class:
112+
return response_data
113+
114+
if isinstance(response_data, list):
115+
return [response_class(**item) for item in response_data]
116+
else:
117+
return response_class(**response_data)
118+
119+
def list_buckets(self) -> Union[list[Bucket], Awaitable[list[Bucket]], None]:
58120
"""Retrieves the details of all storage buckets within an existing product."""
59-
return self._request("GET", f"{self.url}/bucket")
121+
return self._request("GET", f"{self.url}/bucket", response_class=Bucket)
60122

61-
def get_bucket(self, id: str) -> _SyncOrAsyncResponse:
123+
def get_bucket(self, id: str) -> Union[Bucket, Awaitable[Bucket], None]:
62124
"""Retrieves the details of an existing storage bucket.
63125
64126
Parameters
65127
----------
66128
id
67129
The unique identifier of the bucket you would like to retrieve.
68130
"""
69-
return self._request("GET", f"{self.url}/bucket/{id}")
131+
return self._request("GET", f"{self.url}/bucket/{id}", response_class=Bucket)
70132

71133
def create_bucket(
72134
self, id: str, name: str = None, public: bool = False
73-
) -> _SyncOrAsyncResponse:
135+
) -> Union[dict[str, str], Awaitable[dict[str, str]]]:
74136
"""Creates a new storage bucket.
75137
76138
Parameters
@@ -88,7 +150,7 @@ def create_bucket(
88150
json={"id": id, "name": name, "public": public},
89151
)
90152

91-
def empty_bucket(self, id: str) -> _SyncOrAsyncResponse:
153+
def empty_bucket(self, id: str) -> Union[dict[str, str], Awaitable[dict[str, str]]]:
92154
"""Removes all objects inside a single bucket.
93155
94156
Parameters
@@ -98,7 +160,9 @@ def empty_bucket(self, id: str) -> _SyncOrAsyncResponse:
98160
"""
99161
return self._request("POST", f"{self.url}/bucket/{id}/empty", json={})
100162

101-
def delete_bucket(self, id: str) -> _SyncOrAsyncResponse:
163+
def delete_bucket(
164+
self, id: str
165+
) -> Union[dict[str, str], Awaitable[dict[str, str]]]:
102166
"""Deletes an existing bucket. Note that you cannot delete buckets with existing objects inside. You must first
103167
`empty()` the bucket.
104168

0 commit comments

Comments
 (0)