source: orange-bioinformatics/obiKEGG2/caching.py @ 1537:3a5221cffda5

Revision 1537:3a5221cffda5, 5.7 KB checked in by ales_erjavec, 2 years ago (diff)

Replacing the old value in setitem method.

Line 
1"""
2Caching framework for cached kegg api calls.
3 
4"""
5import os
6import UserDict
7import sqlite3
8import cPickle as pickle
9
10from datetime import datetime
11
12
13class Store(object):
14    def __init__(self):
15        self.timestamp = 0
16       
17    def open(self):
18        raise NotImplementedError
19   
20    def __enter__(self):
21        return self
22   
23    def __exit__(self, *args):
24        pass
25   
26   
27class ShelveStore(Store):
28    def __init__(self):
29        import shelve
30        self.fname = shelve.open
31
32
33class Sqlite3Store(Store, UserDict.DictMixin):
34    def __init__(self, filename):
35        self.filename = filename
36        self.con = sqlite3.connect(filename)
37        self.con.execute("""
38        CREATE TABLE IF NOT EXISTS cache
39            (key TEXT UNIQUE,
40             value TEXT
41            )
42        """)
43        self.con.commit()
44       
45    def __getitem__(self, key):
46        cur = self.con.execute("""
47            SELECT value
48            FROM cache
49            WHERE key=?
50        """, (key,))
51        r = cur.fetchall()
52       
53        if not r:
54            raise KeyError(key)
55        else:
56            return pickle.loads(str(r[0][0]))
57   
58    def __setitem__(self, key, value):
59        value = pickle.dumps(value)
60        self.con.execute("""
61            INSERT OR REPLACE INTO cache
62            VALUES (?, ?)
63        """, (key, value))
64        self.con.commit()
65       
66    def __delitem__(self, key):
67        self.con.execute("""
68            DELETE FROM cache
69            WHERE key=?
70        """, (key,))
71        self.con.commit()
72       
73    def keys(self):
74        cur = self.con.execute("""
75            SELECT key
76            FROM cache
77        """)
78        return [str(r[0]) for r in cur.fetchall()]
79       
80    def close(self):
81        pass
82   
83   
84class DictStore(Store, UserDict.DictMixin):
85    def __init__(self):
86        Store.__init__(self)
87       
88    def close(self):
89        pass
90   
91   
92from functools import wraps
93from contextlib import closing
94
95
96class cache_entry(object):
97    def __init__(self, value, mtime=None, expires=None):
98        self.value = value
99        self.mtime = mtime
100        self.expires = expires
101       
102
103class cached_wrapper(object):
104    """ TODO: needs documentation
105    """
106    def __init__(self, function, instance, class_, cache_store, last_modified=None):
107        self.function = function
108        self.instance = instance
109        self.class_ = class_
110        self.cache_store = cache_store
111        self.last_modified = last_modified
112       
113    def has_key(self, key):
114        with closing(self.cache_store()) as store:
115            return key in store
116   
117    def key_from_args(self, args, kwargs=None):
118        key = self.function.__name__ + repr(args)
119        return key
120   
121    def invalidate_key(self, key):
122        with closing(self.cache_store()) as store:
123            del store[key]
124           
125    def last_modified_from_args(self, args, kwargs=None):
126        key = self.key_from_args(args, kwargs)
127        if self.instance is not None:
128            self.instance.last_modified(args)
129       
130    def invalidate_args(self, args):
131        return self.invalidate_key(self.key_from_args(args))
132       
133    def invalidate_all(self):
134        prefix = self.key_from_args(()).rstrip(",)")
135        with self.cache_store() as store:
136            for key in store.keys():
137                if key.startswith(prefix):
138                    del store[key]
139   
140    def memoize(self, args, kwargs, value, timestamp=None):
141        key = self.key_from_args(args, kwargs)
142        if timestamp is None:
143            timestamp = datetime.now()
144           
145        with closing(self.cache_store()) as store:
146            store[key] = cache_entry(value, mtime=timestamp)
147       
148    def __call__(self, *args):
149        key = self.key_from_args(args)
150        with closing(self.cache_store()) as store:
151            valid = True
152            if key not in store:
153                valid = False
154            else:
155                entry = store[key]
156                rval = entry.value
157               
158                if not self.is_entry_valid(entry, args):
159                    valid = False
160                   
161            if not valid:
162                rval = self.function(self.instance, *args)
163                store[key] = cache_entry(rval, datetime.now(), None)
164       
165        return rval
166       
167    def min_timestamp(self, args):
168        key = self.key_from_args(args)
169        return datetime.fromtimestamp(0)
170   
171    def is_entry_valid(self, entry, args):
172        return self.min_timestamp(args) < entry.mtime
173   
174       
175class cached_method(object):
176    def __init__(self, function):
177        self.function = function
178       
179    def __get__(self, instance, owner):
180        if instance is not None:
181            return cached_wrapper(self.function, instance, owner,
182                                  self.get_cache_store(instance, owner))
183        return self
184   
185    def get_cache_store(self, instance, owner):
186        if hasattr(instance, "cache_store"):
187            return instance.cache_store
188        elif not hasattr("_cached_method_cache"):
189            instance._cached_method_cache = DictStore()
190        return instance._cached_method_cache
191
192
193class bget_cached_method(cached_method):
194    def __get__(self, instance, owner):
195        if instance is not None:
196            return cached_wrapper(self.function, instance, owner,
197                                  self.get_cache_store(instance, owner),
198                                  self.get_last_modified(instance, owner))
199        return self
200   
201    def get_last_modified(self, instance, owner):
202        if hasattr(instance, "last_modified"):
203            return instance.last_modified
204   
205def touch_dir(path):
206    path = os.path.expanduser(path)
207    if not os.path.exists(path):
208        os.makedirs(path)
209   
Note: See TracBrowser for help on using the repository browser.