Repository: yt-dlp/yt-dlp (branch: master)
Commit date: 2023-11-01T11:14:16Z

Workflow file: .github/workflows/quick-test.yml (Quick Test)
name: Quick Test
on: [push, pull_request]
permissions:
  contents: read

jobs:
  tests:
    name: Core Test
    if: "!contains(github.event.head_commit.message, 'ci skip all')"
    runs-on: ubuntu-latest
    services:
      pypi_wayback:
        image: ghcr.io/waleko/pypi-wayback
        ports:
          - 8629:8080
    steps:
    - uses: actions/checkout@v3
    - name: Set up Python 3.11
      uses: actions/setup-python@v4
      with:
        python-version: '3.11'
    - name: Install test requirements
      run: pip install pytest pycryptodomex
    - name: Run tests
      run: |
        python3 -m yt_dlp -v || true
        ./devscripts/run_tests.sh core
  flake8:
    name: Linter
    if: "!contains(github.event.head_commit.message, 'ci skip all')"
    runs-on: ubuntu-latest
    services:
      pypi_wayback:
        image: ghcr.io/waleko/pypi-wayback
        ports:
          - 8629:8080
    steps:
    - uses: actions/checkout@v3
    - uses: actions/setup-python@v4
    - name: Install flake8
      run: pip install flake8
    - name: Make lazy extractors
      run: python devscripts/make_lazy_extractors.py
    - name: Run flake8
      run: flake8 .

env:
  PIP_INDEX_URL: http://localhost:8629/2023-11-01
  UV_INDEX_URL: http://localhost:8629/2023-11-01


