Package logilab-common-0 ::
Package 39 ::
Package 0 ::
Module decorators
|
|
1 """A few useful function/method decorators.
2
3 :copyright: 2006-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved.
4 :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
5 :license: General Public License version 2 - http://www.gnu.org/licenses
6 """
7 __docformat__ = "restructuredtext en"
8
9 from types import MethodType
10 from time import clock
11 import sys, re
12
13
14
15 -def cached(callableobj, keyarg=None):
16 """Simple decorator to cache result of method call."""
17
18 if callableobj.func_code.co_argcount == 1 or keyarg == 0:
19
20 def cache_wrapper1(self, *args):
21 cache = '_%s_cache_' % callableobj.__name__
22
23 try:
24 return self.__dict__[cache]
25 except KeyError:
26
27 value = callableobj(self, *args)
28 setattr(self, cache, value)
29 return value
30 return cache_wrapper1
31
32 elif keyarg:
33
34 def cache_wrapper2(self, *args, **kwargs):
35 cache = '_%s_cache_' % callableobj.__name__
36 key = args[keyarg-1]
37
38 try:
39 _cache = self.__dict__[cache]
40 except KeyError:
41
42 _cache = {}
43 setattr(self, cache, _cache)
44 try:
45 return _cache[key]
46 except KeyError:
47
48 _cache[key] = callableobj(self, *args, **kwargs)
49 return _cache[key]
50 return cache_wrapper2
51
52 def cache_wrapper3(self, *args):
53 cache = '_%s_cache_' % callableobj.__name__
54
55 try:
56 _cache = self.__dict__[cache]
57 except KeyError:
58
59 _cache = {}
60 setattr(self, cache, _cache)
61 try:
62 return _cache[args]
63 except KeyError:
64
65 _cache[args] = callableobj(self, *args)
66 return _cache[args]
67 return cache_wrapper3
68
70 """Function to clear a cache handled by the cached decorator."""
71 try:
72 del obj.__dict__['_%s_cache_' % funcname]
73 except KeyError:
74 pass
75
77 """Copy cache for <funcname> from cacheobj to obj."""
78 cache = '_%s_cache_' % funcname
79 try:
80 setattr(obj, cache, cacheobj.__dict__[cache])
81 except KeyError:
82 pass
83
84
86 """Simple descriptor expecting to take a modifier function as first argument
87 and looking for a _<function name> to retrieve the attribute.
88 """
90 self.setfunc = setfunc
91 self.attrname = '_%s' % setfunc.__name__
92
94 self.setfunc(obj, value)
95
97 assert obj is not None
98 return getattr(obj, self.attrname)
99
100
106
107
109 '''Descriptor for method which should be available as class method if called
110 on the class or instance method if called on an instance.
111 '''
114 - def __get__(self, instance, objtype):
115 if instance is None:
116 return MethodType(self.func, objtype, objtype.__class__)
117 return MethodType(self.func, instance, objtype)
118 - def __set__(self, instance, value):
119 raise AttributeError("can't set attribute")
120
121
123 def wrap(*args, **kwargs):
124 t = clock()
125
126 res = f(*args, **kwargs)
127 print '%s time: %.9f' % (f.__name__, clock() - t)
128 return res
129 return wrap
130
131
133 """Decorator taking two methods to acquire/release a lock as argument,
134 returning a decorator function which will call the inner method after
135 having called acquire(self) et will call release(self) afterwards.
136 """
137 def decorator(f):
138 def wrapper(self, *args, **kwargs):
139 acquire(self)
140 try:
141 return f(self, *args, **kwargs)
142 finally:
143 release(self)
144 return wrapper
145 return decorator
146
147
149 """Decorator extending class with the decorated function
150 >>> class A:
151 ... pass
152 >>> @monkeypatch(A)
153 ... def meth(self):
154 ... return 12
155 ...
156 >>> a = A()
157 >>> a.meth()
158 12
159 >>> @monkeypatch(A, 'foo')
160 ... def meth(self):
161 ... return 12
162 ...
163 >>> a.foo()
164 12
165 """
166 def decorator(func):
167 setattr(klass, methodname or func.__name__, func)
168 return func
169 return decorator
170