Skip to content

Commit 8f4a702

Browse files
committed
Code refactoring
1 parent 4f0ed78 commit 8f4a702

File tree

2 files changed

+64
-61
lines changed

2 files changed

+64
-61
lines changed

postgrest_py/request_builder.py

+45-33
Original file line numberDiff line numberDiff line change
@@ -1,50 +1,57 @@
11
from typing import Iterable, Tuple
22

3-
from httpx import AsyncClient, Response
3+
from deprecation import deprecated
4+
from httpx import AsyncClient
45

56
from postgrest_py.utils import sanitize_param, sanitize_pattern_param
7+
from postgrest_py.__version__ import __version__
68

79

810
class RequestBuilder:
9-
def __init__(self, session: AsyncClient, path: str) -> None:
11+
def __init__(self, session: AsyncClient, path: str):
1012
self.session = session
1113
self.path = path
12-
self.json = {}
13-
self.http_method = "GET"
14-
15-
self.negate_next = False
16-
17-
@property
18-
def not_(self):
19-
self.negate_next = True
20-
return self
2114

2215
def select(self, *columns: str):
2316
self.session.params["select"] = ",".join(columns)
24-
self.http_method = "GET"
25-
return GetRequestBuilder.from_request_builder(self)
17+
return SelectRequestBuilder(self.session, self.path, "GET", {})
2618

2719
def insert(self, json: dict, *, upsert=False):
2820
self.session.headers[
2921
"Prefer"
3022
] = f"return=representation{',resolution=merge-duplicates' if upsert else ''}"
31-
self.json = json
32-
self.http_method = "POST"
33-
return self
23+
return NonQueryRequestBuilder(self.session, self.path, "POST", json)
3424

3525
def update(self, json: dict):
3626
self.session.headers["Prefer"] = "return=representation"
37-
self.json = json
38-
self.http_method = "PATCH"
39-
return self
27+
return QueryRequestBuilder(self.session, self.path, "PATCH", json)
4028

4129
def delete(self):
42-
self.http_method = "DELETE"
43-
return self
30+
return QueryRequestBuilder(self.session, self.path, "DELETE", {})
31+
32+
33+
class NonQueryRequestBuilder:
34+
def __init__(self, session: AsyncClient, path: str, http_method: str, json: dict):
35+
self.session = session
36+
self.path = path
37+
self.http_method = http_method
38+
self.json = json
4439

45-
async def execute(self) -> Response:
40+
async def execute(self):
4641
r = await self.session.request(self.http_method, self.path, json=self.json)
47-
return r
42+
return r.json()
43+
44+
45+
class QueryRequestBuilder(NonQueryRequestBuilder):
46+
def __init__(self, session: AsyncClient, path: str, http_method: str, json: dict):
47+
super().__init__(session, path, http_method, json)
48+
49+
self.negate_next = False
50+
51+
@property
52+
def not_(self):
53+
self.negate_next = True
54+
return self
4855

4956
def filter(self, column: str, operator: str, criteria: str):
5057
"""Either filter in or filter out based on Self.negate_next."""
@@ -129,18 +136,15 @@ def adj(self, column: str, range: Tuple[int, int]):
129136
return self.filter(column, "adj", f"({range[0]},{range[1]})")
130137

131138

132-
class GetRequestBuilder(RequestBuilder):
133-
@classmethod
134-
def from_request_builder(cls, builder: RequestBuilder):
135-
result = cls(builder.session, builder.path)
136-
result.json = builder.json
137-
result.http_method = builder.http_method
138-
return result
139+
class SelectRequestBuilder(QueryRequestBuilder):
140+
def __init__(self, session: AsyncClient, path: str, http_method: str, json: dict):
141+
super().__init__(session, path, http_method, json)
139142

