diff --git a/src/storage/src/storage3/_async/vectors.py b/src/storage/src/storage3/_async/vectors.py index 8da9b83f..ee788a54 100644 --- a/src/storage/src/storage3/_async/vectors.py +++ b/src/storage/src/storage3/_async/vectors.py @@ -64,8 +64,10 @@ async def get_index(self, index_name: str) -> Optional[GetVectorIndexResponse]: http_method="POST", path=["GetIndex"], body=body ) return GetVectorIndexResponse.model_validate_json(data.content) - except StorageApiError: - return None + except StorageApiError as exc: + if str(exc.status) == "404": + return None + raise async def list_indexes( self, @@ -190,8 +192,10 @@ async def get_bucket(self, bucket_name: str) -> Optional[GetVectorBucketResponse http_method="POST", path=["GetVectorBucket"], body=body ) return GetVectorBucketResponse.model_validate_json(data.content) - except StorageApiError: - return None + except StorageApiError as exc: + if str(exc.status) == "404": + return None + raise async def list_buckets( self, diff --git a/src/storage/src/storage3/_sync/vectors.py b/src/storage/src/storage3/_sync/vectors.py index 0673bd23..a8b065fe 100644 --- a/src/storage/src/storage3/_sync/vectors.py +++ b/src/storage/src/storage3/_sync/vectors.py @@ -62,8 +62,10 @@ def get_index(self, index_name: str) -> Optional[GetVectorIndexResponse]: try: data = self._request.send(http_method="POST", path=["GetIndex"], body=body) return GetVectorIndexResponse.model_validate_json(data.content) - except StorageApiError: - return None + except StorageApiError as exc: + if str(exc.status) == "404": + return None + raise def list_indexes( self, @@ -178,8 +180,10 @@ def get_bucket(self, bucket_name: str) -> Optional[GetVectorBucketResponse]: http_method="POST", path=["GetVectorBucket"], body=body ) return GetVectorBucketResponse.model_validate_json(data.content) - except StorageApiError: - return None + except StorageApiError as exc: + if str(exc.status) == "404": + return None + raise def list_buckets( self, diff --git a/src/storage/tests/_async/test_vectors.py b/src/storage/tests/_async/test_vectors.py new file mode 100644 index 00000000..2257bc95 --- /dev/null +++ b/src/storage/tests/_async/test_vectors.py @@ -0,0 +1,57 @@ +import httpx +import pytest +from storage3 import AsyncStorageClient +from storage3.exceptions import StorageApiError + + +def error_handler(status_code: int) -> httpx.MockTransport: + def handler(request: httpx.Request) -> httpx.Response: + return httpx.Response( + status_code, + json={ + "statusCode": status_code, + "error": "InternalError" if status_code == 500 else "NotFound", + "message": "Internal server error" + if status_code == 500 + else "Resource not found", + }, + request=request, + ) + + return httpx.MockTransport(handler) + + +async def test_get_vector_bucket_propagates_server_errors() -> None: + async with httpx.AsyncClient(transport=error_handler(500)) as http: + client = AsyncStorageClient( + "https://example.supabase.co/storage/v1/", + {}, + http_client=http, + ) + + with pytest.raises(StorageApiError, match="Internal server error"): + await client.vectors().get_bucket("embeddings") + + +async def test_get_vector_index_propagates_server_errors() -> None: + async with httpx.AsyncClient(transport=error_handler(500)) as http: + client = AsyncStorageClient( + "https://example.supabase.co/storage/v1/", + {}, + http_client=http, + ) + + with pytest.raises(StorageApiError, match="Internal server error"): + await client.vectors().from_("embeddings").get_index("documents") + + +async def test_get_vector_resources_return_none_when_not_found() -> None: + async with httpx.AsyncClient(transport=error_handler(404)) as http: + client = AsyncStorageClient( + "https://example.supabase.co/storage/v1/", + {}, + http_client=http, + ) + + assert await client.vectors().get_bucket("missing") is None + assert await client.vectors().from_("missing").get_index("missing") is None diff --git a/src/storage/tests/_sync/test_vectors.py b/src/storage/tests/_sync/test_vectors.py new file mode 100644 index 00000000..d0d00c2e --- /dev/null +++ b/src/storage/tests/_sync/test_vectors.py @@ -0,0 +1,57 @@ +import httpx +import pytest +from storage3 import SyncStorageClient +from storage3.exceptions import StorageApiError + + +def error_handler(status_code: int) -> httpx.MockTransport: + def handler(request: httpx.Request) -> httpx.Response: + return httpx.Response( + status_code, + json={ + "statusCode": status_code, + "error": "InternalError" if status_code == 500 else "NotFound", + "message": "Internal server error" + if status_code == 500 + else "Resource not found", + }, + request=request, + ) + + return httpx.MockTransport(handler) + + +def test_get_vector_bucket_propagates_server_errors() -> None: + with httpx.Client(transport=error_handler(500)) as http: + client = SyncStorageClient( + "https://example.supabase.co/storage/v1/", + {}, + http_client=http, + ) + + with pytest.raises(StorageApiError, match="Internal server error"): + client.vectors().get_bucket("embeddings") + + +def test_get_vector_index_propagates_server_errors() -> None: + with httpx.Client(transport=error_handler(500)) as http: + client = SyncStorageClient( + "https://example.supabase.co/storage/v1/", + {}, + http_client=http, + ) + + with pytest.raises(StorageApiError, match="Internal server error"): + client.vectors().from_("embeddings").get_index("documents") + + +def test_get_vector_resources_return_none_when_not_found() -> None: + with httpx.Client(transport=error_handler(404)) as http: + client = SyncStorageClient( + "https://example.supabase.co/storage/v1/", + {}, + http_client=http, + ) + + assert client.vectors().get_bucket("missing") is None + assert client.vectors().from_("missing").get_index("missing") is None