[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_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
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View file

@ -10,7 +10,6 @@ import json
import locale
import operator
import os
import platform
import random
import re
import shutil
@ -110,7 +109,6 @@ from .utils import (
number_of_digits,
orderedSet,
parse_filesize,
platform_name,
preferredencoding,
prepend_extension,
register_socks_protocols,
@ -126,6 +124,7 @@ from .utils import (
strftime_or_none,
subtitles_filename,
supports_terminal_sequences,
system_identifier,
timetuple_from_msec,
to_high_limit_path,
traverse_obj,
@ -3656,17 +3655,7 @@ class YoutubeDL:
with contextlib.suppress(Exception):
sys.exc_clear()
def python_implementation():
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()))
write_debug(system_identifier())
exe_versions, ffmpeg_features = FFmpegPostProcessor.get_versions_and_features(self)
ffmpeg_features = {key for key, val in ffmpeg_features.items() if val}

View file

@ -3,17 +3,25 @@ import hashlib
import json
import os
import platform
import re
import subprocess
import sys
from zipimport import zipimporter
from .compat import functools # isort: split
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__
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
@ -79,9 +87,20 @@ class Updater:
self.ydl = ydl
@functools.cached_property
def _new_version_info(self):
self.ydl.write_debug(f'Fetching release info: {API_URL}')
return json.loads(self.ydl.urlopen(API_URL).read().decode())
def _tag(self):
identifier = f'{detect_variant()} {system_identifier()}'
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
def current_version(self):
@ -91,7 +110,7 @@ class Updater:
@property
def new_version(self):
"""Version of the latest release"""
return self._new_version_info['tag_name']
return self._get_version_info(self._tag)['tag_name']
@property
def has_update(self):
@ -103,9 +122,8 @@ class Updater:
"""Filename of the executable"""
return compat_realpath(_get_variant_and_executable_path()[1])
def _download(self, name=None):
name = name or self.release_name
url = traverse_obj(self._new_version_info, (
def _download(self, name, tag):
url = traverse_obj(self._get_version_info(tag), (
'assets', lambda _, v: v['name'] == name, 'browser_download_url'), get_all=False)
if not url:
raise Exception('Unable to find download URL')
@ -123,7 +141,7 @@ class Updater:
@functools.cached_property
def release_hash(self):
"""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]
def _report_error(self, msg, expected=False):
@ -176,7 +194,7 @@ class Updater:
return self._report_error('Unable to remove the old version')
try:
newcontent = self._download()
newcontent = self._download(self.release_name, self._tag)
except OSError:
return self._report_network_error('download latest version')
except Exception:

View file

@ -18,6 +18,7 @@ import html.parser
import http.client
import http.cookiejar
import importlib.util
import inspect
import io
import itertools
import json
@ -1909,12 +1910,23 @@ class DateRange:
def platform_name():
""" Returns the platform name as a str """
res = platform.platform()
if isinstance(res, bytes):
res = res.decode(preferredencoding())
write_string('DeprecationWarning: yt_dlp.utils.platform_name is deprecated, use platform.platform instead')
return platform.platform()
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
@ -5544,8 +5556,27 @@ def merge_headers(*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:
"""classmethod(property(func)) that works in py < 3.9"""
"""property access for class methods"""
def __init__(self, func):
functools.update_wrapper(self, func)