diff --git a/README.md b/README.md index 12f68e98d8..5083341408 100644 --- a/README.md +++ b/README.md @@ -171,6 +171,9 @@ # To install nightly with pip: python3 -m pip install -U --pre "yt-dlp[default]" ``` +When running a yt-dlp version that is older than 90 days, you will see a warning message suggesting to update to the latest version. +You can suppress this warning by adding `--no-update` to your command or configuration file. + ## DEPENDENCIES Python versions 3.9+ (CPython) and 3.11+ (PyPy) are supported. Other versions and implementations may or may not work correctly. diff --git a/devscripts/cli_to_api.py b/devscripts/cli_to_api.py index 9c2710e09f..cc86b413f4 100755 --- a/devscripts/cli_to_api.py +++ b/devscripts/cli_to_api.py @@ -20,6 +20,7 @@ def parse_patched_options(opts): 'fragment_retries': 0, 'extract_flat': False, 'concat_playlist': 'never', + 'update_self': False, }) yt_dlp.options.create_parser = lambda: patched_parser try: diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py index a9f347bf4a..5985d2ec76 100644 --- a/yt_dlp/YoutubeDL.py +++ b/yt_dlp/YoutubeDL.py @@ -73,6 +73,7 @@ from .update import ( REPOSITORY, _get_system_deprecation, + _get_outdated_warning, _make_label, current_git_head, detect_variant, @@ -504,6 +505,7 @@ class YoutubeDL: force_keyframes_at_cuts: Re-encode the video when downloading ranges to get precise cuts noprogress: Do not print the progress bar live_from_start: Whether to download livestreams videos from the start + warn_when_outdated: Emit a warning if the yt-dlp version is older than 90 days The following parameters are not used by YoutubeDL itself, they are used by the downloader (see yt_dlp/downloader/common.py): @@ -703,6 +705,9 @@ def process_color_policy(stream): system_deprecation = _get_system_deprecation() if system_deprecation: self.deprecated_feature(system_deprecation.replace('\n', '\n ')) + elif self.params.get('warn_when_outdated'): + if outdated_warning := _get_outdated_warning(): + self.report_warning(outdated_warning) if self.params.get('allow_unplayable_formats'): self.report_warning( diff --git a/yt_dlp/__init__.py b/yt_dlp/__init__.py index 2e7646b7ec..f705bed1bf 100644 --- a/yt_dlp/__init__.py +++ b/yt_dlp/__init__.py @@ -971,6 +971,7 @@ def parse_options(argv=None): 'geo_bypass': opts.geo_bypass, 'geo_bypass_country': opts.geo_bypass_country, 'geo_bypass_ip_block': opts.geo_bypass_ip_block, + 'warn_when_outdated': opts.update_self is None, '_warnings': warnings, '_deprecation_warnings': deprecation_warnings, 'compat_opts': opts.compat_opts, diff --git a/yt_dlp/update.py b/yt_dlp/update.py index 30cbf538e9..045f7ec7f3 100644 --- a/yt_dlp/update.py +++ b/yt_dlp/update.py @@ -2,6 +2,7 @@ import atexit import contextlib +import datetime as dt import functools import hashlib import json @@ -171,6 +172,22 @@ def _get_system_deprecation(): return f'Support for Python version {major}.{minor} has been deprecated. {PYTHON_MSG}' +def _get_outdated_warning(): + # Only yt-dlp guarantees a stable release at least every 90 days + if not ORIGIN.startswith('yt-dlp/'): + return None + + with contextlib.suppress(Exception): + last_updated = dt.date(*version_tuple(__version__)[:3]) + if last_updated < dt.datetime.now(dt.timezone.utc).date() - dt.timedelta(days=90): + return ('\n '.join(( + f'Your yt-dlp version ({__version__}) is older than 90 days!', + 'It is strongly recommended to always use the latest version.', + f'{is_non_updateable() or """Run "yt-dlp --update" or "yt-dlp -U" to update"""}.', + 'To suppress this warning, add --no-update to your command/config.'))) + return None + + def _sha256_file(path): h = hashlib.sha256() mv = memoryview(bytearray(128 * 1024))