Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add async support #527

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
186 changes: 186 additions & 0 deletions supabase/async_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
import re
from typing import Any, Coroutine, Dict, Union

Check warning on line 2 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L1-L2

Added lines #L1 - L2 were not covered by tests

from httpx import Timeout
from postgrest import (

Check warning on line 5 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L4-L5

Added lines #L4 - L5 were not covered by tests
AsyncFilterRequestBuilder,
AsyncPostgrestClient,
AsyncRequestBuilder,
)
from postgrest.constants import DEFAULT_POSTGREST_CLIENT_TIMEOUT
from supafunc import FunctionsClient

Check warning on line 11 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L10-L11

Added lines #L10 - L11 were not covered by tests

from .exceptions import SupabaseException
from .lib.auth_client import SupabaseAuthClient
from .lib.client_options import ClientOptions
from .lib.storage_client import SupabaseStorageClient

Check warning on line 16 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L13-L16

Added lines #L13 - L16 were not covered by tests


class AsyncSupabaseClient:

Check warning on line 19 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L19

Added line #L19 was not covered by tests
"""Supabase client class."""

def __init__(

Check warning on line 22 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L22

Added line #L22 was not covered by tests
self,
supabase_url: str,
supabase_key: str,
options: ClientOptions = ClientOptions(),
):
"""Instantiate the client.

Parameters
----------
supabase_url: str
The URL to the Supabase instance that should be connected to.
supabase_key: str
The API key to the Supabase instance that should be connected to.
**options
Any extra settings to be optionally specified - also see the
`DEFAULT_OPTIONS` dict.
"""

if not supabase_url:
raise SupabaseException("supabase_url is required")
if not supabase_key:
raise SupabaseException("supabase_key is required")

Check warning on line 44 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L41-L44

Added lines #L41 - L44 were not covered by tests

# Check if the url and key are valid
if not re.match(r"^(https?)://.+", supabase_url):
raise SupabaseException("Invalid URL")

Check warning on line 48 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L47-L48

Added lines #L47 - L48 were not covered by tests

# Check if the key is a valid JWT
if not re.match(

Check warning on line 51 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L51

Added line #L51 was not covered by tests
r"^[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.?[A-Za-z0-9-_.+/=]*$", supabase_key
):
raise SupabaseException("Invalid API key")

Check warning on line 54 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L54

Added line #L54 was not covered by tests

self.supabase_url = supabase_url
self.supabase_key = supabase_key

Check warning on line 57 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L56-L57

Added lines #L56 - L57 were not covered by tests

options.headers.update(self._get_auth_headers())

Check warning on line 59 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L59

Added line #L59 was not covered by tests

self.rest_url: str = f"{supabase_url}/rest/v1"
self.realtime_url: str = f"{supabase_url}/realtime/v1".replace("http", "ws")
self.auth_url: str = f"{supabase_url}/auth/v1"
self.storage_url = f"{supabase_url}/storage/v1"

Check warning on line 64 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L61-L64

Added lines #L61 - L64 were not covered by tests

is_platform = re.search(r"(supabase\.co)|(supabase\.in)", supabase_url)
if is_platform:
url_parts = supabase_url.split(".")
self.functions_url = (

Check warning on line 69 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L66-L69

Added lines #L66 - L69 were not covered by tests
f"{url_parts[0]}.functions.{url_parts[1]}.{url_parts[2]}"
)
else:
self.functions_url = f"{supabase_url}/functions/v1"

Check warning on line 73 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L73

Added line #L73 was not covered by tests

self.schema: str = options.schema

Check warning on line 75 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L75

Added line #L75 was not covered by tests

# Instantiate clients.
self.auth = self._init_supabase_auth_client(

Check warning on line 78 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L78

Added line #L78 was not covered by tests
auth_url=self.auth_url,
client_options=options,
)
# TODO: Bring up to parity with JS client.
# self.realtime: SupabaseRealtimeClient = self._init_realtime_client(
# realtime_url=self.realtime_url,
# supabase_key=self.supabase_key,
# )
self.realtime = None
self.postgrest = self._init_postgrest_client(

Check warning on line 88 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L87-L88

Added lines #L87 - L88 were not covered by tests
rest_url=self.rest_url,
supabase_key=self.supabase_key,
headers=options.headers,
schema=options.schema,
)

async def __aenter__(self):
return self

Check warning on line 96 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L95-L96

Added lines #L95 - L96 were not covered by tests

async def __aexit__(self, exc_type, exc_value, traceback):
await self.postgrest.session.aclose()

Check warning on line 99 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L98-L99

