9 from .utils
import expand_path
, traverse_obj
, version_tuple
, write_json_file
10 from .version
import __version__
14 def __init__(self
, ydl
):
17 def _get_root_dir(self
):
18 res
= self
._ydl
.params
.get('cachedir')
20 cache_root
= os
.getenv('XDG_CACHE_HOME', '~/.cache')
21 res
= os
.path
.join(cache_root
, 'yt-dlp')
22 return expand_path(res
)
24 def _get_cache_fn(self
, section
, key
, dtype
):
25 assert re
.match(r
'^[\w.-]+$', section
), f
'invalid section {section!r}'
26 key
= urllib
.parse
.quote(key
, safe
='').replace('%', ',') # encode non-ascii characters
27 return os
.path
.join(self
._get
_root
_dir
(), section
, f
'{key}.{dtype}')
31 return self
._ydl
.params
.get('cachedir') is not False
33 def store(self
, section
, key
, data
, dtype
='json'):
34 assert dtype
in ('json',)
39 fn
= self
._get
_cache
_fn
(section
, key
, dtype
)
41 os
.makedirs(os
.path
.dirname(fn
), exist_ok
=True)
42 self
._ydl
.write_debug(f
'Saving {section}.{key} to cache')
43 write_json_file({'yt-dlp_version': __version__
, 'data': data
}, fn
)
45 tb
= traceback
.format_exc()
46 self
._ydl
.report_warning(f
'Writing cache to {fn!r} failed: {tb}')
48 def _validate(self
, data
, min_ver
):
49 version
= traverse_obj(data
, 'yt-dlp_version')
50 if not version
: # Backward compatibility
51 data
, version
= {'data': data
}, '2022.08.19'
52 if not min_ver
or version_tuple(version
) >= version_tuple(min_ver
):
54 self
._ydl
.write_debug(f
'Discarding old cache from version {version} (needs {min_ver})')
56 def load(self
, section
, key
, dtype
='json', default
=None, *, min_ver
=None):
57 assert dtype
in ('json',)
62 cache_fn
= self
._get
_cache
_fn
(section
, key
, dtype
)
63 with contextlib
.suppress(OSError):
65 with
open(cache_fn
, encoding
='utf-8') as cachef
:
66 self
._ydl
.write_debug(f
'Loading {section}.{key} from cache')
67 return self
._validate
(json
.load(cachef
), min_ver
)
68 except (ValueError, KeyError):
70 file_size
= os
.path
.getsize(cache_fn
)
73 self
._ydl
.report_warning(f
'Cache retrieval from {cache_fn} failed ({file_size})')
79 self
._ydl
.to_screen('Cache is disabled (Did you combine --no-cache-dir and --rm-cache-dir?)')
82 cachedir
= self
._get
_root
_dir
()
83 if not any((term
in cachedir
) for term
in ('cache', 'tmp')):
84 raise Exception(f
'Not removing directory {cachedir} - this does not look like a cache dir')
87 f
'Removing cache dir {cachedir} .', skip_eol
=True)
88 if os
.path
.exists(cachedir
):
89 self
._ydl
.to_screen('.', skip_eol
=True)
90 shutil
.rmtree(cachedir
)
91 self
._ydl
.to_screen('.')