Skip to content
This repository has been archived by the owner on Jan 11, 2021. It is now read-only.

Commit

Permalink
Added test for advanced decoration
Browse files Browse the repository at this point in the history
  • Loading branch information
mverteuil committed Jun 23, 2015
1 parent aa7ae20 commit ed84746
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 1 deletion.
1 change: 0 additions & 1 deletion rest_framework_swagger/decorators.py
Expand Up @@ -40,7 +40,6 @@ def get_closure_var(func, name=None):
i = unwrap.code.co_freevars.index(name)
return unwrap.closure[i].cell_contents


def wrapper_to_func(wrapper):
noms = wrapper.http_method_names
handlers = [getattr(wrapper, m) for m in noms if m != 'options']
Expand Down
80 changes: 80 additions & 0 deletions rest_framework_swagger/tests.py
Expand Up @@ -10,6 +10,7 @@
from django.contrib.admindocs.utils import trim_docstring
from django.test import TestCase
from django.test.utils import override_settings
from django.utils.decorators import classonlymethod
from django.utils.importlib import import_module
from django.views.generic import View
import django_filters
Expand Down Expand Up @@ -2383,3 +2384,82 @@ def test1(self):
self.assertEqual('tacos', strip_tags('<p>tacos</p>'))
self.assertEqual('tacobeans', strip_tags('<p>taco</p>beans'))
self.assertEqual('tacobeans', strip_tags('taco<p>beans</p>'))


class TestAdvancedDecoratorIntrospection(TestCase):
""" Exercises introspectors in advanced decorator use cases. """
def setUp(self):
self.generator = DocumentationGenerator()

def get_apis_for_viewset(self, stem, viewset):
router = DefaultRouter()
router.register(stem, viewset)
urlconf = MockUrlconfModule(router.urls)
urlparser = UrlParser()
return urlparser.get_apis(urlconf=urlconf)

def test_get_broken_args_viewset(self):
""" Should find decorated view. """
@TestAdvancedDecoratorIntrospection.squashed_class_view_decorator('positional')
class ArgsDecoratedViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = CommentSerializer

apis = self.get_apis_for_viewset('viewset_under_test', ArgsDecoratedViewSet)
docs = self.generator.generate(apis)
self.assertTrue(docs is not None, docs)

def test_get_broken_kwargs_viewset(self):
""" Should find decorated view. """
@TestAdvancedDecoratorIntrospection.squashed_class_view_decorator(keyword=True)
class KwargsDecoratedViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = CommentSerializer

apis = self.get_apis_for_viewset('viewset_under_test', KwargsDecoratedViewSet)
docs = self.generator.generate(apis)
self.assertTrue(docs is not None, docs)

def test_get_broken_args_kwargs_viewset(self):
""" Should find decorated view. """
@TestAdvancedDecoratorIntrospection.squashed_class_view_decorator('positional', keyword=True)
class ArgsKwargsDecoratedViewSet(ModelViewSet):
queryset = User.objects.all()
serializer_class = CommentSerializer

apis = self.get_apis_for_viewset('viewset_under_test', ArgsKwargsDecoratedViewSet)
docs = self.generator.generate(apis)
self.assertTrue(docs is not None, docs)

@staticmethod
def squashed_class_view_decorator(*args, **kwargs):
"""
Squashed version of a decorator that transforms a decorator designed for function-based views to be
Django CBV or DRF ViewSet compatible.
For more info, see: https://github.com/lqc/django/tree/cbvdecoration_ticket14512
"""
def wrapper(cls):
# Get the result of the as_view transformation function
old_as_view = cls.as_view.im_func

# Create the internal as_view method that would normally be decorated
@functools.wraps(old_as_view)
def new_as_view(self, *args, **initkwargs):
# Define an inner decorator that acts as the decorator normally given to class_view_decorator
def inner_decorator(view):
@functools.wraps(view)
def wrapped(*view_args, **view_kwargs):
# IMPORTANT:
# Anything that even mentions the outermost closure value will cause
# decorators.get_closure_var to fail if it relies on a naive algorithm to select the view
# function
args, kwargs
view(*view_args, **view_kwargs)
return wrapped

return inner_decorator(old_as_view(self, *args, **initkwargs))

cls.as_view = classonlymethod(new_as_view)
return cls
return wrapper

0 comments on commit ed84746

Please sign in to comment.