Failed build logs:
step_name: Linter/5_Make lazy extractors.txt
log: ##[group]Run python devscripts/make_lazy_extractors.py
[36;1mpython devscripts/make_lazy_extractors.py[0m
shell: /usr/bin/bash -e {0}
##[endgroup]
Traceback (most recent call last):
  File "/home/runner/work/yt-dlp/yt-dlp/devscripts/make_lazy_extractors.py", line 132, in <module>
    main()
  File "/home/runner/work/yt-dlp/yt-dlp/devscripts/make_lazy_extractors.py", line 41, in main
    _ALL_CLASSES = get_all_ies()  # Must be before import
  File "/home/runner/work/yt-dlp/yt-dlp/devscripts/make_lazy_extractors.py", line 68, in get_all_ies
    from yt_dlp.extractor.extractors import _ALL_CLASSES
  File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/extractors.py", line 17, in <module>
    from ._extractors import *  # noqa: F403
  File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/_extractors.py", line 956, in <module>
    from .laxarxames import LaXarxaMesIE
  File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/laxarxames.py", line 37
    )
    ^
SyntaxError: unmatched ')'
##[error]Process completed with exit code 1.

step_name: Core Test/5_Run tests.txt
log: ##[group]Run python3 -m yt_dlp -v || true
[36;1mpython3 -m yt_dlp -v || true[0m
[36;1m./devscripts/run_tests.sh core[0m
shell: /usr/bin/bash -e {0}
env:
  pythonLocation: /opt/hostedtoolcache/Python/3.11.6/x64
  PKG_CONFIG_PATH: /opt/hostedtoolcache/Python/3.11.6/x64/lib/pkgconfig
  Python_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.6/x64
  Python2_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.6/x64
  Python3_ROOT_DIR: /opt/hostedtoolcache/Python/3.11.6/x64
  LD_LIBRARY_PATH: /opt/hostedtoolcache/Python/3.11.6/x64/lib
##[endgroup]
[debug] Command-line config: ['-v']
Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/__main__.py", line 17, in <module>
    yt_dlp.main()
  File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/__init__.py", line 1008, in main
    _exit(*variadic(_real_main(argv)))
                    ^^^^^^^^^^^^^^^^
  File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/__init__.py", line 962, in _real_main
    with YoutubeDL(ydl_opts) as ydl:
         ^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/YoutubeDL.py", line 681, in __init__
    self.print_debug_header()
  File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/YoutubeDL.py", line 3889, in print_debug_header
    from .extractor.extractors import _LAZY_LOADER
  File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/extractors.py", line 17, in <module>
    from ._extractors import *  # noqa: F403
    ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/_extractors.py", line 956, in <module>
    from .laxarxames import LaXarxaMesIE
  File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/laxarxames.py", line 37
    )
    ^
SyntaxError: unmatched ')'
============================= test session starts ==============================
platform linux -- Python 3.11.6, pytest-7.4.3, pluggy-1.3.0 -- /opt/hostedtoolcache/Python/3.11.6/x64/bin/python3
cachedir: .pytest_cache
rootdir: /home/runner/work/yt-dlp/yt-dlp
configfile: setup.cfg
collecting ... collected 567 items / 9 errors / 6 deselected / 561 selected

==================================== ERRORS ====================================
_________________ ERROR collecting test/test_InfoExtractor.py __________________
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/python.py:617: in _importtestmodule
    mod = import_path(self.path, mode=importmode, root=self.config.rootpath)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/pathlib.py:567: in import_path
    importlib.import_module(module_name)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:186: in exec_module
    exec(co, module.__dict__)
test/test_InfoExtractor.py:16: in <module>
    from yt_dlp.extractor import YoutubeIE, get_info_extractor
<frozen importlib._bootstrap>:1229: in _handle_fromlist
    ???
yt_dlp/compat/compat_utils.py:36: in __getattribute__
    ret = super().__getattribute__(attr)
yt_dlp/compat/compat_utils.py:54: in __getattr__
    ret = from_child(attr)
yt_dlp/compat/compat_utils.py:68: in from_child
    child = importlib.import_module(child, parent.__name__)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
yt_dlp/extractor/extractors.py:17: in <module>
    from ._extractors import *  # noqa: F403
yt_dlp/extractor/_extractors.py:956: in <module>
    from .laxarxames import LaXarxaMesIE
E     File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/laxarxames.py", line 37
E       )
E       ^
E   SyntaxError: unmatched ')'
___________________ ERROR collecting test/test_YoutubeDL.py ____________________
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/python.py:617: in _importtestmodule
    mod = import_path(self.path, mode=importmode, root=self.config.rootpath)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/pathlib.py:567: in import_path
    importlib.import_module(module_name)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:186: in exec_module
    exec(co, module.__dict__)
test/test_YoutubeDL.py:17: in <module>
    from yt_dlp.extractor import YoutubeIE
<frozen importlib._bootstrap>:1229: in _handle_fromlist
    ???
yt_dlp/compat/compat_utils.py:36: in __getattribute__
    ret = super().__getattribute__(attr)
yt_dlp/compat/compat_utils.py:54: in __getattr__
    ret = from_child(attr)
yt_dlp/compat/compat_utils.py:68: in from_child
    child = importlib.import_module(child, parent.__name__)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
yt_dlp/extractor/extractors.py:17: in <module>
    from ._extractors import *  # noqa: F403
yt_dlp/extractor/_extractors.py:956: in <module>
    from .laxarxames import LaXarxaMesIE
E     File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/laxarxames.py", line 37
E       )
E       ^
E   SyntaxError: unmatched ')'
____________________ ERROR collecting test/test_all_urls.py ____________________
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/python.py:617: in _importtestmodule
    mod = import_path(self.path, mode=importmode, root=self.config.rootpath)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/pathlib.py:567: in import_path
    importlib.import_module(module_name)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:186: in exec_module
    exec(co, module.__dict__)
test/test_all_urls.py:14: in <module>
    from yt_dlp.extractor import FacebookIE, YoutubeIE, gen_extractors
<frozen importlib._bootstrap>:1229: in _handle_fromlist
    ???
yt_dlp/compat/compat_utils.py:36: in __getattribute__
    ret = super().__getattribute__(attr)
yt_dlp/compat/compat_utils.py:54: in __getattr__
    ret = from_child(attr)
yt_dlp/compat/compat_utils.py:68: in from_child
    child = importlib.import_module(child, parent.__name__)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
yt_dlp/extractor/extractors.py:17: in <module>
    from ._extractors import *  # noqa: F403
yt_dlp/extractor/_extractors.py:956: in <module>
    from .laxarxames import LaXarxaMesIE
E     File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/laxarxames.py", line 37
E       )
E       ^
E   SyntaxError: unmatched ')'
____________________ ERROR collecting test/test_download.py ____________________
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/python.py:617: in _importtestmodule
    mod = import_path(self.path, mode=importmode, root=self.config.rootpath)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/pathlib.py:567: in import_path
    importlib.import_module(module_name)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:186: in exec_module
    exec(co, module.__dict__)
test/test_download.py:286: in <module>
    inject_tests(normal_test_cases)
test/test_download.py:275: in inject_tests
    for test_case in test_cases:
test/helper.py:91: in gettestcases
    for ie in yt_dlp.extractor.gen_extractors():
yt_dlp/extractor/__init__.py:20: in gen_extractors
    return [klass() for klass in gen_extractor_classes()]
yt_dlp/extractor/__init__.py:11: in gen_extractor_classes
    from .extractors import _ALL_CLASSES
yt_dlp/extractor/extractors.py:17: in <module>
    from ._extractors import *  # noqa: F403
yt_dlp/extractor/_extractors.py:956: in <module>
    from .laxarxames import LaXarxaMesIE
E     File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/laxarxames.py", line 37
E       )
E       ^
E   SyntaxError: unmatched ')'
_____________ ERROR collecting test/test_iqiyi_sdk_interpreter.py ______________
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/python.py:617: in _importtestmodule
    mod = import_path(self.path, mode=importmode, root=self.config.rootpath)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/pathlib.py:567: in import_path
    importlib.import_module(module_name)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:186: in exec_module
    exec(co, module.__dict__)
