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