Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[BUG] Annotating the request of a paginated route crashes #1357

Open
Jonesus opened this issue Dec 10, 2024 · 0 comments
Open

[BUG] Annotating the request of a paginated route crashes #1357

Jonesus opened this issue Dec 10, 2024 · 0 comments

Comments

@Jonesus
Copy link

Jonesus commented Dec 10, 2024

Describe the bug

When annotating the request parameter of a route (in order to type request.auth) that has been decorated with @paginate the django server crashes with the following exception:

  File "/app/.venv/lib/python3.10/site-packages/ninja/router.py", line 268, in decorator
    self.add_api_operation(
  File "/app/.venv/lib/python3.10/site-packages/ninja/router.py", line 319, in add_api_operation
    path_view.add_operation(
  File "/app/.venv/lib/python3.10/site-packages/ninja/operation.py", line 426, in add_operation
    operation = OperationClass(
  File "/app/.venv/lib/python3.10/site-packages/ninja/operation.py", line 82, in __init__
    self.signature = ViewSignature(self.path, self.view_func)
  File "/app/.venv/lib/python3.10/site-packages/ninja/signature/details.py", line 48, in __init__
    self.signature = get_typed_signature(self.view_func)
  File "/app/.venv/lib/python3.10/site-packages/ninja/signature/utils.py", line 38, in get_typed_signature
    typed_params = [
  File "/app/.venv/lib/python3.10/site-packages/ninja/signature/utils.py", line 43, in <listcomp>
    annotation=get_typed_annotation(param, globalns),
  File "/app/.venv/lib/python3.10/site-packages/ninja/signature/utils.py", line 54, in get_typed_annotation
    annotation = make_forwardref(annotation, globalns)
  File "/app/.venv/lib/python3.10/site-packages/ninja/signature/utils.py", line 60, in make_forwardref
    return evaluate_forwardref(forward_ref, globalns, globalns)
  File "/app/.venv/lib/python3.10/site-packages/ninja/signature/utils.py", line 20, in evaluate_forwardref
    return cast(Any, type_)._evaluate(globalns, localns, recursive_guard=set())
  File "/home/app/.local/share/uv/python/cpython-3.10.8-linux-x86_64-gnu/lib/python3.10/typing.py", line 694, in _evaluate
    eval(self.__forward_code__, globalns, localns),
  File "<string>", line 1, in <module>
NameError: name 'AuthenticatedNinjaRequest' is not defined

This can be reproduced with the following minimal route:

from ninja.pagination import paginate
from django.http import HttpRequest

class AuthenticatedNinjaRequest(HttpRequest):
    auth: User

@api.get('/users', response=List[UserSchema])
@paginate
def list_users(request: AuthenticatedNinjaRequest):
    if request.auth:
        return User.objects.all()
    return User.objects.none()

If the pagination decorator is removed, no crash occurs and everything works as expected.

Potential remedy

The crashing can be fixed by patching the function get_typed_signature at ninja/signature/utils.py with:

def get_typed_signature(call: Callable[..., Any]) -> inspect.Signature:
    "Finds call signature and resolves all forwardrefs"
    signature = inspect.signature(call)
    globalns = getattr(call, "__globals__", {})
    typed_params = [
        inspect.Parameter(
            name=param.name,
            kind=param.kind,
            default=param.default,
            annotation=get_typed_annotation(param, globalns),
        )
        # NOTE: the following line has been changed below
        #                                          vvvvvvvvvvvvvvvvvvvvvvvvvv
        for param in signature.parameters.values() if param.name != "request"
    ]
    typed_signature = inspect.Signature(typed_params)
    return typed_signature

But I'm not certain if this is a good solution. I can submit the above patch as a PR if you think it is sufficient, or if you have some other approach in mind I can try that too.

The only somewhat related issue/PR I could find: #1026

Versions (please complete the following information):

  • Python version: 3.10.8
  • Django version: 5.1.3
  • Django-Ninja version: 1.3.0
  • Pydantic version: 2.9.1
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant