Make api_view respect standard wrapper assignments (#8291)

This commit is contained in:
tim-mccurrach 2021-12-13 13:08:40 +00:00 committed by GitHub
parent d0bb4d877f
commit 9c97946531
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 14 additions and 16 deletions

View File

@ -7,6 +7,7 @@ based views, as well as the `@action` decorator, which is used to annotate
methods on viewsets that should be included by routers. methods on viewsets that should be included by routers.
""" """
import types import types
from functools import update_wrapper
from django.forms.utils import pretty_name from django.forms.utils import pretty_name
@ -22,18 +23,8 @@ def api_view(http_method_names=None):
def decorator(func): def decorator(func):
WrappedAPIView = type( class WrappedAPIView(APIView):
'WrappedAPIView', pass
(APIView,),
{'__doc__': func.__doc__}
)
# Note, the above allows us to set the docstring.
# It is the equivalent of:
#
# class WrappedAPIView(APIView):
# pass
# WrappedAPIView.__doc__ = func.doc <--- Not possible to do this
# api_view applied without (method_names) # api_view applied without (method_names)
assert not(isinstance(http_method_names, types.FunctionType)), \ assert not(isinstance(http_method_names, types.FunctionType)), \
@ -52,9 +43,6 @@ def api_view(http_method_names=None):
for method in http_method_names: for method in http_method_names:
setattr(WrappedAPIView, method.lower(), handler) setattr(WrappedAPIView, method.lower(), handler)
WrappedAPIView.__name__ = func.__name__
WrappedAPIView.__module__ = func.__module__
WrappedAPIView.renderer_classes = getattr(func, 'renderer_classes', WrappedAPIView.renderer_classes = getattr(func, 'renderer_classes',
APIView.renderer_classes) APIView.renderer_classes)
@ -73,7 +61,7 @@ def api_view(http_method_names=None):
WrappedAPIView.schema = getattr(func, 'schema', WrappedAPIView.schema = getattr(func, 'schema',
APIView.schema) APIView.schema)
return WrappedAPIView.as_view() return update_wrapper(WrappedAPIView.as_view(), func)
return decorator return decorator

View File

@ -162,6 +162,16 @@ class DecoratorTestCase(TestCase):
assert isinstance(view.cls.schema, CustomSchema) assert isinstance(view.cls.schema, CustomSchema)
def test_wrapper_assignments(self):
@api_view(["GET"])
def test_view(request):
"""example docstring"""
pass
assert test_view.__name__ == "test_view"
assert test_view.__doc__ == "example docstring"
assert test_view.__qualname__ == "DecoratorTestCase.test_wrapper_assignments.<locals>.test_view"
class ActionDecoratorTestCase(TestCase): class ActionDecoratorTestCase(TestCase):