test/test_iqiyi_sdk_interpreter.py:12: in <module>
    from yt_dlp.extractor import IqiyiIE
<frozen importlib._bootstrap>:1229: in _handle_fromlist
    ???
yt_dlp/compat/compat_utils.py:36: in __getattribute__
    ret = super().__getattribute__(attr)
yt_dlp/compat/compat_utils.py:54: in __getattr__
    ret = from_child(attr)
yt_dlp/compat/compat_utils.py:68: in from_child
    child = importlib.import_module(child, parent.__name__)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
yt_dlp/extractor/extractors.py:17: in <module>
    from ._extractors import *  # noqa: F403
yt_dlp/extractor/_extractors.py:956: in <module>
    from .laxarxames import LaXarxaMesIE
E     File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/laxarxames.py", line 37
E       )
E       ^
E   SyntaxError: unmatched ')'
___________________ ERROR collecting test/test_subtitles.py ____________________
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/python.py:617: in _importtestmodule
    mod = import_path(self.path, mode=importmode, root=self.config.rootpath)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/pathlib.py:567: in import_path
    importlib.import_module(module_name)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:186: in exec_module
    exec(co, module.__dict__)
test/test_subtitles.py:12: in <module>
    from yt_dlp.extractor import (
<frozen importlib._bootstrap>:1229: in _handle_fromlist
    ???
yt_dlp/compat/compat_utils.py:36: in __getattribute__
    ret = super().__getattribute__(attr)
yt_dlp/compat/compat_utils.py:54: in __getattr__
    ret = from_child(attr)
yt_dlp/compat/compat_utils.py:68: in from_child
    child = importlib.import_module(child, parent.__name__)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
yt_dlp/extractor/extractors.py:17: in <module>
    from ._extractors import *  # noqa: F403
yt_dlp/extractor/_extractors.py:956: in <module>
    from .laxarxames import LaXarxaMesIE
E     File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/laxarxames.py", line 37
E       )
E       ^
E   SyntaxError: unmatched ')'
_________________ ERROR collecting test/test_youtube_lists.py __________________
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/python.py:617: in _importtestmodule
    mod = import_path(self.path, mode=importmode, root=self.config.rootpath)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/pathlib.py:567: in import_path
    importlib.import_module(module_name)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:186: in exec_module
    exec(co, module.__dict__)
test/test_youtube_lists.py:12: in <module>
    from yt_dlp.extractor import YoutubeIE, YoutubeTabIE
<frozen importlib._bootstrap>:1229: in _handle_fromlist
    ???
yt_dlp/compat/compat_utils.py:36: in __getattribute__
    ret = super().__getattribute__(attr)
yt_dlp/compat/compat_utils.py:54: in __getattr__
    ret = from_child(attr)
yt_dlp/compat/compat_utils.py:68: in from_child
    child = importlib.import_module(child, parent.__name__)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
yt_dlp/extractor/extractors.py:17: in <module>
    from ._extractors import *  # noqa: F403
yt_dlp/extractor/_extractors.py:956: in <module>
    from .laxarxames import LaXarxaMesIE
E     File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/laxarxames.py", line 37
E       )
E       ^
E   SyntaxError: unmatched ')'
__________________ ERROR collecting test/test_youtube_misc.py __________________
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/python.py:617: in _importtestmodule
    mod = import_path(self.path, mode=importmode, root=self.config.rootpath)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/pathlib.py:567: in import_path
    importlib.import_module(module_name)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:186: in exec_module
    exec(co, module.__dict__)
test/test_youtube_misc.py:11: in <module>
    from yt_dlp.extractor import YoutubeIE
<frozen importlib._bootstrap>:1229: in _handle_fromlist
    ???
yt_dlp/compat/compat_utils.py:36: in __getattribute__
    ret = super().__getattribute__(attr)
yt_dlp/compat/compat_utils.py:54: in __getattr__
    ret = from_child(attr)
yt_dlp/compat/compat_utils.py:68: in from_child
    child = importlib.import_module(child, parent.__name__)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
yt_dlp/extractor/extractors.py:17: in <module>
    from ._extractors import *  # noqa: F403
yt_dlp/extractor/_extractors.py:956: in <module>
    from .laxarxames import LaXarxaMesIE
