8784: Fix test for latest firefox.
[arvados.git] / sdk / python / arvados / cache.py
1 from builtins import object
2 import errno
3 import hashlib
4 import os
5 import tempfile
6 import time
7
8 class SafeHTTPCache(object):
9     """Thread-safe replacement for httplib2.FileCache"""
10
11     def __init__(self, path=None, max_age=None):
12         self._dir = path
13         if max_age is not None:
14             try:
15                 self._clean(threshold=time.time() - max_age)
16             except:
17                 pass
18
19     def _clean(self, threshold=0):
20         for ent in os.listdir(self._dir):
21             fnm = os.path.join(self._dir, ent)
22             if os.path.isdir(fnm) or not fnm.endswith('.tmp'):
23                 continue
24             stat = os.lstat(fnm)
25             if stat.st_mtime < threshold:
26                 try:
27                     os.unlink(fnm)
28                 except OSError as err:
29                     if err.errno != errno.ENOENT:
30                         raise
31
32     def __str__(self):
33         return self._dir
34
35     def _filename(self, url):
36         return os.path.join(self._dir, hashlib.md5(url.encode('utf-8')).hexdigest()+'.tmp')
37
38     def get(self, url):
39         filename = self._filename(url)
40         try:
41             with open(filename, 'rb') as f:
42                 return f.read()
43         except (IOError, OSError):
44             return None
45
46     def set(self, url, content):
47         try:
48             fd, tempname = tempfile.mkstemp(dir=self._dir)
49         except:
50             return None
51         try:
52             try:
53                 f = os.fdopen(fd, 'wb')
54             except:
55                 os.close(fd)
56                 raise
57             try:
58                 f.write(content)
59             finally:
60                 f.close()
61             os.rename(tempname, self._filename(url))
62             tempname = None
63         finally:
64             if tempname:
65                 os.unlink(tempname)
66
67     def delete(self, url):
68         try:
69             os.unlink(self._filename(url))
70         except OSError as err:
71             if err.errno != errno.ENOENT:
72                 raise