1 # This Python file uses the following encoding: utf-8
3 Created on May 11, 2011
11 class Cacheable(object):
12 """interface for a class to have results which are cacheable on disk."""
14 def __init__(self
, cachedir
, ignore_cache
=None, debug
=False):
16 @param cachedir: where to store the cached files on disk. if it does not exist, it will be created.
17 @param ignore_cache: a collection of components which should not be cached by this instance.
19 self
.__cachedir
= cachedir
20 self
.__ignore
_cache
= ignore_cache
23 def _filename(self
, component
):
24 """helper method to generate the filename for a component"""
25 return os
.path
.join(self
.__cachedir
, component
)
27 def is_cached(self
, component
):
29 returns C{True} if the specified C{component} is cached
31 @type component: C{str}
34 if self
.__ignore
_cache
and component
in self
.__ignore
_cache
:
37 filename
= self
._filename
(component
)
38 found
= os
.path
.exists(filename
)
42 print "cached file found: %s" % (filename
)
44 print "cached file not found: %s" % (filename
)
48 def get_cache(self
, component
, loader
=cPickle
):
50 returns the specified cached component
52 @type component: C{str}
55 filename
= self
._filename
(component
)
58 print "reading '%s' from cache" % (filename
)
60 with
open(filename
) as file:
61 return loader
.load(file)
64 print "finished reading '%s' from cache" % (filename
)
67 def set_cache(self
, component
, object, dumper
=cPickle
):
69 writes the specified component to cache.
71 @type component: C{str}
72 @type object: anything pickle-able
75 if not os
.path
.exists(self
.__cachedir
):
76 os
.makedirs(self
.__cachedir
)
78 filename
= self
._filename
(component
)
81 print "writing '%s' to cache" % (filename
)
83 with
open(filename
, 'w') as file:
84 dumper
.dump(object, file)
87 print "finished writing '%s' to cache" % (filename
)
94 annotation to indicate a cached function.
96 using it requires specifying a "key" function with which to generate a filename
97 to use as the cache for the result of a specific function call.
100 def __init__(self
, key
=lambda *x
, **y
: str(x
) + str(y
), loader
=cPickle
, dumper
=cPickle
):
102 self
.__loader
= loader
103 self
.__dumper
= dumper
105 def __call__(self
, func
):
106 def caller(*args
, **kwargs
):
109 component
= self
.__key
(*args
[1:], **kwargs
)
111 component
= self
.__key
(*args
[1:])
112 if cacher
.is_cached(component
):
113 return cacher
.get_cache(component
, self
.__loader
)
116 result
= func(*args
, **kwargs
)
119 cacher
.set_cache(component
, result
, self
.__dumper
)
124 """Return the function's docstring."""
125 return self
.func
.__doc
__
127 def __get__(self
, obj
, objtype
):
128 """Support instance methods."""
129 return functools
.partial(self
.__call
__, obj
)
132 class Test(Cacheable
):
136 Cacheable
.__init
__(self
, os
.path
.join("/Users/mjacob/testmemoize", "test memoize"))
138 @Cached(lambda number
, *x
: str(number
))
139 def do_thing(self
, number
, *others
, **kwargs
):
141 return (number
, self
.count
)
143 if __name__
== "__main__":
145 print a
.do_thing(1,4)
146 print a
.do_thing(2,5)
147 print a
.do_thing(3,6)
148 print a
.do_thing(1,4)