Skip to content

Commit

Permalink
Merge pull request #18 from Ori-Roza/release_1_0_2
Browse files Browse the repository at this point in the history
decorators refactor\nsuppot in different paginations
  • Loading branch information
Ori-Roza authored Nov 27, 2023
2 parents 326deb2 + cc69377 commit 84dd06e
Show file tree
Hide file tree
Showing 5 changed files with 66 additions and 12 deletions.
22 changes: 14 additions & 8 deletions drf_api_action/decorators.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
from rest_framework.decorators import action
from rest_framework.exceptions import ValidationError

from drf_api_action.utils import CustomRequest
from drf_api_action.exceptions import ActionsAPIException
from drf_api_action.exceptions import ActionsAPIException, ActionsAPIExceptionMiddleware


def action_api(methods=None, detail=None, url_path=None, url_name=None, **kwargs):
Expand Down Expand Up @@ -69,13 +68,20 @@ def run_as_api(self, **kw):

try:
ret = func(self, request, **kw)
results = {k.lower(): v for k, v in ret.data.items()}
except ValidationError as error:
current_error = str(error.detail)
except Exception as error:
current_error = str(error)
if isinstance(ret.data, list):
results = [dict(res) for res in ret.data]
else:
results = {k.lower(): v for k, v in ret.data.items()}
except Exception as error: # pylint: disable=broad-except
current_error = error

if current_error:
raise ActionsAPIException(current_error)
error_type = type(current_error)

raised_exception = ActionsAPIExceptionMiddleware(current_error,
error_type=error_type,
traceback=current_error.__traceback__)
raise raised_exception # pylint: disable=raising-npn-exception

return results

Expand Down
8 changes: 8 additions & 0 deletions drf_api_action/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,10 @@
class ActionsAPIException(RuntimeError):
pass


class ActionsAPIExceptionMiddleware:
def __new__(cls, *args, **kwargs):
error_type = kwargs.pop('error_type', Exception)
error = error_type(*args)
error.__traceback__ = kwargs.pop('traceback', error_type.__traceback__)
return error
22 changes: 22 additions & 0 deletions drf_api_action/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,25 @@ def extract_page_number(data_input: Optional[str]) -> Optional[int]:
if data_input == '':
return 1
return int(data_input.split("=")[-1])


def extract_limit(data_input: Optional[str]) -> Optional[int]:
"""
extracts the limit from restframework pagination output string
:param data_input: restframework pagination output string
:return: None if data_input is None else the limit extracted
"""
if data_input is None:
return None
return int(data_input.split("&")[0].split("=")[1])


def extract_next_offset(data_input: Optional[str]) -> Optional[int]:
"""
extracts the limit from restframework pagination output string
:param data_input: restframework pagination output string
:return: None if data_input is None else the limit extracted
"""
if data_input is None:
return None
return int(data_input.split("&")[1].split("=")[1])
13 changes: 12 additions & 1 deletion tests/functionality_tests/test_as_api.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import pytest
from django.test import Client
from rest_framework.exceptions import ValidationError

from drf_api_action.exceptions import ActionsAPIException
from tests.test_app.models import DummyModel
Expand All @@ -24,7 +25,7 @@ def test_call_as_api_no_api_mixin(db):
dummy_model.dummy_int = 1
dummy_model.save()
with pytest.raises(ActionsAPIException):
res = api.dummy(request=None, pk=1)
_ = api.dummy(request=None, pk=1)


def test_call_as_rest(db):
Expand Down Expand Up @@ -65,3 +66,13 @@ def test_pagination_data(db):
response = api.by_dummy_int(request=None, dummy_int=1, page=2)
assert extract_page_number(response['previous']) == 1
assert extract_page_number(response['next']) is None


def test_exceptions(db):
api = DummyAPIViewSet()

dummy_model = DummyModel()
dummy_model.dummy_int = 1
dummy_model.save()
with pytest.raises(ValidationError):
_ = api.by_dummy_int(request=None, dummy_int=-1)
13 changes: 10 additions & 3 deletions tests/test_app/views.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from rest_framework.exceptions import ValidationError

from .models import DummyModel
from rest_framework import status
from rest_framework.response import Response
Expand All @@ -16,12 +18,17 @@ class Meta:


class GetDummyByIntSerializer(Serializer):
id = IntegerField(read_only=True)
dummy_int = IntegerField(read_only=True)
id = IntegerField(required=False)
dummy_int = IntegerField()

class Meta:
model = DummyModel
fields = "__all__"
fields = ("dummy_int",)

def validate(self, attrs):
if attrs['dummy_int'] < 1:
raise ValidationError(detail={"error": "dummy_int must be greater equal than 0"}, code=400)
return attrs


class DummyViewSet(ModelViewSet):
Expand Down

0 comments on commit 84dd06e

Please sign in to comment.