Package turbogears :: Module decorator
[hide private]

Source Code for Module turbogears.decorator

  1  import itertools 
  2  from copy import copy 
  3  from inspect import getargspec, formatargspec 
  4   
  5  from peak.util.decorators import decorate_assignment 
  6   
  7   
  8  # Inspired by Michele Simionato's decorator library 
  9  # http://www.phyast.pitt.edu/~micheles/python/documentation.html 
 10   
11 -def decorate(func, caller, signature=None):
12 """Decorate func with caller.""" 13 if signature is not None: 14 argnames, varargs, kwargs, defaults = signature 15 else: 16 argnames, varargs, kwargs, defaults = getargspec(func) 17 if defaults is None: 18 defaults = () 19 parameters = formatargspec(argnames, varargs, kwargs, defaults)[1:-1] 20 defval = itertools.count(len(argnames)-len(defaults)) 21 args = formatargspec(argnames, varargs, kwargs, defaults, 22 formatvalue=lambda value:"=%s" % ( 23 argnames[defval.next()]))[1:-1] 24 25 func_str = """ 26 def %s(%s): 27 return caller(func, %s) 28 """ % (func.__name__, parameters, args) 29 30 exec_dict = dict(func=func, caller=caller) 31 exec func_str in exec_dict 32 newfunc = exec_dict[func.__name__] 33 newfunc.__doc__ = func.__doc__ 34 newfunc.__dict__ = func.__dict__.copy() 35 newfunc.__module__ = func.__module__ 36 if hasattr(func, "__composition__"): 37 newfunc.__composition__ = copy(func.__composition__) 38 else: 39 newfunc.__composition__ = [func] 40 newfunc.__composition__.append(newfunc) 41 return newfunc
42
43 -def decorator(entangler, signature=None):
44 """Decorate function with entangler. 45 46 Use signature as signature or preserve original signature if signature 47 is None. 48 49 Enables alternative decorator syntax for Python 2.3 as seen in PEAK: 50 51 [my_decorator(foo)] 52 def baz(): 53 pass 54 55 Mind, the decorator needs to be a closure for this syntax to work. 56 """ 57 def callback(frame, k, v, old_locals): 58 return decorate(v, entangler(v), signature)
59 return decorate_assignment(callback, 3) 60
61 -def weak_signature_decorator(entangler):
62 """Decorate function with entangler and change signature to accept 63 arbitrary additional arguments. 64 65 Enables alternative decorator syntax for Python 2.3 as seen in PEAK: 66 67 [my_decorator(foo)] 68 def baz(): 69 pass 70 71 Mind, the decorator needs to be a closure for this syntax to work. 72 """ 73 def callback(frame, k, v, old_locals): 74 return decorate(v, entangler(v), make_weak_signature(v))
75 return decorate_assignment(callback, 3) 76
77 -def simple_decorator(caller, signature=None):
78 """Decorate function with caller.""" 79 def entangle(func): 80 return decorate(func, caller, signature)
81 return entangle 82
83 -def simple_weak_signature_decorator(caller):
84 """Decorate function with caller and change signature to accept 85 arbitrary additional arguments.""" 86 def entangle(func): 87 return decorate(func, caller, make_weak_signature(func))
88 return entangle 89
90 -def make_weak_signature(func):
91 """Change signature to accept arbitrary additional arguments.""" 92 argnames, varargs, kwargs, defaults = getargspec(func) 93 if kwargs is None: 94 kwargs = "_decorator__kwargs" 95 if varargs is None: 96 varargs = "_decorator__varargs" 97 return argnames, varargs, kwargs, defaults
98
99 -def compose(*decorators):
100 """Compose decorators.""" 101 return lambda func: reduce(lambda f, g: g(f), decorators, func)
102
103 -def func_composition(func):
104 """Return composition (decorator wise) of function.""" 105 return getattr(func, "__composition__", [func])
106
107 -def func_original(func):
108 """Return original (undecorated) function.""" 109 return func_composition(func)[0]
110
111 -def func_id(func):
112 """Return identity of function. 113 114 Identity is invariant under decorator application (if decorator is 115 created with decorator() or weak_signature_decorator()). 116 """ 117 return id(func_original(func))
118
119 -def func_eq(f, g):
120 """Check if functions are identical.""" 121 return func_id(f) == func_id(g)
122 123 __all__ = ["decorator", "compose", "func_id", "func_eq", "func_original", 124 "func_composition", "weak_signature_decorator", "decorate", 125 "make_weak_signature", "simple_decorator", 126 "simple_weak_signature_decorator",] 127