Improve build/updater

* Fix `get_executable_path` in UNIX
* Update `x86.exe` correctly
* Exit immediately in windows once the update process starts so that the file handle is released correctly
* Show `exe`/`zip`/`source` and 32/64bit in verbose message
* Look for both `yt-dlp` and `youtube-dlc` in releases. This ensures that the updater will keep working when the binary name is changed to yt-dlp
* Disable pycryptodome in win_x86 since it causes `distutils.errors.DistutilsPlatformError: Microsoft Visual C++ 10.0 is required`
This commit is contained in:
pukkandan 2021-02-14 22:40:54 +05:30
parent 273762c8d0
commit e5813e53f0
6 changed files with 52 additions and 29 deletions

View file

@ -122,7 +122,7 @@ jobs:
python-version: '3.4.4'
architecture: 'x86'
- name: Install Requirements for 32 Bit
run: pip install pyinstaller==3.5 mutagen pycryptodome
run: pip install pyinstaller==3.5 mutagen Crypto
- name: Bump version
id: bump_version
run: python devscripts/update-version.py

View file

@ -72,7 +72,7 @@ PyInstaller.__main__.run([
'--exclude-module=test',
'--exclude-module=ytdlp_plugins',
'--hidden-import=mutagen',
'--hidden-import=pycryptodome',
'--hidden-import=%s' % ('Crypto' if _x86 else 'pycryptodome'),
'youtube_dlc/__main__.py',
])
SetVersion('dist/youtube-dlc%s.exe' % _x86, VERSION_FILE)

View file

