1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
# This program is free software; you can redistribute it and/or modify it under
# the terms of the GNU General Public License as published by the Free Software
# Foundation; either version 2 of the License, or (at your option) any later
# version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License along with
# this program; if not, write to the Free Software Foundation, Inc.,
# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
"""this module contains some function/method decorators
:author: Logilab
:copyright: 2006-2008 LOGILAB S.A. (Paris, FRANCE)
:contact: http://www.logilab.fr/ -- mailto:python-projects@logilab.org
"""
__docformat__ = "restructuredtext en"
# XXX rewrite so we can use the decorator syntax when keyarg has to be specified
def cached(callableobj, keyarg=None):
"""simple decorator to cache result of method call"""
#print callableobj, keyarg, callableobj.func_code.co_argcount
if callableobj.func_code.co_argcount == 1 or keyarg == 0:
def cache_wrapper1(self, *args):
cache = '_%s_cache_' % callableobj.__name__
#print 'cache1?', cache
try:
return self.__dict__[cache]
except KeyError:
#print 'miss'
value = callableobj(self, *args)
setattr(self, cache, value)
return value
return cache_wrapper1
elif keyarg:
def cache_wrapper2(self, *args, **kwargs):
cache = '_%s_cache_' % callableobj.__name__
key = args[keyarg-1]
#print 'cache2?', cache, self, key
try:
_cache = self.__dict__[cache]
except KeyError:
#print 'init'
_cache = {}
setattr(self, cache, _cache)
try:
return _cache[key]
except KeyError:
#print 'miss', self, cache, key
_cache[key] = callableobj(self, *args, **kwargs)
return _cache[key]
return cache_wrapper2
def cache_wrapper3(self, *args):
cache = '_%s_cache_' % callableobj.__name__
#print 'cache3?', cache, self, args
try:
_cache = self.__dict__[cache]
except KeyError:
#print 'init'
_cache = {}
setattr(self, cache, _cache)
try:
return _cache[args]
except KeyError:
#print 'miss'
_cache[args] = callableobj(self, *args)
return _cache[args]
return cache_wrapper3
def clear_cache(obj, funcname):
"""function to clear a cache handled by the cached decorator"""
try:
del obj.__dict__['_%s_cache_' % funcname]
except KeyError:
pass
def copy_cache(obj, funcname, cacheobj):
"""copy cache for <funcname> from cacheobj to obj"""
cache = '_%s_cache_' % funcname
try:
setattr(obj, cache, cacheobj.__dict__[cache])
except KeyError:
pass
class wproperty(object):
"""simple descriptor expecting to take a modifier function as first argument
and looking for a _<function name> to retrieve the attribute
"""
def __init__(self, setfunc):
self.setfunc = setfunc
self.attrname = '_%s' % setfunc.__name__
def __set__(self, obj, value):
self.setfunc(obj, value)
def __get__(self, obj, cls):
assert obj is not None
return getattr(obj, self.attrname)
class classproperty(object):
def __init__(self, get):
self.get = get
def __get__(self, inst, cls):
return self.get(cls)
from time import clock
def timed(f):
def wrap(*args, **kwargs):
t = clock()
#for i in range(100):
res = f(*args, **kwargs)
print '%s time: %.9f' % (f.__name__, clock() - t)
return res
return wrap
|