E     File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/laxarxames.py", line 37
E       )
E       ^
E   SyntaxError: unmatched ')'
_______________ ERROR collecting test/test_youtube_signature.py ________________
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/python.py:617: in _importtestmodule
    mod = import_path(self.path, mode=importmode, root=self.config.rootpath)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/pathlib.py:567: in import_path
    importlib.import_module(module_name)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
<frozen importlib._bootstrap>:1204: in _gcd_import
    ???
<frozen importlib._bootstrap>:1176: in _find_and_load
    ???
<frozen importlib._bootstrap>:1147: in _find_and_load_unlocked
    ???
<frozen importlib._bootstrap>:690: in _load_unlocked
    ???
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/site-packages/_pytest/assertion/rewrite.py:186: in exec_module
    exec(co, module.__dict__)
test/test_youtube_signature.py:17: in <module>
    from yt_dlp.extractor import YoutubeIE
<frozen importlib._bootstrap>:1229: in _handle_fromlist
    ???
yt_dlp/compat/compat_utils.py:36: in __getattribute__
    ret = super().__getattribute__(attr)
yt_dlp/compat/compat_utils.py:54: in __getattr__
    ret = from_child(attr)
yt_dlp/compat/compat_utils.py:68: in from_child
    child = importlib.import_module(child, parent.__name__)
/opt/hostedtoolcache/Python/3.11.6/x64/lib/python3.11/importlib/__init__.py:126: in import_module
    return _bootstrap._gcd_import(name[level:], package, level)
yt_dlp/extractor/extractors.py:17: in <module>
    from ._extractors import *  # noqa: F403
yt_dlp/extractor/_extractors.py:956: in <module>
    from .laxarxames import LaXarxaMesIE
E     File "/home/runner/work/yt-dlp/yt-dlp/yt_dlp/extractor/laxarxames.py", line 37
E       )
E       ^
E   SyntaxError: unmatched ')'
=========================== short test summary info ============================
ERROR test/test_InfoExtractor.py
ERROR test/test_YoutubeDL.py
ERROR test/test_all_urls.py
ERROR test/test_download.py
ERROR test/test_iqiyi_sdk_interpreter.py
ERROR test/test_subtitles.py
ERROR test/test_youtube_lists.py
ERROR test/test_youtube_misc.py
ERROR test/test_youtube_signature.py
!!!!!!!!!!!!!!!!!!! Interrupted: 9 errors during collection !!!!!!!!!!!!!!!!!!!!
======================= 6 deselected, 9 errors in 2.30s ========================
##[error]Process completed with exit code 2.


Changed files:
README.md
yt_dlp/YoutubeDL.py
yt_dlp/extractor/_extractors.py
yt_dlp/extractor/generic.py
yt_dlp/extractor/laxarxames.py
yt_dlp/extractor/npo.py
yt_dlp/extractor/orf.py
yt_dlp/extractor/polskieradio.py
yt_dlp/extractor/qdance.py
yt_dlp/extractor/twitcasting.py
yt_dlp/extractor/weverse.py
yt_dlp/extractor/youtube.py

