-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
1c3e9a0
commit d39caf6
Showing
10 changed files
with
234 additions
and
67 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
Empty file.
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
from .middlewares import LimitOffsetPaginationMiddleware, PagePaginationMiddleware | ||
|
||
__all__ = [ | ||
"LimitOffsetPaginationMiddleware", | ||
"PagePaginationMiddleware", | ||
] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
DEFAULT_LIMIT = 100 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,58 @@ | ||
from abc import ABC, abstractmethod | ||
from typing import Container | ||
|
||
from resty.enums import Endpoint | ||
from resty.types import Request, Response | ||
from resty.middlewares import BaseRequestMiddleware, BaseResponseMiddleware | ||
|
||
from .constants import DEFAULT_LIMIT | ||
|
||
|
||
class PaginationMiddleware(BaseRequestMiddleware, BaseResponseMiddleware, ABC): | ||
def __init__(self, endpoints: Container[Endpoint] = None): | ||
self._endpoints = endpoints or { | ||
Endpoint.READ, | ||
} | ||
|
||
@abstractmethod | ||
async def paginate(self, request: Request, **kwargs): # pragma: nocover | ||
... | ||
|
||
async def unpaginate(self, response: Response, **kwargs): | ||
response.json = response.json.get("results", response.json) | ||
|
||
async def _handle_request(self, request: Request, **kwargs): | ||
if request.endpoint in self._endpoints: | ||
await self.paginate(request=request, **kwargs) | ||
|
||
async def _handle_response(self, response: Response, **kwargs): | ||
if response.request.endpoint in self._endpoints: | ||
await self.unpaginate(response=response, **kwargs) | ||
|
||
async def __call__(self, reqresp: Request | Response, **kwargs): | ||
if isinstance(reqresp, Request): | ||
return await self._handle_request(request=reqresp, **kwargs) | ||
return await self._handle_response(response=reqresp, **kwargs) | ||
|
||
|
||
class LimitOffsetPaginationMiddleware(PaginationMiddleware): | ||
def __init__(self, limit: int = DEFAULT_LIMIT, **kwargs): | ||
self._limit = limit | ||
super().__init__(**kwargs) | ||
|
||
async def paginate(self, request: Request, **kwargs): | ||
request.params.update( | ||
{ | ||
"limit": kwargs.pop("limit", self._limit), | ||
"offset": kwargs.pop("offset", 0), | ||
} | ||
) | ||
|
||
|
||
class PagePaginationMiddleware(PaginationMiddleware): | ||
async def paginate(self, request: Request, **kwargs): | ||
request.params.update( | ||
{ | ||
"page": kwargs.pop("page", 1), | ||
} | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
import pytest | ||
|
||
from resty.enums import Method, Endpoint | ||
from resty.types import Request, Response | ||
from resty.ext.django.middlewares.pagination import ( | ||
LimitOffsetPaginationMiddleware, | ||
PagePaginationMiddleware, | ||
) | ||
|
||
|
||
@pytest.mark.asyncio | ||
@pytest.mark.parametrize( | ||
"req, kwargs, expected", | ||
[ | ||
( | ||
Request( | ||
url="https://example.com/", method=Method.GET, endpoint=Endpoint.READ | ||
), | ||
{"limit": 100, "offset": 10}, | ||
{"limit": 100, "offset": 10}, | ||
) | ||
], | ||
) | ||
async def test_limit_offset_pagination(req, kwargs, expected): | ||
middleware = LimitOffsetPaginationMiddleware() | ||
|
||
await middleware(reqresp=req, **kwargs) | ||
|
||
assert req.params == expected | ||
|
||
|
||
@pytest.mark.asyncio | ||
@pytest.mark.parametrize( | ||
"req, kwargs, expected", | ||
[ | ||
( | ||
Request( | ||
url="https://example.com/", method=Method.GET, endpoint=Endpoint.READ | ||
), | ||
{"page": 100}, | ||
{"page": 100}, | ||
) | ||
], | ||
) | ||
async def test_page_pagination(req, kwargs, expected): | ||
middleware = PagePaginationMiddleware() | ||
|
||
await middleware(reqresp=req, **kwargs) | ||
|
||
assert req.params == expected | ||
|
||
|
||
@pytest.mark.asyncio | ||
@pytest.mark.parametrize( | ||
"middleware, resp, expected", | ||
[ | ||
( | ||
LimitOffsetPaginationMiddleware(), | ||
Response( | ||
request=Request( | ||
url="https://example.com/", | ||
method=Method.GET, | ||
endpoint=Endpoint.READ, | ||
), | ||
status=200, | ||
json={ | ||
"results": [ | ||
{"id": 1, "username": "josh"}, | ||
] | ||
}, | ||
), | ||
[ | ||
{"id": 1, "username": "josh"}, | ||
], | ||
), | ||
( | ||
PagePaginationMiddleware(), | ||
Response( | ||
request=Request( | ||
url="https://example.com/", | ||
method=Method.GET, | ||
endpoint=Endpoint.READ, | ||
), | ||
status=200, | ||
json={ | ||
"results": [ | ||
{"id": 1, "username": "josh"}, | ||
] | ||
}, | ||
), | ||
[ | ||
{"id": 1, "username": "josh"}, | ||
], | ||
), | ||
], | ||
) | ||
async def test_unpaginate(middleware, resp, expected): | ||
await middleware(reqresp=resp) | ||
assert resp.json == expected |
Oops, something went wrong.