--- a/web/lib/django/utils/decorators.py Wed May 19 17:43:59 2010 +0200
+++ b/web/lib/django/utils/decorators.py Tue May 25 02:43:45 2010 +0200
@@ -2,60 +2,87 @@
import types
try:
- from functools import wraps
+ from functools import wraps, update_wrapper, WRAPPER_ASSIGNMENTS
except ImportError:
- from django.utils.functional import wraps # Python 2.3, 2.4 fallback.
+ from django.utils.functional import wraps, update_wrapper, WRAPPER_ASSIGNMENTS # Python 2.4 fallback.
+
+
+def method_decorator(decorator):
+ """
+ Converts a function decorator into a method decorator
+ """
+ def _dec(func):
+ def _wrapper(self, *args, **kwargs):
+ def bound_func(*args2, **kwargs2):
+ return func(self, *args2, **kwargs2)
+ # bound_func has the signature that 'decorator' expects i.e. no
+ # 'self' argument, but it is a closure over self so it can call
+ # 'func' correctly.
+ return decorator(bound_func)(*args, **kwargs)
+ return wraps(func)(_wrapper)
+ update_wrapper(_dec, decorator)
+ # Change the name to aid debugging.
+ _dec.__name__ = 'method_dec(%s)' % decorator.__name__
+ return _dec
+
+
+def decorator_from_middleware_with_args(middleware_class):
+ """
+ Like decorator_from_middleware, but returns a function
+ that accepts the arguments to be passed to the middleware_class.
+ Use like::
+
+ cache_page = decorator_from_middleware_with_args(CacheMiddleware)
+ # ...
+
+ @cache_page(3600)
+ def my_view(request):
+ # ...
+ """
+ return make_middleware_decorator(middleware_class)
+
def decorator_from_middleware(middleware_class):
"""
Given a middleware class (not an instance), returns a view decorator. This
- lets you use middleware functionality on a per-view basis.
+ lets you use middleware functionality on a per-view basis. The middleware
+ is created with no params passed.
"""
- def _decorator_from_middleware(*args, **kwargs):
- # For historical reasons, these "decorators" are also called as
- # dec(func, *args) instead of dec(*args)(func). We handle both forms
- # for backwards compatibility.
- has_func = True
- try:
- view_func = kwargs.pop('view_func')
- except KeyError:
- if len(args):
- view_func, args = args[0], args[1:]
- else:
- has_func = False
- if not (has_func and isinstance(view_func, types.FunctionType)):
- # We are being called as a decorator.
- if has_func:
- args = (view_func,) + args
- middleware = middleware_class(*args, **kwargs)
+ return make_middleware_decorator(middleware_class)()
- def decorator_func(fn):
- return _decorator_from_middleware(fn, *args, **kwargs)
- return decorator_func
-
- middleware = middleware_class(*args, **kwargs)
+def available_attrs(fn):
+ """
+ Return the list of functools-wrappable attributes on a callable.
+ This is required as a workaround for http://bugs.python.org/issue3445.
+ """
+ return tuple(a for a in WRAPPER_ASSIGNMENTS if hasattr(fn, a))
- def _wrapped_view(request, *args, **kwargs):
- if hasattr(middleware, 'process_request'):
- result = middleware.process_request(request)
- if result is not None:
- return result
- if hasattr(middleware, 'process_view'):
- result = middleware.process_view(request, view_func, args, kwargs)
- if result is not None:
- return result
- try:
- response = view_func(request, *args, **kwargs)
- except Exception, e:
- if hasattr(middleware, 'process_exception'):
- result = middleware.process_exception(request, e)
+def make_middleware_decorator(middleware_class):
+ def _make_decorator(*m_args, **m_kwargs):
+ middleware = middleware_class(*m_args, **m_kwargs)
+ def _decorator(view_func):
+ def _wrapped_view(request, *args, **kwargs):
+ if hasattr(middleware, 'process_request'):
+ result = middleware.process_request(request)
if result is not None:
return result
- raise
- if hasattr(middleware, 'process_response'):
- result = middleware.process_response(request, response)
- if result is not None:
- return result
- return response
- return wraps(view_func)(_wrapped_view)
- return _decorator_from_middleware
+ if hasattr(middleware, 'process_view'):
+ result = middleware.process_view(request, view_func, args, kwargs)
+ if result is not None:
+ return result
+ try:
+ response = view_func(request, *args, **kwargs)
+ except Exception, e:
+ if hasattr(middleware, 'process_exception'):
+ result = middleware.process_exception(request, e)
+ if result is not None:
+ return result
+ raise
+ if hasattr(middleware, 'process_response'):
+ result = middleware.process_response(request, response)
+ if result is not None:
+ return result
+ return response
+ return wraps(view_func, assigned=available_attrs(view_func))(_wrapped_view)
+ return _decorator
+ return _make_decorator