[update] Ability to set a maximum version for specific variants

This commit is contained in:
pukkandan 2022-06-29 06:43:24 +05:30
parent c2c8921b41
commit b1f94422cc
No known key found for this signature in database
GPG Key ID: 7EEE9E1E817D0A39
4 changed files with 81 additions and 30 deletions

View File

@ -449,6 +449,19 @@ jobs:
asset_name: SHA2-512SUMS asset_name: SHA2-512SUMS
asset_content_type: text/plain asset_content_type: text/plain
- name: Make Update spec
run: |
echo "# This file is used for regulating self-update" >> _update_spec
- name: Upload update spec
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ needs.create_release.outputs.upload_url }}
asset_path: ./_update_spec
asset_name: _update_spec
asset_content_type: text/plain
- name: Finalize release - name: Finalize release
env: env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@ -10,7 +10,6 @@
import locale import locale
import operator import operator
import os import os
import platform
import random import random
import re import re
import shutil import shutil
@ -110,7 +109,6 @@
number_of_digits, number_of_digits,
orderedSet, orderedSet,
parse_filesize, parse_filesize,
platform_name,
preferredencoding, preferredencoding,
prepend_extension, prepend_extension,
register_socks_protocols, register_socks_protocols,
@ -126,6 +124,7 @@
strftime_or_none, strftime_or_none,
subtitles_filename, subtitles_filename,
supports_terminal_sequences, supports_terminal_sequences,
system_identifier,
timetuple_from_msec, timetuple_from_msec,
to_high_limit_path, to_high_limit_path,
traverse_obj, traverse_obj,
@ -3656,17 +3655,7 @@ def get_encoding(stream):
with contextlib.suppress(Exception): with contextlib.suppress(Exception):
sys.exc_clear() sys.exc_clear()
def python_implementation(): write_debug(system_identifier())
impl_name = platform.python_implementation()
if impl_name == 'PyPy' and hasattr(sys, 'pypy_version_info'):
return impl_name + ' version %d.%d.%d' % sys.pypy_version_info[:3]
return impl_name
write_debug('Python version %s (%s %s) - %s' % (
platform.python_version(),
python_implementation(),
platform.architecture()[0],
platform_name()))
exe_versions, ffmpeg_features = FFmpegPostProcessor.get_versions_and_features(self) exe_versions, ffmpeg_features = FFmpegPostProcessor.get_versions_and_features(self)
ffmpeg_features = {key for key, val in ffmpeg_features.items() if val} ffmpeg_features = {key for key, val in ffmpeg_features.items() if val}

View File