Fix diff:
diff --git a/README.md b/README.md
index 3b7432474..d464519f0 100644
--- a/README.md
+++ b/README.md
@@ -1801,7 +1801,7 @@ # EXTRACTOR ARGUMENTS
 #### youtube
 * `lang`: Prefer translated metadata (`title`, `description` etc) of this language code (case-sensitive). By default, the video primary language metadata is preferred, with a fallback to `en` translated. See [youtube.py](https://github.com/yt-dlp/yt-dlp/blob/c26f9b991a0681fd3ea548d535919cec1fbbd430/yt_dlp/extractor/youtube.py#L381-L390) for list of supported content language codes
 * `skip`: One or more of `hls`, `dash` or `translated_subs` to skip extraction of the m3u8 manifests, dash manifests and [auto-translated subtitles](https://github.com/yt-dlp/yt-dlp/issues/4090#issuecomment-1158102032) respectively
-* `player_client`: Clients to extract video data from. The main clients are `web`, `android` and `ios` with variants `_music`, `_embedded`, `_embedscreen`, `_creator` (e.g. `web_embedded`); and `mweb`, `mweb_embedscreen` and `tv_embedded` (agegate bypass) with no variants. By default, `ios,android,web` is used, but `tv_embedded` and `creator` variants are added as required for age-gated videos. Similarly, the music variants are added for `music.youtube.com` urls. You can use `all` to use all the clients, and `default` for the default clients.
+* `player_client`: Clients to extract video data from. The main clients are `web`, `android` and `ios` with variants `_music`, `_embedded`, `_embedscreen`, `_creator` (e.g. `web_embedded`); and `mweb`, `mweb_embedscreen` and `tv_embedded` (agegate bypass) with no variants. By default, `android,web,ios` is used, but `tv_embedded` and `creator` variants are added as required for age-gated videos. Similarly, the music variants are added for `music.youtube.com` urls. You can use `all` to use all the clients, and `default` for the default clients.
 * `player_skip`: Skip some network requests that are generally needed for robust extraction. One or more of `configs` (skip client configs), `webpage` (skip initial webpage), `js` (skip js player). While these options can help reduce the number of requests needed or avoid some rate-limiting, they could cause some issues. See [#860](https://github.com/yt-dlp/yt-dlp/pull/860) for more details
 * `player_params`: YouTube player parameters to use for player requests. Will overwrite any default ones set by yt-dlp.
 * `comment_sort`: `top` or `new` (default) - choose comment sorting mode (on YouTube's side)
diff --git a/yt_dlp/YoutubeDL.py b/yt_dlp/YoutubeDL.py
index 8e11646d3..f10167826 100644
--- a/yt_dlp/YoutubeDL.py
+++ b/yt_dlp/YoutubeDL.py
@@ -2338,7 +2338,7 @@ def _check_formats(formats):
                 return
 
             for f in formats:
-                if f.get('has_drm'):
+                if f.get('has_drm') or f.get('__needs_testing'):
                     yield from self._check_formats([f])
                 else:
                     yield f
@@ -4242,7 +4242,7 @@ def _write_thumbnails(self, label, info_dict, filename, thumb_filename_base=None
             self.write_debug(f'Skipping writing {label} thumbnail')
             return ret
 
-        if not self._ensure_dir_exists(filename):
+        if thumbnails and not self._ensure_dir_exists(filename):
             return None
 
         for idx, t in list(enumerate(thumbnails))[::-1]:
diff --git a/yt_dlp/extractor/_extractors.py b/yt_dlp/extractor/_extractors.py
index f415819ed..a8eac0bc5 100644
--- a/yt_dlp/extractor/_extractors.py
+++ b/yt_dlp/extractor/_extractors.py
@@ -953,7 +953,6 @@
     LastFMPlaylistIE,
     LastFMUserIE,
 )
-from .laxarxames import LaXarxaMesIE
 from .lbry import (
     LBRYIE,
     LBRYChannelIE,
@@ -1417,6 +1416,7 @@
     ORFTVthekIE,
     ORFFM4StoryIE,
     ORFRadioIE,
+    ORFPodcastIE,
     ORFIPTVIE,
 )
 from .outsidetv import OutsideTVIE
diff --git a/yt_dlp/extractor/generic.py b/yt_dlp/extractor/generic.py
index 5e1240c13..ac7cc673f 100644
--- a/yt_dlp/extractor/generic.py
+++ b/yt_dlp/extractor/generic.py
@@ -34,6 +34,7 @@
     unified_timestamp,
     unsmuggle_url,
     update_url_query,
+    urlhandle_detect_ext,
     url_or_none,
     urljoin,
     variadic,
@@ -2459,7 +2460,7 @@ def _real_extract(self, url):
             self.report_detected('direct video link')
             headers = smuggled_data.get('http_headers', {})
             format_id = str(m.group('format_id'))
-            ext = determine_ext(url)
+            ext = determine_ext(url, default_ext=None) or urlhandle_detect_ext(full_response)
             subtitles = {}
             if format_id.endswith('mpegurl') or ext == 'm3u8':
                 formats, subtitles = self._extract_m3u8_formats_and_subtitles(url, video_id, 'mp4', headers=headers)
@@ -2471,6 +2472,7 @@ def _real_extract(self, url):
                 formats = [{
                     'format_id': format_id,
                     'url': url,
+                    'ext': ext,
                     'vcodec': 'none' if m.group('type') == 'audio' else None
                 }]
                 info_dict['direct'] = True
diff --git a/yt_dlp/extractor/laxarxames.py b/yt_dlp/extractor/laxarxames.py
deleted file mode 100644
index b7cad9cdb..000000000
--- a/yt_dlp/extractor/laxarxames.py
+++ /dev/null
@@ -1,97 +0,0 @@
-from .common import InfoExtractor
-
-
-class LaXarxaMesIE(InfoExtractor):
-    _VALID_URL = r'https?://(?:www\.)?laxarxames\.cat/(?:[^/]+/)*?(player|movie-details)/(?P<id>[0-9]+)'
-    _NETRC_MACHINE = 'laxarxames'
-    _IS_LOGGED_IN = False
-    _LOGIN_URL = 'https://www.laxarxames.cat/login'
-    _TESTS = [{
-        'url': 'https://www.laxarxames.cat/player/3459421',
-        'md5': '0966f46c34275934c19af78f3df6e2bc',
-        'info_dict': {
-            'id': '3459421',
-            'ext': 'mp4',
-            'title': 'Resum | UA Horta — UD Viladecans',
-            'type': 'video/mp4',
-        },
-        'skip': 'Requires login',
-    }]
-
-    def _perform_login(self, username, password):
-        login = self._download_json(
-            'https://api.laxarxames.cat/Authorization/SignIn', None, note='Logging in', headers={
-                'X-Tenantorigin': 'https://laxarxames.cat',
-                'Content-Type': 'application/json',
-                'Accept': 'application/json, text/plain, */*',
-                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko)',
-                'Origin': 'https://www.laxarxames.cat',
-            }, data=json.dumps({
-                'Username': username,
-                'Password': password,
-                'Device': {
-                    'PlatformCode': 'WEB',
-                    'Name': 'Mac OS ()',
-                },
-            }).encode('utf-8'))
-        )
-
-        if not login['AuthorizationToken']:
-            raise Exception('Login failed')
-        else:
-            self._set_cookie('www.laxarxames.cat', 'didomi_token', login['AuthorizationToken']['Token'])
-
-    def _real_extract(self, url):
-        video_id = self._match_id(url)
-        authorization = self._get_cookies('https://www.laxarxames.cat/').get('didomi_token')
-
-        if not authorization:
-            self.raise_login_required()
-        mediaplayinfo = self._download_json(
-            'https://api.laxarxames.cat/Media/GetMediaPlayInfo',
-            video_id,
-            data=b'{"MediaId":%s,"StreamType":"MAIN"}' % video_id.encode(),
-            headers={
-                'Authorization': 'Bearer ' + authorization.value,
-                'X-Tenantorigin': 'https://laxarxames.cat',
-                'Content-Type': 'application/json',
-                'Accept': 'application/json, text/plain, */*',
-                'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko)',
-                'Origin': 'https://www.laxarxames.cat',
-            }
-        )
-
-        contenturl = mediaplayinfo['ContentUrl']
-        title = mediaplayinfo['Title']
-
-        videodata = self._download_json(
-            'https://edge.api.brightcove.com/playback/v1/accounts/5779379807001/videos/' + contenturl,
-            video_id,
-            headers={
-                'Accept': 'application/json;pk=BCpkADawqM2uXEFYflHlCdYKQdRAfbdvR3tpOY9_jxup5aqCrMmJxjXtV6k9Khk7hKqFFp15BwULNmQkWBik0SJgtgqDAoni09Ezx2w4dIGs1GAjhnLMWXaeCmveEusJKQYs83DIlSUIPccu'
-            }
-        )
-
-        sources = videodata['sources']
-
-        formats = []
-        for source in sources:
-            url = source['src']
-            type = ''
-            manifest_url = None
-            if 'type' in source:
-                type = source['type']
-                manifest_url = source['src']
-            else:
-                type = 'video/mp4'
-            formats.append({
-                'url': url,
-                'type': type,
-                'manifest_url': manifest_url
-            })
-
-        return {
-            'id': video_id,
-            'title': title,
-            'formats': formats,
-        }
diff --git a/yt_dlp/extractor/npo.py b/yt_dlp/extractor/npo.py
index 40fee24d0..4d5ff50de 100644
--- a/yt_dlp/extractor/npo.py
+++ b/yt_dlp/extractor/npo.py
@@ -245,7 +245,7 @@ def _real_extract(self, url):
                     'quality': 'npoplus',
                     'tokenId': player_token,
                     'streamType': 'broadcast',
-                })
+                }, data=b'')  # endpoint requires POST
             if not streams:
                 continue
             stream = streams.get('stream')
