Mercurial > repos > shellac > guppy_basecaller
comparison env/lib/python3.7/site-packages/cachecontrol/caches/file_cache.py @ 5:9b1c78e6ba9c draft default tip
"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author | shellac |
---|---|
date | Mon, 01 Jun 2020 08:59:25 -0400 |
parents | 79f47841a781 |
children |
comparison
equal
deleted
inserted
replaced
4:79f47841a781 | 5:9b1c78e6ba9c |
---|---|
1 import hashlib | |
2 import os | |
3 | |
4 from lockfile import LockFile | |
5 from lockfile.mkdirlockfile import MkdirLockFile | |
6 | |
7 from ..cache import BaseCache | |
8 from ..controller import CacheController | |
9 | |
10 | |
11 def _secure_open_write(filename, fmode): | |
12 # We only want to write to this file, so open it in write only mode | |
13 flags = os.O_WRONLY | |
14 | |
15 # os.O_CREAT | os.O_EXCL will fail if the file already exists, so we only | |
16 # will open *new* files. | |
17 # We specify this because we want to ensure that the mode we pass is the | |
18 # mode of the file. | |
19 flags |= os.O_CREAT | os.O_EXCL | |
20 | |
21 # Do not follow symlinks to prevent someone from making a symlink that | |
22 # we follow and insecurely open a cache file. | |
23 if hasattr(os, "O_NOFOLLOW"): | |
24 flags |= os.O_NOFOLLOW | |
25 | |
26 # On Windows we'll mark this file as binary | |
27 if hasattr(os, "O_BINARY"): | |
28 flags |= os.O_BINARY | |
29 | |
30 # Before we open our file, we want to delete any existing file that is | |
31 # there | |
32 try: | |
33 os.remove(filename) | |
34 except (IOError, OSError): | |
35 # The file must not exist already, so we can just skip ahead to opening | |
36 pass | |
37 | |
38 # Open our file, the use of os.O_CREAT | os.O_EXCL will ensure that if a | |
39 # race condition happens between the os.remove and this line, that an | |
40 # error will be raised. Because we utilize a lockfile this should only | |
41 # happen if someone is attempting to attack us. | |
42 fd = os.open(filename, flags, fmode) | |
43 try: | |
44 return os.fdopen(fd, "wb") | |
45 except: | |
46 # An error occurred wrapping our FD in a file object | |
47 os.close(fd) | |
48 raise | |
49 | |
50 | |
51 class FileCache(BaseCache): | |
52 def __init__(self, directory, forever=False, filemode=0o0600, | |
53 dirmode=0o0700, use_dir_lock=None, lock_class=None): | |
54 | |
55 if use_dir_lock is not None and lock_class is not None: | |
56 raise ValueError("Cannot use use_dir_lock and lock_class together") | |
57 | |
58 if use_dir_lock: | |
59 lock_class = MkdirLockFile | |
60 | |
61 if lock_class is None: | |
62 lock_class = LockFile | |
63 | |
64 self.directory = directory | |
65 self.forever = forever | |
66 self.filemode = filemode | |
67 self.dirmode = dirmode | |
68 self.lock_class = lock_class | |
69 | |
70 | |
71 @staticmethod | |
72 def encode(x): | |
73 return hashlib.sha224(x.encode()).hexdigest() | |
74 | |
75 def _fn(self, name): | |
76 # NOTE: This method should not change as some may depend on it. | |
77 # See: https://github.com/ionrock/cachecontrol/issues/63 | |
78 hashed = self.encode(name) | |
79 parts = list(hashed[:5]) + [hashed] | |
80 return os.path.join(self.directory, *parts) | |
81 | |
82 def get(self, key): | |
83 name = self._fn(key) | |
84 if not os.path.exists(name): | |
85 return None | |
86 | |
87 with open(name, 'rb') as fh: | |
88 return fh.read() | |
89 | |
90 def set(self, key, value): | |
91 name = self._fn(key) | |
92 | |
93 # Make sure the directory exists | |
94 try: | |
95 os.makedirs(os.path.dirname(name), self.dirmode) | |
96 except (IOError, OSError): | |
97 pass | |
98 | |
99 with self.lock_class(name) as lock: | |
100 # Write our actual file | |
101 with _secure_open_write(lock.path, self.filemode) as fh: | |
102 fh.write(value) | |
103 | |
104 def delete(self, key): | |
105 name = self._fn(key) | |
106 if not self.forever: | |
107 os.remove(name) | |
108 | |
109 | |
110 def url_to_file_path(url, filecache): | |
111 """Return the file cache path based on the URL. | |
112 | |
113 This does not ensure the file exists! | |
114 """ | |
115 key = CacheController.cache_url(url) | |
116 return filecache._fn(key) |