@ -27,6 +27,7 @@ import traceback
import random
from string import ascii_letters
from zipimport import zipimporter
from .compat import (
compat_basestring,
@ -2770,7 +2771,12 @@ class YoutubeDL(object):
self.get_encoding()))
write_string(encoding_str, encoding=None)
self._write_string('[debug] yt-dlp version %s\n' % __version__)
source = (
'(exe)' if hasattr(sys, 'frozen')
else '(zip)' if isinstance(globals().get('__loader__'), zipimporter)
else '(source)' if os.path.basename(sys.argv[0]) == '__main__.py'
else '')
self._write_string('[debug] yt-dlp version %s %s\n' % (__version__, source))
if _LAZY_LOADER:
self._write_string('[debug] Lazy loading extractors enabled\n')
if _PLUGIN_CLASSES:
@ -2797,8 +2803,10 @@ class YoutubeDL(object):
return impl_name + ' version %d.%d.%d' % sys.pypy_version_info[:3]
return impl_name
self._write_string('[debug] Python version %s (%s) - %s\n' % (
platform.python_version(), python_implementation(),
self._write_string('[debug] Python version %s (%s %s) - %s\n' % (
platform.python_version(),
python_implementation(),
platform.architecture()[0],
platform_name()))
exe_versions = FFmpegPostProcessor.get_versions(self)

View file

@ -549,16 +549,22 @@ def _real_main(argv=None):
}
with YoutubeDL(ydl_opts) as ydl:
# Update version
if opts.update_self:
update_self(ydl.to_screen, opts.verbose, ydl._opener)
actual_use = len(all_urls) or opts.load_info_filename
# Remove cache dir
if opts.rm_cachedir:
ydl.cache.remove()
# Update version
if opts.update_self:
# If updater returns True, exit. Required for windows
if update_self(ydl.to_screen, opts.verbose, ydl._opener):
if actual_use:
parser.error('The program must exit for the update to complete')
sys.exit()
# Maybe do nothing
if (len(all_urls) < 1) and (opts.load_info_filename is None):
if not actual_use:
if opts.update_self or opts.rm_cachedir:
sys.exit()

View file

@ -5,6 +5,7 @@ import json
import traceback
import hashlib
import os
import platform
import subprocess
import sys
from zipimport import zipimporter
@ -32,7 +33,10 @@ def rsa_verify(message, signature, key):
def update_self(to_screen, verbose, opener):
"""Update the program file with the latest version from the repository"""
"""
Update the program file with the latest version from the repository
Returns whether the program should terminate
"""
JSON_URL = 'https://api.github.com/repos/pukkandan/yt-dlp/releases/latest'
@ -48,7 +52,7 @@ def update_self(to_screen, verbose, opener):
to_screen('Current Build Hash %s' % sha256sum())
if not isinstance(globals().get('__loader__'), zipimporter) and not hasattr(sys, 'frozen'):
to_screen('It looks like you installed youtube-dlc with a package manager, pip, setup.py or a tarball. Please use that to update.')
to_screen('It looks like you installed yt-dlp with a package manager, pip, setup.py or a tarball. Please use that to update.')
return
# Download and check versions info
@ -62,25 +66,28 @@ def update_self(to_screen, verbose, opener):
to_screen('Visit https://github.com/pukkandan/yt-dlp/releases/latest')
return
version_id = version_info['tag_name']
if version_id == __version__:
to_screen('youtube-dlc is up-to-date (' + __version__ + ')')
return
def version_tuple(version_str):
return tuple(map(int, version_str.split('.')))
version_id = version_info['tag_name']
if version_tuple(__version__) >= version_tuple(version_id):
to_screen('youtube-dlc is up to date (%s)' % __version__)
to_screen('yt-dlp is up to date (%s)' % __version__)
return
to_screen('Updating to version ' + version_id + ' ...')
version = {
'bin': next(i for i in version_info['assets'] if i['name'] == 'youtube-dlc'),
'exe': next(i for i in version_info['assets'] if i['name'] == 'youtube-dlc.exe'),
'exe_x86': next(i for i in version_info['assets'] if i['name'] == 'youtube-dlc_x86.exe'),
}
def get_bin_info(bin_or_exe, version):
labels = {
'zip_3': '',
'zip_2': '',
# 'zip_2': '_py2',
'exe_64': '.exe',
'exe_32': '_x86.exe',
}
label = labels['%s_%s' % (bin_or_exe, version)]
return next(
i for i in version_info['assets']
if i['name'] in ('yt-dlp%s' % label, 'youtube-dlc%s' % label))
# sys.executable is set to the full pathname of the exe-file for py2exe
# though symlinks are not followed so that we need to do this manually
@ -100,10 +107,11 @@ def update_self(to_screen, verbose, opener):
return
try:
urlh = opener.open(version['exe']['browser_download_url'])
arch = platform.architecture()[0][:2]
urlh = opener.open(get_bin_info('exe', arch)['browser_download_url'])
newcontent = urlh.read()
urlh.close()
except (IOError, OSError):
except (IOError, OSError, StopIteration):
if verbose:
to_screen(encode_compat_str(traceback.format_exc()))
to_screen('ERROR: unable to download latest version')
@ -127,7 +135,7 @@ def update_self(to_screen, verbose, opener):
echo.Waiting for file handle to be closed ...
ping 127.0.0.1 -n 5 -w 1000 > NUL
move /Y "%s.new" "%s" > NUL
echo.Updated youtube-dlc to version %s.
echo.Updated yt-dlp to version %s.
)
@start /b "" cmd /c del "%%~f0"&exit /b
''' % (exe, exe, version_id))
@ -143,10 +151,11 @@ def update_self(to_screen, verbose, opener):
# Zip unix package
elif isinstance(globals().get('__loader__'), zipimporter):
try:
urlh = opener.open(version['bin']['browser_download_url'])
py_ver = platform.python_version()[0]
urlh = opener.open(get_bin_info('zip', py_ver)['browser_download_url'])
newcontent = urlh.read()
urlh.close()
except (IOError, OSError):
except (IOError, OSError, StopIteration):
if verbose:
to_screen(encode_compat_str(traceback.format_exc()))
to_screen('ERROR: unable to download latest version')
@ -162,7 +171,7 @@ def update_self(to_screen, verbose, opener):
to_screen('ERROR: unable to overwrite current version')
return
to_screen('Updated youtube-dlc. Restart youtube-dlc to use the new version.')
to_screen('Updated yt-dlp. Restart youtube-dlc to use the new version.')
''' # UNUSED

View file

@ -5936,7 +5936,7 @@ def make_dir(path, to_screen=None):
def get_executable_path():
path = os.path.dirname(sys.argv[0])
if os.path.abspath(sys.argv[0]) != os.path.abspath(sys.executable): # Not packaged
if os.path.basename(sys.argv[0]) == '__main__': # Running from source
path = os.path.join(path, '..')
return os.path.abspath(path)