typeddjango / djangorestframework-stubs

PEP-484 stubs for django-rest-framework
MIT License
453 stars 117 forks source link

__name__ attribute missing from the ViewSetAction type #447

Closed Myselfito closed 7 months ago

Myselfito commented 1 year ago

Bug report

What's wrong

mypy doesn't recognize the __name__ attribute of an action. See minimal example with error below:

from typing import Any

from rest_framework import decorators, viewsets
from rest_framework.request import Request
from rest_framework.response import Response

class TestViewSet(viewsets.GenericViewSet[Any]):
    @decorators.action(methods=["get"], detail=False)
    def example_action(self, request: Request, **kwargs: Any) -> Response:
        return Response({})

TestViewSet.example_action.__name__  # error: "ViewSetAction[Callable[[TestViewSet, Request, KwArg(Any)], Response]]" has no attribute "__name__"  [attr-defined]

How is that should be

The above snippet should not raise an error. In order to achieve this we can add the __name__ attribute to the ViewSetAction. The actions are all methods so the __name__ attribute is always defined. See also below for the use case.

# rest_framework-stubs/decorators.pyi

class ViewSetAction(Protocol[_View]):
    detail: bool
    methods: _LOWER_CASE_HTTP_VERBS
    url_path: str
    url_name: str
    kwargs: Mapping[str, Any]
    mapping: MethodMapper
    __call__: _View
    __name__: str  # <-- Defining the __name__ attribute here would solve the issue

Use case

When checking actions in viewset methods, we could use self.action == self.__class__.example_action.__name__ instead of self.action == "example_action" to limit the potential risk of action naming update (type checkers would detect the attribute error) and avoid the use of error-prone strings.

System information

intgr commented 1 year ago

Makes sense. Also it seems the methods attribute doesn't actually exist.

Sakhi29 commented 1 year ago

@intgr I can work on this issue, please assign it to me.

intgr commented 1 year ago

@Sakhi29 Sorry, your comment got lost among all notifications I'm receiving. I've assigned you. In the future, there's no need to wait for assigment, just fire a PR 😄

igorgaming commented 7 months ago

up