diff options
| author | Jamie Matthews | 2012-09-26 13:52:29 +0100 | 
|---|---|---|
| committer | Jamie Matthews | 2012-09-26 13:52:29 +0100 | 
| commit | c13c8fe5bc41c0b8ea9a740663e937b812c3fef9 (patch) | |
| tree | 8afd537c40281f5fe795f249fa6b22a8cb483d01 | |
| parent | 4be937a9b3731c3bb86b34b07eecb059f3bb374c (diff) | |
| download | django-rest-framework-c13c8fe5bc41c0b8ea9a740663e937b812c3fef9.tar.bz2 | |
Update to new rest_framework package name, simplify implementation
| -rw-r--r-- | rest_framework/decorators.py | 149 | ||||
| -rw-r--r-- | rest_framework/tests/decorators.py (renamed from djangorestframework/tests/decorators.py) | 69 | 
2 files changed, 103 insertions, 115 deletions
diff --git a/rest_framework/decorators.py b/rest_framework/decorators.py index 1483cb56..5df8ced0 100644 --- a/rest_framework/decorators.py +++ b/rest_framework/decorators.py @@ -6,95 +6,78 @@ from rest_framework import status  from rest_framework.response import Response  from rest_framework.request import Request  from rest_framework.settings import api_settings -from rest_framwork.views import APIView +from rest_framework.views import APIView -class LazyViewCreator(object): +def api_view(http_method_names):      """ -    This class is responsible for dynamically creating an APIView subclass that -    will wrap a function-based view. Instances of this class are created -    by the function-based view decorators (below), and each decorator is -    responsible for setting attributes on the instance that will eventually be -    copied onto the final class-based view. The CBV gets created lazily the first -    time it's needed, and then cached for future use. - -    This is done so that the ordering of stacked decorators is irrelevant. +    Decorator that converts a function-based view into an APIView subclass. +    Takes a list of allowed methods for the view as an argument.      """ -    def __init__(self, wrapped_view): - -        self.wrapped_view = wrapped_view - -        # Each item in this dictionary will be copied onto the final -        # class-based view that gets created when this object is called -        self.final_view_attrs = { -            'http_method_names': APIView.http_method_names, -            'renderer_classes': APIView.renderer_classes, -            'parser_classes': APIView.parser_classes, -            'authentication_classes': APIView.authentication_classes, -            'throttle_classes': APIView.throttle_classes, -            'permission_classes': APIView.permission_classes, -        } -        self._cached_view = None - -    def handler(self, *args, **kwargs): -        return self.wrapped_view(*args, **kwargs) - -    @property -    def view(self): -        """ -        Accessor for the dynamically created class-based view. This will -        be created if necessary and cached for next time. -        """ - -        if self._cached_view is None: - -            class WrappedAPIView(APIView): -                pass - -            for attr, value in self.final_view_attrs.items(): -                setattr(WrappedAPIView, attr, value) - -            # Attach the wrapped view function for each of the -            # allowed HTTP methods -            for method in WrappedAPIView.http_method_names: -                setattr(WrappedAPIView, method.lower(), self.handler) - -            self._cached_view = WrappedAPIView.as_view() - -        return self._cached_view - -    def __call__(self, *args, **kwargs): -        """ -        This is the actual code that gets run per-request -        """ -        return self.view(*args, **kwargs) - -    @staticmethod -    def maybe_create(func_or_instance): -        """ -        If the argument is already an instance of LazyViewCreator, -        just return it. Otherwise, create a new one. -        """ -        if isinstance(func_or_instance, LazyViewCreator): -            return func_or_instance -        return LazyViewCreator(func_or_instance) - - -def _create_attribute_setting_decorator(attribute, filter=lambda item: item): -    def decorator(value): -        def inner(func): -            wrapper = LazyViewCreator.maybe_create(func) -            wrapper.final_view_attrs[attribute] = filter(value) -            return wrapper -        return inner +    def decorator(func): + +        class WrappedAPIView(APIView): +            pass + +        WrappedAPIView.http_method_names = [method.lower() for method in http_method_names] + +        def handler(self, *args, **kwargs): +            return func(*args, **kwargs) + +        for method in http_method_names: +            setattr(WrappedAPIView, method.lower(), handler) + +        WrappedAPIView.renderer_classes = getattr(func, 'renderer_classes', +                                                  APIView.renderer_classes) + +        WrappedAPIView.parser_classes = getattr(func, 'parser_classes', +                                                APIView.parser_classes) + +        WrappedAPIView.authentication_classes = getattr(func, 'authentication_classes', +                                                        APIView.authentication_classes) + +        WrappedAPIView.throttle_classes = getattr(func, 'throttle_classes', +                                                  APIView.throttle_classes) + +        WrappedAPIView.permission_classes = getattr(func, 'permission_classes', +                                                    APIView.permission_classes) + +        return WrappedAPIView.as_view()      return decorator -api_view = _create_attribute_setting_decorator('http_method_names', filter=lambda methods: [method.lower() for method in methods]) -renderer_classes = _create_attribute_setting_decorator('renderer_classes') -parser_classes = _create_attribute_setting_decorator('parser_classes') -authentication_classes = _create_attribute_setting_decorator('authentication_classes') -throttle_classes = _create_attribute_setting_decorator('throttle_classes') -permission_classes = _create_attribute_setting_decorator('permission_classes') +def renderer_classes(renderer_classes): +    def decorator(func): +        setattr(func, 'renderer_classes', renderer_classes) +        return func +    return decorator + + +def parser_classes(parser_classes): +    def decorator(func): +        setattr(func, 'parser_classes', parser_classes) +        return func +    return decorator + + +def authentication_classes(authentication_classes): +    def decorator(func): +        setattr(func, 'authentication_classes', authentication_classes) +        return func +    return decorator + + +def throttle_classes(throttle_classes): +    def decorator(func): +        setattr(func, 'throttle_classes', throttle_classes) +        return func +    return decorator + + +def permission_classes(permission_classes): +    def decorator(func): +        setattr(func, 'permission_classes', permission_classes) +        return func +    return decorator diff --git a/djangorestframework/tests/decorators.py b/rest_framework/tests/decorators.py index 0d3be8f3..d41f05d4 100644 --- a/djangorestframework/tests/decorators.py +++ b/rest_framework/tests/decorators.py @@ -1,19 +1,19 @@  from django.test import TestCase -from djangorestframework.response import Response -from djangorestframework.compat import RequestFactory -from djangorestframework.renderers import JSONRenderer -from djangorestframework.parsers import JSONParser -from djangorestframework.authentication import BasicAuthentication -from djangorestframework.throttling import SimpleRateThottle -from djangorestframework.permissions import IsAuthenticated -from djangorestframework.decorators import ( +from rest_framework.response import Response +from rest_framework.compat import RequestFactory +from rest_framework.renderers import JSONRenderer +from rest_framework.parsers import JSONParser +from rest_framework.authentication import BasicAuthentication +from rest_framework.throttling import SimpleRateThottle +from rest_framework.permissions import IsAuthenticated +from rest_framework.views import APIView +from rest_framework.decorators import (      api_view,      renderer_classes,      parser_classes,      authentication_classes,      throttle_classes,      permission_classes, -    LazyViewCreator  ) @@ -22,13 +22,18 @@ class DecoratorTestCase(TestCase):      def setUp(self):          self.factory = RequestFactory() +    def _finalize_response(self, request, response, *args, **kwargs): +        print "HAI" +        response.request = request +        return APIView.finalize_response(self, request, response, *args, **kwargs) +      def test_wrap_view(self):          @api_view(['GET'])          def view(request):              return Response({}) -        self.assertTrue(isinstance(view, LazyViewCreator)) +        self.assertTrue(isinstance(view.cls_instance, APIView))      def test_calling_method(self): @@ -46,57 +51,57 @@ class DecoratorTestCase(TestCase):      def test_renderer_classes(self): -        @renderer_classes([JSONRenderer])          @api_view(['GET']) +        @renderer_classes([JSONRenderer])          def view(request):              return Response({})          request = self.factory.get('/')          response = view(request) -        self.assertEqual(response.renderer_classes, [JSONRenderer]) +        self.assertTrue(isinstance(response.renderer, JSONRenderer))      def test_parser_classes(self): -        @parser_classes([JSONParser])          @api_view(['GET']) +        @parser_classes([JSONParser])          def view(request): +            self.assertEqual(request.parser_classes, [JSONParser])              return Response({})          request = self.factory.get('/') -        response = view(request) -        self.assertEqual(response.request.parser_classes, [JSONParser]) +        view(request)      def test_authentication_classes(self): +        @api_view(['GET'])          @authentication_classes([BasicAuthentication]) +        def view(request): +            self.assertEqual(request.authentication_classes, [BasicAuthentication]) +            return Response({}) + +        request = self.factory.get('/') +        view(request) + +    def test_permission_classes(self): +          @api_view(['GET']) +        @permission_classes([IsAuthenticated])          def view(request): +            self.assertEqual(request.permission_classes, [IsAuthenticated])              return Response({})          request = self.factory.get('/') -        response = view(request) -        self.assertEqual(response.request.authentication_classes, [BasicAuthentication]) +        view(request) -# Doesn't look like these bits are working quite yet +# Doesn't look like this bits are working quite yet  #    def test_throttle_classes(self): -# -#        @throttle_classes([SimpleRateThottle]) -#        @api_view(['GET']) -#        def view(request): -#            return Response({}) -# -#        request = self.factory.get('/') -#        response = view(request) -#        self.assertEqual(response.request.throttle, [SimpleRateThottle]) -#    def test_permission_classes(self): - -#        @permission_classes([IsAuthenticated])  #        @api_view(['GET']) +#        @throttle_classes([SimpleRateThottle])  #        def view(request): +#            self.assertEqual(request.throttle_classes, [SimpleRateThottle])  #            return Response({})  #        request = self.factory.get('/') -#        response = view(request) -#        self.assertEqual(response.request.permission_classes, [IsAuthenticated]) +#        view(request)  | 
