10
class AbrekCache(object):
18
home = os.environ.get('HOME', '/')
19
basecache = os.environ.get('XDG_CACHE_HOME',
20
os.path.join(home, '.cache'))
21
self.cache_dir = os.path.join(basecache, 'abrek')
24
def get_instance(cls):
25
if cls._instance is None:
29
def open_cached(self, key, mode="r"):
31
Acts like open() but the pathname is relative to the
32
abrek-specific cache directory.
34
if "w" in mode and not os.path.exists(self.cache_dir):
35
os.makedirs(self.cache_dir)
36
if os.path.isabs(key):
37
raise ValueError("key cannot be an absolute path")
39
stream = open(os.path.join(self.cache_dir, key), mode)
44
def _key_for_url(self, url):
45
return hashlib.sha1(url).hexdigest()
47
def _refresh_url_cache(self, key, url):
48
with contextlib.nested(
49
contextlib.closing(urllib2.urlopen(url)),
50
self.open_cached(key, "wb")) as (in_stream, out_stream):
51
out_stream.write(in_stream.read())
53
@contextlib.contextmanager
54
def open_cached_url(self, url):
56
Like urlopen.open() but the content may be cached.
58
# Do not cache local files, this is not what users would expect
60
# workaround - not using cache at all.
61
# TODO: fix this and use the cache
62
# if url.startswith("file://"):
64
stream = urllib2.urlopen(url)
66
key = self._key_for_url(url)
68
stream = self.open_cached(key, "rb")
69
except IOError as exc:
70
self._refresh_url_cache(key, url)
71
stream = self.open_cached(key, "rb")