diff options
author | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
---|---|---|
committer | S. Solomon Darnell | 2025-03-28 21:52:21 -0500 |
commit | 4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch) | |
tree | ee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/supabase | |
parent | cc961e04ba734dd72309fb548a2f97d67d578813 (diff) | |
download | gn-ai-master.tar.gz |
Diffstat (limited to '.venv/lib/python3.12/site-packages/supabase')
13 files changed, 1122 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/supabase/__init__.py b/.venv/lib/python3.12/site-packages/supabase/__init__.py new file mode 100644 index 00000000..adf895a2 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/__init__.py @@ -0,0 +1,74 @@ +from gotrue.errors import ( + AuthApiError, + AuthError, + AuthImplicitGrantRedirectError, + AuthInvalidCredentialsError, + AuthRetryableError, + AuthSessionMissingError, + AuthUnknownError, + AuthWeakPasswordError, +) +from postgrest import APIError as PostgrestAPIError +from postgrest import APIResponse as PostgrestAPIResponse +from realtime import AuthorizationError, NotConnectedError +from storage3.utils import StorageException +from supafunc.errors import FunctionsError, FunctionsHttpError, FunctionsRelayError + +# Async Client +from ._async.auth_client import AsyncSupabaseAuthClient as ASupabaseAuthClient +from ._async.client import AsyncClient +from ._async.client import AsyncClient as AClient +from ._async.client import AsyncStorageClient as ASupabaseStorageClient +from ._async.client import SupabaseException as ASupabaseException +from ._async.client import create_client as acreate_client +from ._async.client import create_client as create_async_client + +# Sync Client +from ._sync.auth_client import SyncSupabaseAuthClient as SupabaseAuthClient +from ._sync.client import SupabaseException +from ._sync.client import SyncClient as Client +from ._sync.client import SyncStorageClient as SupabaseStorageClient +from ._sync.client import create_client + +# Lib +from .lib.client_options import AsyncClientOptions +from .lib.client_options import AsyncClientOptions as AClientOptions +from .lib.client_options import SyncClientOptions as ClientOptions + +# Version +from .version import __version__ + +__all__ = ( + "acreate_client", + "create_async_client", + "AClient", + "ASupabaseAuthClient", + "ASupabaseStorageClient", + "AClientOptions", + "AsyncClient", + "AsyncClientOptions", + "create_client", + "Client", + "SupabaseAuthClient", + "SupabaseStorageClient", + "ClientOptions", + "PostgrestAPIError", + "PostgrestAPIResponse", + "StorageException", + "__version__", + "AuthApiError", + "AuthError", + "AuthImplicitGrantRedirectError", + "AuthInvalidCredentialsError", + "AuthRetryableError", + "AuthSessionMissingError", + "AuthWeakPasswordError", + "AuthUnknownError", + "FunctionsHttpError", + "FunctionsRelayError", + "FunctionsError", + "AuthorizationError", + "NotConnectedError", + "SupabaseException", + "ASupabaseException", +) diff --git a/.venv/lib/python3.12/site-packages/supabase/_async/__init__.py b/.venv/lib/python3.12/site-packages/supabase/_async/__init__.py new file mode 100644 index 00000000..9d48db4f --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/_async/__init__.py @@ -0,0 +1 @@ +from __future__ import annotations diff --git a/.venv/lib/python3.12/site-packages/supabase/_async/auth_client.py b/.venv/lib/python3.12/site-packages/supabase/_async/auth_client.py new file mode 100644 index 00000000..6557b4a8 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/_async/auth_client.py @@ -0,0 +1,58 @@ +from typing import Dict, Optional + +from gotrue import ( + AsyncGoTrueClient, + AsyncMemoryStorage, + AsyncSupportedStorage, + AuthFlowType, +) +from gotrue.http_clients import AsyncClient + + +class AsyncSupabaseAuthClient(AsyncGoTrueClient): + """Supabase Auth Client for asynchronous operations.""" + + def __init__( + self, + *, + url: str, + headers: Optional[Dict[str, str]] = None, + storage_key: Optional[str] = None, + auto_refresh_token: bool = True, + persist_session: bool = True, + storage: AsyncSupportedStorage = AsyncMemoryStorage(), + http_client: Optional[AsyncClient] = None, + flow_type: AuthFlowType = "implicit", + verify: bool = True, + proxy: Optional[str] = None, + ): + """ + Instantiate a SupabaseAuthClient instance. + + Args: + url (str): The URL of the Supabase instance. + headers (Optional[Dict[str, str]]): Optional headers to include in requests. + storage_key (Optional[str]): Key to store session information. + auto_refresh_token (bool): Whether to automatically refresh the token. Defaults to True. + persist_session (bool): Whether to persist the session. Defaults to True. + storage (AsyncSupportedStorage): Storage mechanism. Defaults to AsyncMemoryStorage(). + http_client (Optional[AsyncClient]): HTTP client for making requests. Defaults to None. + flow_type (AuthFlowType): Type of authentication flow. Defaults to "implicit". + verify (bool): Whether to verify SSL certificates. Defaults to True. + proxy (Optional[str]): Proxy URL. Defaults to None. + """ + if headers is None: + headers = {} + + super().__init__( + url=url, + headers=headers, + storage_key=storage_key, + auto_refresh_token=auto_refresh_token, + persist_session=persist_session, + storage=storage, + http_client=http_client, + flow_type=flow_type, + verify=verify, + proxy=proxy, + ) diff --git a/.venv/lib/python3.12/site-packages/supabase/_async/client.py b/.venv/lib/python3.12/site-packages/supabase/_async/client.py new file mode 100644 index 00000000..ad21c7cd --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/_async/client.py @@ -0,0 +1,339 @@ +import asyncio +import re +from typing import Any, Dict, List, Optional, Union + +from gotrue import AsyncMemoryStorage +from gotrue.types import AuthChangeEvent, Session +from httpx import Timeout +from postgrest import ( + AsyncPostgrestClient, + AsyncRequestBuilder, + AsyncRPCFilterRequestBuilder, +) +from postgrest.constants import DEFAULT_POSTGREST_CLIENT_TIMEOUT +from realtime import AsyncRealtimeChannel, AsyncRealtimeClient, RealtimeChannelOptions +from storage3 import AsyncStorageClient +from storage3.constants import DEFAULT_TIMEOUT as DEFAULT_STORAGE_CLIENT_TIMEOUT +from supafunc import AsyncFunctionsClient + +from ..lib.client_options import AsyncClientOptions as ClientOptions +from .auth_client import AsyncSupabaseAuthClient + + +# 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) + + +class AsyncClient: + """Supabase client class.""" + + def __init__( + self, + supabase_url: str, + supabase_key: str, + options: Optional[ClientOptions] = None, + ): + """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 if the url and key are valid + if not re.match(r"^(https?)://.+", supabase_url): + raise SupabaseException("Invalid URL") + + # Check if the key is a valid JWT + if not re.match( + r"^[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.?[A-Za-z0-9-_.+/=]*$", supabase_key + ): + raise SupabaseException("Invalid API key") + + if options is None: + options = ClientOptions(storage=AsyncMemoryStorage()) + + self.supabase_url = supabase_url + self.supabase_key = supabase_key + self.options = options + options.headers.update(self._get_auth_headers()) + self.rest_url = f"{supabase_url}/rest/v1" + self.realtime_url = f"{supabase_url}/realtime/v1".replace("http", "ws") + self.auth_url = f"{supabase_url}/auth/v1" + self.storage_url = f"{supabase_url}/storage/v1" + self.functions_url = f"{supabase_url}/functions/v1" + + # Instantiate clients. + self.auth = self._init_supabase_auth_client( + auth_url=self.auth_url, + client_options=options, + ) + self.realtime = self._init_realtime_client( + realtime_url=self.realtime_url, + supabase_key=self.supabase_key, + options=options.realtime if options else None, + ) + self._postgrest = None + self._storage = None + self._functions = None + self.auth.on_auth_state_change(self._listen_to_auth_events) + + @classmethod + async def create( + cls, + supabase_url: str, + supabase_key: str, + options: Optional[ClientOptions] = None, + ): + auth_header = options.headers.get("Authorization") if options else None + client = cls(supabase_url, supabase_key, options) + + if auth_header is None: + try: + session = await client.auth.get_session() + session_access_token = client._create_auth_header(session.access_token) + except Exception as err: + session_access_token = None + + client.options.headers.update( + client._get_auth_headers(session_access_token) + ) + + return client + + def table(self, table_name: str) -> AsyncRequestBuilder: + """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 `.from_()` method. + """ + return self.from_(table_name) + + def schema(self, schema: str) -> AsyncPostgrestClient: + """Select a schema to query or perform an function (rpc) call. + + The schema needs to be on the list of exposed schemas inside Supabase. + """ + if self.options.schema != schema: + self.options.schema = schema + if self._postgrest: + self._postgrest.schema(schema) + return self.postgrest + + def from_(self, table_name: str) -> AsyncRequestBuilder: + """Perform a table operation. + + See the `table` method. + """ + return self.postgrest.from_(table_name) + + def rpc( + self, fn: str, params: Optional[Dict[Any, Any]] = None + ) -> AsyncRPCFilterRequestBuilder: + """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. + """ + if params is None: + params = {} + return self.postgrest.rpc(fn, params) + + @property + def postgrest(self): + if self._postgrest is None: + self._postgrest = self._init_postgrest_client( + rest_url=self.rest_url, + headers=self.options.headers, + schema=self.options.schema, + timeout=self.options.postgrest_client_timeout, + ) + + return self._postgrest + + @property + def storage(self): + if self._storage is None: + self._storage = self._init_storage_client( + storage_url=self.storage_url, + headers=self.options.headers, + storage_client_timeout=self.options.storage_client_timeout, + ) + return self._storage + + @property + def functions(self): + if self._functions is None: + self._functions = AsyncFunctionsClient( + self.functions_url, + self.options.headers, + self.options.function_client_timeout, + ) + return self._functions + + def channel( + self, topic: str, params: RealtimeChannelOptions = {} + ) -> AsyncRealtimeChannel: + """Creates a Realtime channel with Broadcast, Presence, and Postgres Changes.""" + return self.realtime.channel(topic, params) + + def get_channels(self) -> List[AsyncRealtimeChannel]: + """Returns all realtime channels.""" + return self.realtime.get_channels() + + async def remove_channel(self, channel: AsyncRealtimeChannel) -> None: + """Unsubscribes and removes Realtime channel from Realtime client.""" + await self.realtime.remove_channel(channel) + + async def remove_all_channels(self) -> None: + """Unsubscribes and removes all Realtime channels from Realtime client.""" + await self.realtime.remove_all_channels() + + @staticmethod + def _init_realtime_client( + realtime_url: str, supabase_key: str, options: Optional[Dict[str, Any]] = None + ) -> AsyncRealtimeClient: + if options is None: + options = {} + """Private method for creating an instance of the realtime-py client.""" + return AsyncRealtimeClient(realtime_url, token=supabase_key, **options) + + @staticmethod + def _init_storage_client( + storage_url: str, + headers: Dict[str, str], + storage_client_timeout: int = DEFAULT_STORAGE_CLIENT_TIMEOUT, + verify: bool = True, + proxy: Optional[str] = None, + ) -> AsyncStorageClient: + return AsyncStorageClient( + storage_url, headers, storage_client_timeout, verify, proxy + ) + + @staticmethod + def _init_supabase_auth_client( + auth_url: str, + client_options: ClientOptions, + verify: bool = True, + proxy: Optional[str] = None, + ) -> AsyncSupabaseAuthClient: + """Creates a wrapped instance of the GoTrue Client.""" + return AsyncSupabaseAuthClient( + url=auth_url, + auto_refresh_token=client_options.auto_refresh_token, + persist_session=client_options.persist_session, + storage=client_options.storage, + headers=client_options.headers, + flow_type=client_options.flow_type, + verify=verify, + proxy=proxy, + ) + + @staticmethod + def _init_postgrest_client( + rest_url: str, + headers: Dict[str, str], + schema: str, + timeout: Union[int, float, Timeout] = DEFAULT_POSTGREST_CLIENT_TIMEOUT, + verify: bool = True, + proxy: Optional[str] = None, + ) -> AsyncPostgrestClient: + """Private helper for creating an instance of the Postgrest client.""" + return AsyncPostgrestClient( + rest_url, + headers=headers, + schema=schema, + timeout=timeout, + verify=verify, + proxy=proxy, + ) + + def _create_auth_header(self, token: str): + return f"Bearer {token}" + + def _get_auth_headers(self, authorization: Optional[str] = None) -> Dict[str, str]: + if authorization is None: + authorization = self.options.headers.get( + "Authorization", self._create_auth_header(self.supabase_key) + ) + + """Helper method to get auth headers.""" + return { + "apiKey": self.supabase_key, + "Authorization": authorization, + } + + def _listen_to_auth_events( + self, event: AuthChangeEvent, session: Optional[Session] + ): + access_token = self.supabase_key + if event in ["SIGNED_IN", "TOKEN_REFRESHED", "SIGNED_OUT"]: + # reset postgrest and storage instance on event change + self._postgrest = None + self._storage = None + self._functions = None + access_token = session.access_token if session else self.supabase_key + + self.options.headers["Authorization"] = self._create_auth_header(access_token) + asyncio.create_task(self.realtime.set_auth(access_token)) + + +async def create_client( + supabase_url: str, + supabase_key: str, + options: Optional[ClientOptions] = None, +) -> AsyncClient: + """Create client function to instantiate supabase client like JS runtime. + + 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. + + Examples + -------- + Instantiating the client. + >>> import os + >>> from supabase import create_client, Client + >>> + >>> url: str = os.environ.get("SUPABASE_TEST_URL") + >>> key: str = os.environ.get("SUPABASE_TEST_KEY") + >>> supabase: Client = create_client(url, key) + + Returns + ------- + Client + """ + return await AsyncClient.create( + supabase_url=supabase_url, supabase_key=supabase_key, options=options + ) diff --git a/.venv/lib/python3.12/site-packages/supabase/_sync/__init__.py b/.venv/lib/python3.12/site-packages/supabase/_sync/__init__.py new file mode 100644 index 00000000..9d48db4f --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/_sync/__init__.py @@ -0,0 +1 @@ +from __future__ import annotations diff --git a/.venv/lib/python3.12/site-packages/supabase/_sync/auth_client.py b/.venv/lib/python3.12/site-packages/supabase/_sync/auth_client.py new file mode 100644 index 00000000..cd2836c3 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/_sync/auth_client.py @@ -0,0 +1,58 @@ +from typing import Dict, Optional + +from gotrue import ( + AuthFlowType, + SyncGoTrueClient, + SyncMemoryStorage, + SyncSupportedStorage, +) +from gotrue.http_clients import SyncClient + + +class SyncSupabaseAuthClient(SyncGoTrueClient): + """Supabase Auth Client for synchronous operations.""" + + def __init__( + self, + *, + url: str, + headers: Optional[Dict[str, str]] = None, + storage_key: Optional[str] = None, + auto_refresh_token: bool = True, + persist_session: bool = True, + storage: SyncSupportedStorage = SyncMemoryStorage(), + http_client: Optional[SyncClient] = None, + flow_type: AuthFlowType = "implicit", + verify: bool = True, + proxy: Optional[str] = None, + ): + """ + Instantiate a SupabaseAuthClient instance. + + Args: + url (str): The URL of the Supabase instance. + headers (Optional[Dict[str, str]]): Optional headers to include in requests. + storage_key (Optional[str]): Key to store session information. + auto_refresh_token (bool): Whether to automatically refresh the token. Defaults to True. + persist_session (bool): Whether to persist the session. Defaults to True. + storage (SyncSupportedStorage): Storage mechanism. Defaults to SyncMemoryStorage(). + http_client (Optional[SyncClient]): HTTP client for making requests. Defaults to None. + flow_type (AuthFlowType): Type of authentication flow. Defaults to "implicit". + verify (bool): Whether to verify SSL certificates. Defaults to True. + proxy (Optional[str]): Proxy URL. Defaults to None. + """ + if headers is None: + headers = {} + + super().__init__( + url=url, + headers=headers, + storage_key=storage_key, + auto_refresh_token=auto_refresh_token, + persist_session=persist_session, + storage=storage, + http_client=http_client, + flow_type=flow_type, + verify=verify, + proxy=proxy, + ) diff --git a/.venv/lib/python3.12/site-packages/supabase/_sync/client.py b/.venv/lib/python3.12/site-packages/supabase/_sync/client.py new file mode 100644 index 00000000..680a7aea --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/_sync/client.py @@ -0,0 +1,337 @@ +import re +from typing import Any, Dict, List, Optional, Union + +from gotrue import SyncMemoryStorage +from gotrue.types import AuthChangeEvent, Session +from httpx import Timeout +from postgrest import ( + SyncPostgrestClient, + SyncRequestBuilder, + SyncRPCFilterRequestBuilder, +) +from postgrest.constants import DEFAULT_POSTGREST_CLIENT_TIMEOUT +from realtime import RealtimeChannelOptions, SyncRealtimeChannel, SyncRealtimeClient +from storage3 import SyncStorageClient +from storage3.constants import DEFAULT_TIMEOUT as DEFAULT_STORAGE_CLIENT_TIMEOUT +from supafunc import SyncFunctionsClient + +from ..lib.client_options import SyncClientOptions as ClientOptions +from .auth_client import SyncSupabaseAuthClient + + +# 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) + + +class SyncClient: + """Supabase client class.""" + + def __init__( + self, + supabase_url: str, + supabase_key: str, + options: Optional[ClientOptions] = None, + ): + """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 if the url and key are valid + if not re.match(r"^(https?)://.+", supabase_url): + raise SupabaseException("Invalid URL") + + # Check if the key is a valid JWT + if not re.match( + r"^[A-Za-z0-9-_=]+\.[A-Za-z0-9-_=]+\.?[A-Za-z0-9-_.+/=]*$", supabase_key + ): + raise SupabaseException("Invalid API key") + + if options is None: + options = ClientOptions(storage=SyncMemoryStorage()) + + self.supabase_url = supabase_url + self.supabase_key = supabase_key + self.options = options + options.headers.update(self._get_auth_headers()) + self.rest_url = f"{supabase_url}/rest/v1" + self.realtime_url = f"{supabase_url}/realtime/v1".replace("http", "ws") + self.auth_url = f"{supabase_url}/auth/v1" + self.storage_url = f"{supabase_url}/storage/v1" + self.functions_url = f"{supabase_url}/functions/v1" + + # Instantiate clients. + self.auth = self._init_supabase_auth_client( + auth_url=self.auth_url, + client_options=options, + ) + self.realtime = self._init_realtime_client( + realtime_url=self.realtime_url, + supabase_key=self.supabase_key, + options=options.realtime if options else None, + ) + self._postgrest = None + self._storage = None + self._functions = None + self.auth.on_auth_state_change(self._listen_to_auth_events) + + @classmethod + def create( + cls, + supabase_url: str, + supabase_key: str, + options: Optional[ClientOptions] = None, + ): + auth_header = options.headers.get("Authorization") if options else None + client = cls(supabase_url, supabase_key, options) + + if auth_header is None: + try: + session = client.auth.get_session() + session_access_token = client._create_auth_header(session.access_token) + except Exception as err: + session_access_token = None + + client.options.headers.update( + client._get_auth_headers(session_access_token) + ) + + return client + + def table(self, table_name: str) -> SyncRequestBuilder: + """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 `.from_()` method. + """ + return self.from_(table_name) + + def schema(self, schema: str) -> SyncPostgrestClient: + """Select a schema to query or perform an function (rpc) call. + + The schema needs to be on the list of exposed schemas inside Supabase. + """ + if self.options.schema != schema: + self.options.schema = schema + if self._postgrest: + self._postgrest.schema(schema) + return self.postgrest + + def from_(self, table_name: str) -> SyncRequestBuilder: + """Perform a table operation. + + See the `table` method. + """ + return self.postgrest.from_(table_name) + + def rpc( + self, fn: str, params: Optional[Dict[Any, Any]] = None + ) -> SyncRPCFilterRequestBuilder: + """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. + """ + if params is None: + params = {} + return self.postgrest.rpc(fn, params) + + @property + def postgrest(self): + if self._postgrest is None: + self._postgrest = self._init_postgrest_client( + rest_url=self.rest_url, + headers=self.options.headers, + schema=self.options.schema, + timeout=self.options.postgrest_client_timeout, + ) + + return self._postgrest + + @property + def storage(self): + if self._storage is None: + self._storage = self._init_storage_client( + storage_url=self.storage_url, + headers=self.options.headers, + storage_client_timeout=self.options.storage_client_timeout, + ) + return self._storage + + @property + def functions(self): + if self._functions is None: + self._functions = SyncFunctionsClient( + self.functions_url, + self.options.headers, + self.options.function_client_timeout, + ) + return self._functions + + def channel( + self, topic: str, params: RealtimeChannelOptions = {} + ) -> SyncRealtimeChannel: + """Creates a Realtime channel with Broadcast, Presence, and Postgres Changes.""" + return self.realtime.channel(topic, params) + + def get_channels(self) -> List[SyncRealtimeChannel]: + """Returns all realtime channels.""" + return self.realtime.get_channels() + + def remove_channel(self, channel: SyncRealtimeChannel) -> None: + """Unsubscribes and removes Realtime channel from Realtime client.""" + self.realtime.remove_channel(channel) + + def remove_all_channels(self) -> None: + """Unsubscribes and removes all Realtime channels from Realtime client.""" + self.realtime.remove_all_channels() + + @staticmethod + def _init_realtime_client( + realtime_url: str, supabase_key: str, options: Optional[Dict[str, Any]] = None + ) -> SyncRealtimeClient: + if options is None: + options = {} + """Private method for creating an instance of the realtime-py client.""" + return SyncRealtimeClient(realtime_url, token=supabase_key, **options) + + @staticmethod + def _init_storage_client( + storage_url: str, + headers: Dict[str, str], + storage_client_timeout: int = DEFAULT_STORAGE_CLIENT_TIMEOUT, + verify: bool = True, + proxy: Optional[str] = None, + ) -> SyncStorageClient: + return SyncStorageClient( + storage_url, headers, storage_client_timeout, verify, proxy + ) + + @staticmethod + def _init_supabase_auth_client( + auth_url: str, + client_options: ClientOptions, + verify: bool = True, + proxy: Optional[str] = None, + ) -> SyncSupabaseAuthClient: + """Creates a wrapped instance of the GoTrue Client.""" + return SyncSupabaseAuthClient( + url=auth_url, + auto_refresh_token=client_options.auto_refresh_token, + persist_session=client_options.persist_session, + storage=client_options.storage, + headers=client_options.headers, + flow_type=client_options.flow_type, + verify=verify, + proxy=proxy, + ) + + @staticmethod + def _init_postgrest_client( + rest_url: str, + headers: Dict[str, str], + schema: str, + timeout: Union[int, float, Timeout] = DEFAULT_POSTGREST_CLIENT_TIMEOUT, + verify: bool = True, + proxy: Optional[str] = None, + ) -> SyncPostgrestClient: + """Private helper for creating an instance of the Postgrest client.""" + return SyncPostgrestClient( + rest_url, + headers=headers, + schema=schema, + timeout=timeout, + verify=verify, + proxy=proxy, + ) + + def _create_auth_header(self, token: str): + return f"Bearer {token}" + + def _get_auth_headers(self, authorization: Optional[str] = None) -> Dict[str, str]: + if authorization is None: + authorization = self.options.headers.get( + "Authorization", self._create_auth_header(self.supabase_key) + ) + + """Helper method to get auth headers.""" + return { + "apiKey": self.supabase_key, + "Authorization": authorization, + } + + def _listen_to_auth_events( + self, event: AuthChangeEvent, session: Optional[Session] + ): + access_token = self.supabase_key + if event in ["SIGNED_IN", "TOKEN_REFRESHED", "SIGNED_OUT"]: + # reset postgrest and storage instance on event change + self._postgrest = None + self._storage = None + self._functions = None + access_token = session.access_token if session else self.supabase_key + + self.options.headers["Authorization"] = self._create_auth_header(access_token) + + +def create_client( + supabase_url: str, + supabase_key: str, + options: Optional[ClientOptions] = None, +) -> SyncClient: + """Create client function to instantiate supabase client like JS runtime. + + 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. + + Examples + -------- + Instantiating the client. + >>> import os + >>> from supabase import create_client, Client + >>> + >>> url: str = os.environ.get("SUPABASE_TEST_URL") + >>> key: str = os.environ.get("SUPABASE_TEST_KEY") + >>> supabase: Client = create_client(url, key) + + Returns + ------- + Client + """ + return SyncClient.create( + supabase_url=supabase_url, supabase_key=supabase_key, options=options + ) diff --git a/.venv/lib/python3.12/site-packages/supabase/client.py b/.venv/lib/python3.12/site-packages/supabase/client.py new file mode 100644 index 00000000..363fa37b --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/client.py @@ -0,0 +1,68 @@ +from gotrue.errors import ( + AuthApiError, + AuthError, + AuthImplicitGrantRedirectError, + AuthInvalidCredentialsError, + AuthRetryableError, + AuthSessionMissingError, + AuthUnknownError, + AuthWeakPasswordError, +) +from postgrest import APIError as PostgrestAPIError +from postgrest import APIResponse as PostgrestAPIResponse +from realtime import AuthorizationError, NotConnectedError +from storage3.utils import StorageException +from supafunc.errors import FunctionsError, FunctionsHttpError, FunctionsRelayError + +# Async Client +from ._async.auth_client import AsyncSupabaseAuthClient +from ._async.client import AsyncClient +from ._async.client import AsyncStorageClient as AsyncSupabaseStorageClient +from ._async.client import create_client as acreate_client +from ._async.client import create_client as create_async_client + +# Sync Client +from ._sync.auth_client import SyncSupabaseAuthClient as SupabaseAuthClient +from ._sync.client import SyncClient as Client +from ._sync.client import SyncStorageClient as SupabaseStorageClient +from ._sync.client import create_client + +# Lib +from .lib.client_options import AsyncClientOptions +from .lib.client_options import AsyncClientOptions as AClientOptions +from .lib.client_options import SyncClientOptions as ClientOptions + +# Version +from .version import __version__ + +__all__ = [ + "AsyncSupabaseAuthClient", + "acreate_client", + "create_async_client", + "AClientOptions", + "AsyncClient", + "AsyncClientOptions", + "AsyncSupabaseStorageClient", + "SupabaseAuthClient", + "create_client", + "Client", + "ClientOptions", + "SupabaseStorageClient", + "PostgrestAPIError", + "PostgrestAPIResponse", + "StorageException", + "__version__", + "AuthApiError", + "AuthError", + "AuthImplicitGrantRedirectError", + "AuthInvalidCredentialsError", + "AuthRetryableError", + "AuthSessionMissingError", + "AuthWeakPasswordError", + "AuthUnknownError", + "FunctionsHttpError", + "FunctionsRelayError", + "FunctionsError", + "AuthorizationError", + "NotConnectedError", +] diff --git a/.venv/lib/python3.12/site-packages/supabase/lib/__init__.py b/.venv/lib/python3.12/site-packages/supabase/lib/__init__.py new file mode 100644 index 00000000..9c3bbcfd --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/lib/__init__.py @@ -0,0 +1,3 @@ +from supabase._async import auth_client + +__all__ = ["auth_client"] diff --git a/.venv/lib/python3.12/site-packages/supabase/lib/client_options.py b/.venv/lib/python3.12/site-packages/supabase/lib/client_options.py new file mode 100644 index 00000000..47498c13 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/lib/client_options.py @@ -0,0 +1,174 @@ +from dataclasses import dataclass, field +from typing import Dict, Optional, Union + +from gotrue import ( + AsyncMemoryStorage, + AsyncSupportedStorage, + AuthFlowType, + SyncMemoryStorage, + SyncSupportedStorage, +) +from httpx import Timeout +from postgrest.constants import DEFAULT_POSTGREST_CLIENT_TIMEOUT +from storage3.constants import DEFAULT_TIMEOUT as DEFAULT_STORAGE_CLIENT_TIMEOUT +from supafunc.utils import DEFAULT_FUNCTION_CLIENT_TIMEOUT + +from supabase.types import RealtimeClientOptions + +from ..version import __version__ + +DEFAULT_HEADERS = {"X-Client-Info": f"supabase-py/{__version__}"} + + +@dataclass +class ClientOptions: + schema: str = "public" + """ + The Postgres schema which your tables belong to. + Must be on the list of exposed schemas in Supabase. Defaults to 'public'. + """ + + headers: Dict[str, str] = field(default_factory=DEFAULT_HEADERS.copy) + """Optional headers for initializing the client.""" + + auto_refresh_token: bool = True + """Automatically refreshes the token for logged in users.""" + + persist_session: bool = True + """Whether to persist a logged in session to storage.""" + + storage: SyncSupportedStorage = field(default_factory=SyncMemoryStorage) + """A storage provider. Used to store the logged in session.""" + + realtime: Optional[RealtimeClientOptions] = None + """Options passed to the realtime-py instance""" + + postgrest_client_timeout: Union[int, float, Timeout] = ( + DEFAULT_POSTGREST_CLIENT_TIMEOUT + ) + """Timeout passed to the SyncPostgrestClient instance.""" + + storage_client_timeout: Union[int, float, Timeout] = DEFAULT_STORAGE_CLIENT_TIMEOUT + """Timeout passed to the SyncStorageClient instance""" + + function_client_timeout: Union[int, float, Timeout] = ( + DEFAULT_FUNCTION_CLIENT_TIMEOUT + ) + """Timeout passed to the SyncFunctionsClient instance.""" + + flow_type: AuthFlowType = "pkce" + """flow type to use for authentication""" + + def replace( + self, + schema: Optional[str] = None, + headers: Optional[Dict[str, str]] = None, + auto_refresh_token: Optional[bool] = None, + persist_session: Optional[bool] = None, + storage: Optional[SyncSupportedStorage] = None, + realtime: Optional[RealtimeClientOptions] = None, + postgrest_client_timeout: Union[ + int, float, Timeout + ] = DEFAULT_POSTGREST_CLIENT_TIMEOUT, + storage_client_timeout: Union[ + int, float, Timeout + ] = DEFAULT_STORAGE_CLIENT_TIMEOUT, + flow_type: Optional[AuthFlowType] = None, + ) -> "ClientOptions": + """Create a new SupabaseClientOptions with changes""" + client_options = ClientOptions() + client_options.schema = schema or self.schema + client_options.headers = headers or self.headers + client_options.auto_refresh_token = ( + auto_refresh_token or self.auto_refresh_token + ) + client_options.persist_session = persist_session or self.persist_session + client_options.storage = storage or self.storage + client_options.realtime = realtime or self.realtime + client_options.postgrest_client_timeout = ( + postgrest_client_timeout or self.postgrest_client_timeout + ) + client_options.storage_client_timeout = ( + storage_client_timeout or self.storage_client_timeout + ) + client_options.flow_type = flow_type or self.flow_type + return client_options + + +@dataclass +class AsyncClientOptions(ClientOptions): + storage: AsyncSupportedStorage = field(default_factory=AsyncMemoryStorage) + """A storage provider. Used to store the logged in session.""" + + def replace( + self, + schema: Optional[str] = None, + headers: Optional[Dict[str, str]] = None, + auto_refresh_token: Optional[bool] = None, + persist_session: Optional[bool] = None, + storage: Optional[AsyncSupportedStorage] = None, + realtime: Optional[RealtimeClientOptions] = None, + postgrest_client_timeout: Union[ + int, float, Timeout + ] = DEFAULT_POSTGREST_CLIENT_TIMEOUT, + storage_client_timeout: Union[ + int, float, Timeout + ] = DEFAULT_STORAGE_CLIENT_TIMEOUT, + flow_type: Optional[AuthFlowType] = None, + ) -> "AsyncClientOptions": + """Create a new SupabaseClientOptions with changes""" + client_options = AsyncClientOptions() + client_options.schema = schema or self.schema + client_options.headers = headers or self.headers + client_options.auto_refresh_token = ( + auto_refresh_token or self.auto_refresh_token + ) + client_options.persist_session = persist_session or self.persist_session + client_options.storage = storage or self.storage + client_options.realtime = realtime or self.realtime + client_options.postgrest_client_timeout = ( + postgrest_client_timeout or self.postgrest_client_timeout + ) + client_options.storage_client_timeout = ( + storage_client_timeout or self.storage_client_timeout + ) + client_options.flow_type = flow_type or self.flow_type + return client_options + + +@dataclass +class SyncClientOptions(ClientOptions): + def replace( + self, + schema: Optional[str] = None, + headers: Optional[Dict[str, str]] = None, + auto_refresh_token: Optional[bool] = None, + persist_session: Optional[bool] = None, + storage: Optional[SyncSupportedStorage] = None, + realtime: Optional[RealtimeClientOptions] = None, + postgrest_client_timeout: Union[ + int, float, Timeout + ] = DEFAULT_POSTGREST_CLIENT_TIMEOUT, + storage_client_timeout: Union[ + int, float, Timeout + ] = DEFAULT_STORAGE_CLIENT_TIMEOUT, + flow_type: Optional[AuthFlowType] = None, + ) -> "SyncClientOptions": + """Create a new SupabaseClientOptions with changes""" + client_options = SyncClientOptions() + client_options.schema = schema or self.schema + client_options.headers = headers or self.headers + client_options.auto_refresh_token = ( + auto_refresh_token or self.auto_refresh_token + ) + client_options.persist_session = persist_session or self.persist_session + client_options.storage = storage or self.storage + client_options.realtime = realtime or self.realtime + client_options.postgrest_client_timeout = ( + postgrest_client_timeout or self.postgrest_client_timeout + ) + client_options.storage_client_timeout = ( + storage_client_timeout or self.storage_client_timeout + ) + client_options.flow_type = flow_type or self.flow_type + return client_options diff --git a/.venv/lib/python3.12/site-packages/supabase/py.typed b/.venv/lib/python3.12/site-packages/supabase/py.typed new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/py.typed diff --git a/.venv/lib/python3.12/site-packages/supabase/types.py b/.venv/lib/python3.12/site-packages/supabase/types.py new file mode 100644 index 00000000..4f774531 --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/types.py @@ -0,0 +1,8 @@ +from typing import TypedDict + + +class RealtimeClientOptions(TypedDict, total=False): + auto_reconnect: bool + hb_interval: int + max_retries: int + initial_backoff: float diff --git a/.venv/lib/python3.12/site-packages/supabase/version.py b/.venv/lib/python3.12/site-packages/supabase/version.py new file mode 100644 index 00000000..361c401f --- /dev/null +++ b/.venv/lib/python3.12/site-packages/supabase/version.py @@ -0,0 +1 @@ +__version__ = "2.14.0" # {x-release-please-version} |