Added lines #L98 - L99 were not covered by tests

def functions(self) -> FunctionsClient:

Check warning on line 101 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L101

Added line #L101 was not covered by tests
"""Create instance of the functions client"""
return FunctionsClient(self.functions_url, self._get_auth_headers())

Check warning on line 103 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L103

Added line #L103 was not covered by tests

def storage(self) -> SupabaseStorageClient:

Check warning on line 105 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L105

Added line #L105 was not covered by tests
"""Create instance of the storage client"""
return SupabaseStorageClient(self.storage_url, self._get_auth_headers())

Check warning on line 107 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L107

Added line #L107 was not covered by tests

def table(self, table_name: str) -> AsyncRequestBuilder:

Check warning on line 109 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L109

Added line #L109 was not covered by tests
"""Perform a table operation.

Note that the supabase client uses the `from` method, but in Python,
this is a reserved keyword, so we have elected to use the name `table`.
Alternatively you can use the `.on()` method.
"""
return self.on(table_name)

Check warning on line 116 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L116

Added line #L116 was not covered by tests

def on(self, table_name: str) -> AsyncRequestBuilder:

Check warning on line 118 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L118

Added line #L118 was not covered by tests
"""
An alias for `from_`.
"""
return self.postgrest.from_(table_name)

Check warning on line 122 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L122

Added line #L122 was not covered by tests

def from_(self, table_name: str) -> AsyncRequestBuilder:

Check warning on line 124 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L124

Added line #L124 was not covered by tests
"""Perform a table operation.

See the `table` method.
"""
return self.postgrest.from_(table_name)

Check warning on line 129 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L129

Added line #L129 was not covered by tests

def rpc(

Check warning on line 131 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L131

Added line #L131 was not covered by tests
self, fn: str, params: Dict[Any, Any]
) -> Coroutine[Any, Any, AsyncFilterRequestBuilder]:
"""Performs a stored procedure call.

Parameters
----------
fn : callable
The stored procedure call to be executed.
params : dict of any
Parameters passed into the stored procedure call.

Returns
-------
SyncFilterRequestBuilder
Returns a filter builder. This lets you apply filters on the response
of an RPC.
"""
return self.postgrest.rpc(fn, params)

Check warning on line 149 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L149

Added line #L149 was not covered by tests

@staticmethod
def _init_supabase_auth_client(

Check warning on line 152 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L151-L152

Added lines #L151 - L152 were not covered by tests
auth_url: str,
client_options: ClientOptions,
) -> SupabaseAuthClient:
"""Creates a wrapped instance of the GoTrue SupabaseClient."""
return SupabaseAuthClient(

Check warning on line 157 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L157

Added line #L157 was not covered by tests
url=auth_url,
auto_refresh_token=client_options.auto_refresh_token,
persist_session=client_options.persist_session,
local_storage=client_options.local_storage,
headers=client_options.headers,
)

@staticmethod
def _init_postgrest_client(

Check warning on line 166 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L165-L166

Added lines #L165 - L166 were not covered by tests
rest_url: str,
supabase_key: str,
headers: Dict[str, str],
schema: str,
timeout: Union[int, float, Timeout] = DEFAULT_POSTGREST_CLIENT_TIMEOUT,
) -> AsyncPostgrestClient:
"""Private helper for creating an instance of the Postgrest client."""
client = AsyncPostgrestClient(

Check warning on line 174 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L174

Added line #L174 was not covered by tests
rest_url, headers=headers, schema=schema, timeout=timeout
)
client.auth(token=supabase_key)
return client

Check warning on line 178 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L177-L178

Added lines #L177 - L178 were not covered by tests

def _get_auth_headers(self) -> Dict[str, str]:

Check warning on line 180 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L180

Added line #L180 was not covered by tests
"""Helper method to get auth headers."""
# What's the corresponding method to get the token
return {

Check warning on line 183 in supabase/async_client.py

View check run for this annotation

Codecov / codecov/patch

supabase/async_client.py#L183

Added line #L183 was not covered by tests
"apiKey": self.supabase_key,
"Authorization": f"Bearer {self.supabase_key}",
}
5 changes: 5 additions & 0 deletions supabase/exceptions.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Create an exception class when user does not provide a valid url or key.
class SupabaseException(Exception):
def __init__(self, message: str):
self.message = message
super().__init__(self.message)

Check warning on line 5 in supabase/exceptions.py

View check run for this annotation

Codecov / codecov/patch

supabase/exceptions.py#L2-L5

Added lines #L2 - L5 were not covered by tests
Loading