140143
def order(self, column: str, *, desc=False, nullsfirst=False):
141-
self.session.params.setdefault("order", []).append(
142-
f"{column}{'.desc' if desc else ''}{'.nullsfirst' if nullsfirst else ''}"
143-
)
144+
self.session.params[
145+
"order"
146+
] = f"{column}{'.desc' if desc else ''}{'.nullsfirst' if nullsfirst else ''}"
147+
144148
return self
145149

146150
def limit(self, size: int, *, start=0):
@@ -156,3 +160,11 @@ def range(self, start: int, end: int):
156160
def single(self):
157161
self.session.headers["Accept"] = "application/vnd.pgrst.object+json"
158162
return self
163+
164+
165+
class GetRequestBuilder(SelectRequestBuilder):
166+
"""Alias to SelectRequestBuilder."""
167+
168+
@deprecated("0.4.0", "1.0.0", __version__, "Use SelectRequestBuilder instead")
169+
def __init__(self, *args, **kwargs):
170+
super().__init__(*args, **kwargs)

tests/test_request_builder.py

+19-28
Original file line numberDiff line numberDiff line change
@@ -9,56 +9,47 @@ async def request_builder():
99
yield RequestBuilder(client, "/example_table")
1010

1111

12-
@pytest.mark.asyncio
1312
def test_constructor(request_builder):
1413
assert request_builder.path == "/example_table"
15-
assert request_builder.json == {}
16-
assert request_builder.http_method == "GET"
17-
assert request_builder.negate_next == False
1814

1915

2016
def test_select(request_builder):
21-
request_builder.select("col1", "col2")
17+
builder = request_builder.select("col1", "col2")
2218

23-
assert request_builder.session.params["select"] == "col1,col2"
24-
assert request_builder.http_method == "GET"
19+
assert builder.session.params["select"] == "col1,col2"
20+
assert builder.http_method == "GET"
21+
assert builder.json == {}
2522

2623

2724
class TestInsert:
2825
def test_insert(self, request_builder):
29-
request_builder.insert({"key1": "val1"})
26+
builder = request_builder.insert({"key1": "val1"})
3027

31-
assert request_builder.session.headers["prefer"] == "return=representation"
32-
assert request_builder.json == {"key1": "val1"}
33-
assert request_builder.http_method == "POST"
28+
assert builder.session.headers["prefer"] == "return=representation"
29+
assert builder.http_method == "POST"
30+
assert builder.json == {"key1": "val1"}
3431

3532
def test_upsert(self, request_builder):
36-
request_builder.insert({"key1": "val1"}, upsert=True)
33+
builder = request_builder.insert({"key1": "val1"}, upsert=True)
3734

3835
assert (
39-
request_builder.session.headers["prefer"]
36+
builder.session.headers["prefer"]
4037
== "return=representation,resolution=merge-duplicates"
4138
)
42-
assert request_builder.json == {"key1": "val1"}
43-
assert request_builder.http_method == "POST"
39+
assert builder.http_method == "POST"
40+
assert builder.json == {"key1": "val1"}
4441

4542

4643
def test_update(request_builder):
47-
request_builder.update({"key1": "val1"})
44+
builder = request_builder.update({"key1": "val1"})
4845

49-
assert request_builder.session.headers["prefer"] == "return=representation"
50-
assert request_builder.json == {"key1": "val1"}
51-
assert request_builder.http_method == "PATCH"
46+
assert builder.session.headers["prefer"] == "return=representation"
47+
assert builder.http_method == "PATCH"
48+
assert builder.json == {"key1": "val1"}
5249

5350

5451
def test_delete(request_builder):
55-
request_builder.delete()
52+
builder = request_builder.delete()
5653

57-
assert request_builder.http_method == "DELETE"
58-
59-
60-
@pytest.mark.asyncio
61-
def test_not_(request_builder):
62-
request_builder.not_
63-
64-
assert request_builder.negate_next == True
54+
assert builder.http_method == "DELETE"
55+
assert builder.json == {}

0 commit comments

Comments
 (0)