1 """Decorator tools"""
2
3 import itertools
4 from inspect import getargspec, formatargspec
5
6
7 -def decorate(func, caller, signature=None):
8 """Decorate func with caller.
9
10 Inspired by Michele Simionato's decorator library:
11 http://www.phyast.pitt.edu/~micheles/python/documentation.html
12
13 """
14 argnames, varargs, kwargs, defaults = \
15 signature is None and getargspec(func) or signature
16 if defaults is None:
17 defaults = ()
18 parameters = formatargspec(argnames, varargs, kwargs, defaults)[1:-1]
19 defval = itertools.count(len(argnames) - len(defaults))
20 args = formatargspec(argnames, varargs, kwargs, defaults,
21 formatvalue=lambda value:"=%s" % argnames[defval.next()])[1:-1]
22 exec_dict = dict(func=func, caller=caller)
23 exec "\ndef %s(%s):\n\treturn caller(func, %s)\n" % (
24 func.__name__, parameters, args) in exec_dict
25 new_func = exec_dict[func.__name__]
26 new_func.__doc__ = func.__doc__
27 new_func.__dict__ = func.__dict__.copy()
28 new_func.__module__ = func.__module__
29 new_func.__composition__ = getattr(func, '__composition__',
30 [func]) + [new_func]
31 return new_func
32
33
35 """Decorate function with entangler.
36
37 Use new signature or preserve original signature if signature is None.
38
39 """
40 def entangle(func):
41 return decorate(func, entangler(func), signature)
42 return entangle
43
44
46 """Decorate function with entangler and weak signature.
47
48 Changes signature to accept arbitrary additional arguments.
49
50 """
51 def entangle(func):
52 return decorate(func, entangler(func), make_weak_signature(func))
53 return entangle
54
55
57 """Decorate function with caller."""
58 def entangle(func):
59 return decorate(func, caller, signature)
60 return entangle
61
62
64 """Decorate function with caller and weak signature.
65
66 Changes signature to accept arbitrary additional arguments.
67
68 """
69 def entangle(func):
70 return decorate(func, caller, make_weak_signature(func))
71 return entangle
72
73
75 """Change signature to accept arbitrary additional arguments."""
76 argnames, varargs, kwargs, defaults = getargspec(func)
77 if kwargs is None:
78 kwargs = "_decorator__kwargs"
79 if varargs is None:
80 varargs = "_decorator__varargs"
81 return argnames, varargs, kwargs, defaults
82
83
85 """Compose decorators."""
86 return lambda func: reduce(lambda f, g: g(f), decorators, func)
87
88
90 """Return composition (decorator wise) of function."""
91 return getattr(func, "__composition__", [func])
92
93
95 """Return original (undecorated) function."""
96 return func_composition(func)[0]
97
98
100 """Return identity of function.
101
102 If decorator was created with decorator() or weak_signature_decorator(),
103 identity is invariant under decorator application.
104
105 """
106 return id(func_original(func))
107
108
110 """Check if functions are identical."""
111 return func_id(f) == func_id(g)
112
113
114 __all__ = ["decorate", "make_weak_signature", "compose",
115 "decorator", "weak_signature_decorator",
116 "simple_decorator", "simple_weak_signature_decorator",
117 "func_id", "func_eq", "func_original", "func_composition"]
118