Skip to content

Commit

Permalink
Code refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
lqmanh committed Sep 7, 2020
1 parent 4f0ed78 commit 8f4a702
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 61 deletions.
78 changes: 45 additions & 33 deletions postgrest_py/request_builder.py
@@ -1,50 +1,57 @@
from typing import Iterable, Tuple

from httpx import AsyncClient, Response
from deprecation import deprecated
from httpx import AsyncClient

from postgrest_py.utils import sanitize_param, sanitize_pattern_param
from postgrest_py.__version__ import __version__


class RequestBuilder:
def __init__(self, session: AsyncClient, path: str) -> None:
def __init__(self, session: AsyncClient, path: str):
self.session = session
self.path = path
self.json = {}
self.http_method = "GET"

self.negate_next = False

@property
def not_(self):
self.negate_next = True
return self

def select(self, *columns: str):
self.session.params["select"] = ",".join(columns)
self.http_method = "GET"
return GetRequestBuilder.from_request_builder(self)
return SelectRequestBuilder(self.session, self.path, "GET", {})

def insert(self, json: dict, *, upsert=False):
self.session.headers[
"Prefer"
] = f"return=representation{',resolution=merge-duplicates' if upsert else ''}"
self.json = json
self.http_method = "POST"
return self
return NonQueryRequestBuilder(self.session, self.path, "POST", json)

def update(self, json: dict):
self.session.headers["Prefer"] = "return=representation"
self.json = json
self.http_method = "PATCH"
return self
return QueryRequestBuilder(self.session, self.path, "PATCH", json)

def delete(self):
self.http_method = "DELETE"
return self
return QueryRequestBuilder(self.session, self.path, "DELETE", {})


class NonQueryRequestBuilder:
def __init__(self, session: AsyncClient, path: str, http_method: str, json: dict):
self.session = session
self.path = path
self.http_method = http_method
self.json = json

async def execute(self) -> Response:
async def execute(self):
r = await self.session.request(self.http_method, self.path, json=self.json)
return r
return r.json()


class QueryRequestBuilder(NonQueryRequestBuilder):
def __init__(self, session: AsyncClient, path: str, http_method: str, json: dict):
super().__init__(session, path, http_method, json)

self.negate_next = False

@property
def not_(self):
self.negate_next = True
return self

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


class GetRequestBuilder(RequestBuilder):
@classmethod
def from_request_builder(cls, builder: RequestBuilder):
result = cls(builder.session, builder.path)
result.json = builder.json
result.http_method = builder.http_method
return result
class SelectRequestBuilder(QueryRequestBuilder):
def __init__(self, session: AsyncClient, path: str, http_method: str, json: dict):
super().__init__(session, path, http_method, json)

def order(self, column: str, *, desc=False, nullsfirst=False):
self.session.params.setdefault("order", []).append(
f"{column}{'.desc' if desc else ''}{'.nullsfirst' if nullsfirst else ''}"
)
self.session.params[
"order"
] = f"{column}{'.desc' if desc else ''}{'.nullsfirst' if nullsfirst else ''}"

return self

def limit(self, size: int, *, start=0):
Expand All @@ -156,3 +160,11 @@ def range(self, start: int, end: int):
def single(self):
self.session.headers["Accept"] = "application/vnd.pgrst.object+json"
return self


class GetRequestBuilder(SelectRequestBuilder):
"""Alias to SelectRequestBuilder."""

@deprecated("0.4.0", "1.0.0", __version__, "Use SelectRequestBuilder instead")
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
47 changes: 19 additions & 28 deletions tests/test_request_builder.py
Expand Up @@ -9,56 +9,47 @@ async def request_builder():
yield RequestBuilder(client, "/example_table")


@pytest.mark.asyncio
def test_constructor(request_builder):
assert request_builder.path == "/example_table"
assert request_builder.json == {}
assert request_builder.http_method == "GET"
assert request_builder.negate_next == False


def test_select(request_builder):
request_builder.select("col1", "col2")
builder = request_builder.select("col1", "col2")

assert request_builder.session.params["select"] == "col1,col2"
assert request_builder.http_method == "GET"
assert builder.session.params["select"] == "col1,col2"
assert builder.http_method == "GET"
assert builder.json == {}


class TestInsert:
def test_insert(self, request_builder):
request_builder.insert({"key1": "val1"})
builder = request_builder.insert({"key1": "val1"})

assert request_builder.session.headers["prefer"] == "return=representation"
assert request_builder.json == {"key1": "val1"}
assert request_builder.http_method == "POST"
assert builder.session.headers["prefer"] == "return=representation"
assert builder.http_method == "POST"
assert builder.json == {"key1": "val1"}

def test_upsert(self, request_builder):
request_builder.insert({"key1": "val1"}, upsert=True)
builder = request_builder.insert({"key1": "val1"}, upsert=True)

assert (
request_builder.session.headers["prefer"]
builder.session.headers["prefer"]
== "return=representation,resolution=merge-duplicates"
)
assert request_builder.json == {"key1": "val1"}
assert request_builder.http_method == "POST"
assert builder.http_method == "POST"
assert builder.json == {"key1": "val1"}


def test_update(request_builder):
request_builder.update({"key1": "val1"})
builder = request_builder.update({"key1": "val1"})

assert request_builder.session.headers["prefer"] == "return=representation"
assert request_builder.json == {"key1": "val1"}
assert request_builder.http_method == "PATCH"
assert builder.session.headers["prefer"] == "return=representation"
assert builder.http_method == "PATCH"
assert builder.json == {"key1": "val1"}


def test_delete(request_builder):
request_builder.delete()
builder = request_builder.delete()

assert request_builder.http_method == "DELETE"


@pytest.mark.asyncio
def test_not_(request_builder):
request_builder.not_

assert request_builder.negate_next == True
assert builder.http_method == "DELETE"
assert builder.json == {}

0 comments on commit 8f4a702

Please sign in to comment.