mirror of
https://github.com/yt-dlp/yt-dlp.git
synced 2024-11-15 05:33:05 +00:00
Compare commits
3 Commits
69b59b4b4b
...
059bc4db19
Author | SHA1 | Date | |
---|---|---|---|
|
059bc4db19 | ||
|
9196cbfe8b | ||
|
9cd080508d |
2
Makefile
2
Makefile
@ -66,7 +66,7 @@ offlinetest: codetest
|
|||||||
|
|
||||||
# XXX: This is hard to maintain
|
# XXX: This is hard to maintain
|
||||||
CODE_FOLDERS = yt_dlp yt_dlp/downloader yt_dlp/extractor yt_dlp/postprocessor yt_dlp/compat \
|
CODE_FOLDERS = yt_dlp yt_dlp/downloader yt_dlp/extractor yt_dlp/postprocessor yt_dlp/compat \
|
||||||
yt_dlp/compat/asyncio yt_dlp/extractor/anvato_token_generator
|
yt_dlp/extractor/anvato_token_generator
|
||||||
yt-dlp: yt_dlp/*.py yt_dlp/*/*.py
|
yt-dlp: yt_dlp/*.py yt_dlp/*/*.py
|
||||||
mkdir -p zip
|
mkdir -p zip
|
||||||
for d in $(CODE_FOLDERS) ; do \
|
for d in $(CODE_FOLDERS) ; do \
|
||||||
|
@ -7,6 +7,7 @@ import unittest
|
|||||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||||
|
|
||||||
|
|
||||||
|
from yt_dlp import compat
|
||||||
from yt_dlp.compat import (
|
from yt_dlp.compat import (
|
||||||
compat_etree_fromstring,
|
compat_etree_fromstring,
|
||||||
compat_expanduser,
|
compat_expanduser,
|
||||||
@ -21,6 +22,12 @@ from yt_dlp.compat import (
|
|||||||
|
|
||||||
|
|
||||||
class TestCompat(unittest.TestCase):
|
class TestCompat(unittest.TestCase):
|
||||||
|
def test_compat_passthrough(self):
|
||||||
|
with self.assertWarns(DeprecationWarning):
|
||||||
|
compat.compat_basestring
|
||||||
|
|
||||||
|
compat.asyncio.events # Must not raise error
|
||||||
|
|
||||||
def test_compat_getenv(self):
|
def test_compat_getenv(self):
|
||||||
test_str = 'тест'
|
test_str = 'тест'
|
||||||
compat_setenv('yt_dlp_COMPAT_GETENV', test_str)
|
compat_setenv('yt_dlp_COMPAT_GETENV', test_str)
|
||||||
|
@ -2,11 +2,18 @@ import contextlib
|
|||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import types
|
import warnings
|
||||||
import xml.etree.ElementTree as etree
|
import xml.etree.ElementTree as etree
|
||||||
|
|
||||||
from . import re
|
from . import re
|
||||||
from ._deprecated import * # noqa: F401, F403
|
from ._deprecated import * # noqa: F401, F403
|
||||||
|
from .compat_utils import passthrough_module
|
||||||
|
|
||||||
|
|
||||||
|
# XXX: Implement this the same way as other DeprecationWarnings without circular import
|
||||||
|
passthrough_module(__name__, '._legacy', callback=lambda attr: warnings.warn(
|
||||||
|
DeprecationWarning(f'{__name__}.{attr} is deprecated'), stacklevel=2))
|
||||||
|
del passthrough_module
|
||||||
|
|
||||||
|
|
||||||
# HTMLParseError has been deprecated in Python 3.3 and removed in
|
# HTMLParseError has been deprecated in Python 3.3 and removed in
|
||||||
@ -85,24 +92,3 @@ def windows_enable_vt_mode(): # TODO: Do this the proper way https://bugs.pytho
|
|||||||
with contextlib.suppress(Exception):
|
with contextlib.suppress(Exception):
|
||||||
subprocess.Popen('', shell=True, startupinfo=startupinfo).wait()
|
subprocess.Popen('', shell=True, startupinfo=startupinfo).wait()
|
||||||
WINDOWS_VT_MODE = True
|
WINDOWS_VT_MODE = True
|
||||||
|
|
||||||
|
|
||||||
class _PassthroughLegacy(types.ModuleType):
|
|
||||||
def __getattr__(self, attr):
|
|
||||||
import importlib
|
|
||||||
with contextlib.suppress(ImportError):
|
|
||||||
return importlib.import_module(f'.{attr}', __name__)
|
|
||||||
|
|
||||||
legacy = importlib.import_module('._legacy', __name__)
|
|
||||||
if not hasattr(legacy, attr):
|
|
||||||
raise AttributeError(f'module {__name__} has no attribute {attr}')
|
|
||||||
|
|
||||||
# XXX: Implement this the same way as other DeprecationWarnings without circular import
|
|
||||||
import warnings
|
|
||||||
warnings.warn(DeprecationWarning(f'{__name__}.{attr} is deprecated'), stacklevel=2)
|
|
||||||
return getattr(legacy, attr)
|
|
||||||
|
|
||||||
|
|
||||||
# Python 3.6 does not have module level __getattr__
|
|
||||||
# https://peps.python.org/pep-0562/
|
|
||||||
sys.modules[__name__].__class__ = _PassthroughLegacy
|
|
||||||
|
@ -2,7 +2,10 @@
|
|||||||
|
|
||||||
from asyncio import * # noqa: F403
|
from asyncio import * # noqa: F403
|
||||||
|
|
||||||
from . import tasks # noqa: F401
|
from .compat_utils import passthrough_module
|
||||||
|
|
||||||
|
passthrough_module(__name__, 'asyncio')
|
||||||
|
del passthrough_module
|
||||||
|
|
||||||
try:
|
try:
|
||||||
run # >= 3.7
|
run # >= 3.7
|
||||||
@ -14,3 +17,8 @@ except NameError:
|
|||||||
loop = new_event_loop()
|
loop = new_event_loop()
|
||||||
set_event_loop(loop)
|
set_event_loop(loop)
|
||||||
loop.run_until_complete(coro)
|
loop.run_until_complete(coro)
|
||||||
|
|
||||||
|
try:
|
||||||
|
all_tasks # >= 3.7
|
||||||
|
except NameError:
|
||||||
|
all_tasks = Task.all_tasks
|
@ -1,8 +0,0 @@
|
|||||||
# flake8: noqa: F405
|
|
||||||
|
|
||||||
from asyncio.tasks import * # noqa: F403
|
|
||||||
|
|
||||||
try: # >= 3.7
|
|
||||||
all_tasks
|
|
||||||
except NameError:
|
|
||||||
all_tasks = Task.all_tasks
|
|
44
yt_dlp/compat/compat_utils.py
Normal file
44
yt_dlp/compat/compat_utils.py
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
import contextlib
|
||||||
|
import importlib
|
||||||
|
import sys
|
||||||
|
import types
|
||||||
|
|
||||||
|
|
||||||
|
def _is_package(module):
|
||||||
|
try:
|
||||||
|
module.__getattribute__('__path__')
|
||||||
|
except AttributeError:
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
_NO_ATTRIBUTE = object()
|
||||||
|
|
||||||
|
|
||||||
|
def passthrough_module(parent, child, *, callback=lambda _: None):
|
||||||
|
parent_module = importlib.import_module(parent)
|
||||||
|
child_module = importlib.import_module(child, parent)
|
||||||
|
|
||||||
|
class PassthroughModule(types.ModuleType):
|
||||||
|
def __getattr__(self, attr):
|
||||||
|
if _is_package(parent_module):
|
||||||
|
with contextlib.suppress(ImportError):
|
||||||
|
return importlib.import_module(f'.{attr}', parent)
|
||||||
|
|
||||||
|
ret = _NO_ATTRIBUTE
|
||||||
|
with contextlib.suppress(AttributeError):
|
||||||
|
ret = getattr(child_module, attr)
|
||||||
|
|
||||||
|
if _is_package(child_module):
|
||||||
|
with contextlib.suppress(ImportError):
|
||||||
|
ret = importlib.import_module(f'.{attr}', child)
|
||||||
|
|
||||||
|
if ret is _NO_ATTRIBUTE:
|
||||||
|
raise AttributeError(f'module {parent} has no attribute {attr}')
|
||||||
|
|
||||||
|
callback(attr)
|
||||||
|
return ret
|
||||||
|
|
||||||
|
# Python 3.6 does not have module level __getattr__
|
||||||
|
# https://peps.python.org/pep-0562/
|
||||||
|
sys.modules[parent].__class__ = PassthroughModule
|
@ -2,6 +2,11 @@
|
|||||||
|
|
||||||
from re import * # F403
|
from re import * # F403
|
||||||
|
|
||||||
|
from .compat_utils import passthrough_module
|
||||||
|
|
||||||
|
passthrough_module(__name__, 're')
|
||||||
|
del passthrough_module
|
||||||
|
|
||||||
try:
|
try:
|
||||||
Pattern # >= 3.7
|
Pattern # >= 3.7
|
||||||
except NameError:
|
except NameError:
|
||||||
|
@ -36,7 +36,6 @@ import tempfile
|
|||||||
import time
|
import time
|
||||||
import traceback
|
import traceback
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import warnings
|
|
||||||
import xml.etree.ElementTree
|
import xml.etree.ElementTree
|
||||||
import zlib
|
import zlib
|
||||||
|
|
||||||
@ -5223,10 +5222,7 @@ class WebSocketsWrapper():
|
|||||||
|
|
||||||
def __init__(self, url, headers=None, connect=True):
|
def __init__(self, url, headers=None, connect=True):
|
||||||
self.loop = asyncio.new_event_loop()
|
self.loop = asyncio.new_event_loop()
|
||||||
with warnings.catch_warnings():
|
# XXX: "loop" is deprecated
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
# https://github.com/aaugustin/websockets/blob/9c87d43f1d7bbf6847350087aae74fd35f73a642/src/websockets/legacy/client.py#L480
|
|
||||||
# the reason to keep giving `loop` parameter: we aren't in async function
|
|
||||||
self.conn = websockets.connect(
|
self.conn = websockets.connect(
|
||||||
url, extra_headers=headers, ping_interval=None,
|
url, extra_headers=headers, ping_interval=None,
|
||||||
close_timeout=float('inf'), loop=self.loop, ping_timeout=float('inf'))
|
close_timeout=float('inf'), loop=self.loop, ping_timeout=float('inf'))
|
||||||
@ -5236,8 +5232,6 @@ class WebSocketsWrapper():
|
|||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
if not self.pool:
|
if not self.pool:
|
||||||
with warnings.catch_warnings():
|
|
||||||
warnings.simplefilter("ignore")
|
|
||||||
self.pool = self.run_with_loop(self.conn.__aenter__(), self.loop)
|
self.pool = self.run_with_loop(self.conn.__aenter__(), self.loop)
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -5270,7 +5264,7 @@ class WebSocketsWrapper():
|
|||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _cancel_all_tasks(loop):
|
def _cancel_all_tasks(loop):
|
||||||
to_cancel = asyncio.tasks.all_tasks(loop)
|
to_cancel = asyncio.all_tasks(loop)
|
||||||
|
|
||||||
if not to_cancel:
|
if not to_cancel:
|
||||||
return
|
return
|
||||||
@ -5278,8 +5272,9 @@ class WebSocketsWrapper():
|
|||||||
for task in to_cancel:
|
for task in to_cancel:
|
||||||
task.cancel()
|
task.cancel()
|
||||||
|
|
||||||
|
# XXX: "loop" is removed in python 3.10+
|
||||||
loop.run_until_complete(
|
loop.run_until_complete(
|
||||||
asyncio.tasks.gather(*to_cancel, loop=loop, return_exceptions=True))
|
asyncio.gather(*to_cancel, loop=loop, return_exceptions=True))
|
||||||
|
|
||||||
for task in to_cancel:
|
for task in to_cancel:
|
||||||
if task.cancelled():
|
if task.cancelled():
|
||||||
|
Loading…
Reference in New Issue
Block a user