@ -3,17 +3,25 @@
import json import json
import os import os
import platform import platform
import re
import subprocess import subprocess
import sys import sys
from zipimport import zipimporter from zipimport import zipimporter
from .compat import functools # isort: split from .compat import functools # isort: split
from .compat import compat_realpath from .compat import compat_realpath
from .utils import Popen, shell_quote, traverse_obj, version_tuple from .utils import (
Popen,
cached_method,
shell_quote,
system_identifier,
traverse_obj,
version_tuple,
)
from .version import __version__ from .version import __version__
REPOSITORY = 'yt-dlp/yt-dlp' REPOSITORY = 'yt-dlp/yt-dlp'
API_URL = f'https://api.github.com/repos/{REPOSITORY}/releases/latest' API_URL = f'https://api.github.com/repos/{REPOSITORY}/releases'
@functools.cache @functools.cache
@ -79,9 +87,20 @@ def __init__(self, ydl):
self.ydl = ydl self.ydl = ydl
@functools.cached_property @functools.cached_property
def _new_version_info(self): def _tag(self):
self.ydl.write_debug(f'Fetching release info: {API_URL}') identifier = f'{detect_variant()} {system_identifier()}'
return json.loads(self.ydl.urlopen(API_URL).read().decode()) for line in self._download('_update_spec', 'latest').decode().splitlines():
if not line.startswith('lock '):
continue
_, tag, pattern = line.split(' ', 2)
if re.match(pattern, identifier):
return f'tags/{tag}'
return 'latest'
@cached_method
def _get_version_info(self, tag):
self.ydl.write_debug(f'Fetching release info: {API_URL}/{tag}')
return json.loads(self.ydl.urlopen(f'{API_URL}/{tag}').read().decode())
@property @property
def current_version(self): def current_version(self):
@ -91,7 +110,7 @@ def current_version(self):
@property @property
def new_version(self): def new_version(self):
"""Version of the latest release""" """Version of the latest release"""
return self._new_version_info['tag_name'] return self._get_version_info(self._tag)['tag_name']
@property @property
def has_update(self): def has_update(self):
@ -103,9 +122,8 @@ def filename(self):
"""Filename of the executable""" """Filename of the executable"""
return compat_realpath(_get_variant_and_executable_path()[1]) return compat_realpath(_get_variant_and_executable_path()[1])
def _download(self, name=None): def _download(self, name, tag):
name = name or self.release_name url = traverse_obj(self._get_version_info(tag), (
url = traverse_obj(self._new_version_info, (
'assets', lambda _, v: v['name'] == name, 'browser_download_url'), get_all=False) 'assets', lambda _, v: v['name'] == name, 'browser_download_url'), get_all=False)
if not url: if not url:
raise Exception('Unable to find download URL') raise Exception('Unable to find download URL')
@ -123,7 +141,7 @@ def release_name(self):
@functools.cached_property @functools.cached_property
def release_hash(self): def release_hash(self):
"""Hash of the latest release""" """Hash of the latest release"""
hash_data = dict(ln.split()[::-1] for ln in self._download('SHA2-256SUMS').decode().splitlines()) hash_data = dict(ln.split()[::-1] for ln in self._download('SHA2-256SUMS', self._tag).decode().splitlines())
return hash_data[self.release_name] return hash_data[self.release_name]
def _report_error(self, msg, expected=False): def _report_error(self, msg, expected=False):
@ -176,7 +194,7 @@ def update(self):
return self._report_error('Unable to remove the old version') return self._report_error('Unable to remove the old version')
try: try:
newcontent = self._download() newcontent = self._download(self.release_name, self._tag)
except OSError: except OSError:
return self._report_network_error('download latest version') return self._report_network_error('download latest version')
except Exception: except Exception:

View File

@ -18,6 +18,7 @@
import http.client import http.client
import http.cookiejar import http.cookiejar
import importlib.util import importlib.util
import inspect
import io import io
import itertools import itertools
import json import json
@ -1909,12 +1910,23 @@ def __str__(self):
def platform_name(): def platform_name():
""" Returns the platform name as a str """ """ Returns the platform name as a str """
res = platform.platform() write_string('DeprecationWarning: yt_dlp.utils.platform_name is deprecated, use platform.platform instead')
if isinstance(res, bytes): return platform.platform()
res = res.decode(preferredencoding())
assert isinstance(res, str)
return res @functools.cache
def system_identifier():
python_implementation = platform.python_implementation()
if python_implementation == 'PyPy' and hasattr(sys, 'pypy_version_info'):
python_implementation += ' version %d.%d.%d' % sys.pypy_version_info[:3]
return 'Python %s (%s %s) - %s %s' % (
platform.python_version(),
python_implementation,
platform.architecture()[0],
platform.platform(),
format_field(join_nonempty(*platform.libc_ver(), delim=' '), None, '(%s)'),
)
@functools.cache @functools.cache
@ -5544,8 +5556,27 @@ def merge_headers(*dicts):
return {k.title(): v for k, v in itertools.chain.from_iterable(map(dict.items, dicts))} return {k.title(): v for k, v in itertools.chain.from_iterable(map(dict.items, dicts))}
def cached_method(f):
"""Cache a method"""
signature = inspect.signature(f)
@functools.wraps(f)
def wrapper(self, *args, **kwargs):
bound_args = signature.bind(self, *args, **kwargs)
bound_args.apply_defaults()
key = tuple(bound_args.arguments.values())
if not hasattr(self, '__cached_method__cache'):
self.__cached_method__cache = {}
cache = self.__cached_method__cache.setdefault(f.__name__, {})
if key not in cache:
cache[key] = f(self, *args, **kwargs)
return cache[key]
return wrapper
class classproperty: class classproperty:
"""classmethod(property(func)) that works in py < 3.9""" """property access for class methods"""
def __init__(self, func): def __init__(self, func):
functools.update_wrapper(self, func) functools.update_wrapper(self, func)