Skip to content

Commit

Permalink
Add: tests for django-middlewraes
Browse files Browse the repository at this point in the history
  • Loading branch information
CrazyProger1 committed Apr 29, 2024
1 parent 1c3e9a0 commit d39caf6
Show file tree
Hide file tree
Showing 10 changed files with 234 additions and 67 deletions.
7 changes: 6 additions & 1 deletion docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@

## v0.0.6

- Change Manager API:
- Changed Manager API:

Now instantiating manager is required.

Expand All @@ -51,4 +51,9 @@ response = await manager.read(
)
```

- Added Django pagination middlewares:

- `LimitOffsetPaginationMiddleware`
- `PagePaginationMiddleware`


Empty file added resty/ext/__init__.py
Empty file.
Empty file added resty/ext/django/__init__.py
Empty file.
Empty file.
6 changes: 6 additions & 0 deletions resty/ext/django/middlewares/pagination/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from .middlewares import LimitOffsetPaginationMiddleware, PagePaginationMiddleware

__all__ = [
"LimitOffsetPaginationMiddleware",
"PagePaginationMiddleware",
]
1 change: 1 addition & 0 deletions resty/ext/django/middlewares/pagination/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
DEFAULT_LIMIT = 100
58 changes: 58 additions & 0 deletions resty/ext/django/middlewares/pagination/middlewares.py
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),
}
)
54 changes: 27 additions & 27 deletions resty/managers/managers.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ def get_serializer(self, **kwargs) -> type[BaseSerializer]:
raise RuntimeError("Serializer not specified")

if not (
isinstance(serializer, BaseSerializer)
or inspect.isclass(serializer)
and issubclass(serializer, BaseSerializer)
isinstance(serializer, BaseSerializer)
or inspect.isclass(serializer)
and issubclass(serializer, BaseSerializer)
):
raise RuntimeError("The serializer must be a subclass of BaseSerializer")

Expand Down Expand Up @@ -125,7 +125,7 @@ def _prepare_request(self, endpoint: Endpoint, **kwargs) -> Request:
)

def _handle_response(
self, response: Response, response_type: ResponseType, **kwargs
self, response: Response, response_type: ResponseType, **kwargs
) -> any:
if not response:
return
Expand All @@ -147,14 +147,14 @@ def _handle_response(
return response.json

async def create[
T: Schema
T: Schema
](
self,
obj: Schema | Mapping,
response_type: ResponseType = None,
**kwargs,
self,
obj: Schema | Mapping,
response_type: ResponseType = None,
**kwargs,
) -> (
T | None
T | None
):
request = self._prepare_request(endpoint=Endpoint.CREATE, obj=obj, **kwargs)
response = await self._make_request(request=request, **kwargs)
Expand All @@ -163,7 +163,7 @@ async def create[
)

async def read[
T: Schema
T: Schema
](self, response_type: ResponseType = None, **kwargs) -> Iterable[T]:
request = self._prepare_request(endpoint=Endpoint.READ, **kwargs)
response = await self._make_request(request=request, **kwargs)
Expand All @@ -172,12 +172,12 @@ async def read[
)

async def read_one[
T: Schema
T: Schema
](
self,
obj_or_pk: Schema | Mapping | any,
response_type: ResponseType = None,
**kwargs,
self,
obj_or_pk: Schema | Mapping | any,
response_type: ResponseType = None,
**kwargs,
) -> T:

request = self._prepare_request(
Expand All @@ -189,14 +189,14 @@ async def read_one[
)

async def update[
T: Schema
T: Schema
](
self,
obj: Schema | Mapping,
response_type: ResponseType = None,
**kwargs,
self,
obj: Schema | Mapping,
response_type: ResponseType = None,
**kwargs,
) -> (
T | None
T | None
):
request = self._prepare_request(
endpoint=Endpoint.UPDATE,
Expand All @@ -210,12 +210,12 @@ async def update[
)

async def delete[
T: Schema
T: Schema
](
self,
obj_or_pk: Schema | Mapping | any,
response_type: ResponseType = None,
**kwargs,
self,
obj_or_pk: Schema | Mapping | any,
response_type: ResponseType = None,
**kwargs,
) -> (T | None):
request = self._prepare_request(
endpoint=Endpoint.DELETE, pk=self._get_pk(obj_or_pk=obj_or_pk), **kwargs
Expand Down
99 changes: 99 additions & 0 deletions tests/ext/django/test_django_pagination_middlewares.py
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
Loading

0 comments on commit d39caf6

Please sign in to comment.