Skip to content

Commit e600144

Browse files
authored
Merge pull request #2 from sinisaos/async_version
async version experiment
2 parents 5e7151d + 6247ec5 commit e600144

File tree

6 files changed

+57
-42
lines changed

6 files changed

+57
-42
lines changed

README.md

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,15 @@ TaskModelOut: t.Any = create_pydantic_model(
3131
@app.get("/tasks/", response_model=t.List[TaskModelOut])
3232
async def tasks(
3333
request: Request,
34-
__cursor: str,
34+
__cursor: t.Optional[str] = None,
3535
__previous: t.Optional[str] = None,
3636
):
3737
try:
38-
cursor = request.query_params["__cursor"]
3938
previous = request.query_params["__previous"]
40-
paginator = CursorPagination(cursor=cursor)
41-
rows_result, headers_result = paginator.get_cursor_rows(Task, request)
39+
paginator = CursorPagination(cursor=__cursor)
40+
rows_result, headers_result = await paginator.get_cursor_rows(
41+
Task, request
42+
)
4243
rows = await rows_result.run()
4344
headers = headers_result
4445
response = JSONResponse(
@@ -48,9 +49,10 @@ async def tasks(
4849
},
4950
)
5051
except KeyError:
51-
cursor = request.query_params["__cursor"]
52-
paginator = CursorPagination(cursor=cursor)
53-
rows_result, headers_result = paginator.get_cursor_rows(Task, request)
52+
paginator = CursorPagination(cursor=__cursor)
53+
rows_result, headers_result = await paginator.get_cursor_rows(
54+
Task, request
55+
)
5456
rows = await rows_result.run()
5557
headers = headers_result
5658
response = JSONResponse(

example/app.py

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,17 @@
4141
@app.get("/tasks/", response_model=t.List[TaskModelOut])
4242
async def tasks(
4343
request: Request,
44-
__cursor: str,
44+
__cursor: t.Optional[str] = None,
4545
__previous: t.Optional[str] = None,
4646
):
4747
try:
48-
cursor = request.query_params["__cursor"]
4948
previous = request.query_params["__previous"]
50-
paginator = CursorPagination(cursor=cursor, page_size=1, order_by="id")
51-
rows_result, headers_result = paginator.get_cursor_rows(Task, request)
49+
paginator = CursorPagination(
50+
cursor=__cursor, page_size=10, order_by="id"
51+
)
52+
rows_result, headers_result = await paginator.get_cursor_rows(
53+
Task, request
54+
)
5255
rows = await rows_result.run()
5356
headers = headers_result
5457
response = JSONResponse(
@@ -58,9 +61,12 @@ async def tasks(
5861
},
5962
)
6063
except KeyError:
61-
cursor = request.query_params["__cursor"]
62-
paginator = CursorPagination(cursor=cursor, page_size=1, order_by="id")
63-
rows_result, headers_result = paginator.get_cursor_rows(Task, request)
64+
paginator = CursorPagination(
65+
cursor=__cursor, page_size=10, order_by="id"
66+
)
67+
rows_result, headers_result = await paginator.get_cursor_rows(
68+
Task, request
69+
)
6470
rows = await rows_result.run()
6571
headers = headers_result
6672
response = JSONResponse(
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
__VERSION__ = "0.1.0"

piccolo_cursor_pagination/pagination.py

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ class CursorPagination:
2424
page_size: int = 15
2525
order_by: str = "-id"
2626

27-
def get_cursor_rows(self, table: t.Type[Table], request: Request):
27+
async def get_cursor_rows(self, table: t.Type[Table], request: Request):
2828
# headers to adding next_cursor
2929
headers: t.Dict[str, str] = {}
3030

@@ -37,7 +37,7 @@ def get_cursor_rows(self, table: t.Type[Table], request: Request):
3737
query = query.limit(self.page_size + 1)
3838

3939
# decoded query params cursor
40-
decoded_cursor = self.decode_cursor(self.cursor, table)
40+
decoded_cursor = await self.decode_cursor(self.cursor, table)
4141

4242
try:
4343
# preform operation if previous in query params
@@ -50,15 +50,15 @@ def get_cursor_rows(self, table: t.Type[Table], request: Request):
5050
.order_by(table._meta.primary_key, ascending=False)
5151
.limit(self.page_size)
5252
)
53-
rows = query.run_sync()
53+
rows = await query.run()
5454
try:
5555
# set new value to next_cursor
5656
next_cursor = self.encode_cursor(str(rows[-1]["id"]))
5757
headers["cursor"] = next_cursor
5858
# return empty cursor if no more results
59-
last_row = table.select().limit(1).first().run_sync()
59+
last_row = await table.select().limit(1).first().run()
6060
if (
61-
self.decode_cursor(next_cursor, table)
61+
await self.decode_cursor(next_cursor, table)
6262
== last_row["id"]
6363
):
6464
headers["cursor"] = ""
@@ -69,7 +69,7 @@ def get_cursor_rows(self, table: t.Type[Table], request: Request):
6969
query = query.where(
7070
table._meta.primary_key >= int(decoded_cursor)
7171
).limit(self.page_size + 1)
72-
rows = query.run_sync()
72+
rows = await query.run()
7373
# set new value to next_cursor
7474
next_cursor = self.encode_cursor(str(rows[-1]["id"]))
7575
headers["cursor"] = next_cursor
@@ -83,7 +83,7 @@ def get_cursor_rows(self, table: t.Type[Table], request: Request):
8383
query = query.limit(self.page_size + 1)
8484

8585
# decoded query params cursor
86-
decoded_cursor = self.decode_cursor(self.cursor, table)
86+
decoded_cursor = await self.decode_cursor(self.cursor, table)
8787

8888
try:
8989
# preform operation if previous in query params
@@ -96,21 +96,21 @@ def get_cursor_rows(self, table: t.Type[Table], request: Request):
9696
.order_by(table._meta.primary_key, ascending=True)
9797
.limit(self.page_size)
9898
)
99-
rows = query.run_sync()
99+
rows = await query.run()
100100
try:
101101
# set new value to next_cursor
102102
next_cursor = self.encode_cursor(str(rows[-1]["id"]))
103103
headers["cursor"] = next_cursor
104104
# return empty cursor if no more results
105-
last_row = (
105+
last_row = await (
106106
table.select()
107107
.limit(1)
108108
.order_by(table._meta.primary_key, ascending=False)
109109
.first()
110-
.run_sync()
110+
.run()
111111
)
112112
if (
113-
self.decode_cursor(next_cursor, table)
113+
await self.decode_cursor(next_cursor, table)
114114
== last_row["id"]
115115
):
116116
headers["cursor"] = ""
@@ -121,7 +121,7 @@ def get_cursor_rows(self, table: t.Type[Table], request: Request):
121121
query = query.where(
122122
table._meta.primary_key <= int(decoded_cursor)
123123
).limit(self.page_size + 1)
124-
rows = query.run_sync()
124+
rows = await query.run()
125125
# set new value to next_cursor
126126
next_cursor = self.encode_cursor(str(rows[-1]["id"]))
127127
headers["cursor"] = next_cursor
@@ -134,17 +134,17 @@ def encode_cursor(self, cursor: str) -> str:
134134
base64_bytes = base64.b64encode(cursor_bytes)
135135
return base64_bytes.decode("ascii")
136136

137-
def decode_cursor(self, cursor: str, table: t.Type[Table]) -> int:
137+
async def decode_cursor(self, cursor: str, table: t.Type[Table]) -> int:
138+
if cursor is None:
139+
cursor = ""
138140
base64_bytes = cursor.encode("ascii")
139141
cursor_bytes = base64.b64decode(base64_bytes)
140-
# we provide initial cursor like this because
141-
# we cannot pass empty string to FastAPI openapi
142-
initial_cursor = (
142+
initial_cursor = await (
143143
table.select()
144144
.order_by(table._meta.primary_key, ascending=False)
145145
.limit(1)
146146
.first()
147-
.run_sync()
147+
.run()
148148
)
149149
return (
150150
int(cursor_bytes.decode("ascii") or 0)

tests/test_cursor_pagination_asc.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,18 @@ def get_readable(cls):
2424

2525

2626
@app.get("/movies/")
27-
def movies(
27+
async def movies(
2828
request: Request,
2929
__cursor: str,
3030
__previous: t.Optional[str] = None,
3131
):
3232
try:
3333
cursor = request.query_params["__cursor"]
3434
paginator = CursorPagination(cursor=cursor, page_size=1, order_by="id")
35-
rows_result, headers_result = paginator.get_cursor_rows(Movie, request)
36-
rows = rows_result.run_sync()
35+
rows_result, headers_result = await paginator.get_cursor_rows(
36+
Movie, request
37+
)
38+
rows = await rows_result.run()
3739
headers = headers_result
3840
response = JSONResponse(
3941
{"rows": rows[::-1]},
@@ -44,8 +46,10 @@ def movies(
4446
except KeyError:
4547
cursor = request.query_params["__cursor"]
4648
paginator = CursorPagination(cursor=cursor, page_size=1, order_by="id")
47-
rows_result, headers_result = paginator.get_cursor_rows(Movie, request)
48-
rows = rows_result.run_sync()
49+
rows_result, headers_result = await paginator.get_cursor_rows(
50+
Movie, request
51+
)
52+
rows = await rows_result.run()
4953
headers = headers_result
5054
response = JSONResponse(
5155
{"rows": rows},

tests/test_cursor_pagination_desc.py

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def get_readable(cls):
2424

2525

2626
@app.get("/movies/")
27-
def movies(
27+
async def movies(
2828
request: Request,
2929
__cursor: str,
3030
__previous: t.Optional[str] = None,
@@ -34,8 +34,10 @@ def movies(
3434
paginator = CursorPagination(
3535
cursor=cursor, page_size=1, order_by="-id"
3636
)
37-
rows_result, headers_result = paginator.get_cursor_rows(Movie, request)
38-
rows = rows_result.run_sync()
37+
rows_result, headers_result = await paginator.get_cursor_rows(
38+
Movie, request
39+
)
40+
rows = await rows_result.run()
3941
headers = headers_result
4042
response = JSONResponse(
4143
{"rows": rows[::-1]},
@@ -48,8 +50,10 @@ def movies(
4850
paginator = CursorPagination(
4951
cursor=cursor, page_size=1, order_by="-id"
5052
)
51-
rows_result, headers_result = paginator.get_cursor_rows(Movie, request)
52-
rows = rows_result.run_sync()
53+
rows_result, headers_result = await paginator.get_cursor_rows(
54+
Movie, request
55+
)
56+
rows = await rows_result.run()
5357
headers = headers_result
5458
response = JSONResponse(
5559
{"rows": rows},

0 commit comments

Comments
 (0)