Ticket #5701: 5701.diff
File 5701.diff, 13.7 KB (added by , 17 years ago) |
---|
-
tests/regressiontests/decorators/models.py
=== added directory 'tests/regressiontests/decorators' === added file 'tests/regressiontests/decorators/__init__.py' === added file 'tests/regressiontests/decorators/models.py'
1 # A models.py so that tests run. 2 -
tests/regressiontests/decorators/tests.py
=== added file 'tests/regressiontests/decorators/tests.py'
1 from unittest import TestCase 2 from sys import version_info 3 4 from django.views.decorators.http import require_http_methods 5 from django.views.decorators.vary import vary_on_headers, vary_on_cookie 6 from django.views.decorators.cache import cache_page, never_cache, cache_control 7 from django.contrib.auth.decorators import user_passes_test 8 from django.contrib.admin.views.decorators import staff_member_required 9 10 def fully_decorated(request): 11 """Expected __doc__""" 12 return HttpResponse('<html><body>dummy</body></html>') 13 fully_decorated.anything = "Expected __dict__" 14 15 fully_decorated = require_http_methods(["GET"])(fully_decorated) 16 17 fully_decorated = vary_on_headers('Accept-language')(fully_decorated) 18 fully_decorated = vary_on_cookie(fully_decorated) 19 20 fully_decorated = cache_page(60*15)(fully_decorated) 21 fully_decorated = cache_control(private=True)(fully_decorated) 22 fully_decorated = never_cache(fully_decorated) 23 24 fully_decorated = user_passes_test(lambda u:True)(fully_decorated) 25 fully_decorated = staff_member_required(fully_decorated) 26 27 28 class DecoratorsTest(TestCase): 29 30 def test_attributes(self): 31 """ 32 Tests that django decorators set certain attributes of the wrapped 33 function. 34 """ 35 self.assertEquals(fully_decorated.__doc__, 'Expected __doc__') 36 self.assertEquals(fully_decorated.__dict__['anything'], 'Expected __dict__') 37 # Only run this test on Python 2.4 or later since __name__ can't be 38 # assigned to in earlier versions. 39 if version_info[0] >= 2 and version_info[1] >= 4: 40 self.assertEquals(fully_decorated.__name__, 'fully_decorated') -
django/contrib/admin/views/decorators.py
=== modified file 'django/contrib/admin/views/decorators.py'
1 import base64 2 import md5 3 import cPickle as pickle 4 try: 5 from functools import wraps 6 except ImportError: 7 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 8 1 9 from django import http, template 2 10 from django.conf import settings 3 11 from django.contrib.auth.models import User … … 5 13 from django.shortcuts import render_to_response 6 14 from django.utils.translation import ugettext_lazy, ugettext as _ 7 15 from django.utils.safestring import mark_safe 8 import base64, datetime, md59 import cPickle as pickle10 16 11 17 ERROR_MESSAGE = ugettext_lazy("Please enter a correct username and password. Note that both fields are case-sensitive.") 12 18 LOGIN_FORM_KEY = 'this_is_the_login_form' … … 104 110 else: 105 111 return _display_login_form(request, ERROR_MESSAGE) 106 112 107 return _checklogin113 return wraps(view_func)(_checklogin) -
django/contrib/auth/decorators.py
=== modified file 'django/contrib/auth/decorators.py'
1 try: 2 from functools import wraps 3 except ImportError: 4 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 5 1 6 from django.contrib.auth import REDIRECT_FIELD_NAME 2 7 from django.http import HttpResponseRedirect 3 8 from django.utils.http import urlquote … … 9 14 that takes the user object and returns True if the user passes. 10 15 """ 11 16 def decorate(view_func): 12 return _CheckLogin(view_func, test_func, login_url, redirect_field_name)17 return wraps(view_func)(_CheckLogin(view_func, test_func, login_url, redirect_field_name)) 13 18 return decorate 14 19 15 20 def login_required(function=None, redirect_field_name=REDIRECT_FIELD_NAME): -
django/template/defaultfilters.py
=== modified file 'django/template/defaultfilters.py'
2 2 3 3 import re 4 4 import random as random_module 5 try: 6 from functools import wraps 7 except ImportError: 8 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 5 9 6 10 from django.template import Variable, Library 7 11 from django.conf import settings … … 35 39 for attr in ('is_safe', 'needs_autoescape'): 36 40 if hasattr(func, attr): 37 41 setattr(_dec, attr, getattr(func, attr)) 38 return _dec42 return wraps(func)(_dec) 39 43 40 44 ################### 41 45 # STRINGS # -
django/utils/decorators.py
=== modified file 'django/utils/decorators.py'
1 1 "Functions that help with dynamically creating decorators for views." 2 2 3 3 import types 4 try: 5 from functools import wraps 6 except ImportError: 7 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 4 8 5 9 def decorator_from_middleware(middleware_class): 6 10 """ … … 53 57 if result is not None: 54 58 return result 55 59 return response 56 return _wrapped_view60 return wraps(view_func)(_wrapped_view) 57 61 return _decorator_from_middleware -
django/utils/functional.py
=== modified file 'django/utils/functional.py'
1 # License for code in this file that was taken from Python 2.5. 2 3 # PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 4 # -------------------------------------------- 5 # 6 # 1. This LICENSE AGREEMENT is between the Python Software Foundation 7 # ("PSF"), and the Individual or Organization ("Licensee") accessing and 8 # otherwise using this software ("Python") in source or binary form and 9 # its associated documentation. 10 # 11 # 2. Subject to the terms and conditions of this License Agreement, PSF 12 # hereby grants Licensee a nonexclusive, royalty-free, world-wide 13 # license to reproduce, analyze, test, perform and/or display publicly, 14 # prepare derivative works, distribute, and otherwise use Python 15 # alone or in any derivative version, provided, however, that PSF's 16 # License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 17 # 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation; 18 # All Rights Reserved" are retained in Python alone or in any derivative 19 # version prepared by Licensee. 20 # 21 # 3. In the event Licensee prepares a derivative work that is based on 22 # or incorporates Python or any part thereof, and wants to make 23 # the derivative work available to others as provided herein, then 24 # Licensee hereby agrees to include in any such work a brief summary of 25 # the changes made to Python. 26 # 27 # 4. PSF is making Python available to Licensee on an "AS IS" 28 # basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR 29 # IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND 30 # DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS 31 # FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT 32 # INFRINGE ANY THIRD PARTY RIGHTS. 33 # 34 # 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON 35 # FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS 36 # A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, 37 # OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 38 # 39 # 6. This License Agreement will automatically terminate upon a material 40 # breach of its terms and conditions. 41 # 42 # 7. Nothing in this License Agreement shall be deemed to create any 43 # relationship of agency, partnership, or joint venture between PSF and 44 # Licensee. This License Agreement does not grant permission to use PSF 45 # trademarks or trade name in a trademark sense to endorse or promote 46 # products or services of Licensee, or any third party. 47 # 48 # 8. By copying, installing or otherwise using Python, Licensee 49 # agrees to be bound by the terms and conditions of this License 50 # Agreement. 51 52 1 53 def curry(_curried_func, *args, **kwargs): 2 54 def _curried(*moreargs, **morekwargs): 3 55 return _curried_func(*(args+moreargs), **dict(kwargs, **morekwargs)) 4 56 return _curried 5 57 58 ### Begin from Python 2.5 functools.py ######################################## 59 60 # Changes made to this Python 2.5 code: 61 # * swapped ``partial`` for ``curry`` to maintain backwards-compatibility 62 # in Django. 63 # * Wrapped the setattr call in update_wrapper with a try-except block to 64 # make it compatible with Python 2.3, which doesn't allow assigning 65 # to __name__. 66 67 # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007 Python Software Foundation. 68 # All Rights Reserved. 69 70 # update_wrapper() and wraps() are tools to help write 71 # wrapper functions that can handle naive introspection 72 73 WRAPPER_ASSIGNMENTS = ('__module__', '__name__', '__doc__') 74 WRAPPER_UPDATES = ('__dict__',) 75 def update_wrapper(wrapper, 76 wrapped, 77 assigned = WRAPPER_ASSIGNMENTS, 78 updated = WRAPPER_UPDATES): 79 """Update a wrapper function to look like the wrapped function 80 81 wrapper is the function to be updated 82 wrapped is the original function 83 assigned is a tuple naming the attributes assigned directly 84 from the wrapped function to the wrapper function (defaults to 85 functools.WRAPPER_ASSIGNMENTS) 86 updated is a tuple naming the attributes off the wrapper that 87 are updated with the corresponding attribute from the wrapped 88 function (defaults to functools.WRAPPER_UPDATES) 89 """ 90 for attr in assigned: 91 try: 92 setattr(wrapper, attr, getattr(wrapped, attr)) 93 except TypeError: # Python 2.3 doesn't allow assigning to __name__. 94 pass 95 for attr in updated: 96 getattr(wrapper, attr).update(getattr(wrapped, attr)) 97 # Return the wrapper so this can be used as a decorator via curry() 98 return wrapper 99 100 def wraps(wrapped, 101 assigned = WRAPPER_ASSIGNMENTS, 102 updated = WRAPPER_UPDATES): 103 """Decorator factory to apply update_wrapper() to a wrapper function 104 105 Returns a decorator that invokes update_wrapper() with the decorated 106 function as the wrapper argument and the arguments to wraps() as the 107 remaining arguments. Default arguments are as for update_wrapper(). 108 This is a convenience function to simplify applying curry() to 109 update_wrapper(). 110 """ 111 return curry(update_wrapper, wrapped=wrapped, 112 assigned=assigned, updated=updated) 113 114 ### End from Python 2.5 functools.py ########################################## 115 6 116 def memoize(func, cache, num_args): 7 117 """ 8 118 Wrap a function so that results for any argument tuple are stored in -
django/views/decorators/cache.py
=== modified file 'django/views/decorators/cache.py'
11 11 account on caching -- just like the middleware does. 12 12 """ 13 13 14 try: 15 from functools import wraps 16 except ImportError: 17 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 18 14 19 from django.utils.decorators import decorator_from_middleware 15 20 from django.utils.cache import patch_cache_control, add_never_cache_headers 16 21 from django.middleware.cache import CacheMiddleware … … 26 31 patch_cache_control(response, **kwargs) 27 32 return response 28 33 29 return _cache_controlled34 return wraps(viewfunc)(_cache_controlled) 30 35 31 36 return _cache_controller 32 37 … … 39 44 response = view_func(request, *args, **kwargs) 40 45 add_never_cache_headers(response) 41 46 return response 42 return _wrapped_view_func47 return wraps(view_func)(_wrapped_view_func) -
django/views/decorators/http.py
=== modified file 'django/views/decorators/http.py'
2 2 Decorators for views based on HTTP headers. 3 3 """ 4 4 5 try: 6 from functools import wraps 7 except ImportError: 8 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 9 5 10 from django.utils.decorators import decorator_from_middleware 6 11 from django.middleware.http import ConditionalGetMiddleware 7 12 from django.http import HttpResponseNotAllowed … … 24 29 if request.method not in request_method_list: 25 30 return HttpResponseNotAllowed(request_method_list) 26 31 return func(request, *args, **kwargs) 27 return inner32 return wraps(func)(inner) 28 33 return decorator 29 34 30 35 require_GET = require_http_methods(["GET"]) -
django/views/decorators/vary.py
=== modified file 'django/views/decorators/vary.py'
1 try: 2 from functools import wraps 3 except ImportError: 4 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 5 1 6 from django.utils.cache import patch_vary_headers 2 7 3 8 def vary_on_headers(*headers): … … 16 21 response = func(*args, **kwargs) 17 22 patch_vary_headers(response, headers) 18 23 return response 19 return inner_func24 return wraps(func)(inner_func) 20 25 return decorator 21 26 22 27 def vary_on_cookie(func): … … 32 37 response = func(*args, **kwargs) 33 38 patch_vary_headers(response, ('Cookie',)) 34 39 return response 35 return inner_func40 return wraps(func)(inner_func)