diff --git a/yt_dlp/extractor/orf.py b/yt_dlp/extractor/orf.py
index cc3c003fa..f33b0501f 100644
--- a/yt_dlp/extractor/orf.py
+++ b/yt_dlp/extractor/orf.py
@@ -20,7 +20,9 @@
     unified_strdate,
     unsmuggle_url,
     url_or_none,
+    mimetype2ext,
 )
+from ..utils.traversal import traverse_obj
 
 
 class ORFTVthekIE(InfoExtractor):
@@ -334,6 +336,45 @@ def _real_extract(self, url):
             self._entries(data, station or station2), show_id, data.get('title'), clean_html(data.get('subtitle')))
 
 
+class ORFPodcastIE(InfoExtractor):
+    IE_NAME = 'orf:podcast'
+    _STATION_RE = '|'.join(map(re.escape, (
+        'bgl', 'fm4', 'ktn', 'noe', 'oe1', 'oe3',
+        'ooe', 'sbg', 'stm', 'tir', 'tv', 'vbg', 'wie')))
+    _VALID_URL = rf'https?://sound\.orf\.at/podcast/(?P<station>{_STATION_RE})/(?P<show>[\w-]+)/(?P<id>[\w-]+)'
+    _TESTS = [{
+        'url': 'https://sound.orf.at/podcast/oe3/fruehstueck-bei-mir/nicolas-stockhammer-15102023',
+        'md5': '526a5700e03d271a1505386a8721ab9b',
+        'info_dict': {
+            'id': 'nicolas-stockhammer-15102023',
+            'ext': 'mp3',
+            'title': 'Nicolas Stockhammer (15.10.2023)',
+            'duration': 3396.0,
+            'series': 'Frühstück bei mir',
+        },
+        'skip': 'ORF podcasts are only available for a limited time'
+    }]
+
+    def _real_extract(self, url):
+        station, show, show_id = self._match_valid_url(url).group('station', 'show', 'id')
+        data = self._download_json(
+            f'https://audioapi.orf.at/radiothek/api/2.0/podcast/{station}/{show}/{show_id}', show_id)
+
+        return {
+            'id': show_id,
+            'ext': 'mp3',
+            'vcodec': 'none',
+            **traverse_obj(data, ('payload', {
+                'url': ('enclosures', 0, 'url'),
+                'ext': ('enclosures', 0, 'type', {mimetype2ext}),
+                'title': 'title',
+                'description': ('description', {clean_html}),
+                'duration': ('duration', {functools.partial(float_or_none, scale=1000)}),
+                'series': ('podcast', 'title'),
+            })),
+        }
+
+
 class ORFIPTVIE(InfoExtractor):
     IE_NAME = 'orf:iptv'
     IE_DESC = 'iptv.ORF.at'
