Ticket #14512: ticket14512.3.diff

File ticket14512.3.diff, 3.8 KB (added by roalddevries, 4 years ago)

Improvement of ticket14512.2.diff

  • regressiontests/utils/decorators.py

     
    33from django.template import Template, Context
    44from django.template.response import TemplateResponse
    55from django.test import TestCase, RequestFactory
    6 from django.utils.decorators import decorator_from_middleware
     6from django.utils.decorators import decorator_from_middleware, wraps, view_decorator
     7from django.views.generic import View
    78
    89
    910xview_dec = decorator_from_middleware(XViewMiddleware)
     
    104105        self.assertTrue(getattr(request, 'process_response_reached', False))
    105106        # Check that process_response saw the rendered content
    106107        self.assertEqual(request.process_response_content, "Hello world")
     108
     109
     110def simple_dec(func):
     111    """
     112    Simple decorator for testing view_decorator. It assumes a request
     113    argument and one extra argument. Prepends string "decorator:" to the
     114    result.
     115    """
     116    def wrapper(request, arg, func=func):
     117        return "decorator:" + func(request, arg)
     118    wrapper = wraps(func)(wrapper)
     119    wrapper.is_decorated = True
     120    return wrapper
     121
     122
     123class TextView(View):
     124    def __init__(self, *args, **kwargs):
     125        super(TextView, self).__init__(*args, **kwargs)
     126    def get(self, request, text):
     127        return "get1:" + text
     128    def post(self, request, text):
     129        return "post1:" + text
     130TextView = view_decorator(simple_dec)(TextView)
     131
     132
     133class BaseTextView(View):
     134    def __init__(self, *args, **kwargs):
     135        super(BaseTextView, self).__init__(*args, **kwargs)
     136
     137    def get(self, request, text):
     138        return "get1:" + text
     139
     140
     141class ExtendedTextView(BaseTextView):
     142    def __init__(self, **initargs):
     143        self.recursion_count = 0
     144        super(ExtendedTextView, self).__init__(**initargs)
     145
     146    def get(self, *args, **kwargs):
     147        self.recursion_count += 1
     148        if self.recursion_count > 10:
     149            raise Exception("Decoration caused recursive super() calls.")
     150        return "get2:" + super(ExtendedTextView, self).get(*args, **kwargs)
     151ExtendedTextView = view_decorator(simple_dec)(ExtendedTextView)
     152
     153
     154class ClassBasedViewDecorationTests(TestCase):
     155    rf = RequestFactory()
     156
     157    def test_decorate_view(self):
     158        self.assertTrue(getattr(TextView.as_view(), "is_decorated", False),
     159                        "Class based view decorator didn't preserve attributes.")
     160        self.assertEqual(TextView.as_view()(self.rf.get('/'), "hello"),
     161                         "decorator:get1:hello")
     162        self.assertEqual(TextView.as_view()(self.rf.post('/'), "hello"),
     163                         "decorator:post1:hello")
     164
     165    def test_decorate_derived_view(self):
     166        # NOTE: it's important for this test, that the definition
     167        # and decoration of the class happens in the *same scope*.
     168        view = ExtendedTextView.as_view()
     169        result = view(self.rf.get('/'), "A")
     170        self.assertEqual(result, "decorator:get2:get1:A")
     171
     172    def test_base_unmodified(self):
     173        DecoratedView = view_decorator(simple_dec)(BaseTextView)
     174
     175        # since a super(TestView) is called in the __init__ method of the
     176        # following assertion, and the DecorationView instance is no instance of
     177        # TestView, a TypeError is raised. This is a Python subtlety, and
     178        # therefore not the concern of view_decorator.
     179        self.assertRaises(TypeError, DecoratedView.as_view(), (self.rf.get('/'), "A"))
     180
     181        self.assertEqual(BaseTextView.as_view()(self.rf.get('/'), "A"), "get1:A")
     182        self.assertFalse(DecoratedView is BaseTextView)
     183        self.assertEqual(DecoratedView.mro(), [DecoratedView] + BaseTextView.mro()[1:])
     184
Back to Top