-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathcaching.py
More file actions
150 lines (135 loc) · 5.04 KB
/
Copy pathcaching.py
File metadata and controls
150 lines (135 loc) · 5.04 KB
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
'''
Created on 07/02/2014
@author: MMPE
'''
import sys
from collections import OrderedDict
import os
import inspect
import numpy as np
def set_cache_property(obj, name, get_func, set_func=None):
"""Create a cached property
Parameters
----------
obj : object
Class to add property to
name : str
Name of property
get_func : func
Getter function
set_func : func, optional
Setter function
Examples
--------
>>> class Example(object):
>>> def __init__(self):
>>> set_cache_property(self, "test", self.slow_function)
>>>
>>> e = Example()
>>> e.test # Call, store and return result of e.slow_function
>>> e.test # Return stored result of e.slow_function
>>> e._test = None # clear cache result
>>> e.test # Call, store and return result of e.slow_function
"""
_name = "_" + name
setattr(obj, _name, None)
def get(self):
if getattr(obj, _name) is None:
setattr(obj, _name, get_func())
return getattr(obj, _name)
p = property(lambda self:get(self), set_func)
return setattr(obj.__class__, name, p)
def cache_function(f):
"""Cache function decorator
Example:
>>> class Example(object):
>>> @cache_function
>>> def slow_function(self):
>>> # calculate slow result
>>> return 1
>>>
>>> e = Example()
>>> e.slow_function() # Call, store and return result of e.slow_function
>>> e.slow_function() # Return stored result of e.slow_function
"""
def wrap(*args, **kwargs):
self = args[0]
name = "_" + f.__name__
if not hasattr(self, name) or getattr(self, name) is None or kwargs.get("reload", False):
try:
del kwargs['reload']
except KeyError:
pass
# ======HERE============
setattr(self, name, f(*args, **kwargs))
# ======================
if not hasattr(self, "cache_attr_lst"):
self.cache_attr_lst = set()
def clear_cache():
for attr in self.cache_attr_lst:
delattr(self, attr)
self.cache_attr_lst = set()
self.clear_cache = clear_cache
self.cache_attr_lst.add(name)
return getattr(self, name)
version = sys.version_info
if version >= (3,3):
if 'reload' in inspect.signature(f).parameters.values():
raise AttributeError("Functions decorated with cache_function are not allowed to take a parameter called 'reload'")
elif 'reload' in inspect.getargspec(f)[0]:
raise AttributeError("Functions decorated with cache_function are not allowed to take a parameter called 'reload'")
return wrap
class cache_method():
def __init__(self, N):
self.N = N
def __call__(self, f):
def wrapped(caller_obj, *args):
name = "_" + f.__name__
arg_id = ";".join([str(a) for a in args])
if not hasattr(caller_obj,'%s_cache_dict'%name):
setattr(caller_obj,'%s_cache_dict'%name, OrderedDict())
cache_dict = getattr(caller_obj,'%s_cache_dict'%name)
if arg_id not in cache_dict:
cache_dict[arg_id] = f(caller_obj, *args)
if len(cache_dict)>self.N:
cache_dict.popitem(last=False)
return cache_dict[arg_id]
return wrapped
def cache_npsave(f):
def wrap(filename,*args,**kwargs):
np_filename = os.path.splitext(filename)[0] + ".npy"
def loadsave():
res = f(filename,*args,**kwargs)
np.save(np_filename,res)
return res
if os.path.isfile(np_filename) and (not os.path.isfile(filename) or os.path.getmtime(np_filename) > os.path.getmtime(filename)):
try:
return np.load(np_filename)
except:
return loadsave()
else:
return loadsave()
return wrap
def _get_npsavez_wrap(f, compress):
def wrap(filename,*args,**kwargs):
np_filename = os.path.splitext(filename)[0] + ".npy%s.npz"%("",".c")[compress]
def loadsave():
res = f(filename,*args,**kwargs)
if compress:
np.savez_compressed(np_filename,*res)
else:
np.savez(np_filename,*res)
return res
if os.path.isfile(np_filename) and (not os.path.isfile(filename) or os.path.getmtime(np_filename) > os.path.getmtime(filename)):
try:
npzfile = np.load(np_filename)
return [npzfile['arr_%d'%i] for i in range(len(npzfile.files))]
except:
return loadsave()
else:
return loadsave()
return wrap
def cache_npsavez(f):
return _get_npsavez_wrap(f,False)
def cache_npsavez_compressed(f):
return _get_npsavez_wrap(f, True)