File-system result backend. Arguments: url (str): URL to the directory we should use open (Callable): open function to use when opening files unlink (Callable): unlink function to use when deleting files sep (str): directory separator (to join the directory with
| 23 | |
| 24 | |
| 25 | class FilesystemBackend(KeyValueStoreBackend): |
| 26 | """File-system result backend. |
| 27 | |
| 28 | Arguments: |
| 29 | url (str): URL to the directory we should use |
| 30 | open (Callable): open function to use when opening files |
| 31 | unlink (Callable): unlink function to use when deleting files |
| 32 | sep (str): directory separator (to join the directory with the key) |
| 33 | encoding (str): encoding used on the file-system |
| 34 | """ |
| 35 | |
| 36 | def __init__(self, url=None, open=open, unlink=os.unlink, sep=os.sep, |
| 37 | encoding=default_encoding, *args, **kwargs): |
| 38 | super().__init__(*args, **kwargs) |
| 39 | self.url = url |
| 40 | path = self._find_path(url) |
| 41 | |
| 42 | # Remove forwarding "/" for Windows os |
| 43 | if os.name == "nt" and path.startswith("/"): |
| 44 | path = path[1:] |
| 45 | |
| 46 | # We need the path and separator as bytes objects |
| 47 | self.path = path.encode(encoding) |
| 48 | self.sep = sep.encode(encoding) |
| 49 | |
| 50 | self.open = open |
| 51 | self.unlink = unlink |
| 52 | |
| 53 | # Let's verify that we've everything setup right |
| 54 | self._do_directory_test(b'.fs-backend-' + uuid().encode(encoding)) |
| 55 | |
| 56 | def __reduce__(self, args=(), kwargs=None): |
| 57 | kwargs = {} if not kwargs else kwargs |
| 58 | return super().__reduce__(args, {**kwargs, 'url': self.url}) |
| 59 | |
| 60 | def _find_path(self, url): |
| 61 | if not url: |
| 62 | raise ImproperlyConfigured(E_NO_PATH_SET) |
| 63 | if url.startswith('file://localhost/'): |
| 64 | return url[16:] |
| 65 | if url.startswith('file://'): |
| 66 | return url[7:] |
| 67 | raise ImproperlyConfigured(E_PATH_NON_CONFORMING_SCHEME) |
| 68 | |
| 69 | def _do_directory_test(self, key): |
| 70 | try: |
| 71 | self.set(key, b'test value') |
| 72 | assert self.get(key) == b'test value' |
| 73 | self.delete(key) |
| 74 | except OSError: |
| 75 | raise ImproperlyConfigured(E_PATH_INVALID) |
| 76 | |
| 77 | def _filename(self, key): |
| 78 | return self.sep.join((self.path, key)) |
| 79 | |
| 80 | def get(self, key): |
| 81 | try: |
| 82 | with self.open(self._filename(key), 'rb') as infile: |
no outgoing calls