diff --git a/yt_dlp/extractor/polskieradio.py b/yt_dlp/extractor/polskieradio.py
index 5bf92b9b5..e0b22fffd 100644
--- a/yt_dlp/extractor/polskieradio.py
+++ b/yt_dlp/extractor/polskieradio.py
@@ -262,14 +262,14 @@ def _call_lp3(self, path, query, video_id, note):
             query=query, headers={'x-api-key': '9bf6c5a2-a7d0-4980-9ed7-a3f7291f2a81'})
 
     def _entries(self, playlist_id, has_episodes, has_articles):
-        for i in itertools.count(1) if has_episodes else []:
+        for i in itertools.count(0) if has_episodes else []:
             page = self._call_lp3(
                 'AudioArticle/GetListByCategoryId', {
                     'categoryId': playlist_id,
                     'PageSize': 10,
                     'skip': i,
                     'format': 400,
-                }, playlist_id, f'Downloading episode list page {i}')
+                }, playlist_id, f'Downloading episode list page {i + 1}')
             if not traverse_obj(page, 'data'):
                 break
             for episode in page['data']:
@@ -281,14 +281,14 @@ def _entries(self, playlist_id, has_episodes, has_articles):
                     'timestamp': parse_iso8601(episode.get('datePublic')),
                 }
 
-        for i in itertools.count(1) if has_articles else []:
+        for i in itertools.count(0) if has_articles else []:
             page = self._call_lp3(
                 'Article/GetListByCategoryId', {
                     'categoryId': playlist_id,
                     'PageSize': 9,
                     'skip': i,
                     'format': 400,
-                }, playlist_id, f'Downloading article list page {i}')
+                }, playlist_id, f'Downloading article list page {i + 1}')
             if not traverse_obj(page, 'data'):
                 break
             for article in page['data']:
diff --git a/yt_dlp/extractor/qdance.py b/yt_dlp/extractor/qdance.py
index d817677f0..934ebbfd7 100644
--- a/yt_dlp/extractor/qdance.py
+++ b/yt_dlp/extractor/qdance.py
@@ -15,7 +15,7 @@
 
 class QDanceIE(InfoExtractor):
     _NETRC_MACHINE = 'qdance'
