aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpukkandan <pukkandan.ytdlp@gmail.com>2022-06-29 06:43:24 +0530
committerpukkandan <pukkandan.ytdlp@gmail.com>2022-06-29 06:43:24 +0530
commitb1f94422cc22886e18e3c3fb8243506eee573e98 (patch)
treedec222b1949fecd41aee7635166a0e3c86e71c41
parentc2c8921b419a4a9b41b99eab9a155245bdd5f7a4 (diff)
downloadhypervideo-pre-b1f94422cc22886e18e3c3fb8243506eee573e98.tar.lz
hypervideo-pre-b1f94422cc22886e18e3c3fb8243506eee573e98.tar.xz
hypervideo-pre-b1f94422cc22886e18e3c3fb8243506eee573e98.zip
[update] Ability to set a maximum version for specific variants
-rw-r--r--.github/workflows/build.yml13
-rw-r--r--yt_dlp/YoutubeDL.py15
-rw-r--r--yt_dlp/update.py40
-rw-r--r--yt_dlp/utils.py43
4 files changed, 81 insertions, 30 deletions
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index ca17a1e59..0c8831927 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -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 }}
diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py
index c6882d0d7..9ebb0b82a 100644
--- a/yt_dlp/YoutubeDL.py
+++ b/yt_dlp/YoutubeDL.py
@@ -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}
diff --git a/yt_dlp/update.py b/yt_dlp/update.py
index c42144337..9589443a7 100644
--- a/yt_dlp/update.py
+++ b/yt_dlp/update.py
@@ -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:
diff --git a/yt_dlp/utils.py b/yt_dlp/utils.py
index 40cefd62e..9c9be5fe5 100644
--- a/yt_dlp/utils.py
+++ b/yt_dlp/utils.py
@@ -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)