]>
Commit | Line | Data |
---|---|---|
a0e07d31 PH |
1 | from __future__ import unicode_literals |
2 | ||
3 | import errno | |
4 | import io | |
5 | import json | |
6 | import os | |
7 | import re | |
8 | import shutil | |
9 | import traceback | |
10 | ||
590bc6f6 S |
11 | from .compat import compat_getenv |
12 | from .utils import ( | |
13 | expand_path, | |
14 | write_json_file, | |
15 | ) | |
a0e07d31 PH |
16 | |
17 | ||
18 | class Cache(object): | |
19 | def __init__(self, ydl): | |
20 | self._ydl = ydl | |
21 | ||
22 | def _get_root_dir(self): | |
23 | res = self._ydl.params.get('cachedir') | |
24 | if res is None: | |
92120217 | 25 | cache_root = compat_getenv('XDG_CACHE_HOME', '~/.cache') |
a0e07d31 | 26 | res = os.path.join(cache_root, 'youtube-dl') |
590bc6f6 | 27 | return expand_path(res) |
a0e07d31 PH |
28 | |
29 | def _get_cache_fn(self, section, key, dtype): | |
674c869a PH |
30 | assert re.match(r'^[a-zA-Z0-9_.-]+$', section), \ |
31 | 'invalid section %r' % section | |
32 | assert re.match(r'^[a-zA-Z0-9_.-]+$', key), 'invalid key %r' % key | |
a0e07d31 PH |
33 | return os.path.join( |
34 | self._get_root_dir(), section, '%s.%s' % (key, dtype)) | |
35 | ||
36 | @property | |
37 | def enabled(self): | |
38 | return self._ydl.params.get('cachedir') is not False | |
39 | ||
40 | def store(self, section, key, data, dtype='json'): | |
41 | assert dtype in ('json',) | |
42 | ||
43 | if not self.enabled: | |
44 | return | |
45 | ||
46 | fn = self._get_cache_fn(section, key, dtype) | |
47 | try: | |
48 | try: | |
49 | os.makedirs(os.path.dirname(fn)) | |
50 | except OSError as ose: | |
51 | if ose.errno != errno.EEXIST: | |
52 | raise | |
53 | write_json_file(data, fn) | |
54 | except Exception: | |
55 | tb = traceback.format_exc() | |
56 | self._ydl.report_warning( | |
57 | 'Writing cache to %r failed: %s' % (fn, tb)) | |
58 | ||
59 | def load(self, section, key, dtype='json', default=None): | |
60 | assert dtype in ('json',) | |
61 | ||
62 | if not self.enabled: | |
63 | return default | |
64 | ||
65 | cache_fn = self._get_cache_fn(section, key, dtype) | |
66 | try: | |
67 | try: | |
68 | with io.open(cache_fn, 'r', encoding='utf-8') as cachef: | |
69 | return json.load(cachef) | |
70 | except ValueError: | |
71 | try: | |
72 | file_size = os.path.getsize(cache_fn) | |
73 | except (OSError, IOError) as oe: | |
74 | file_size = str(oe) | |
75 | self._ydl.report_warning( | |
76 | 'Cache retrieval from %s failed (%s)' % (cache_fn, file_size)) | |
77 | except IOError: | |
78 | pass # No cache available | |
79 | ||
80 | return default | |
81 | ||
82 | def remove(self): | |
83 | if not self.enabled: | |
84 | self._ydl.to_screen('Cache is disabled (Did you combine --no-cache-dir and --rm-cache-dir?)') | |
85 | return | |
86 | ||
87 | cachedir = self._get_root_dir() | |
88 | if not any((term in cachedir) for term in ('cache', 'tmp')): | |
89 | raise Exception('Not removing directory %s - this does not look like a cache dir' % cachedir) | |
90 | ||
91 | self._ydl.to_screen( | |
92 | 'Removing cache dir %s .' % cachedir, skip_eol=True) | |
93 | if os.path.exists(cachedir): | |
94 | self._ydl.to_screen('.', skip_eol=True) | |
95 | shutil.rmtree(cachedir) | |
96 | self._ydl.to_screen('.') |