-    _VALID_URL = r'https?://(?:www\.)?q-dance\.com/network/(?:library|live)/(?P<id>\d+)'
+    _VALID_URL = r'https?://(?:www\.)?q-dance\.com/network/(?:library|live)/(?P<id>[\w-]+)'
     _TESTS = [{
         'note': 'vod',
         'url': 'https://www.q-dance.com/network/library/146542138',
@@ -53,6 +53,27 @@ class QDanceIE(InfoExtractor):
             'channel_id': 'qdancenetwork.video_149170353',
         },
         'skip': 'Completed livestream',
+    }, {
+        'note': 'vod with alphanumeric id',
+        'url': 'https://www.q-dance.com/network/library/WhDleSIWSfeT3Q9ObBKBeA',
+        'info_dict': {
+            'id': 'WhDleSIWSfeT3Q9ObBKBeA',
+            'ext': 'mp4',
+            'title': 'Aftershock I Defqon.1 Weekend Festival 2023 I Sunday I BLUE',
+            'display_id': 'naam-i-defqon-1-weekend-festival-2023-i-dag-i-podium',
+            'description': 'Relive Defqon.1 Path of the Warrior with Aftershock at the BLUE 🔥',
+            'series': 'Defqon.1',
+            'series_id': '31840378',
+            'season': 'Defqon.1 Weekend Festival 2023',
+            'season_id': '141735599',
+            'duration': 3507,
+            'availability': 'premium_only',
+            'thumbnail': 'https://images.q-dance.network/1698158361-230625-135716-defqon-1-aftershock.jpg',
+        },
+        'params': {'skip_download': 'm3u8'},
+    }, {
+        'url': 'https://www.q-dance.com/network/library/-uRFKXwmRZGVnve7av9uqA',
+        'only_matching': True,
     }]
 
     _access_token = None
diff --git a/yt_dlp/extractor/twitcasting.py b/yt_dlp/extractor/twitcasting.py
index 540e217fd..32a38c86e 100644
--- a/yt_dlp/extractor/twitcasting.py
+++ b/yt_dlp/extractor/twitcasting.py
@@ -142,7 +142,7 @@ def _real_extract(self, url):
             'https://twitcasting.tv/streamserver.php?target=%s&mode=client' % uploader_id, video_id,
             'Downloading live info', fatal=False)
 
-        is_live = 'data-status="online"' in webpage
+        is_live = any(f'data-{x}' in webpage for x in ['is-onlive="true"', 'live-type="live"', 'status="online"'])
         if not traverse_obj(stream_server_data, 'llfmp4') and is_live:
             self.raise_login_required(method='cookies')
 
diff --git a/yt_dlp/extractor/weverse.py b/yt_dlp/extractor/weverse.py
index 47f36806b..c94ca9db9 100644
--- a/yt_dlp/extractor/weverse.py
+++ b/yt_dlp/extractor/weverse.py
@@ -45,10 +45,10 @@ def _perform_login(self, username, password):
             'x-acc-trace-id': str(uuid.uuid4()),
             'x-clog-user-device-id': str(uuid.uuid4()),
         }
-        check_username = self._download_json(
-            f'{self._ACCOUNT_API_BASE}/signup/email/status', None,
-            note='Checking username', query={'email': username}, headers=headers)
-        if not check_username.get('hasPassword'):
+        valid_username = traverse_obj(self._download_json(
+            f'{self._ACCOUNT_API_BASE}/signup/email/status', None, note='Checking username',
+            query={'email': username}, headers=headers, expected_status=(400, 404)), 'hasPassword')
+        if not valid_username:
             raise ExtractorError('Invalid username provided', expected=True)
 
         headers['content-type'] = 'application/json'
diff --git a/yt_dlp/extractor/youtube.py b/yt_dlp/extractor/youtube.py
index ac28ed7d2..ddbd614d6 100644
--- a/yt_dlp/extractor/youtube.py
+++ b/yt_dlp/extractor/youtube.py
@@ -3619,7 +3619,7 @@ def _extract_player_response(self, client, video_id, master_ytcfg, player_ytcfg,
 
     def _get_requested_clients(self, url, smuggled_data):
         requested_clients = []
-        default = ['ios', 'android', 'web']
+        default = ['android', 'web', 'ios']
         allowed_clients = sorted(
             (client for client in INNERTUBE_CLIENTS.keys() if client[:1] != '_'),
             key=lambda client: INNERTUBE_CLIENTS[client]['priority'], reverse=True)
@@ -4560,6 +4560,14 @@ def process_language(container, base_url, lang_code, sub_name, query):
                 self._parse_time_text(self._get_text(vpir, 'dateText'))) or upload_date
         info['upload_date'] = upload_date
 
+        if upload_date and live_status not in ('is_live', 'post_live', 'is_upcoming'):
+            # Newly uploaded videos' HLS formats are potentially problematic and need to be checked
+            upload_datetime = datetime_from_str(upload_date).replace(tzinfo=datetime.timezone.utc)
+            if upload_datetime >= datetime_from_str('today-1day'):
+                for fmt in info['formats']:
+                    if fmt.get('protocol') == 'm3u8_native':
+                        fmt['__needs_testing'] = True
+
         for s_k, d_k in [('artist', 'creator'), ('track', 'alt_title')]:
             v = info.get(s_k)
             if v: