Ticket #6700: smart_decorator.diff
File smart_decorator.diff, 3.9 KB (added by , 17 years ago) |
---|
-
django/utils/decorators.py
1 "Functions that help with dynamically creating decorators for views."1 "Functions that help with creating decorators." 2 2 3 3 import types 4 from inspect import getargspec 4 5 try: 5 6 from functools import wraps 6 7 except ImportError: 7 8 from django.utils.functional import wraps # Python 2.3, 2.4 fallback. 8 9 10 def smart_decorator(decorator): 11 """ 12 Smartens up "decorators" which accept additional arguments. 13 14 It allows the decorator to be called correctly in any of the following 15 formats:: 16 17 @my_smartened_decorator(arg1, arg2) 18 my_func = my_smartened_decorator(arg1, arg2)(my_func) 19 my_func = my_smartened_decorator(my_func, arg1, arg2) 20 21 If all additional decorator arguments have defaults, it also allows for the 22 following formats:: 23 24 @my_smartened_decorator 25 my_func = my_smartened_decorator(my_func) 26 """ 27 def _simple_dec(function): 28 return decorator(function) 29 def _dec_with_args(*args, **kwargs): 30 def _inner_dec(function): 31 return decorator(function, *args, **kwargs) 32 return wraps(decorator)(_inner_dec) 33 def _smart_dec(function_or_value, *args, **kwargs): 34 if not isinstance(function_or_value, types.FunctionType): 35 args = (function_or_value,) + args 36 return _dec_with_args(*args, **kwargs) 37 return decorator(function_or_value, *args, **kwargs) 38 args, varargs, varkw, defaults = getargspec(decorator) 39 assert args, 'Decorators must take at least one argument' 40 if not varargs and not varkw: 41 if len(args) == 1: 42 return wraps(decorator)(_simple_dec) 43 if len(defaults) == len(args) - 1: 44 return wraps(decorator)(_smart_dec) 45 return wraps(decorator)(_dec_with_args) 46 9 47 def decorator_from_middleware(middleware_class): 10 48 """ 11 49 Given a middleware class (not an instance), returns a view decorator. This -
tests/regressiontests/utils/decorators.py
1 r""" 2 >>> from django.utils.decorators import smart_decorator, wraps 3 4 >>> def ping(extra_text=''): 5 ... "Simple ping method" 6 ... print extra_text or 'ping' 7 8 >>> def my_dec(func, arg='arg1', arg2=None): 9 ... print arg 10 ... if arg2: 11 ... print 'arg2:', arg2 12 ... def _dec(*args, **kwargs): 13 ... return func(*args, **kwargs) 14 ... return wraps(func)(_dec) 15 >>> my_dec = smart_decorator(my_dec) 16 17 # It accepts just the function 18 >>> p1 = my_dec(ping) 19 arg1 20 21 # ... or the function and arguments 22 >>> p2 = my_dec(ping, 'two') 23 two 24 >>> p2 = my_dec(ping, arg2='two') 25 arg1 26 arg2: two 27 28 # ... or the 2.4 syntax of (arguments)(function) 29 >>> p3 = my_dec('three')(ping) 30 three 31 32 # In any of those cases, the actual decorated function still works fine: 33 >>> p1() 34 ping 35 >>> p1('pong') 36 pong 37 >>> p1(extra_text='pang') 38 pang 39 >>> p2() 40 ping 41 >>> p2('pong') 42 pong 43 >>> p2(extra_text='pang') 44 pang 45 >>> p3() 46 ping 47 >>> p3('pong') 48 pong 49 >>> p3(extra_text='pang') 50 pang 51 52 >>> p1.__doc__ 53 'Simple ping method' 54 >>> p2.__doc__ 55 'Simple ping method' 56 >>> p3.__doc__ 57 'Simple ping method' 58 """ -
tests/regressiontests/utils/tests.py
8 8 9 9 import timesince 10 10 import datastructures 11 import decorators 11 12 12 13 # Extra tests 13 14 __test__ = { 14 15 'timesince': timesince, 15 16 'datastructures': datastructures, 17 'decorators': decorators, 16 18 } 17 19 18 20 class TestUtilsHtml(TestCase):