Repository: makridenko/supadantic

Issue:
Add `BaseClient` abstract class

Discussion:

Patch:
diff --git a/supadantic/clients/__init__.py b/supadantic/clients/__init__.py
new file mode 100644
index 0000000..684d880
--- /dev/null
+++ b/supadantic/clients/__init__.py
@@ -0,0 +1,1 @@
+from .supabase import SupabaseClient
diff --git a/supadantic/clients/base.py b/supadantic/clients/base.py
new file mode 100644
index 0000000..0c57e83
--- /dev/null
+++ b/supadantic/clients/base.py
@@ -0,0 +1,31 @@
+from abc import ABC, abstractmethod
+from typing import Any, Dict, Iterable, List
+
+
+class BaseClient(ABC):
+    def __init__(self, table_name: str) -> None:
+        pass
+
+    @abstractmethod
+    def insert(self, data: Dict[str, Any]) -> Dict[str, Any]:
+        raise NotImplementedError
+
+    @abstractmethod
+    def update(self, *, id: int, data: Dict[str, Any]) -> Dict[str, Any]:
+        raise NotImplementedError
+
+    @abstractmethod
+    def select(self, *, eq: Dict[str, Any] | None = None, neq: Dict[str, Any] | None = None) -> List[Dict[str, Any]]:
+        raise NotImplementedError
+
+    @abstractmethod
+    def delete(self, *, id: int) -> None:
+        raise NotImplementedError
+
+    @abstractmethod
+    def bulk_update(self, *, ids: Iterable[int], data: Dict[str, Any]) -> List[Dict[str, Any]]:
+        raise NotImplementedError
+
+    @abstractmethod
+    def bulk_delete(self, *, ids: Iterable[int]) -> List[Dict[str, Any]]:
+        raise NotImplementedError
diff --git a/supadantic/supabase_client.py b/supadantic/clients/supabase.py
similarity index 96%
rename from supadantic/supabase_client.py
rename to supadantic/clients/supabase.py
index c80df21..bb5d250 100644
--- a/supadantic/supabase_client.py
+++ b/supadantic/clients/supabase.py
@@ -3,8 +3,10 @@ from typing import Any, Dict, Iterable, List
 
 from supabase.client import create_client
 
+from .base import BaseClient
 
-class SupabaseClient:
+
+class SupabaseClient(BaseClient):
     def __init__(self, table_name: str):
         url: str = os.getenv('SUPABASE_URL') or ''
         key: str = os.getenv('SUPABASE_KEY') or ''
diff --git a/supadantic/models.py b/supadantic/models.py
index 6db35c9..64d3d10 100644
--- a/supadantic/models.py
+++ b/supadantic/models.py
@@ -4,8 +4,8 @@ from typing import Dict, NoReturn
 from pydantic import BaseModel
 from typing_extensions import Self
 
+from .clients import SupabaseClient
 from .q_set import QSet
-from .supabase_client import SupabaseClient
 
 
 class BaseSBModel(BaseModel, ABC):


Test patch:
diff --git a/tests/test_classes/supabase_client.py b/tests/test_classes/supabase_client.py
index cadd996..70ee9cb 100644
--- a/tests/test_classes/supabase_client.py
+++ b/tests/test_classes/supabase_client.py
@@ -1,7 +1,9 @@
 from typing import Any, Dict, Iterable, List
 
+from supadantic.clients.base import BaseClient
 
-class SupabaseClientMock:
+
+class SupabaseClientMock(BaseClient):
     def __init__(self, table_name: str):
         pass
 
diff --git a/tests/test_supabase_client.py b/tests/test_supabase_client.py
index 495899d..f3997e8 100644
--- a/tests/test_supabase_client.py
+++ b/tests/test_supabase_client.py
@@ -3,13 +3,13 @@ from unittest.mock import MagicMock, Mock, PropertyMock
 import pytest
 from pytest_mock import MockerFixture
 
-from supadantic.supabase_client import SupabaseClient
+from supadantic.clients import SupabaseClient
 
 
 class TestSupabaseClient:
     @pytest.fixture(autouse=True)
     def mock_create_client(self, mocker: MockerFixture) -> MagicMock:
-        return mocker.patch('supadantic.supabase_client.create_client')
+        return mocker.patch('supadantic.clients.supabase.create_client')
 
     @pytest.fixture
     def supabase_client(self) -> SupabaseClient: