+import atexit
import hashlib
import json
import os
from .compat import functools # isort: split
from .compat import compat_realpath
-from .utils import Popen, traverse_obj, version_tuple
+from .utils import Popen, shell_quote, traverse_obj, version_tuple
from .version import __version__
REPOSITORY = 'yt-dlp/yt-dlp'
'py2exe': '_min.exe',
'win32_exe': '.exe',
'darwin_exe': '_macos',
+ 'linux_exe': '_linux',
}
_NON_UPDATEABLE_REASONS = {
**{variant: None for variant in _FILE_SUFFIXES}, # Updatable
**{variant: f'Auto-update is not supported for unpackaged {name} executable; Re-download the latest release'
- for variant, name in {'win32_dir': 'Windows', 'darwin_dir': 'MacOS'}.items()},
+ for variant, name in {'win32_dir': 'Windows', 'darwin_dir': 'MacOS', 'linux_dir': 'Linux'}.items()},
'source': 'You cannot update when running from source code; Use git to pull the latest changes',
'unknown': 'It looks like you installed yt-dlp with a package manager, pip or setup.py; Use that to update',
'other': 'It looks like you are using an unofficial build of yt-dlp; Build the executable again',
if detect_variant() not in ('win32_exe', 'py2exe'):
if old_filename:
os.remove(old_filename)
- self.ydl.to_screen(f'Updated yt-dlp to version {self.new_version}; Restart yt-dlp to use the new version')
- return
+ else:
+ atexit.register(Popen, f'ping 127.0.0.1 -n 5 -w 1000 & del /F "{old_filename}"',
+ shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
- try:
- # Continues to run in the background
- Popen(f'ping 127.0.0.1 -n 5 -w 1000 & del /F "{old_filename}"',
- shell=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
- self.ydl.to_screen(f'Updated yt-dlp to version {self.new_version}')
- return True # Exit app
- except OSError:
- self._report_unable('delete the old version')
+ self.ydl.to_screen(f'Updated yt-dlp to version {self.new_version}')
+ return True
+
+ @functools.cached_property
+ def cmd(self):
+ """The command-line to run the executable, if known"""
+ # There is no sys.orig_argv in py < 3.10. Also, it can be [] when frozen
+ if getattr(sys, 'orig_argv', None):
+ return sys.orig_argv
+ elif hasattr(sys, 'frozen'):
+ return sys.argv
+
+ def restart(self):
+ """Restart the executable"""
+ assert self.cmd, 'Must be frozen or Py >= 3.10'
+ self.ydl.write_debug(f'Restarting: {shell_quote(self.cmd)}')
+ _, _, returncode = Popen.run(self.cmd)
+ return returncode
def run_update(ydl):