diff --git a/rest_framework/decorators.py b/rest_framework/decorators.py index 7ba43d37c..30b9d84d4 100644 --- a/rest_framework/decorators.py +++ b/rest_framework/decorators.py @@ -7,7 +7,6 @@ based views, as well as the `@action` decorator, which is used to annotate methods on viewsets that should be included by routers. """ import types -from functools import update_wrapper from django.forms.utils import pretty_name @@ -23,8 +22,18 @@ def api_view(http_method_names=None): def decorator(func): - class WrappedAPIView(APIView): - pass + WrappedAPIView = type( + 'WrappedAPIView', + (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) assert not(isinstance(http_method_names, types.FunctionType)), \ @@ -43,6 +52,9 @@ def api_view(http_method_names=None): for method in http_method_names: setattr(WrappedAPIView, method.lower(), handler) + WrappedAPIView.__name__ = func.__name__ + WrappedAPIView.__module__ = func.__module__ + WrappedAPIView.renderer_classes = getattr(func, 'renderer_classes', APIView.renderer_classes) @@ -61,7 +73,7 @@ def api_view(http_method_names=None): WrappedAPIView.schema = getattr(func, 'schema', APIView.schema) - return update_wrapper(WrappedAPIView.as_view(), func) + return WrappedAPIView.as_view() return decorator diff --git a/tests/test_decorators.py b/tests/test_decorators.py index 116d6f1be..99ba13e60 100644 --- a/tests/test_decorators.py +++ b/tests/test_decorators.py @@ -162,16 +162,6 @@ class DecoratorTestCase(TestCase): 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..test_view" - class ActionDecoratorTestCase(TestCase):