Skip to content

Commit

Permalink
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Showing 6 changed files with 161 additions and 15 deletions.
25 changes: 16 additions & 9 deletions supabase_py/client.py
Original file line number Diff line number Diff line change
@@ -5,6 +5,11 @@
from supabase_py.lib.auth_client import SupabaseAuthClient
from supabase_py.lib.query_builder import SupabaseQueryBuilder
from supabase_py.lib.realtime_client import SupabaseRealtimeClient
from supabase_py.lib.supabase_storage_client import SupabaseStorageClient


from typing import Any, Dict


DEFAULT_OPTIONS = {
"schema": "public",
@@ -52,6 +57,7 @@ def __init__(
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"
self.schema: str = settings.pop("schema")
# Instantiate clients.
self.auth: SupabaseAuthClient = self._init_supabase_auth_client(
@@ -60,15 +66,20 @@ def __init__(
**settings,
)
# TODO(fedden): 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: SupabaseRealtimeClient = self._init_realtime_client(
# realtime_url=self.realtime_url,
# supabase_key=self.supabase_key,
# )
self.realtime = None
self.postgrest: PostgrestClient = self._init_postgrest_client(
rest_url=self.rest_url,
supabase_key=supabase_key,
)

def storage(self):
"""Create instance of the storage client"""
return SupabaseStorageClient(self.storage_url, self._get_auth_headers())

def table(self, table_name: str) -> SupabaseQueryBuilder:
"""Perform a table operation.
@@ -138,13 +149,9 @@ def get_subscriptions(self):
return self.realtime.channels

@staticmethod
def _init_realtime_client(
realtime_url: str, supabase_key: str
) -> SupabaseRealtimeClient:
def _init_realtime_client(realtime_url: str, supabase_key: str) -> SupabaseRealtimeClient:
"""Private method for creating an instance of the realtime-py client."""
return SupabaseRealtimeClient(
realtime_url, {"params": {"apikey": supabase_key}}
)
return SupabaseRealtimeClient(realtime_url, {"params": {"apikey": supabase_key}})

@staticmethod
def _init_supabase_auth_client(
6 changes: 3 additions & 3 deletions supabase_py/lib/realtime_client.py
Original file line number Diff line number Diff line change
@@ -14,12 +14,12 @@ def __init__(self, socket: Socket, schema: str, table_name: str):
self.subscription = socket.set_channel(topic)

def get_payload_records(self, payload: Any):
records = {"new": {}, "old": {}}
records: dict = {"new": {}, "old": {}}
if payload.type == "INSERT" or payload.type == "UPDATE":
records.new = payload.record
records["new"] = payload.record
convert_change_data(payload.columns, payload.record)
if payload.type == "UPDATE" or payload.type == "DELETE":
records.old = payload.record
records["old"] = payload.record
convert_change_data(payload.columns, payload.old_record)
return records

98 changes: 98 additions & 0 deletions supabase_py/lib/storage/storage_bucket_api.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
from typing import Dict, Any

import requests
from requests import HTTPError


class StorageBucketAPI:
"""This class abstracts access to the endpoint to the Get, List, Empty, and Delete operations on a bucket"""

def __init__(self, url, headers):
self.url = url
self.headers = headers

def list_buckets(self) -> Dict[str, Any]:
"""Retrieves the details of all storage buckets within an existing product."""
try:
response = requests.get(f"{self.url}/bucket", headers=self.headers)
response.raise_for_status()
except HTTPError as http_err:
print(f"HTTP error occurred: {http_err}") # Python 3.6
except Exception as err:
print(f"Other error occurred: {err}") # Python 3.6
else:
return response.json()

def get_bucket(self, id: str) -> Dict[str, Any]:
"""Retrieves the details of an existing storage bucket.
Parameters
----------
id
The unique identifier of the bucket you would like to retrieve.
"""
try:
response = requests.get(f"{self.url}/bucket/{id}", headers=self.headers)
response.raise_for_status()
except HTTPError as http_err:
print(f"HTTP error occurred: {http_err}") # Python 3.6
except Exception as err:
print(f"Other error occurred: {err}") # Python 3.6
else:
return response.json()

def create_bucket(self, id: str) -> Dict[str, Any]:
"""Creates a new storage bucket.
Parameters
----------
id
A unique identifier for the bucket you are creating.
"""
try:
response = requests.post(f"{self.url}/bucket", data={"id": id}, headers=self.headers)
response.raise_for_status()
except HTTPError as http_err:
print(f"HTTP error occurred: {http_err}") # Python 3.6
except Exception as err:
print(f"Other error occurred: {err}") # Python 3.6
else:
return response.json()

def empty_bucket(self, id: str) -> Dict[str, Any]:
"""Removes all objects inside a single bucket.
Parameters
----------
id
The unique identifier of the bucket you would like to empty.
"""
try:
response = requests.post(f"{self.url}/bucket/{id}/empty", data={}, headers=self.headers)
response.raise_for_status()
except HTTPError as http_err:
print(f"HTTP error occurred: {http_err}") # Python 3.6
except Exception as err:
print(f"Other error occurred: {err}") # Python 3.6
else:
return response.json()

def delete_bucket(self, id: str) -> Dict[str, Any]:
"""Deletes an existing bucket. Note that you cannot delete buckets with existing objects inside. You must first
`empty()` the bucket.
Parameters
----------
id
The unique identifier of the bucket you would like to delete.
"""
try:
response = requests.delete(f"{self.url}/bucket/{id}", data={}, headers=self.headers)

response.raise_for_status()
except HTTPError as http_err:
print(f"HTTP error occurred: {http_err}") # Python 3.6
except Exception as err:
print(f"Other error occurred: {err}") # Python 3.6
else:
return response.json()
24 changes: 24 additions & 0 deletions supabase_py/lib/supabase_storage_client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
from supabase_py.lib.storage.storage_bucket_api import StorageBucketAPI


class SupabaseStorageClient(StorageBucketAPI):
"""
Manage the storage bucket and files
Examples
--------
>>> url = storage_file.create_signed_url("poll3o/test2.txt", 80) # signed url
>>> loop.run_until_complete(storage_file.download("poll3o/test2.txt")) #upload or download
>>> loop.run_until_complete(storage_file.upload("poll3o/test2.txt","path_file_upload"))
>>> list_buckets = storage.list_buckets()
>>> list_files = storage_file.list("pollo")
"""

def __init__(self, url, headers):
super().__init__(url, headers)

# def StorageFileApi(self, id_, replace=False):
# return StorageFileApi(self.url, self.headers, id_, replace)

def StorageBucketAPI(self):
return StorageBucketAPI(self.url, self.headers)
18 changes: 15 additions & 3 deletions tests/test_client.py
Original file line number Diff line number Diff line change
@@ -26,9 +26,7 @@ def _assert_authenticated_user(data: Dict[str, Any]) -> None:
assert user.get("aud") == "authenticated"


@pytest.mark.xfail(
reason="None of these values should be able to instanciate a client object"
)
@pytest.mark.xfail(reason="None of these values should be able to instanciate a client object")
@pytest.mark.parametrize("url", ["", None, "valeefgpoqwjgpj", 139, -1, {}, []])
@pytest.mark.parametrize("key", ["", None, "valeefgpoqwjgpj", 139, -1, {}, []])
def test_incorrect_values_dont_instanciate_client(url: Any, key: Any) -> None:
@@ -83,3 +81,17 @@ def test_client_insert(supabase: Client) -> None:
assert current_length == previous_length + 1
# Check returned result for insert was valid.
assert result.get("status_code", 400) == 201


def test_client_bucket(supabase: Client) -> None:

"""Ensure that the storage bucket operations work"""
TEST_BUCKET_NAME = "atestbucket"
# TODO[Joel] - Reinstate once permissions on test instance are updated
# storage = supabase.storage()
# storage_bucket = storage.StorageBucketAPI()
# storage_bucket.create_bucket(TEST_BUCKET_NAME)
# storage_bucket.list_buckets()
# storage_bucket.get_bucket(TEST_BUCKET_NAME)
# storage_bucket.empty_bucket(TEST_BUCKET_NAME)
# storage_bucket.delete_bucket(TEST_BUCKET_NAME)
5 changes: 5 additions & 0 deletions tests/test_dummy.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
import pytest


import supabase_py

"""
@@ -7,10 +10,12 @@
"""



def test_dummy() -> None:
# Test auth component
assert True == True



def test_client_initialziation() -> None:
client = supabase_py.Client("http://testwebsite.com", "atestapi")

0 comments on commit 6f0e6d6

Please sign in to comment.