1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 """A few useful function/method decorators.
19
20
21
22
23 """
24 __docformat__ = "restructuredtext en"
25
26 from types import MethodType
27 from time import clock, time
28 import sys, re
29
30
31
32 -def cached(callableobj, keyarg=None):
33 """Simple decorator to cache result of method call."""
34 if callableobj.func_code.co_argcount == 1 or keyarg == 0:
35
36 def cache_wrapper1(self, *args):
37 cache = '_%s_cache_' % callableobj.__name__
38
39 try:
40 return self.__dict__[cache]
41 except KeyError:
42
43 value = callableobj(self, *args)
44 setattr(self, cache, value)
45 return value
46 cache_wrapper1.__doc__ = callableobj.__doc__
47 return cache_wrapper1
48
49 elif keyarg:
50
51 def cache_wrapper2(self, *args, **kwargs):
52 cache = '_%s_cache_' % callableobj.__name__
53 key = args[keyarg-1]
54
55 try:
56 _cache = self.__dict__[cache]
57 except KeyError:
58
59 _cache = {}
60 setattr(self, cache, _cache)
61 try:
62 return _cache[key]
63 except KeyError:
64
65 _cache[key] = callableobj(self, *args, **kwargs)
66 return _cache[key]
67 cache_wrapper2.__doc__ = callableobj.__doc__
68 return cache_wrapper2
69
70 def cache_wrapper3(self, *args):
71 cache = '_%s_cache_' % callableobj.__name__
72
73 try:
74 _cache = self.__dict__[cache]
75 except KeyError:
76
77 _cache = {}
78 setattr(self, cache, _cache)
79 try:
80 return _cache[args]
81 except KeyError:
82
83 _cache[args] = callableobj(self, *args)
84 return _cache[args]
85 cache_wrapper3.__doc__ = callableobj.__doc__
86 return cache_wrapper3
87
89 """Function to clear a cache handled by the cached decorator."""
90 try:
91 del obj.__dict__['_%s_cache_' % funcname]
92 except KeyError:
93 pass
94
96 """Copy cache for <funcname> from cacheobj to obj."""
97 cache = '_%s_cache_' % funcname
98 try:
99 setattr(obj, cache, cacheobj.__dict__[cache])
100 except KeyError:
101 pass
102
104 """Simple descriptor expecting to take a modifier function as first argument
105 and looking for a _<function name> to retrieve the attribute.
106 """
108 self.setfunc = setfunc
109 self.attrname = '_%s' % setfunc.__name__
110
112 self.setfunc(obj, value)
113
115 assert obj is not None
116 return getattr(obj, self.attrname)
117
118
120 """this is a simple property-like class but for class attributes.
121 """
126
127
129 '''Descriptor for method which should be available as class method if called
130 on the class or instance method if called on an instance.
131 '''
134 - def __get__(self, instance, objtype):
135 if instance is None:
136 return MethodType(self.func, objtype, objtype.__class__)
137 return MethodType(self.func, instance, objtype)
138 - def __set__(self, instance, value):
139 raise AttributeError("can't set attribute")
140
141
143 def wrap(*args, **kwargs):
144 t = time()
145 c = clock()
146 res = f(*args, **kwargs)
147 print '%s clock: %.9f / time: %.9f' % (f.__name__,
148 clock() - c, time() - t)
149 return res
150 return wrap
151
152
154 """Decorator taking two methods to acquire/release a lock as argument,
155 returning a decorator function which will call the inner method after
156 having called acquire(self) et will call release(self) afterwards.
157 """
158 def decorator(f):
159 def wrapper(self, *args, **kwargs):
160 acquire(self)
161 try:
162 return f(self, *args, **kwargs)
163 finally:
164 release(self)
165 return wrapper
166 return decorator
167
168
170 """Decorator extending class with the decorated function
171 >>> class A:
172 ... pass
173 >>> @monkeypatch(A)
174 ... def meth(self):
175 ... return 12
176 ...
177 >>> a = A()
178 >>> a.meth()
179 12
180 >>> @monkeypatch(A, 'foo')
181 ... def meth(self):
182 ... return 12
183 ...
184 >>> a.foo()
185 12
186 """
187 def decorator(func):
188 setattr(klass, methodname or func.__name__, func)
189 return func
190 return decorator
191