Skip to content

Commit b1423b5

Browse files
leynierDani Reinón
and
Dani Reinón
authored
feat: implement async sync with unasync-cli (#30)
Co-authored-by: Dani Reinón <[email protected]>
1 parent ba83ba4 commit b1423b5

23 files changed

+676
-79
lines changed

poetry.lock

+47-9
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

postgrest_py/__init__.py

+13-2
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,13 @@
1-
from postgrest_py.__version__ import __version__
2-
from postgrest_py.client import DEFAULT_POSTGREST_CLIENT_HEADERS, Client, PostgrestClient
1+
from postgrest_py._async.client import AsyncPostgrestClient # noqa: F401
2+
from postgrest_py._async.request_builder import AsyncFilterRequestBuilder # noqa: F401
3+
from postgrest_py._async.request_builder import AsyncQueryRequestBuilder # noqa: F401
4+
from postgrest_py._async.request_builder import AsyncRequestBuilder # noqa: F401
5+
from postgrest_py._async.request_builder import AsyncSelectRequestBuilder # noqa: F401
6+
from postgrest_py._sync.client import SyncPostgrestClient # noqa: F401
7+
from postgrest_py._sync.request_builder import SyncFilterRequestBuilder # noqa: F401
8+
from postgrest_py._sync.request_builder import SyncQueryRequestBuilder # noqa: F401
9+
from postgrest_py._sync.request_builder import SyncRequestBuilder # noqa: F401
10+
from postgrest_py._sync.request_builder import SyncSelectRequestBuilder # noqa: F401
11+
from postgrest_py.config import DEFAULT_POSTGREST_CLIENT_HEADERS # noqa: F401
12+
from postgrest_py.deprecated_client import Client, PostgrestClient # noqa: F401
13+
from postgrest_py.deprecated_get_request_builder import GetRequestBuilder # noqa: F401

postgrest_py/_async/__init__.py

Whitespace-only changes.

postgrest_py/client.py renamed to postgrest_py/_async/client.py

+8-18
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
from typing import Dict, Optional, Union
22

33
from deprecation import deprecated
4-
from httpx import AsyncClient, BasicAuth, Response
4+
from httpx import BasicAuth, Response
55

66
from postgrest_py.__version__ import __version__
7-
from postgrest_py.request_builder import RequestBuilder
7+
from postgrest_py.config import DEFAULT_POSTGREST_CLIENT_HEADERS
8+
from postgrest_py.utils import AsyncClient
89

9-
DEFAULT_POSTGREST_CLIENT_HEADERS: Dict[str, str] = {
10-
"Accept": "application/json",
11-
"Content-Type": "application/json",
12-
}
10+
from .request_builder import AsyncRequestBuilder
1311

1412

15-
class PostgrestClient:
13+
class AsyncPostgrestClient:
1614
"""PostgREST client."""
1715

1816
def __init__(
@@ -66,12 +64,12 @@ def schema(self, schema: str):
6664
self.session.headers.update({"Accept-Profile": schema, "Content-Profile": schema})
6765
return self
6866

69-
def from_(self, table: str) -> RequestBuilder:
67+
def from_(self, table: str) -> AsyncRequestBuilder:
7068
"""Perform a table operation."""
71-
return RequestBuilder(self.session, f"/{table}")
69+
return AsyncRequestBuilder(self.session, f"/{table}")
7270

7371
@deprecated("0.2.0", "1.0.0", __version__, "Use PostgrestClient.from_() instead")
74-
def from_table(self, table: str) -> RequestBuilder:
72+
def from_table(self, table: str) -> AsyncRequestBuilder:
7573
"""Alias to Self.from_()."""
7674
return self.from_(table)
7775

@@ -80,11 +78,3 @@ async def rpc(self, func: str, params: dict) -> Response:
8078
path = f"/rpc/{func}"
8179
r = await self.session.post(path, json=params)
8280
return r
83-
84-
85-
class Client(PostgrestClient):
86-
"""Alias to PostgrestClient."""
87-
88-
@deprecated("0.2.0", "1.0.0", __version__, "Use PostgrestClient instead")
89-
def __init__(self, *args, **kwargs):
90-
super().__init__(*args, **kwargs)

postgrest_py/request_builder.py renamed to postgrest_py/_async/request_builder.py

+9-21
Original file line numberDiff line numberDiff line change
@@ -7,16 +7,12 @@
77
else:
88
from typing import Literal
99

10-
from deprecation import deprecated
11-
from httpx import AsyncClient
12-
13-
from postgrest_py.__version__ import __version__
14-
from postgrest_py.utils import sanitize_param, sanitize_pattern_param
10+
from postgrest_py.utils import AsyncClient, sanitize_param, sanitize_pattern_param
1511

1612
CountMethod = Union[Literal["exact"], Literal["planned"], Literal["estimated"]]
1713

1814

19-
class RequestBuilder:
15+
class AsyncRequestBuilder:
2016
def __init__(self, session: AsyncClient, path: str):
2117
self.session = session
2218
self.path = path
@@ -31,7 +27,7 @@ def select(self, *columns: str, count: Optional[CountMethod] = None):
3127
if count:
3228
self.session.headers["Prefer"] = f"count={count}"
3329

34-
return SelectRequestBuilder(self.session, self.path, method, {})
30+
return AsyncSelectRequestBuilder(self.session, self.path, method, {})
3531

3632
def insert(self, json: dict, *, count: Optional[CountMethod] = None, upsert=False):
3733
prefer_headers = ["return=representation"]
@@ -40,24 +36,24 @@ def insert(self, json: dict, *, count: Optional[CountMethod] = None, upsert=Fals
4036
if upsert:
4137
prefer_headers.append("resolution=merge-duplicates")
4238
self.session.headers["prefer"] = ",".join(prefer_headers)
43-
return QueryRequestBuilder(self.session, self.path, "POST", json)
39+
return AsyncQueryRequestBuilder(self.session, self.path, "POST", json)
4440

4541
def update(self, json: dict, *, count: Optional[CountMethod] = None):
4642
prefer_headers = ["return=representation"]
4743
if count:
4844
prefer_headers.append(f"count={count}")
4945
self.session.headers["prefer"] = ",".join(prefer_headers)
50-
return FilterRequestBuilder(self.session, self.path, "PATCH", json)
46+
return AsyncFilterRequestBuilder(self.session, self.path, "PATCH", json)
5147

5248
def delete(self, *, count: Optional[CountMethod] = None):
5349
prefer_headers = ["return=representation"]
5450
if count:
5551
prefer_headers.append(f"count={count}")
5652
self.session.headers["prefer"] = ",".join(prefer_headers)
57-
return FilterRequestBuilder(self.session, self.path, "DELETE", {})
53+
return AsyncFilterRequestBuilder(self.session, self.path, "DELETE", {})
5854

5955

60-
class QueryRequestBuilder:
56+
class AsyncQueryRequestBuilder:
6157
def __init__(self, session: AsyncClient, path: str, http_method: str, json: dict):
6258
self.session = session
6359
self.path = path
@@ -81,7 +77,7 @@ async def execute(self) -> Tuple[Any, Optional[int]]:
8177
return r.json(), count
8278

8379

84-
class FilterRequestBuilder(QueryRequestBuilder):
80+
class AsyncFilterRequestBuilder(AsyncQueryRequestBuilder):
8581
def __init__(self, session: AsyncClient, path: str, http_method: str, json: dict):
8682
super().__init__(session, path, http_method, json)
8783

@@ -183,7 +179,7 @@ def match(self, query: Dict[str, Any]):
183179
return updated_query
184180

185181

186-
class SelectRequestBuilder(FilterRequestBuilder):
182+
class AsyncSelectRequestBuilder(AsyncFilterRequestBuilder):
187183
def __init__(self, session: AsyncClient, path: str, http_method: str, json: dict):
188184
super().__init__(session, path, http_method, json)
189185

@@ -207,11 +203,3 @@ def range(self, start: int, end: int):
207203
def single(self):
208204
self.session.headers["Accept"] = "application/vnd.pgrst.object+json"
209205
return self
210-
211-
212-
class GetRequestBuilder(SelectRequestBuilder):
213-
"""Alias to SelectRequestBuilder."""
214-
215-
@deprecated("0.4.0", "1.0.0", __version__, "Use SelectRequestBuilder instead")
216-
def __init__(self, *args, **kwargs):
217-
super().__init__(*args, **kwargs)

postgrest_py/_sync/__init__.py

Whitespace-only changes.

postgrest_py/_sync/client.py

+80
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
from typing import Dict, Optional, Union
2+
3+
from deprecation import deprecated
4+
from httpx import BasicAuth, Response
5+
6+
from postgrest_py.__version__ import __version__
7+
from postgrest_py.config import DEFAULT_POSTGREST_CLIENT_HEADERS
8+
from postgrest_py.utils import SyncClient
9+
10+
from .request_builder import SyncRequestBuilder
11+
12+
13+
class SyncPostgrestClient:
14+
"""PostgREST client."""
15+
16+
def __init__(
17+
self,
18+
base_url: str,
19+
*,
20+
schema: str = "public",
21+
headers: Dict[str, str] = DEFAULT_POSTGREST_CLIENT_HEADERS,
22+
) -> None:
23+
headers = {
24+
**headers,
25+
"Accept-Profile": schema,
26+
"Content-Profile": schema,
27+
}
28+
self.session = SyncClient(base_url=base_url, headers=headers)
29+
30+
def __enter__(self):
31+
return self
32+
33+
def __exit__(self, exc_type, exc, tb) -> None:
34+
self.aclose()
35+
36+
def aclose(self) -> None:
37+
self.session.aclose()
38+
39+
def auth(
40+
self,
41+
token: Optional[str],
42+
*,
43+
username: Union[str, bytes, None] = None,
44+
password: Union[str, bytes] = "",
45+
):
46+
"""
47+
Authenticate the client with either bearer token or basic authentication.
48+
49+
Raise `ValueError` if neither authentication scheme is provided.
50+
Bearer token is preferred if both ones are provided.
51+
"""
52+
if token:
53+
self.session.headers["Authorization"] = f"Bearer {token}"
54+
elif username:
55+
self.session.auth = BasicAuth(username, password)
56+
else:
57+
raise ValueError(
58+
"Neither bearer token or basic authentication scheme is provided"
59+
)
60+
return self
61+
62+
def schema(self, schema: str):
63+
"""Switch to another schema."""
64+
self.session.headers.update({"Accept-Profile": schema, "Content-Profile": schema})
65+
return self
66+
67+
def from_(self, table: str) -> SyncRequestBuilder:
68+
"""Perform a table operation."""
69+
return SyncRequestBuilder(self.session, f"/{table}")
70+
71+
@deprecated("0.2.0", "1.0.0", __version__, "Use PostgrestClient.from_() instead")
72+
def from_table(self, table: str) -> SyncRequestBuilder:
73+
"""Alias to Self.from_()."""
74+
return self.from_(table)
75+
76+
def rpc(self, func: str, params: dict) -> Response:
77+
"""Perform a stored procedure call."""
78+
path = f"/rpc/{func}"
79+
r = self.session.post(path, json=params)
80+
return r

0 commit comments

Comments
 (0)