Skip to content
Open
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
10 changes: 8 additions & 2 deletions src/postgrest/src/postgrest/_async/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def __init__(
verify: Optional[bool] = None,
proxy: Optional[str] = None,
http_client: Optional[AsyncClient] = None,
retry_enabled: bool = True,
) -> None:
headers = {
"X-Client-Info": (
Expand Down Expand Up @@ -93,7 +94,7 @@ def __init__(
verify=self.verify,
proxy=proxy,
)

self.retry_enabled = retry_enabled
self.session = http_client or AsyncClient(
base_url=base_url,
headers=self.headers,
Expand All @@ -113,6 +114,7 @@ def schema(self, schema: str) -> AsyncPostgrestClient:
timeout=self.timeout,
verify=self.verify,
proxy=self.proxy,
retry_enabled=self.retry_enabled,
)

async def __aenter__(self) -> AsyncPostgrestClient:
Expand All @@ -134,7 +136,11 @@ def from_(self, table: str) -> AsyncRequestBuilder:
:class:`AsyncRequestBuilder`
"""
return AsyncRequestBuilder(
self.session, self.base_url.joinpath(table), self.headers, self.basic_auth
self.session,
self.base_url.joinpath(table),
self.headers,
self.basic_auth,
self.retry_enabled,
)

def table(self, table: str) -> AsyncRequestBuilder:
Expand Down
13 changes: 12 additions & 1 deletion src/postgrest/src/postgrest/_async/request_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,18 @@ def explain(

class AsyncRequestBuilder: #
def __init__(
self, session: AsyncClient, path: URL, headers: Headers, auth: BasicAuth | None
self,
session: AsyncClient,
path: URL,
headers: Headers,
auth: BasicAuth | None,
retry_enabled: bool = True,
) -> None:
self.session = session
self.path = path
self.headers = headers
self.auth = auth
self.retry_enabled = retry_enabled

def select(
self,
Expand All @@ -321,6 +327,7 @@ def select(
session=self.session,
path=self.path,
auth=self.auth,
retry_enabled=self.retry_enabled,
params=params,
http_method=method,
headers=headers,
Expand Down Expand Up @@ -362,6 +369,7 @@ def insert(
session=self.session,
path=self.path,
auth=self.auth,
retry_enabled=self.retry_enabled,
params=params,
http_method=method,
headers=headers,
Expand Down Expand Up @@ -407,6 +415,7 @@ def upsert(
session=self.session,
path=self.path,
auth=self.auth,
retry_enabled=self.retry_enabled,
params=params,
http_method=method,
headers=headers,
Expand Down Expand Up @@ -440,6 +449,7 @@ def update(
session=self.session,
path=self.path,
auth=self.auth,
retry_enabled=self.retry_enabled,
params=params,
http_method=method,
headers=headers,
Expand Down Expand Up @@ -470,6 +480,7 @@ def delete(
session=self.session,
path=self.path,
auth=self.auth,
retry_enabled=self.retry_enabled,
params=params,
http_method=method,
headers=headers,
Expand Down
10 changes: 9 additions & 1 deletion src/postgrest/src/postgrest/_sync/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ def __init__(
verify: Optional[bool] = None,
proxy: Optional[str] = None,
http_client: Optional[Client] = None,
retry_enabled: bool = True,
) -> None:
headers = {
"X-Client-Info": (
Expand Down Expand Up @@ -94,6 +95,8 @@ def __init__(
proxy=proxy,
)

self.retry_enabled = retry_enabled

self.session = http_client or Client(
base_url=base_url,
headers=self.headers,
Expand All @@ -113,6 +116,7 @@ def schema(self, schema: str) -> SyncPostgrestClient:
timeout=self.timeout,
verify=self.verify,
proxy=self.proxy,
retry_enabled=self.retry_enabled,
)

def __enter__(self) -> SyncPostgrestClient:
Expand All @@ -134,7 +138,11 @@ def from_(self, table: str) -> SyncRequestBuilder:
:class:`AsyncRequestBuilder`
"""
return SyncRequestBuilder(
self.session, self.base_url.joinpath(table), self.headers, self.basic_auth
self.session,
self.base_url.joinpath(table),
self.headers,
self.basic_auth,
self.retry_enabled,
)

def table(self, table: str) -> SyncRequestBuilder:
Expand Down
13 changes: 12 additions & 1 deletion src/postgrest/src/postgrest/_sync/request_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,12 +294,18 @@ def explain(

class SyncRequestBuilder: #
def __init__(
self, session: Client, path: URL, headers: Headers, auth: BasicAuth | None
self,
session: Client,
path: URL,
headers: Headers,
auth: BasicAuth | None,
retry_enabled: bool = True,
) -> None:
self.session = session
self.path = path
self.headers = headers
self.auth = auth
self.retry_enabled = retry_enabled

def select(
self,
Expand All @@ -325,6 +331,7 @@ def select(
http_method=method,
headers=headers,
json=json,
retry_enabled=self.retry_enabled,
)
return SyncSelectRequestBuilder(request)

Expand Down Expand Up @@ -366,6 +373,7 @@ def insert(
http_method=method,
headers=headers,
json=json,
retry_enabled=self.retry_enabled,
)
return SyncQueryRequestBuilder(request)

Expand Down Expand Up @@ -411,6 +419,7 @@ def upsert(
http_method=method,
headers=headers,
json=json,
retry_enabled=self.retry_enabled,
)
return SyncQueryRequestBuilder(request)

Expand Down Expand Up @@ -444,6 +453,7 @@ def update(
http_method=method,
headers=headers,
json=json,
retry_enabled=self.retry_enabled,
)
return SyncFilterRequestBuilder(request)

Expand Down Expand Up @@ -474,5 +484,6 @@ def delete(
http_method=method,
headers=headers,
json=json,
retry_enabled=self.retry_enabled,
)
return SyncFilterRequestBuilder(request)
9 changes: 9 additions & 0 deletions src/supabase/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,16 @@ url: str = os.environ.get("SUPABASE_URL")
key: str = os.environ.get("SUPABASE_KEY")
supabase: Client = create_client(url, key)
```
### Configure PostgREST retries

PostgREST requests retry transient errors by default. To disable automatic
retries, pass `postgrest_client_retry=False` through `ClientOptions`:

```python
from supabase import Client, ClientOptions, create_client

options = ClientOptions(postgrest_client_retry=False)
supabase: Client = create_client(url, key, options)
Use the supabase client to interface with your database.

### Sign-up
Expand Down
3 changes: 3 additions & 0 deletions src/supabase/src/supabase/_async/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,6 +188,7 @@ def postgrest(self) -> AsyncPostgrestClient:
schema=self.options.schema,
timeout=self.options.postgrest_client_timeout,
http_client=self.options.httpx_client,
retry_enabled=self.options.postgrest_client_retry,
)

return self._postgrest
Expand Down Expand Up @@ -300,6 +301,7 @@ def _init_postgrest_client(
verify: bool = True,
proxy: Optional[str] = None,
http_client: Union[AsyncHttpxClient, None] = None,
retry_enabled: bool = True,
) -> AsyncPostgrestClient:
"""Private helper for creating an instance of the Postgrest client."""
if http_client is not None:
Expand All @@ -315,6 +317,7 @@ def _init_postgrest_client(
verify=verify,
proxy=proxy,
http_client=None,
retry_enabled=retry_enabled,
)

def _create_auth_header(self, token: str) -> str:
Expand Down
5 changes: 4 additions & 1 deletion src/supabase/src/supabase/_sync/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ def postgrest(self) -> SyncPostgrestClient:
schema=self.options.schema,
timeout=self.options.postgrest_client_timeout,
http_client=self.options.httpx_client,
retry_enabled=self.options.postgrest_client_retry,
)

return self._postgrest
Expand Down Expand Up @@ -255,7 +256,7 @@ def _init_storage_client(
verify: bool = True,
proxy: Optional[str] = None,
http_client: Union[SyncHttpxClient, None] = None,
) -> SyncStorageClient:
) -> SyncStorageClient:
if http_client is not None:
# If an http client is provided, use it
return SyncStorageClient(
Expand Down Expand Up @@ -299,6 +300,7 @@ def _init_postgrest_client(
verify: bool = True,
proxy: Optional[str] = None,
http_client: Union[SyncHttpxClient, None] = None,
retry_enabled: bool = True,
) -> SyncPostgrestClient:
"""Private helper for creating an instance of the Postgrest client."""
if http_client is not None:
Expand All @@ -314,6 +316,7 @@ def _init_postgrest_client(
verify=verify,
proxy=proxy,
http_client=None,
retry_enabled=retry_enabled,
)

def _create_auth_header(self, token: str) -> str:
Expand Down
15 changes: 15 additions & 0 deletions src/supabase/src/supabase/lib/client_options.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ class ClientOptions:
)
"""Timeout passed to the SyncPostgrestClient instance."""

postgrest_client_retry: bool = True
"""Whether to retry transient PostgREST errors."""

storage_client_timeout: int = DEFAULT_STORAGE_CLIENT_TIMEOUT
"""Timeout passed to the SyncStorageClient instance"""

Expand Down Expand Up @@ -86,6 +89,7 @@ def replace(
postgrest_client_timeout: Union[
int, float, Timeout
] = DEFAULT_POSTGREST_CLIENT_TIMEOUT,
postgrest_client_retry: Optional[bool] = None,
storage_client_timeout: int = DEFAULT_STORAGE_CLIENT_TIMEOUT,
flow_type: Optional[AuthFlowType] = None,
) -> "AsyncClientOptions":
Expand All @@ -107,6 +111,11 @@ def replace(
client_options.postgrest_client_timeout = (
postgrest_client_timeout or self.postgrest_client_timeout
)
client_options.postgrest_client_retry = (
postgrest_client_retry
if postgrest_client_retry is not None
else self.postgrest_client_retry
)
client_options.storage_client_timeout = (
storage_client_timeout or self.storage_client_timeout
)
Expand All @@ -133,6 +142,7 @@ def replace(
postgrest_client_timeout: Union[
int, float, Timeout
] = DEFAULT_POSTGREST_CLIENT_TIMEOUT,
postgrest_client_retry: Optional[bool] = None,
storage_client_timeout: int = DEFAULT_STORAGE_CLIENT_TIMEOUT,
flow_type: Optional[AuthFlowType] = None,
) -> "SyncClientOptions":
Expand All @@ -154,6 +164,11 @@ def replace(
client_options.postgrest_client_timeout = (
postgrest_client_timeout or self.postgrest_client_timeout
)
client_options.postgrest_client_retry = (
postgrest_client_retry
if postgrest_client_retry is not None
else self.postgrest_client_retry
)
client_options.storage_client_timeout = (
storage_client_timeout or self.storage_client_timeout
)
Expand Down
9 changes: 9 additions & 0 deletions src/supabase/tests/_async/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,16 @@ async def test_postgrest_client() -> None:
client = await create_async_client(url, key)
assert client.table("sample")
assert client.postgrest.schema("new_schema")
async def test_postgrest_client_retry_option() -> None:
client = await create_async_client(
"https://example.supabase.co",
"test-key",
AsyncClientOptions(postgrest_client_retry=False),
)

request = client.table("sample").select("*")

assert request.request.retry_enabled is False

async def test_rpc_client() -> None:
url = os.environ["SUPABASE_TEST_URL"]
Expand Down
12 changes: 12 additions & 0 deletions src/supabase/tests/_sync/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,18 @@ def test_postgrest_client() -> None:
assert client.postgrest.schema("new_schema")


def test_postgrest_client_retry_option() -> None:
client = create_client(
"https://example.supabase.co",
"test-key",
ClientOptions(postgrest_client_retry=False),
)

request = client.table("sample").select("*")

assert request.request.retry_enabled is False


def test_rpc_client() -> None:
url = os.environ["SUPABASE_TEST_URL"]
key = os.environ["SUPABASE_TEST_KEY"]
Expand Down