From 056c940f0d723eb66fc06b43c28a743c84d54b3b Mon Sep 17 00:00:00 2001 From: Russell Keith-Magee Date: Fri, 9 Apr 2010 11:07:17 +0000 Subject: [PATCH] Fixed #13304 -- Updated auth decorators so they can be used with callable classes. Thanks to Horst Gutmann for the report and patch. git-svn-id: http://code.djangoproject.com/svn/django/trunk@12938 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/contrib/auth/decorators.py | 3 ++- django/contrib/auth/tests/__init__.py | 9 +++++---- django/contrib/auth/tests/decorators.py | 25 +++++++++++++++++++++++++ 3 files changed, 32 insertions(+), 5 deletions(-) create mode 100644 django/contrib/auth/tests/decorators.py diff --git a/django/contrib/auth/decorators.py b/django/contrib/auth/decorators.py index 97db3bb1c9..50c09247b8 100644 --- a/django/contrib/auth/decorators.py +++ b/django/contrib/auth/decorators.py @@ -5,6 +5,7 @@ except ImportError: from django.contrib.auth import REDIRECT_FIELD_NAME from django.http import HttpResponseRedirect +from django.utils.decorators import available_attrs from django.utils.http import urlquote @@ -25,7 +26,7 @@ def user_passes_test(test_func, login_url=None, redirect_field_name=REDIRECT_FIE path = urlquote(request.get_full_path()) tup = login_url, redirect_field_name, path return HttpResponseRedirect('%s?%s=%s' % tup) - return wraps(view_func)(_wrapped_view) + return wraps(view_func, assigned=available_attrs(view_func))(_wrapped_view) return decorator diff --git a/django/contrib/auth/tests/__init__.py b/django/contrib/auth/tests/__init__.py index 5b1f5a0de3..965ea2d6be 100644 --- a/django/contrib/auth/tests/__init__.py +++ b/django/contrib/auth/tests/__init__.py @@ -1,12 +1,13 @@ +from django.contrib.auth.tests.auth_backends import BackendTest, RowlevelBackendTest, AnonymousUserBackendTest, NoAnonymousUserBackendTest from django.contrib.auth.tests.basic import BASIC_TESTS -from django.contrib.auth.tests.views \ - import PasswordResetTest, ChangePasswordTest, LoginTest, LogoutTest +from django.contrib.auth.tests.decorators import LoginRequiredTestCase from django.contrib.auth.tests.forms import FORM_TESTS from django.contrib.auth.tests.remote_user \ import RemoteUserTest, RemoteUserNoCreateTest, RemoteUserCustomTest -from django.contrib.auth.tests.auth_backends import BackendTest, RowlevelBackendTest, AnonymousUserBackendTest, NoAnonymousUserBackendTest -from django.contrib.auth.tests.tokens import TOKEN_GENERATOR_TESTS from django.contrib.auth.tests.models import ProfileTestCase +from django.contrib.auth.tests.tokens import TOKEN_GENERATOR_TESTS +from django.contrib.auth.tests.views \ + import PasswordResetTest, ChangePasswordTest, LoginTest, LogoutTest # The password for the fixture data users is 'password' diff --git a/django/contrib/auth/tests/decorators.py b/django/contrib/auth/tests/decorators.py new file mode 100644 index 0000000000..7efd9d8ccf --- /dev/null +++ b/django/contrib/auth/tests/decorators.py @@ -0,0 +1,25 @@ +from unittest import TestCase + +from django.contrib.auth.decorators import login_required + + +class LoginRequiredTestCase(TestCase): + """ + Tests the login_required decorators + """ + def testCallable(self): + """ + Check that login_required is assignable to callable objects. + """ + class CallableView(object): + def __call__(self, *args, **kwargs): + pass + login_required(CallableView()) + + def testView(self): + """ + Check that login_required is assignable to normal views. + """ + def normal_view(request): + pass + login_required(normal_view) \ No newline at end of file