Skip to content

Commit

Permalink
fixed controller operation order
Browse files Browse the repository at this point in the history
  • Loading branch information
eadwinCode committed Dec 5, 2024
1 parent 58c5fe3 commit 8008402
Show file tree
Hide file tree
Showing 2 changed files with 48 additions and 4 deletions.
22 changes: 19 additions & 3 deletions ninja_extra/controllers/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import inspect
import re
import uuid
from abc import ABC
from typing import (
TYPE_CHECKING,
Any,
Expand Down Expand Up @@ -62,9 +63,24 @@ class MissingAPIControllerDecoratorException(Exception):


def get_route_functions(cls: Type) -> Iterable[RouteFunction]:
for _, method in inspect.getmembers(cls, predicate=inspect.isfunction):
if hasattr(method, ROUTE_FUNCTION):
yield getattr(method, ROUTE_FUNCTION)
"""
Get all route functions from a controller class.
This function will recursively search for route functions in the base classes of the controller class
in order that they are defined.
Args:
cls (Type): The controller class.
Returns:
Iterable[RouteFunction]: An iterable of route functions.
"""

bases = inspect.getmro(cls)
for base_cls in reversed(bases):
if base_cls not in [ControllerBase, ABC, object]:
for method in base_cls.__dict__.values():
if hasattr(method, ROUTE_FUNCTION):
yield getattr(method, ROUTE_FUNCTION)


def get_all_controller_route_function(
Expand Down
30 changes: 29 additions & 1 deletion tests/test_operation.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import uuid

import django
import pytest

from ninja_extra import api_controller, route
from ninja_extra import api_controller, http_delete, http_get, route, status
from ninja_extra.controllers import AsyncRouteFunction, RouteFunction
from ninja_extra.helper import get_route_function
from ninja_extra.operation import AsyncOperation, Operation
Expand Down Expand Up @@ -113,3 +115,29 @@ async def test_async_route_operation_execution_should_log_execution(self):
client = TestAsyncClient(self.SomeTestController)
with pytest.raises(CustomException):
await client.get("/example_exception")


def test_controller_operation_order():
@api_controller("/my/api/users", tags=["User"])
class UserAPIController:
@http_get("/me")
def get_current_user(self, request):
return {"debug": "ok", "message": "Current user"}

@http_get("/{user_id}")
def get_user(self, request, user_id: uuid.UUID):
return {"debug": "ok", "message": "User"}

@http_delete("/{user_id}", response={status.HTTP_204_NO_CONTENT: None})
def delete_user_from_clinic(self, request, user_id: uuid.UUID):
return {"debug": "ok", "message": "User deleted"}

client = TestClient(UserAPIController)
response = client.get("/me")
assert response.json() == {"debug": "ok", "message": "Current user"}

response = client.get(f"/{uuid.uuid4()}")
assert response.json() == {"debug": "ok", "message": "User"}

response = client.delete(f"/{uuid.uuid4()}")
assert response.content == b""

0 comments on commit 8008402

Please sign in to comment.