Compare commits

..
101 Commits
Author SHA1 Message Date
github-actions[bot] f264a6cbd1 Release 2026.10.26
Created by: bashonly

:ci skip all
2026-10-26 22:07:14 +00:00
dlp-bot c91f8de0bf [build] Update 3 dependencies (#17933)
* Bump brotlicffi 1.2.0.2 => 1.2.1.0
* Fully address https://github.com/advisories/GHSA-9v8h-qqgm-4m35
* Bump setuptools 84.0.0 => 84.2.1
* Bump virtualenv 21.14.11 => 21.14.13

Authored by: dlp-bot
2026-10-26 21:26:52 +00:00
doe1080andbashonly 7e3644cfa6 [cleanup] Misc (#17892)
Authored by: doe1080, bashonly

Co-authored-by: bashonly <88596187+bashonly@users.noreply.github.com>
2026-10-26 21:07:11 +00:00
gamer191 755a01732c [ci] Test with PyPy 3.12 (#17926)
Authored by: gamer191
2026-10-26 20:37:27 +00:00
dlp-botandbashonly fd26888eb0 [ci] Update 7 actions in 9 workflows (#17925)
* Bump actions/download-artifact v8.0.1 => v8.0.2
* Bump actions/setup-node v7.0.0 => v7.1.0
* Bump actions/setup-python v7.0.0 => v7.1.0
* Bump actions/upload-artifact v7.0.1 => v7.0.2
* Bump github/codeql-action v4.38.2 => v4.39.1
* Bump pypa/gh-action-pypi-publish v1.14.2 => v1.14.3
* Bump zizmorcore/zizmor-action v0.6.4 => v0.8.0

Authored by: bashonly, dlp-bot

Co-authored-by: bashonly <bashonly@protonmail.com>
2026-10-26 20:16:22 +00:00
dlp-botandbashonly 7747073a2b [build] Update 13 dependencies (#17924)
* Bump brotli 1.2.0 => 1.2.1
* Address https://github.com/advisories/GHIS-4ggp-56x3-8hjh
* Bump certifi 2026.10.19 => 2026.10.23
* Bump curl-cffi 0.16.3 => 0.17.0
* Fully address https://github.com/advisories/GHSA-6q48-6c7w-9gw2
* Bump distlib 0.4.3 => 0.4.4
* Bump filelock 4.1.2 => 4.2.4
* Bump platformdirs 4.13.0 => 4.13.5
* Bump pluggy 1.6.0 => 1.7.0
* Bump python-discovery 1.6.2 => 1.6.4
* Bump ruff 0.16.10 => 0.17.1
* Bump tomlkit 0.15.1 => 0.15.2
* Bump uv 0.13.4 => 0.13.5
* Bump virtualenv 21.14.7 => 21.14.11
* Bump websockets 17.2 => 17.3

Closes #17920
Authored by: bashonly, dlp-bot

Co-authored-by: bashonly <bashonly@protonmail.com>
2026-10-26 20:02:06 +00:00
bashonly 15262b0b98 [test:networking] Fix supported impersonate targets test (#17931)
Fix 7f7106cd32

Authored by: bashonly
2026-10-26 19:46:13 +00:00
bashonly 7f7106cd32 [rh:curl_cffi] Support curl_cffi 0.17.x (#17929)
Authored by: bashonly
2026-10-26 18:21:29 +00:00
bashonly fa9886678e [ie/odnoklassniki] Fix boosty direct link extraction (#17749)
Fix 51bab8a011

Authored by: bashonly
2026-10-23 15:18:52 +00:00
bashonly 9b58cb33d0 [build] Always use latest Python version on Windows (#17901)
Authored by: bashonly
2026-10-23 03:56:15 +00:00
bashonly 43a45ae374 [docs] Add changelog entries for dropping Py3.10 & Win8 support (#17889)
Authored by: bashonly
2026-10-21 22:17:41 +00:00
3d28cf4780 Remove Python 3.10 support (#17160)
* Also upgrade Windows builds to Python 3.14

Closes #16916, Closes #16917
Authored by: bashonly, doe1080, Grub4K

Co-authored-by: doe1080 <98906116+doe1080@users.noreply.github.com>
Co-authored-by: Simon Sawicki <contact@grub4k.dev>
2026-10-21 22:04:43 +00:00
github-actions[bot] 6ccd977303 Release 2026.10.21
Created by: bashonly

:ci skip all
2026-10-21 21:36:21 +00:00
bashonly 8cdf4fea48 [build] Fix armv7l executable verification (#17886)
Authored by: bashonly
2026-10-21 21:35:14 +00:00
36b92b4f16 [cleanup] Misc (#17569)
Closes #17566, Closes #17815
Authored by: bashonly, gamer191, tcely

Co-authored-by: tcely <tcely@users.noreply.github.com>
Co-authored-by: gamer191 <83270075+gamer191@users.noreply.github.com>
2026-10-21 20:18:51 +00:00
gamer191 a51ef56c03 [ie/youtube] Improve error messages (#17884)
Authored by: gamer191
2026-10-21 20:08:55 +00:00
dlp-botandbashonly f59cd0ba0a [build] Update 2 dependencies (#17882)
* Bump deno 2.9.7 => 2.9.8
* Bump filelock 4.1.1 => 4.1.2

Authored by: bashonly, dlp-bot

Co-authored-by: bashonly <bashonly@protonmail.com>
2026-10-21 16:27:36 +00:00
bashonly f82b268121 [build] Bypass cooldown for deno (#17880)
Authored by: bashonly
2026-10-21 16:03:08 +00:00
InvalidUsernameException 12ac9aca79 [ie/youtube] Fix initial data extraction (#17703)
Closes #17656
Authored by: InvalidUsernameException
2026-10-21 15:01:35 +00:00
doe1080andInvalidUsernameException fe84bef396 [ie/kick] Rework extractors (#17322)
Closes #14189, Closes #15888, Closes #17284
Authored by: doe1080, InvalidUsernameException

Co-authored-by: InvalidUsernameException <InvalidUsernameException@users.noreply.github.com>
2026-10-21 14:28:46 +00:00
dlp-botandbashonly 70279f2f0c [build] Update 33 dependencies (#17581)
* Bump brotlicffi 1.2.0.1 => 1.2.0.2
* Bump build 1.5.0 => 1.6.1
* Bump certifi 2026.7.22 => 2026.10.19
* Bump charset-normalizer 3.5.0 => 3.5.2
* Bump cryptography 50.0.0 => 50.0.2
* Bump curl-cffi 0.16.0 => 0.16.3
* Bump deno 2.9.5 => 2.9.7
* Bump filelock 3.32.2 => 4.1.1
* Bump hatchling 1.32.0 => 1.32.4
* Bump identify 2.6.19 => 2.6.20
* Bump idna 3.18 => 3.20
* Bump importlib-metadata 9.0.0 => 9.0.1
* Bump iniconfig 2.3.0 => 2.3.1
* Bump nodeenv 1.10.0 => 1.11.0
* Bump pip 26.2.1 => 26.2.2
* Bump platformdirs 4.11.2 => 4.13.0
* Bump pre-commit 4.6.2 => 4.7.0
* Bump pycodestyle 2.14.0 => 2.15.0
* Bump pycparser 3.0 => 3.11
* Bump pycryptodomex 3.23.0 => 3.24.1
* Bump pygments 2.20.0 => 2.21.0
* Bump pyinstaller-hooks-contrib 2026.6 => 2026.8
* Bump pyproject-hooks 1.2.0 => 1.3.3
* Bump pytest-rerunfailures 16.4 => 16.7
* Bump python-discovery 1.5.2 => 1.6.2
* Bump ruff 0.16.2 => 0.16.10
* Bump tomli 2.4.1 => 2.5.0
* Bump trove-classifiers 2026.6.1.19 => 2026.9.21.13
* Bump urllib3 2.7.0 => 2.8.0
* Bump uv 0.12.3 => 0.13.4
* Bump virtualenv 21.7.4 => 21.14.7
* Bump websockets 17.0.1 => 17.2
* Bump zipp 4.1.0 => 4.1.1

Authored by: bashonly, dlp-bot

Co-authored-by: bashonly <bashonly@protonmail.com>
2026-10-21 13:57:55 +00:00
ruben1PvP 897341241f [ie/youtube] Set tv_samsung as a default client (#17805)
Authored by: ruben1PvP
2026-10-10 23:15:52 +02:00
error-reporting 817450d28d [ie/youtube] Add tv_samsung client (#17723)
Authored by: error-reporting
2026-10-11 08:56:51 +13:00
InvalidUsernameException 51bab8a011 [ie/odnoklassniki] Fix extractor (#17739)
Closes #17585, Closes #17600
Authored by: InvalidUsernameException
2026-09-27 22:09:13 +00:00
dlp-botandbashonly 779f599669 [ci] Update 3 actions in 3 workflows (#17748)
* Bump docker/setup-qemu-action v4.2.0 => v4.4.0
* Bump github/codeql-action v4.37.7 => v4.38.2
* Bump zizmorcore/zizmor-action v0.6.2 => v0.6.4
* Use self-repository syntax in reusable workflow calls

Authored by: bashonly, dlp-bot

Co-authored-by: bashonly <bashonly@protonmail.com>
2026-09-27 21:12:35 +00:00
bashonly a29f2a2b92 [rh:websockets] Add legacy connect workaround for >=17.1 (#17747)
Authored by: bashonly
2026-09-27 20:17:39 +00:00
doe1080 caf63903a1 [networking] Fix + decoding in SOCKS proxy credentials (#17728)
Authored by: doe1080
2026-09-27 20:44:21 +02:00
doe1080 28731cbacb [utils] Improve Content-Disposition filename parsing (#17727)
Authored by: doe1080
2026-09-27 20:21:54 +02:00
doe1080 c2901ed367 [rh:urllib] Fix relative redirects with dot segments (#17712)
Authored by: doe1080
2026-09-27 19:55:49 +02:00
doe1080 f9eee6ba62 [rh:urllib] Eagerly release BytesIO responses (#17717)
Authored by: doe1080
2026-09-27 19:54:19 +02:00
doe1080 9dd5e68cd7 [test:websockets] Update server hang workaround (#17718)
Authored by: doe1080
2026-09-27 19:50:36 +02:00
doe1080 39b31b2755 [utils] setproctitle: Fix NUL termination (#17724)
Authored by: doe1080
2026-09-27 19:40:54 +02:00
Simon Sawicki f45f14bd79 [misc/requirements] Fix locking for pycparser (#17746)
Authored by: Grub4K
2026-09-27 19:27:44 +02:00
doe1080 8a49065e18 [devscripts] update_requirements: Preserve cffi dependencies on PyPy (#17716)
Authored by: doe1080
2026-09-27 18:34:03 +02:00
gamer191 c7fb478d21 [ie/youtube] Use Safari UA for web_embedded client (#17684)
Authored by: gamer191
2026-09-16 19:48:51 +12:00
doe1080 bbc809a116 [utils] devalue: Improve binary type parsing (#16934)
Authored by: doe1080
2026-08-30 15:58:45 +02:00
FraFraFra-LongD 9caaf45401 [ie] Do not warn on intentional generic results (#16683)
Authored by: FraFraFra-LongD
2026-08-30 15:53:37 +02:00
tcely 2f3929ba1a [ie/applepodcasts] Fix token caching (#17567)
Fix aaf7405ba3

Authored by: tcely
2026-08-29 23:22:47 +00:00
Atsushi2965 f1df65d5d7 [utils]download_range_func: Update __eq__ and __repr__ to include from_info (#16393)
Authored by: atsushi2965
2026-08-30 00:31:58 +02:00
doe1080 3d062c86ea [docs] Fix Namespace documentation (#17324)
Authored by: doe1080
2026-08-30 00:12:11 +02:00
doe1080 fcdbefb85f [utils] subs_list_to_dict: Fix empty value handling (#17311)
Authored by: doe1080
2026-08-29 23:55:22 +02:00
bashonly 8377aa9555 [update] Detect GitHub error page responses (#17555)
Closes #17550
Authored by: bashonly
2026-08-27 23:05:38 +00:00
bashonly 28d35b7762 [ie/twitch:clips] Fix extractor (#17554)
Closes #17553
Authored by: bashonly
2026-08-27 22:52:39 +00:00
Lillie 94eba4c156 [ie/globalplayer] Fix extractors (#17442)
Closes #17215, Closes #17429
Authored by: LillieH1000
2026-08-26 23:44:14 +00:00
bashonly 1d1351f40f [ie/bandcamp] Fix extractors (#17546)
Fix ec9425fcd0

Closes #17506
Authored by: bashonly
2026-08-26 23:27:37 +00:00
InvalidUsernameException 2089f8ad37 [ie/tubitv:series] Fix extractor (#17545)
Closes #17543
Authored by: InvalidUsernameException
2026-08-26 22:34:11 +00:00
wlerinanddoe1080 a2a8846b0d [ie/showroom] Fix extractor (#17488)
Closes #17331
Authored by: wlerin, doe1080

Co-authored-by: doe1080 <98906116+doe1080@users.noreply.github.com>
2026-08-26 22:22:17 +00:00
InvalidUsernameException d1cb4709cc [ie/tubitv] Improve extractor (#16428)
Closes #16422
Authored by: InvalidUsernameException
2026-08-26 20:40:14 +00:00
ache e164eebe19 [ie/adn] Add profile_id extractor-arg (#17522)
Authored by: arobase-che
2026-08-26 20:39:10 +00:00
norepro 66f49765d5 [ie/go] Improve error handling (#15882)
Closes #15774
Authored by: norepro
2026-08-25 16:30:27 +00:00
InvalidUsernameException 9fb5969797 [ie/ted] Fix extractor (#17510)
Closes #17507
Authored by: InvalidUsernameException
2026-08-25 01:45:23 +00:00
doe1080 88a9516584 [cleanup] Remove obsolete Python compatibility code (#17357)
Authored by: doe1080
2026-08-25 01:32:13 +00:00
doe1080 81ecd58b13 [ie/niconico:channel] Support channels (#17398)
Closes #9421
Authored by: doe1080
2026-08-20 22:26:03 +00:00
bashonly 5022b8c119 [update] Remove bad advice (#17492)
Authored by: bashonly
2026-08-20 22:20:28 +00:00
Mikel Olasagasti Uranga 91f784d6fd [test] Fix handshake error matching for OpenSSL 4.x (#17491)
Closes #17490
Authored by: mikelolasagasti
2026-08-20 22:04:50 +00:00
github-actions[bot] 3a08beaf03 Release 2026.08.19
Created by: bashonly

:ci skip all
2026-08-19 23:31:25 +00:00
bashonly 594bd50c2c [cleanup] Misc (#17446)
Thanks to @chloricacid

Authored by: bashonly
2026-08-19 23:27:56 +00:00
Simonandbashonly cf68b8f43f [ie/youtube:tab] Always extract channel metadata (#17386)
Closes #13155
Authored by: bbilly1, bashonly

Co-authored-by: bashonly <88596187+bashonly@users.noreply.github.com>
2026-08-19 23:26:11 +00:00
bashonly d3ea2cf84a [ie/whyp] Fix extractor (#17467)
Closes #17466
Authored by: bashonly
2026-08-19 23:23:07 +00:00
InvalidUsernameException ec9425fcd0 [ie/bandcamp] Support browser impersonation (#17422)
Closes #17356
Authored by: InvalidUsernameException
2026-08-19 23:22:30 +00:00
doe1080 2bbfb9972c [ie/twitter:broadcast] Fix events handling (#17323)
Authored by: doe1080
2026-08-19 23:20:13 +00:00
0xvd 537ed68684 [ie/BFMTV] Fix extractor (#16905)
Closes #16864
Authored by: 0xvd
2026-08-19 23:19:30 +00:00
bashonly 370f7820ea [ie/vimeo] Remove broken macos_basic client (#17481)
Partially revert fdcc954df4

Authored by: bashonly
2026-08-19 23:10:36 +00:00
bashonly 2c0bf96092 [ie/tiktok] Re-implement impersonation support (#17480)
Fix b375e1d85c

Authored by: bashonly
2026-08-19 22:56:04 +00:00
dlp-bot 1b0074911e [build] Update 11 dependencies (#17479)
* Add tomlkit 0.15.1
* Bump charset-normalizer 3.4.9 => 3.5.0
* Bump hatchling 1.31.0 => 1.32.0
* Bump platformdirs 4.11.1 => 4.11.2
* Bump pre-commit 4.6.1 => 4.6.2
* Bump pyinstaller 6.22.1 => 6.22.0
* Bump pyinstaller[win32] 6.22.1 => 6.22.0
* Bump pyinstaller[win_amd64] 6.22.1 => 6.22.0
* Bump pyinstaller[win_arm64] 6.22.1 => 6.22.0
* Bump python-discovery 1.5.1 => 1.5.2
* Bump virtualenv 21.7.3 => 21.7.4

Authored by: dlp-bot
2026-08-19 22:28:04 +00:00
bashonly 42fc40026f [build] Temporarily pin PyInstaller to v6.22.0 (#17478)
Authored by: bashonly
2026-08-19 22:11:45 +00:00
doe1080 0d1e029d14 [utils] Deprecate random_uuidv4 (#17301)
Authored by: doe1080
2026-08-19 15:42:14 +09:00
doe1080 4ce0e4d331 [utils] Deprecate number_of_digits (#17300)
Authored by: doe1080
2026-08-19 12:55:26 +09:00
doe1080 93a7a995e0 [utils] float_or_none: Catch OverflowError (#17299)
Authored by: doe1080
2026-08-19 11:48:42 +09:00
bashonly 5d5b634d8e [ie/youtube] Add web_embedded client fallbacks (#17462)
Authored by: bashonly
2026-08-18 12:10:10 +00:00
bashonly 6218535213 [ie/tiktok] Support share URLs (#17459)
Authored by: bashonly
2026-08-18 11:49:08 +00:00
bashonly 06ab8f6a90 [ie/tiktok] Fix formats extraction (#17460)
Closes #16622, Closes #17293, Closes #17372
Authored by: bashonly
2026-08-18 11:41:47 +00:00
bashonly dae52d8386 [ie/youtube] Remove android_vr from default clients (#17461)
Closes #17456
Authored by: bashonly
2026-08-18 11:38:11 +00:00
bashonly b375e1d85c [ie/tiktok] Fix extractor (#17452)
Closes #17403, Closes #17437
Authored by: bashonly
2026-08-18 10:17:12 +00:00
bashonly f1896c57f5 [build] Trigger nightly on requirement changes (#17450)
Authored by: bashonly
2026-08-17 07:37:52 +00:00
bashonly 2bf72df3de [build] Bump Windows PyInstaller requirements (#17449)
Closes #17448
Authored by: bashonly
2026-08-17 07:25:02 +00:00
dlp-bot 874af899e7 [ci] Update 7 actions in 10 workflows (#17345)
* Bump actions/checkout v7.0.0 => v7.0.1
* Bump actions/setup-node v6.4.0 => v7.0.0
* Bump actions/setup-python v6.3.0 => v7.0.0
* Bump denoland/setup-deno v2.0.4 => v2.0.5
* Bump github/codeql-action v4.36.3 => v4.37.7
* Bump pypa/gh-action-pypi-publish v1.14.0 => v1.14.2
* Bump zizmorcore/zizmor-action v0.5.7 => v0.6.2

Authored by: dlp-bot
2026-08-16 01:54:39 +00:00
dlp-botandbashonly dedde41288 [build] Update 27 dependencies (#17346)
* Bump certifi 2026.6.17 => 2026.7.22
* Bump cffi 2.0.0 => 2.1.1
* Bump charset-normalizer 3.4.7 => 3.4.9
* Bump cryptography 49.0.0 => 50.0.0
* Bump curl-cffi 0.15.0 => 0.16.0
* Bump deno 2.8.3 => 2.9.5
* Bump filelock 3.29.4 => 3.32.2
* Bump hatchling 1.30.1 => 1.31.0
* Bump packaging 26.2 => 26.3
* Bump pip 26.1.2 => 26.2.1
* Bump platformdirs 4.10.0 => 4.11.1
* Bump pre-commit 4.6.0 => 4.6.1
* Bump pyinstaller 6.21.0 => 6.22.1
* Bump pyinstaller[win32] 6.21.0 => 6.22.1
* Bump pyinstaller[win_amd64] 6.21.0 => 6.22.1
* Bump pyinstaller[win_arm64] 6.21.0 => 6.22.1
* Bump pytest-rerunfailures 16.3 => 16.4
* Bump python-discovery 1.4.2 => 1.5.1
* Bump ruff 0.15.19 => 0.16.2
* Bump setuptools 82.0.1 => 84.0.0
* Bump typing-extensions 4.15.0 => 4.16.0
* Bump uv 0.11.24 => 0.12.3
* Bump virtualenv 21.5.1 => 21.7.3
* Bump websockets 16.0 => 17.0.1
* Remove markdown-it-py 4.2.0
* Remove mdurl 0.1.2
* Remove rich 15.0.0

Authored by: bashonly, dlp-bot

Co-authored-by: bashonly <bashonly@protonmail.com>
2026-08-16 01:48:25 +00:00
bashonly 5f22bafc14 [build] Fix curl-cffi 0.16.x support on Python 3.10 (#17441)
Fix 4dc054d51c

Ref: https://github.com/lexiforest/curl_cffi/issues/834

Authored by: bashonly
2026-08-16 01:15:32 +00:00
4e969d3a6c [cleanup] Misc (#17159)
Closes #17196, Closes #17385
Authored by: bashonly, dialmaster, gamer191, BOplaid

Co-authored-by: Christopher Dial <dial.chris@gmail.com>
Co-authored-by: BOplaid <146466352+BOplaid@users.noreply.github.com>
Co-authored-by: gamer191 <83270075+gamer191@users.noreply.github.com>
2026-08-15 23:53:52 +00:00
bashonlyandcoletdjnz 4dc054d51c [rh:curl_cffi] Support curl_cffi 0.16.x (#17439)
Closes #17341
Authored by: bashonly, coletdjnz

Co-authored-by: coletdjnz <coletdjnz@protonmail.com>
2026-08-15 23:50:51 +00:00
InvalidUsernameException d2dcbfc574 [build] Support release tags that shadow branch names (#17409)
Authored by: InvalidUsernameException
2026-08-15 20:54:24 +00:00
doe1080 3f78dc4797 [test:socks] Fix compatibility with websockets>=17 (#17433)
Closes #17383
Authored by: doe1080
2026-08-15 20:34:51 +00:00
doe1080 3128f6a433 [test:networking] Fix logging handler removal test (#17379)
Ref: https://github.com/python/cpython/issues/79366

Authored by: doe1080
2026-08-15 19:52:26 +00:00
bashonly 5d6b8c8cd1 [ie/youtube] Extract channel_follower_count for collaborators (#17363)
To clarify the somewhat misleading subject line: this patch
only extracts the 1st collaborator's channel_follower_count
for videos with multiple collaborators.

Closes #17360
Authored by: bashonly
2026-08-04 22:58:34 +00:00
dlp-bot 15941bd48f [utils] random_user_agent: Bump version range 144-150 => 145-151 (#17344)
Authored by: dlp-bot
2026-08-04 14:28:47 +00:00
bashonly d798b9b8fb [ci] Fix broken Windows PyPy tests (#17347)
Workaround for https://github.com/actions/setup-python/issues/1348

Authored by: bashonly
2026-08-04 05:01:09 +00:00
bashonly fdcc954df4 [ie/vimeo] Add macos_basic client (#17292)
Authored by: bashonly
2026-07-23 16:54:48 +00:00
bashonly 07591f601e [ie/vimeo] Remove ios and macos clients (#17290)
Closes #17271, Closes #17286
Authored by: bashonly
2026-07-23 10:59:57 +00:00
bashonly aaf7405ba3 [ie/apple] Rework extractors (#17277)
* Add API fallback for ApplePodcastsIE
* Fix AppleConnectIE token extraction
* Refactor and add AppleBaseIE

Closes #17266
Authored by: bashonly
2026-07-21 23:09:21 +00:00
bashonly 1f1101d0dc [ie/instagram] Fix logged-in extraction (#17278)
Closes #17275
Authored by: bashonly
2026-07-21 23:02:13 +00:00
bashonly a8be438aac [ie/vimeo] Client maintenance (#17272)
Closes #17271
Authored by: bashonly
2026-07-20 23:41:12 +00:00
bashonly 69ea200067 [ie/youtube] Player client maintenance (#17261)
* Add visionos to logged-out default clients
* Add POT policy for android_vr
* Use tv_downgraded for VR fallback client
* Move back to web from web_safari in defaults

Closes #14997
Closes #15583
Closes #15756
Closes #15798
Closes #16064
Closes #17143
Closes #17232
Closes #17252

Authored by: bashonly
2026-07-20 23:36:39 +00:00
bashonly 93ceb95cdf [ie/youtube] Fix live adaptive fragments generation (#17262)
Fix bug in 8c1f07d813

Closes #17208
Authored by: bashonly
2026-07-20 23:24:23 +00:00
doe1080 aefce1eea4 [fd/hls] Fix crash on empty fragment lists in tests (#17218)
Authored by: doe1080
2026-07-14 14:14:20 +00:00
Brian Marks d9813a3da6 [ie/americastestkitchen] Fix season/series extraction (#17151)
Authored by: bm1549
2026-07-12 19:39:51 +00:00
doe1080 6a188aed91 [ie/showroom] Rework extractors (#17142)
Closes #2072, Closes #7297
Authored by: doe1080
2026-07-12 00:48:16 +00:00
bashonly 59d9ae606a [ie/youtube] Update player client versions (#17185)
Authored by: bashonly
2026-07-09 23:11:00 +00:00
bashonly 1328586f72 [ie/youtube] Add visionos player client (#17184)
Authored by: bashonly
2026-07-09 21:42:39 +00:00
bashonlyandsepro b3854cc41b [misc] Fix third party license information (#17150)
Authored by: bashonly, seproDev

Co-authored-by: sepro <sepro@sepr0.com>
2026-07-06 21:46:30 +00:00
InvalidUsernameException 981190089f [ie/ard] Remove dead extractor (#17158)
Closes #2630
Authored by: InvalidUsernameException
2026-07-06 21:44:28 +00:00
136 changed files with 6279 additions and 5715 deletions
+1 -1
View File
@@ -64,7 +64,7 @@ body:
[debug] Command-line config: ['-vU', 'https://www.youtube.com/watch?v=YE7VzlLtp-4']
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version nightly@... from yt-dlp/yt-dlp-nightly-builds [1a176d874] (win_exe)
[debug] Python 3.10.11 (CPython AMD64 64bit) - Windows-10-10.0.20348-SP0 (OpenSSL 1.1.1t 7 Feb 2023)
[debug] Python 3.14.x (CPython AMD64 64bit) - Windows-10-... (OpenSSL 3.y ...)
[debug] exe versions: ffmpeg 7.0.2 (setts), ffprobe 7.0.2
[debug] Optional libraries: Cryptodome-3.21.0, brotli-1.1.0, certifi-2024.08.30, curl_cffi-0.5.10, mutagen-1.47.0, requests-2.32.3, sqlite3-3.40.1, urllib3-2.2.3, websockets-13.1
[debug] Proxy map: {}
@@ -76,7 +76,7 @@ body:
[debug] Command-line config: ['-vU', 'https://www.youtube.com/watch?v=YE7VzlLtp-4']
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version nightly@... from yt-dlp/yt-dlp-nightly-builds [1a176d874] (win_exe)
[debug] Python 3.10.11 (CPython AMD64 64bit) - Windows-10-10.0.20348-SP0 (OpenSSL 1.1.1t 7 Feb 2023)
[debug] Python 3.14.x (CPython AMD64 64bit) - Windows-10-... (OpenSSL 3.y ...)
[debug] exe versions: ffmpeg 7.0.2 (setts), ffprobe 7.0.2
[debug] Optional libraries: Cryptodome-3.21.0, brotli-1.1.0, certifi-2024.08.30, curl_cffi-0.5.10, mutagen-1.47.0, requests-2.32.3, sqlite3-3.40.1, urllib3-2.2.3, websockets-13.1
[debug] Proxy map: {}
@@ -72,7 +72,7 @@ body:
[debug] Command-line config: ['-vU', 'https://www.youtube.com/watch?v=YE7VzlLtp-4']
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version nightly@... from yt-dlp/yt-dlp-nightly-builds [1a176d874] (win_exe)
[debug] Python 3.10.11 (CPython AMD64 64bit) - Windows-10-10.0.20348-SP0 (OpenSSL 1.1.1t 7 Feb 2023)
[debug] Python 3.14.x (CPython AMD64 64bit) - Windows-10-... (OpenSSL 3.y ...)
[debug] exe versions: ffmpeg 7.0.2 (setts), ffprobe 7.0.2
[debug] Optional libraries: Cryptodome-3.21.0, brotli-1.1.0, certifi-2024.08.30, curl_cffi-0.5.10, mutagen-1.47.0, requests-2.32.3, sqlite3-3.40.1, urllib3-2.2.3, websockets-13.1
[debug] Proxy map: {}
+1 -1
View File
@@ -53,7 +53,7 @@ body:
[debug] Command-line config: ['-vU', 'https://www.youtube.com/watch?v=YE7VzlLtp-4']
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version nightly@... from yt-dlp/yt-dlp-nightly-builds [1a176d874] (win_exe)
[debug] Python 3.10.11 (CPython AMD64 64bit) - Windows-10-10.0.20348-SP0 (OpenSSL 1.1.1t 7 Feb 2023)
[debug] Python 3.14.x (CPython AMD64 64bit) - Windows-10-... (OpenSSL 3.y ...)
[debug] exe versions: ffmpeg 7.0.2 (setts), ffprobe 7.0.2
[debug] Optional libraries: Cryptodome-3.21.0, brotli-1.1.0, certifi-2024.08.30, curl_cffi-0.5.10, mutagen-1.47.0, requests-2.32.3, sqlite3-3.40.1, urllib3-2.2.3, websockets-13.1
[debug] Proxy map: {}
+1 -1
View File
@@ -53,7 +53,7 @@ body:
[debug] Command-line config: ['-vU', 'https://www.youtube.com/watch?v=YE7VzlLtp-4']
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version nightly@... from yt-dlp/yt-dlp-nightly-builds [1a176d874] (win_exe)
[debug] Python 3.10.11 (CPython AMD64 64bit) - Windows-10-10.0.20348-SP0 (OpenSSL 1.1.1t 7 Feb 2023)
[debug] Python 3.14.x (CPython AMD64 64bit) - Windows-10-... (OpenSSL 3.y ...)
[debug] exe versions: ffmpeg 7.0.2 (setts), ffprobe 7.0.2
[debug] Optional libraries: Cryptodome-3.21.0, brotli-1.1.0, certifi-2024.08.30, curl_cffi-0.5.10, mutagen-1.47.0, requests-2.32.3, sqlite3-3.40.1, urllib3-2.2.3, websockets-13.1
[debug] Proxy map: {}
+1 -1
View File
@@ -59,7 +59,7 @@ body:
[debug] Command-line config: ['-vU', 'https://www.youtube.com/watch?v=YE7VzlLtp-4']
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version nightly@... from yt-dlp/yt-dlp-nightly-builds [1a176d874] (win_exe)
[debug] Python 3.10.11 (CPython AMD64 64bit) - Windows-10-10.0.20348-SP0 (OpenSSL 1.1.1t 7 Feb 2023)
[debug] Python 3.14.x (CPython AMD64 64bit) - Windows-10-... (OpenSSL 3.y ...)
[debug] exe versions: ffmpeg 7.0.2 (setts), ffprobe 7.0.2
[debug] Optional libraries: Cryptodome-3.21.0, brotli-1.1.0, certifi-2024.08.30, curl_cffi-0.5.10, mutagen-1.47.0, requests-2.32.3, sqlite3-3.40.1, urllib3-2.2.3, websockets-13.1
[debug] Proxy map: {}
+12
View File
@@ -22,3 +22,15 @@ paths:
ignore:
# https://github.com/rhysd/actionlint/issues/657
- 'unexpected key "queue" for "concurrency" section.+'
.github/workflows/release-master.yml:
ignore:
# https://github.com/rhysd/actionlint/issues/711
- 'reusable workflow call .+ at "uses" is not following the format.+'
.github/workflows/release-nightly.yml:
ignore:
# https://github.com/rhysd/actionlint/issues/711
- 'reusable workflow call .+ at "uses" is not following the format.+'
.github/workflows/release.yml:
ignore:
# https://github.com/rhysd/actionlint/issues/711
- 'reusable workflow call .+ at "uses" is not following the format.+'
+26 -20
View File
@@ -99,7 +99,7 @@ jobs:
import os
import re
INPUTS = json.loads(os.environ['INPUTS'])
timestamp = dt.datetime.now(tz=dt.timezone.utc).strftime('%Y.%m.%d.%H%M%S.%f')
timestamp = dt.datetime.now(tz=dt.UTC).strftime('%Y.%m.%d.%H%M%S.%f')
version = INPUTS.get('version')
if version and '.' not in version:
# build.yml was dispatched with only a revision as the version input value
@@ -195,14 +195,14 @@ jobs:
UPDATE_TO: yt-dlp/yt-dlp@2025.09.05
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # Needed for changelog
persist-credentials: false
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.10"
python-version: '3.14'
- name: Install Requirements
run: |
@@ -229,7 +229,7 @@ jobs:
[[ "${version}" != "${downgraded_version}" ]]
- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: build-bin-${{ github.job }}
path: |
@@ -259,13 +259,13 @@ jobs:
SKIP_ONEFILE_BUILD: ${{ (!matrix.onefile && '1') || '' }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up QEMU
if: matrix.qemu_platform
uses: docker/setup-qemu-action@96fe6ef7f33517b61c61be40b68a1882f3264fb8 # v4.2.0
uses: docker/setup-qemu-action@99012661954931238ded8c8b007157a8430204e1 # v4.4.0
with:
image: tonistiigi/binfmt:qemu-v10.0.4-56@sha256:30cc9a4d03765acac9be2ed0afc23af1ad018aed2c28ea4be8c2eb9afe03fbd1
cache-image: false
@@ -291,7 +291,7 @@ jobs:
docker compose up --build --exit-code-from "${SERVICE}" "${SERVICE}"
- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: build-bin-${{ matrix.os }}_${{ matrix.arch }}
path: |
@@ -312,7 +312,7 @@ jobs:
UPDATE_TO: yt-dlp/yt-dlp@2025.09.05
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
@@ -376,7 +376,7 @@ jobs:
[[ "$version" != "$downgraded_version" ]]
- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: build-bin-${{ github.job }}
path: |
@@ -396,7 +396,7 @@ jobs:
steps:
- name: Download artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
path: dist
pattern: build-bin-macos
@@ -423,13 +423,10 @@ jobs:
include:
- arch: 'x64'
runner: windows-2025
python_version: '3.10'
- arch: 'x86'
runner: windows-2025
python_version: '3.10'
- arch: 'arm64'
runner: windows-11-arm
python_version: '3.13' # arm64 only has Python >= 3.11 available
env:
CHANNEL: ${{ inputs.channel }}
ORIGIN: ${{ needs.process.outputs.origin }}
@@ -438,14 +435,15 @@ jobs:
UPDATE_TO: yt-dlp/yt-dlp@2025.09.05
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: ${{ matrix.python_version }}
python-version: '3.14'
architecture: ${{ matrix.arch }}
check-latest: true
- name: Install Requirements
env:
@@ -498,7 +496,7 @@ jobs:
}
- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: build-bin-${{ github.job }}-${{ matrix.arch }}
path: |
@@ -519,7 +517,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
path: artifact
pattern: build-bin-*
@@ -550,6 +548,8 @@ jobs:
lock 2025.08.11 darwin_legacy_exe .+
lock 2025.08.27 linux_armv7l_exe .+
lock 2025.10.14 zip Python 3\.9
lock 2026.10.21 zip Python 3\.10
lock 2026.10.21 win(?:_x86)?_exe Python .+ Windows-(?:8|2012Server)
lockV2 yt-dlp/yt-dlp 2022.08.18.36 .+ Python 3\.6
lockV2 yt-dlp/yt-dlp 2023.11.16 zip Python 3\.7
lockV2 yt-dlp/yt-dlp 2023.11.16 win_x86_exe .+ Windows-(?:Vista|2008Server)
@@ -559,6 +559,8 @@ jobs:
lockV2 yt-dlp/yt-dlp 2025.08.11 darwin_legacy_exe .+
lockV2 yt-dlp/yt-dlp 2025.08.27 linux_armv7l_exe .+
lockV2 yt-dlp/yt-dlp 2025.10.14 zip Python 3\.9
lockV2 yt-dlp/yt-dlp 2026.10.21 zip Python 3\.10
lockV2 yt-dlp/yt-dlp 2026.10.21 win(?:_x86)?_exe Python .+ Windows-(?:8|2012Server)
lockV2 yt-dlp/yt-dlp-nightly-builds 2023.11.15.232826 zip Python 3\.7
lockV2 yt-dlp/yt-dlp-nightly-builds 2023.11.15.232826 win_x86_exe .+ Windows-(?:Vista|2008Server)
lockV2 yt-dlp/yt-dlp-nightly-builds 2024.10.22.051025 py2exe .+
@@ -567,6 +569,8 @@ jobs:
lockV2 yt-dlp/yt-dlp-nightly-builds 2025.08.12.233030 darwin_legacy_exe .+
lockV2 yt-dlp/yt-dlp-nightly-builds 2025.08.30.232839 linux_armv7l_exe .+
lockV2 yt-dlp/yt-dlp-nightly-builds 2025.10.14.232845 zip Python 3\.9
lockV2 yt-dlp/yt-dlp-nightly-builds 2026.10.21.202512 zip Python 3\.10
lockV2 yt-dlp/yt-dlp-nightly-builds 2026.10.21.202512 win(?:_x86)?_exe Python .+ Windows-(?:8|2012Server)
lockV2 yt-dlp/yt-dlp-master-builds 2023.11.15.232812 zip Python 3\.7
lockV2 yt-dlp/yt-dlp-master-builds 2023.11.15.232812 win_x86_exe .+ Windows-(?:Vista|2008Server)
lockV2 yt-dlp/yt-dlp-master-builds 2024.10.22.045052 py2exe .+
@@ -575,6 +579,8 @@ jobs:
lockV2 yt-dlp/yt-dlp-master-builds 2025.08.12.232447 darwin_legacy_exe .+
lockV2 yt-dlp/yt-dlp-master-builds 2025.09.05.212910 linux_armv7l_exe .+
lockV2 yt-dlp/yt-dlp-master-builds 2025.10.14.232330 zip Python 3\.9
lockV2 yt-dlp/yt-dlp-master-builds 2026.10.21.213530 zip Python 3\.10
lockV2 yt-dlp/yt-dlp-master-builds 2026.10.21.213530 win(?:_x86)?_exe Python .+ Windows-(?:8|2012Server)
EOF
- name: Sign checksum files
@@ -588,7 +594,7 @@ jobs:
done
- name: Upload artifacts
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: build-${{ github.job }}
path: |
+30 -14
View File
@@ -36,52 +36,68 @@ jobs:
fail-fast: false
matrix:
os: [ubuntu-latest, windows-latest]
python-version: ['3.10', '3.11', '3.12', '3.13', '3.14', '3.15', pypy-3.11]
python-version: ['3.11', '3.12', '3.13', '3.14', '3.15', pypy-3.11, pypy-3.12]
env:
QJS_VERSION: '2025-04-26' # Earliest version with rope strings
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
- name: Install Deno
uses: denoland/setup-deno@667a34cdef165d8d2b2e98dde39547c9daac7282 # v2.0.4
uses: denoland/setup-deno@22d081ff2d3a40755e97629de92e3bcbfa7cf2ed # v2.0.5
with:
deno-version: '2.3.0' # minimum supported version
- name: Install Bun
uses: oven-sh/setup-bun@0c5077e51419868618aeaa5fe8019c62421857d6 # v2.2.0
with:
bun-version: '1.2.11' # minimum supported version
no-cache: true
- name: Install Node
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v6.4.0
uses: actions/setup-node@949feb2413d6458794dcd2491c4babbbce0c15c1 # v7.1.0
with:
node-version: '22.0' # minimum supported version
- name: Install QuickJS (Linux)
if: matrix.os == 'ubuntu-latest'
shell: bash
run: |
wget "https://bellard.org/quickjs/binary_releases/quickjs-linux-x86_64-${QJS_VERSION}.zip" -O quickjs.zip
unzip quickjs.zip qjs
sudo install qjs /usr/local/bin/qjs
wget "https://bellard.org/quickjs/binary_releases/quickjs-linux-x86_64-${QJS_VERSION}.zip" -O quickjs.zip
unzip quickjs.zip qjs
sudo install qjs /usr/local/bin/qjs
- name: Install QuickJS (Windows)
if: matrix.os == 'windows-latest'
shell: pwsh
run: |
$ErrorActionPreference = "Stop"
$PSNativeCommandUseErrorActionPreference = $true
Invoke-WebRequest "https://bellard.org/quickjs/binary_releases/quickjs-win-x86_64-${Env:QJS_VERSION}.zip" -OutFile quickjs.zip
unzip quickjs.zip
- name: Install test requirements
shell: bash
$ErrorActionPreference = "Stop"
$PSNativeCommandUseErrorActionPreference = $true
Invoke-WebRequest "https://bellard.org/quickjs/binary_releases/quickjs-win-x86_64-${Env:QJS_VERSION}.zip" -OutFile quickjs.zip
unzip quickjs.zip
- name: Install test requirements (cpython)
if: ${{ !startsWith(matrix.python-version, 'pypy') }}
run: |
python -m pip install -U --require-hashes -r "bundle/requirements/pip.txt"
python -m pip install -U --require-hashes -r "bundle/requirements/test.txt"
python -m pip install -U --require-hashes -r "bundle/requirements/default.txt"
- name: Install test requirements (PyPy)
if: ${{ startsWith(matrix.python-version, 'pypy') }}
run: |
# Upgrading/downgrading pip on Windows with actions/setup-python's PyPy can cause breakage
# See https://github.com/actions/setup-python/issues/1348
python -m pip install -U --require-hashes -r "bundle/requirements/test.txt"
python -m pip install -U --require-hashes -r "bundle/requirements/default.txt"
- name: Run tests
timeout-minutes: 15
shell: bash
+3 -3
View File
@@ -31,17 +31,17 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Initialize CodeQL
uses: github/codeql-action/init@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
uses: github/codeql-action/init@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
languages: ${{ matrix.language }}
build-mode: none
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@54f647b7e1bb85c95cddabcd46b0c578ec92bc1a # v4.36.3
uses: github/codeql-action/analyze@9b3254085494b55a0f7c4c2b3d2d52cc712ce370 # v4.39.1
with:
category: "/language:${{matrix.language}}"
+12 -23
View File
@@ -4,8 +4,8 @@ on:
branches: ['master']
paths:
- pyproject.toml
- .github/**
- devscripts/**
- .github/workflows/core.yml
- devscripts/run_tests.py
- test/**
- yt_dlp/**.py
- '!yt_dlp/extractor/**.py'
@@ -17,8 +17,8 @@ on:
branches: ['**']
paths:
- pyproject.toml
- .github/**
- devscripts/**
- .github/workflows/core.yml
- devscripts/run_tests.py
- test/**
- yt_dlp/**.py
- '!yt_dlp/extractor/**.py'
@@ -43,37 +43,25 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [ubuntu-latest]
# CPython 3.10 is in quick-test
python-version: ['3.11', '3.12', '3.13', '3.14', '3.15', pypy-3.11]
os: [ubuntu-latest, windows-latest]
# Linux CPython 3.11 is covered by quick-test.yml
python-version: ['3.12', '3.13', '3.14', '3.15', pypy-3.11, pypy-3.12]
include:
# atleast one of each CPython/PyPy tests must be in windows
- os: windows-latest
python-version: '3.10'
- os: windows-latest
python-version: '3.11'
- os: windows-latest
python-version: '3.12'
- os: windows-latest
python-version: '3.13'
- os: windows-latest
python-version: '3.14'
- os: windows-latest
python-version: '3.15'
- os: windows-latest
python-version: pypy-3.11
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: ${{ matrix.python-version }}
allow-prereleases: true
check-latest: true
- name: Install test requirements (cpython)
if: ${{ !startsWith(matrix.python-version, 'pypy') }}
@@ -85,7 +73,8 @@ jobs:
- name: Install test requirements (PyPy)
if: ${{ startsWith(matrix.python-version, 'pypy') }}
run: |
python -m pip install -U --require-hashes -r "bundle/requirements/pip.txt"
# Upgrading/downgrading pip on Windows with actions/setup-python's PyPy can cause breakage
# See https://github.com/actions/setup-python/issues/1348
python -m pip install -U --require-hashes -r "bundle/requirements/test.txt"
python -m pip install -U --require-hashes -r "bundle/requirements/default.txt"
+6 -6
View File
@@ -21,13 +21,13 @@ jobs:
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Set up Python 3.10
uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
- name: Set up Python 3.11
uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: '3.10'
python-version: '3.11'
- name: Install test requirements
shell: bash
run: |
@@ -48,10 +48,10 @@ jobs:
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: '3.14'
- name: Install dev dependencies
+3 -3
View File
@@ -24,7 +24,7 @@ jobs:
permissions:
contents: write # May be needed to publish release
id-token: write # Needed for trusted publishing
uses: ./.github/workflows/release.yml
uses: $/.github/workflows/release.yml
with:
prerelease: true
source: ${{ (github.repository != 'yt-dlp/yt-dlp' && vars.MASTER_ARCHIVE_REPO) || 'master' }}
@@ -42,11 +42,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
path: dist
name: build-pypi
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
with:
verbose: true
+5 -4
View File
@@ -16,7 +16,7 @@ jobs:
outputs:
commit: ${{ steps.check_for_new_commits.outputs.commit }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: false
@@ -46,6 +46,7 @@ jobs:
"bundle/*.py"
"bundle/docker/compose.yml"
"bundle/docker/linux/*"
"bundle/requirements/*"
"pyproject.toml"
"Makefile"
".github/workflows/build.yml"
@@ -76,7 +77,7 @@ jobs:
permissions:
contents: write # May be needed to publish release
id-token: write # Needed for trusted publishing
uses: ./.github/workflows/release.yml
uses: $/.github/workflows/release.yml
with:
prerelease: true
source: ${{ (github.repository != 'yt-dlp/yt-dlp' && vars.NIGHTLY_ARCHIVE_REPO) || 'nightly' }}
@@ -94,12 +95,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Download artifacts
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
path: dist
name: build-pypi
- name: Publish to PyPI
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
with:
verbose: true
+15 -15
View File
@@ -84,15 +84,15 @@ jobs:
head_sha: ${{ steps.get_target.outputs.head_sha }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: true # Needed to git-push the release commit
ssh-key: ${{ secrets.RELEASE_KEY }}
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13" # Keep this in sync with test-workflows.yml
python-version: '3.14' # Keep this in sync with test-workflows.yml
- name: Process inputs
id: process_inputs
@@ -155,7 +155,7 @@ jobs:
needs: [prepare]
permissions:
contents: read
uses: ./.github/workflows/build.yml
uses: $/.github/workflows/build.yml
with:
version: ${{ needs.prepare.outputs.version }}
channel: ${{ needs.prepare.outputs.channel }}
@@ -174,13 +174,13 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0 # Needed for changelog
persist-credentials: false
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
python-version: '3.14'
- name: Install Requirements
run: |
@@ -215,7 +215,7 @@ jobs:
- name: Upload artifacts
if: github.event.workflow != '.github/workflows/release.yml' # Reusable workflow_call
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
with:
name: build-pypi
path: |
@@ -224,7 +224,7 @@ jobs:
- name: Publish to PyPI
if: github.event.workflow == '.github/workflows/release.yml' # Direct workflow_dispatch
uses: pypa/gh-action-pypi-publish@cef221092ed1bacb1cc03d23a2d87d1d172e277b # v1.14.0
uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # v1.14.3
with:
verbose: true
@@ -240,19 +240,19 @@ jobs:
VERSION: ${{ needs.prepare.outputs.version }}
HEAD_SHA: ${{ needs.prepare.outputs.head_sha }}
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
fetch-depth: 0
persist-credentials: true # Needed to git-push the release tag
ssh-key: ${{ secrets.RELEASE_KEY }}
- uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
with:
path: artifact
pattern: build-*
merge-multiple: true
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13"
python-version: '3.14'
- name: Generate release notes
env:
@@ -280,7 +280,7 @@ jobs:
fi
printf '\n\n%s\n\n%s%s%s\n\n---\n' \
"#### A description of the various files is in the [README](https://github.com/${REPOSITORY}#release-files)" \
"The zipimport Unix executable contains code licensed under ISC and MIT. " \
"The zipimport Unix executable and release tarball contain code licensed under ISC and MIT. " \
"The PyInstaller-bundled executables are subject to these and other licenses, all of which are compiled in " \
"[THIRD_PARTY_LICENSES.txt](https://github.com/${BASE_REPO}/blob/${HEAD_SHA}/THIRD_PARTY_LICENSES.txt)" >> ./RELEASE_NOTES
python ./devscripts/make_changelog.py -vv --collapsible >> ./RELEASE_NOTES
@@ -316,7 +316,7 @@ jobs:
if: env.TARGET_REPO == github.repository
run: |
git tag "${TARGET_TAG}" "${HEAD_SHA}"
git push origin "${TARGET_TAG}"
git push origin "refs/tags/${TARGET_TAG}"
sleep 5 # Enough time to cover git-push vs gh-release-create race condition
- name: Publish release
+1 -1
View File
@@ -2,7 +2,7 @@ name: Sanitize comment
on:
issue_comment:
types: [created, edited]
types: [created, edited] # zizmor: ignore[dangerous-triggers]
permissions: {}
+5 -5
View File
@@ -26,13 +26,13 @@ jobs:
contents: read
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- uses: actions/setup-python@ece7cb06caefa5fff74198d8649806c4678c61a1 # v6.3.0
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7.1.0
with:
python-version: "3.13" # Keep this in sync with release.yml's prepare job
python-version: '3.14' # Keep this in sync with release.yml's prepare job
- name: Install Python dependencies
run: |
@@ -78,12 +78,12 @@ jobs:
actions: read # Needed by zizmorcore/zizmor-action if repository is private
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Run zizmor
uses: zizmorcore/zizmor-action@192e21d79ab29983730a13d1382995c2307fbcaa # v0.5.7
uses: zizmorcore/zizmor-action@53290badfa369cb0bf7ad16342cb62c2fa47ac7b # v0.8.0
with:
advanced-security: false
persona: pedantic
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
contents: write # Needed to git-push to the wiki
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
repository: yt-dlp/yt-dlp-wiki
ref: master
+2 -2
View File
@@ -64,7 +64,7 @@ $ yt-dlp -vU <your command line>
[debug] Command-line config: ['-vU', 'https://www.example.com/']
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version nightly@... from yt-dlp/yt-dlp-nightly-builds [1a176d874] (win_exe)
[debug] Python 3.10.11 (CPython AMD64 64bit) - Windows-10-10.0.20348-SP0 (OpenSSL 1.1.1t 7 Feb 2023)
[debug] Python 3.14.x (CPython AMD64 64bit) - Windows-10-... (OpenSSL 3.y ...)
[debug] exe versions: ffmpeg 7.0.2 (setts), ffprobe 7.0.2
[debug] Optional libraries: Cryptodome-3.21.0, brotli-1.1.0, certifi-2024.08.30, curl_cffi-0.5.10, mutagen-1.47.0, requests-2.32.3, sqlite3-3.40.1, urllib3-2.2.3, websockets-13.1
[debug] Proxy map: {}
@@ -294,7 +294,7 @@ After you have ensured this site is distributing its content legally, you can fo
You can use `hatch fmt` to automatically fix problems. Rules that the linter/formatter enforces should not be disabled with `# noqa` unless a maintainer requests it. The only exception allowed is for old/printf-style string formatting in GraphQL query templates (use `# noqa: UP031`).
1. Make sure your code works under all [Python](https://www.python.org/) versions supported by yt-dlp, namely CPython >=3.10 and PyPy >=3.11. Backward compatibility is not required for even older versions of Python.
1. Make sure your code works under all [Python](https://www.python.org/) versions supported by yt-dlp, namely CPython >=3.11 and PyPy >=3.11. Backward compatibility is not required for even older versions of Python.
1. When the tests pass, [add](https://git-scm.com/docs/git-add) the new files, [commit](https://git-scm.com/docs/git-commit) them and [push](https://git-scm.com/docs/git-push) the result, like this:
```shell
+7
View File
@@ -899,3 +899,10 @@ Sec-Wayne
selfhoster1312
tcely
tewhalen
bm1549
error-reporting
FraFraFra-LongD
LillieH1000
mikelolasagasti
ruben1PvP
wlerin
+156
View File
@@ -4,6 +4,162 @@
# To create a release, dispatch the https://github.com/yt-dlp/yt-dlp/actions/workflows/release.yml workflow on master
-->
### 2026.10.26
#### Important changes
- **The minimum *required* Python version has been raised to 3.11**
- Python 3.10 has reached its end-of-life as of October 2026, and yt-dlp has now removed support for it. [Read more](https://github.com/yt-dlp/yt-dlp/issues/16916)
- **The official Windows release binaries now require Windows 10 or later.** [Read more](https://github.com/yt-dlp/yt-dlp/issues/16917)
- Security: The recent `brotli` and `certifi` vulnerabilities have now been fully addressed in the executables
- The `brotli` package bundled with the executables has been upgraded to version 1.2.1, and the `curl-cffi` package has been upgraded to version 0.17.0. These upgrades address the recent [`brotli` security vulnerability](https://github.com/advisories/GHSA-9v8h-qqgm-4m35)
- `curl-cffi` 0.17.0 also fully addresses the recent [`certifi` security vulnerability](https://github.com/advisories/GHSA-6q48-6c7w-9gw2) that was already partially addressed by upgrading the `certifi` package bundled with the executables
#### Core changes
- [Remove Python 3.10 support](https://github.com/yt-dlp/yt-dlp/commit/3d28cf4780fa88689fc50010d72cf2f40ce3a3b8) ([#17160](https://github.com/yt-dlp/yt-dlp/issues/17160)) by [bashonly](https://github.com/bashonly), [doe1080](https://github.com/doe1080), [Grub4K](https://github.com/Grub4K)
#### Extractor changes
- **odnoklassniki**: [Fix boosty direct link extraction](https://github.com/yt-dlp/yt-dlp/commit/fa9886678eb65103303c627b8e013f13f8999b41) ([#17749](https://github.com/yt-dlp/yt-dlp/issues/17749)) by [bashonly](https://github.com/bashonly)
#### Networking changes
- **Request Handler**: curl_cffi: [Support `curl_cffi` 0.17.x](https://github.com/yt-dlp/yt-dlp/commit/7f7106cd323e17ffd3d4119250739cf1ae520cea) ([#17929](https://github.com/yt-dlp/yt-dlp/issues/17929)) by [bashonly](https://github.com/bashonly) (With fixes in [15262b0](https://github.com/yt-dlp/yt-dlp/commit/15262b0b9813131e72236f7fc9a663407ac295b1))
#### Misc. changes
- **build**
- [Always use latest Python version on Windows](https://github.com/yt-dlp/yt-dlp/commit/9b58cb33d0cd3e823c8d8732f6adce8faa1f37e3) ([#17901](https://github.com/yt-dlp/yt-dlp/issues/17901)) by [bashonly](https://github.com/bashonly)
- [Update 13 dependencies](https://github.com/yt-dlp/yt-dlp/commit/7747073a2b00ca4688637eef4e168af9d2a806cb) ([#17924](https://github.com/yt-dlp/yt-dlp/issues/17924)) by [bashonly](https://github.com/bashonly), [dlp-bot](https://github.com/dlp-bot)
- [Update 3 dependencies](https://github.com/yt-dlp/yt-dlp/commit/c91f8de0bfb3577894abad716eaaa01659e6bd14) ([#17933](https://github.com/yt-dlp/yt-dlp/issues/17933)) by [dlp-bot](https://github.com/dlp-bot)
- **ci**
- [Test with PyPy 3.12](https://github.com/yt-dlp/yt-dlp/commit/755a01732c2d8f1406b23221f0d1b68af8e00fc5) ([#17926](https://github.com/yt-dlp/yt-dlp/issues/17926)) by [gamer191](https://github.com/gamer191)
- [Update 7 actions in 9 workflows](https://github.com/yt-dlp/yt-dlp/commit/fd26888eb0087daf601ae3b2c79650e0d693ea60) ([#17925](https://github.com/yt-dlp/yt-dlp/issues/17925)) by [bashonly](https://github.com/bashonly), [dlp-bot](https://github.com/dlp-bot)
- **cleanup**: Miscellaneous: [7e3644c](https://github.com/yt-dlp/yt-dlp/commit/7e3644cfa6d6a965889ce23c9e50f46ecc1cb705) by [bashonly](https://github.com/bashonly), [doe1080](https://github.com/doe1080)
- **docs**: [Add changelog entries for dropping Py3.10 & Win8 support](https://github.com/yt-dlp/yt-dlp/commit/43a45ae37419b2a90db710c9fd06cd250ef524d3) ([#17889](https://github.com/yt-dlp/yt-dlp/issues/17889)) by [bashonly](https://github.com/bashonly)
### 2026.10.21
#### Important changes
- Security: Old yt-dlp executables are vulnerable to man-in-the-middle attacks
- A man-in-the-middle/MITM attack is when your internet traffic is intercepted by an attacker that impersonates the website(s) you browse and sends you malicious data instead.
- If you think you may be targeted by such an attack, it is strongly recommended to avoid using the self-updater (e.g. the `-U`, `--update`, `--update-to` command-line options), and instead manually download and install this release's executable.
- For more details, see the [`certifi` security advisory](https://github.com/advisories/GHSA-6q48-6c7w-9gw2)
#### Core changes
- **update**
- [Detect GitHub error page responses](https://github.com/yt-dlp/yt-dlp/commit/8377aa9555c308ca95630a28c1f91decd6c2235a) ([#17555](https://github.com/yt-dlp/yt-dlp/issues/17555)) by [bashonly](https://github.com/bashonly)
- [Remove bad advice](https://github.com/yt-dlp/yt-dlp/commit/5022b8c1192b643a19b2750e5989dd9212ab41dc) ([#17492](https://github.com/yt-dlp/yt-dlp/issues/17492)) by [bashonly](https://github.com/bashonly)
- **utils**
- [Improve `Content-Disposition` filename parsing](https://github.com/yt-dlp/yt-dlp/commit/28731cbacbac08268d027d5d35fbe567aee5812a) ([#17727](https://github.com/yt-dlp/yt-dlp/issues/17727)) by [doe1080](https://github.com/doe1080)
- `devalue`: [Improve binary type parsing](https://github.com/yt-dlp/yt-dlp/commit/bbc809a1161d3bfca51fa36f59dda35556ee85a0) ([#16934](https://github.com/yt-dlp/yt-dlp/issues/16934)) by [doe1080](https://github.com/doe1080)
- `download_range_func`: [Improve `__eq__` and `__repr__`](https://github.com/yt-dlp/yt-dlp/commit/f1df65d5d7a97bd81b3c70bf4bc41897b0616f6e) ([#16393](https://github.com/yt-dlp/yt-dlp/issues/16393)) by [atsushi2965](https://github.com/atsushi2965)
- `setproctitle`: [Fix NUL termination](https://github.com/yt-dlp/yt-dlp/commit/39b31b2755ad480f4bf07307e7d9cfc664cb2333) ([#17724](https://github.com/yt-dlp/yt-dlp/issues/17724)) by [doe1080](https://github.com/doe1080)
- `subs_list_to_dict`: [Fix empty value handling](https://github.com/yt-dlp/yt-dlp/commit/fcdbefb85f34059302215407b4a9f332eeffda23) ([#17311](https://github.com/yt-dlp/yt-dlp/issues/17311)) by [doe1080](https://github.com/doe1080)
#### Extractor changes
- [Do not warn on intentional generic results](https://github.com/yt-dlp/yt-dlp/commit/9caaf45401494e87a44562784a100e018e40f90e) ([#16683](https://github.com/yt-dlp/yt-dlp/issues/16683)) by [FraFraFra-LongD](https://github.com/FraFraFra-LongD)
- **adn**: [Add `profile_id` extractor-arg](https://github.com/yt-dlp/yt-dlp/commit/e164eebe19a6cb1aa1db4b45a8d6eb46ed7fbb48) ([#17522](https://github.com/yt-dlp/yt-dlp/issues/17522)) by [arobase-che](https://github.com/arobase-che)
- **applepodcasts**: [Fix token caching](https://github.com/yt-dlp/yt-dlp/commit/2f3929ba1a79996779deb4ad0d7b11368ca355ac) ([#17567](https://github.com/yt-dlp/yt-dlp/issues/17567)) by [tcely](https://github.com/tcely)
- **bandcamp**: [Fix extractors](https://github.com/yt-dlp/yt-dlp/commit/1d1351f40f0cbccd113e5b1ad1a37621008361ff) ([#17546](https://github.com/yt-dlp/yt-dlp/issues/17546)) by [bashonly](https://github.com/bashonly)
- **globalplayer**: [Fix extractors](https://github.com/yt-dlp/yt-dlp/commit/94eba4c156af080e87caf10cf8ffbea03bd17407) ([#17442](https://github.com/yt-dlp/yt-dlp/issues/17442)) by [LillieH1000](https://github.com/LillieH1000)
- **go**: [Improve error handling](https://github.com/yt-dlp/yt-dlp/commit/66f49765d5a46c7be1c2c414f245c71530c4a2fd) ([#15882](https://github.com/yt-dlp/yt-dlp/issues/15882)) by [norepro](https://github.com/norepro)
- **kick**: [Rework extractors](https://github.com/yt-dlp/yt-dlp/commit/fe84bef3969de96ceb39ca988425fdd3895bbfb1) ([#17322](https://github.com/yt-dlp/yt-dlp/issues/17322)) by [doe1080](https://github.com/doe1080), [InvalidUsernameException](https://github.com/InvalidUsernameException)
- **niconico**: channel: [Support channels](https://github.com/yt-dlp/yt-dlp/commit/81ecd58b1394793e6da9998cc19fdb45657f1685) ([#17398](https://github.com/yt-dlp/yt-dlp/issues/17398)) by [doe1080](https://github.com/doe1080)
- **odnoklassniki**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/51bab8a0116f4d8004c315706d809782607d5847) ([#17739](https://github.com/yt-dlp/yt-dlp/issues/17739)) by [InvalidUsernameException](https://github.com/InvalidUsernameException)
- **showroom**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/a2a8846b0d3ee87f5c31fc8615c790a84874dde7) ([#17488](https://github.com/yt-dlp/yt-dlp/issues/17488)) by [doe1080](https://github.com/doe1080), [wlerin](https://github.com/wlerin)
- **ted**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/9fb5969797e79d5138605ae6c2ae59e2a6e3be55) ([#17510](https://github.com/yt-dlp/yt-dlp/issues/17510)) by [InvalidUsernameException](https://github.com/InvalidUsernameException)
- **tubitv**
- [Improve extractor](https://github.com/yt-dlp/yt-dlp/commit/d1cb4709cc7cb6130a544ec9d5f5be40943aa383) ([#16428](https://github.com/yt-dlp/yt-dlp/issues/16428)) by [InvalidUsernameException](https://github.com/InvalidUsernameException)
- series: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/2089f8ad37de3a197c14afa4fb2bf066324409fd) ([#17545](https://github.com/yt-dlp/yt-dlp/issues/17545)) by [InvalidUsernameException](https://github.com/InvalidUsernameException)
- **twitch**: clips: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/28d35b7762ee4fb8c1214b2d26e7a28630d03992) ([#17554](https://github.com/yt-dlp/yt-dlp/issues/17554)) by [bashonly](https://github.com/bashonly)
- **youtube**
- [Add `tv_samsung` client](https://github.com/yt-dlp/yt-dlp/commit/817450d28d72e12c9fbac6b4c435ee97e68083ef) ([#17723](https://github.com/yt-dlp/yt-dlp/issues/17723)) by [error-reporting](https://github.com/error-reporting)
- [Fix initial data extraction](https://github.com/yt-dlp/yt-dlp/commit/12ac9aca79671420724227aca37bc888c604a6f8) ([#17703](https://github.com/yt-dlp/yt-dlp/issues/17703)) by [InvalidUsernameException](https://github.com/InvalidUsernameException)
- [Improve error messages](https://github.com/yt-dlp/yt-dlp/commit/a51ef56c03e64c37fe6fe0337752515fc3b06354) ([#17884](https://github.com/yt-dlp/yt-dlp/issues/17884)) by [gamer191](https://github.com/gamer191)
- [Set `tv_samsung` as a default client](https://github.com/yt-dlp/yt-dlp/commit/897341241f2bfb2439fe0367f4c7c9ccd29a3828) ([#17805](https://github.com/yt-dlp/yt-dlp/issues/17805)) by [ruben1PvP](https://github.com/ruben1PvP)
- [Use Safari UA for web_embedded client](https://github.com/yt-dlp/yt-dlp/commit/c7fb478d21e9e59524befbe23f7801bb267fb880) ([#17684](https://github.com/yt-dlp/yt-dlp/issues/17684)) by [gamer191](https://github.com/gamer191)
#### Networking changes
- [Fix `+` decoding in SOCKS proxy credentials](https://github.com/yt-dlp/yt-dlp/commit/caf63903a1f59e1765bfb390df2d89f47ae7a310) ([#17728](https://github.com/yt-dlp/yt-dlp/issues/17728)) by [doe1080](https://github.com/doe1080)
- **Request Handler**
- urllib
- [Eagerly release `BytesIO` responses](https://github.com/yt-dlp/yt-dlp/commit/f9eee6ba6252ea7924d2afcc27da4fd99c4dae3f) ([#17717](https://github.com/yt-dlp/yt-dlp/issues/17717)) by [doe1080](https://github.com/doe1080)
- [Fix relative redirects with dot segments](https://github.com/yt-dlp/yt-dlp/commit/c2901ed367e359e9b70309a10f99c0ba449edcf4) ([#17712](https://github.com/yt-dlp/yt-dlp/issues/17712)) by [doe1080](https://github.com/doe1080)
- websockets: [Add legacy `connect` workaround for >=17.1](https://github.com/yt-dlp/yt-dlp/commit/a29f2a2b926cc16db9f8183172aeb5e17c8aa6d0) ([#17747](https://github.com/yt-dlp/yt-dlp/issues/17747)) by [bashonly](https://github.com/bashonly)
#### Misc. changes
- **build**
- [Bypass cooldown for `deno`](https://github.com/yt-dlp/yt-dlp/commit/f82b268121fcb9313c5d78654f053606223d8483) ([#17880](https://github.com/yt-dlp/yt-dlp/issues/17880)) by [bashonly](https://github.com/bashonly)
- [Fix armv7l executable verification](https://github.com/yt-dlp/yt-dlp/commit/8cdf4fea48ecf4064387375301d7f294ebdb17c1) ([#17886](https://github.com/yt-dlp/yt-dlp/issues/17886)) by [bashonly](https://github.com/bashonly)
- [Update 2 dependencies](https://github.com/yt-dlp/yt-dlp/commit/f59cd0ba0a3c666fa5d8793b073fa9f03cfecc22) ([#17882](https://github.com/yt-dlp/yt-dlp/issues/17882)) by [bashonly](https://github.com/bashonly), [dlp-bot](https://github.com/dlp-bot)
- [Update 33 dependencies](https://github.com/yt-dlp/yt-dlp/commit/70279f2f0c576e23e1ec1406317d2cb85586af3f) ([#17581](https://github.com/yt-dlp/yt-dlp/issues/17581)) by [bashonly](https://github.com/bashonly), [dlp-bot](https://github.com/dlp-bot)
- **ci**: [Update 3 actions in 3 workflows](https://github.com/yt-dlp/yt-dlp/commit/779f59966974dcec0370a5834f78d7747aafe43c) ([#17748](https://github.com/yt-dlp/yt-dlp/issues/17748)) by [bashonly](https://github.com/bashonly), [dlp-bot](https://github.com/dlp-bot)
- **cleanup**
- [Remove obsolete Python compatibility code](https://github.com/yt-dlp/yt-dlp/commit/88a9516584a2de7e27ffdbcd39875d2bf4813378) ([#17357](https://github.com/yt-dlp/yt-dlp/issues/17357)) by [doe1080](https://github.com/doe1080)
- Miscellaneous: [36b92b4](https://github.com/yt-dlp/yt-dlp/commit/36b92b4f16c886df59de36f238db2534525b64a4) by [bashonly](https://github.com/bashonly), [gamer191](https://github.com/gamer191), [tcely](https://github.com/tcely)
- **devscripts**: `update_requirements`: [Preserve `cffi` dependencies on `PyPy`](https://github.com/yt-dlp/yt-dlp/commit/8a49065e18f34b437b71169bfb04319d9fcd229f) ([#17716](https://github.com/yt-dlp/yt-dlp/issues/17716)) by [doe1080](https://github.com/doe1080)
- **docs**: [Fix `Namespace` documentation](https://github.com/yt-dlp/yt-dlp/commit/3d062c86eab289a4dfd5b4f8c1992dc2a96e8c78) ([#17324](https://github.com/yt-dlp/yt-dlp/issues/17324)) by [doe1080](https://github.com/doe1080)
- **requirements**: [Fix locking for `pycparser`](https://github.com/yt-dlp/yt-dlp/commit/f45f14bd792bb998e987916608371939c345afce) ([#17746](https://github.com/yt-dlp/yt-dlp/issues/17746)) by [Grub4K](https://github.com/Grub4K)
- **test**
- [Fix handshake error matching for OpenSSL 4.x](https://github.com/yt-dlp/yt-dlp/commit/91f784d6fd911c0b8fc91645a9ba61ded0a8abb4) ([#17491](https://github.com/yt-dlp/yt-dlp/issues/17491)) by [mikelolasagasti](https://github.com/mikelolasagasti)
- websockets: [Update server hang workaround](https://github.com/yt-dlp/yt-dlp/commit/9dd5e68cd7adf3abc70d229ab6805d4686414f1b) ([#17718](https://github.com/yt-dlp/yt-dlp/issues/17718)) by [doe1080](https://github.com/doe1080)
### 2026.08.19
#### Core changes
- **utils**
- [Deprecate `number_of_digits`](https://github.com/yt-dlp/yt-dlp/commit/4ce0e4d331c34ea1fb8b7f7ec50a0036f3ddcab3) ([#17300](https://github.com/yt-dlp/yt-dlp/issues/17300)) by [doe1080](https://github.com/doe1080)
- [Deprecate `random_uuidv4`](https://github.com/yt-dlp/yt-dlp/commit/0d1e029d14058ddfb986fdafb07c00869c89105a) ([#17301](https://github.com/yt-dlp/yt-dlp/issues/17301)) by [doe1080](https://github.com/doe1080)
- `float_or_none`: [Catch `OverflowError`](https://github.com/yt-dlp/yt-dlp/commit/93a7a995e02b098d95b3e7e8d48a3fe16aa511ec) ([#17299](https://github.com/yt-dlp/yt-dlp/issues/17299)) by [doe1080](https://github.com/doe1080)
- `random_user_agent`: [Bump version range 144-150 => 145-151](https://github.com/yt-dlp/yt-dlp/commit/15941bd48fdbc665c12232b047b9a1c89a5a8a29) ([#17344](https://github.com/yt-dlp/yt-dlp/issues/17344)) by [dlp-bot](https://github.com/dlp-bot)
#### Extractor changes
- **americastestkitchen**: [Fix season/series extraction](https://github.com/yt-dlp/yt-dlp/commit/d9813a3da6959662841dfb34cad0ee6c07a65d1e) ([#17151](https://github.com/yt-dlp/yt-dlp/issues/17151)) by [bm1549](https://github.com/bm1549)
- **apple**: [Rework extractors](https://github.com/yt-dlp/yt-dlp/commit/aaf7405ba3a45b32c59f160426efc9b561af035a) ([#17277](https://github.com/yt-dlp/yt-dlp/issues/17277)) by [bashonly](https://github.com/bashonly)
- **ard**: [Remove dead extractor](https://github.com/yt-dlp/yt-dlp/commit/981190089f5bb75ae691c29c8a5d9d7be87ba8a6) ([#17158](https://github.com/yt-dlp/yt-dlp/issues/17158)) by [InvalidUsernameException](https://github.com/InvalidUsernameException)
- **bandcamp**: [Support browser impersonation](https://github.com/yt-dlp/yt-dlp/commit/ec9425fcd06b04cb980eb73c03aae241ef6e87a3) ([#17422](https://github.com/yt-dlp/yt-dlp/issues/17422)) by [InvalidUsernameException](https://github.com/InvalidUsernameException)
- **bfmtv**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/537ed68684587fc9aa191275154f0c350f5a452a) ([#16905](https://github.com/yt-dlp/yt-dlp/issues/16905)) by [0xvd](https://github.com/0xvd)
- **instagram**: [Fix logged-in extraction](https://github.com/yt-dlp/yt-dlp/commit/1f1101d0dc8a0ee316540fc938edbaca43e4977b) ([#17278](https://github.com/yt-dlp/yt-dlp/issues/17278)) by [bashonly](https://github.com/bashonly)
- **showroom**: [Rework extractors](https://github.com/yt-dlp/yt-dlp/commit/6a188aed91fb0a1b9d62f20377015b8fd2c69762) ([#17142](https://github.com/yt-dlp/yt-dlp/issues/17142)) by [doe1080](https://github.com/doe1080)
- **tiktok**
- [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/b375e1d85c8f32c1499bb6ea25f0f200fca25c33) ([#17452](https://github.com/yt-dlp/yt-dlp/issues/17452)) by [bashonly](https://github.com/bashonly) (With fixes in [2c0bf96](https://github.com/yt-dlp/yt-dlp/commit/2c0bf960920da8c0a6595293a401ae6fdd311f76))
- [Fix formats extraction](https://github.com/yt-dlp/yt-dlp/commit/06ab8f6a907d9495c9a90605e5a03acc8e21f976) ([#17460](https://github.com/yt-dlp/yt-dlp/issues/17460)) by [bashonly](https://github.com/bashonly)
- [Support share URLs](https://github.com/yt-dlp/yt-dlp/commit/6218535213c4e9f4cd053707483f0c012e8e2fb8) ([#17459](https://github.com/yt-dlp/yt-dlp/issues/17459)) by [bashonly](https://github.com/bashonly)
- **twitter**: broadcast: [Fix events handling](https://github.com/yt-dlp/yt-dlp/commit/2bbfb9972c8f514740a5fcfdff38374d08e9c15c) ([#17323](https://github.com/yt-dlp/yt-dlp/issues/17323)) by [doe1080](https://github.com/doe1080)
- **vimeo**: [Remove `ios` and `macos` clients](https://github.com/yt-dlp/yt-dlp/commit/07591f601e55c9d23399c07bf5fe1136f0913888) ([#17290](https://github.com/yt-dlp/yt-dlp/issues/17290)) by [bashonly](https://github.com/bashonly)
- **whyp**: [Fix extractor](https://github.com/yt-dlp/yt-dlp/commit/d3ea2cf84a02dfff9cf92bf7ecc31ce936e64621) ([#17467](https://github.com/yt-dlp/yt-dlp/issues/17467)) by [bashonly](https://github.com/bashonly)
- **youtube**
- [Add `visionos` player client](https://github.com/yt-dlp/yt-dlp/commit/1328586f72cef4cb4cff33e9eff87ad5b7b9fb60) ([#17184](https://github.com/yt-dlp/yt-dlp/issues/17184)) by [bashonly](https://github.com/bashonly)
- [Add `web_embedded` client fallbacks](https://github.com/yt-dlp/yt-dlp/commit/5d5b634d8e6b41dc2891847a5ea7a5a3f569a28c) ([#17462](https://github.com/yt-dlp/yt-dlp/issues/17462)) by [bashonly](https://github.com/bashonly)
- [Extract `channel_follower_count` for collaborators](https://github.com/yt-dlp/yt-dlp/commit/5d6b8c8cd19785c3086ae3a9ec618c45e25eb3bc) ([#17363](https://github.com/yt-dlp/yt-dlp/issues/17363)) by [bashonly](https://github.com/bashonly)
- [Fix live adaptive fragments generation](https://github.com/yt-dlp/yt-dlp/commit/93ceb95cdf0eb05d8a2515e3760fd62239683b82) ([#17262](https://github.com/yt-dlp/yt-dlp/issues/17262)) by [bashonly](https://github.com/bashonly)
- [Player client maintenance](https://github.com/yt-dlp/yt-dlp/commit/69ea200067c274667984c6495578a957ab7ca606) ([#17261](https://github.com/yt-dlp/yt-dlp/issues/17261)) by [bashonly](https://github.com/bashonly)
- [Remove `android_vr` from default clients](https://github.com/yt-dlp/yt-dlp/commit/dae52d8386557f4c19ab58a9ae56062b8d52b3af) ([#17461](https://github.com/yt-dlp/yt-dlp/issues/17461)) by [bashonly](https://github.com/bashonly)
- [Update player client versions](https://github.com/yt-dlp/yt-dlp/commit/59d9ae606a24a80523da35de9fb75b71eb35b501) ([#17185](https://github.com/yt-dlp/yt-dlp/issues/17185)) by [bashonly](https://github.com/bashonly)
- tab: [Always extract channel metadata](https://github.com/yt-dlp/yt-dlp/commit/cf68b8f43f141eff995c079c427014111022a755) ([#17386](https://github.com/yt-dlp/yt-dlp/issues/17386)) by [bashonly](https://github.com/bashonly), [bbilly1](https://github.com/bbilly1)
#### Downloader changes
- **hls**: [Fix crash on empty fragment lists in tests](https://github.com/yt-dlp/yt-dlp/commit/aefce1eea4d0b6bab1ec2bd3beff09bff91a39c8) ([#17218](https://github.com/yt-dlp/yt-dlp/issues/17218)) by [doe1080](https://github.com/doe1080)
#### Networking changes
- **Request Handler**: curl_cffi: [Support `curl_cffi` 0.16.x](https://github.com/yt-dlp/yt-dlp/commit/4dc054d51c243c99ec1fe36d580bac9ccf7126d0) ([#17439](https://github.com/yt-dlp/yt-dlp/issues/17439)) by [bashonly](https://github.com/bashonly), [coletdjnz](https://github.com/coletdjnz) (With fixes in [5f22baf](https://github.com/yt-dlp/yt-dlp/commit/5f22bafc14ac32f56efe960b1a754636388d72a4) by [bashonly](https://github.com/bashonly))
#### Misc. changes
- [Fix third party license information](https://github.com/yt-dlp/yt-dlp/commit/b3854cc41bc906c905e3b0f7bb39755210acd6d1) ([#17150](https://github.com/yt-dlp/yt-dlp/issues/17150)) by [bashonly](https://github.com/bashonly), [seproDev](https://github.com/seproDev)
- **build**
- [Support release tags that shadow branch names](https://github.com/yt-dlp/yt-dlp/commit/d2dcbfc5747190ad83093c7364491526bb724516) ([#17409](https://github.com/yt-dlp/yt-dlp/issues/17409)) by [InvalidUsernameException](https://github.com/InvalidUsernameException)
- [Temporarily pin PyInstaller to v6.22.0](https://github.com/yt-dlp/yt-dlp/commit/42fc40026f5ae107020f30882be6683d3e80e546) ([#17478](https://github.com/yt-dlp/yt-dlp/issues/17478)) by [bashonly](https://github.com/bashonly)
- [Trigger nightly on requirement changes](https://github.com/yt-dlp/yt-dlp/commit/f1896c57f5ba4b92741bb509790837d6838ec99e) ([#17450](https://github.com/yt-dlp/yt-dlp/issues/17450)) by [bashonly](https://github.com/bashonly)
- [Update 11 dependencies](https://github.com/yt-dlp/yt-dlp/commit/1b0074911e515f2affdddc4dd2f0ae5ddda9bb31) ([#17479](https://github.com/yt-dlp/yt-dlp/issues/17479)) by [dlp-bot](https://github.com/dlp-bot)
- [Update 27 dependencies](https://github.com/yt-dlp/yt-dlp/commit/dedde412880cee41b73e532e4d398d269ed51832) ([#17346](https://github.com/yt-dlp/yt-dlp/issues/17346)) by [bashonly](https://github.com/bashonly), [dlp-bot](https://github.com/dlp-bot)
- **ci**
- [Fix broken Windows PyPy tests](https://github.com/yt-dlp/yt-dlp/commit/d798b9b8fbbcc9dd8d2b8df863bcddfa18362f5d) ([#17347](https://github.com/yt-dlp/yt-dlp/issues/17347)) by [bashonly](https://github.com/bashonly)
- [Update 7 actions in 10 workflows](https://github.com/yt-dlp/yt-dlp/commit/874af899e7da61d616c82a823a6865070ee4745d) ([#17345](https://github.com/yt-dlp/yt-dlp/issues/17345)) by [dlp-bot](https://github.com/dlp-bot)
- **cleanup**
- Miscellaneous
- [4e969d3](https://github.com/yt-dlp/yt-dlp/commit/4e969d3a6ccf831246dd5c0c15c55376df09ccdf) by [bashonly](https://github.com/bashonly), [BOplaid](https://github.com/BOplaid), [dialmaster](https://github.com/dialmaster), [gamer191](https://github.com/gamer191)
- [594bd50](https://github.com/yt-dlp/yt-dlp/commit/594bd50c2c78ac432f81600d309fdc4e0a92d82c) by [bashonly](https://github.com/bashonly)
- **test**
- networking: [Fix logging handler removal test](https://github.com/yt-dlp/yt-dlp/commit/3128f6a43399cec279aa3db37cb9c9c2ad95c539) ([#17379](https://github.com/yt-dlp/yt-dlp/issues/17379)) by [doe1080](https://github.com/doe1080)
- socks: [Fix compatibility with `websockets>=17`](https://github.com/yt-dlp/yt-dlp/commit/3f78dc4797e1d3f53caad63778d180e28d1345d6) ([#17433](https://github.com/yt-dlp/yt-dlp/issues/17433)) by [doe1080](https://github.com/doe1080)
### 2026.07.04
#### Important changes
+2
View File
@@ -94,3 +94,5 @@ Triage Maintainers are frequent contributors who can manage issues and pull requ
- [pzhlkj6612](https://github.com/pzhlkj6612)
- [DTrombett](https://github.com/dtrombett)
- [grqz](https://github.com/grqz)
- [InvalidUsernameException](https://github.com/InvalidUsernameException)
- [ruben1PvP](https://github.com/ruben1PvP)
+1 -1
View File
@@ -197,7 +197,7 @@ CONTRIBUTORS: Changelog.md
$(PYTHON) devscripts/make_changelog.py -v -c > /dev/null ; \
fi
# The following EJS_-prefixed variables are auto-generated by devscripts/update_ejs.py
# The following EJS_-prefixed variables are auto-generated by dlp-bot
# DO NOT EDIT!
EJS_VERSION = 0.8.0
EJS_WHEEL_NAME = yt_dlp_ejs-0.8.0-py3-none-any.whl
+23 -20
View File
@@ -6,7 +6,7 @@
[![Release version](https://img.shields.io/github/v/release/yt-dlp/yt-dlp?color=brightgreen&label=Latest&style=for-the-badge)](#installation "Installation")
[![Python Version](https://img.shields.io/python/required-version-toml?tomlFilePath=https%3A%2F%2Fraw.githubusercontent.com%2Fyt-dlp%2Fyt-dlp%2Frefs%2Fheads%2Fmaster%2Fpyproject.toml&style=for-the-badge)](https://github.com/yt-dlp/yt-dlp/blob/master/pyproject.toml "Python Version")
[![PyPI](https://img.shields.io/badge/-PyPI-blue.svg?logo=pypi&labelColor=555555&style=for-the-badge)](https://pypi.org/project/yt-dlp "PyPI")
[![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?&logo=discord&logoColor=white&style=for-the-badge)]([#](https://discord.gg/H5MNcFW63r "Discord")
[![Discord](https://img.shields.io/badge/Discord-%235865F2.svg?&logo=discord&logoColor=white&style=for-the-badge)](https://discord.gg/H5MNcFW63r "Discord")
[![License: Unlicense](https://img.shields.io/badge/-Unlicense-red.svg?style=for-the-badge)](LICENSE "License")
[![Commits](https://img.shields.io/github/commit-activity/m/yt-dlp/yt-dlp?label=commits&style=for-the-badge)](https://github.com/yt-dlp/yt-dlp/commits "Commit History")
@@ -95,7 +95,7 @@ You can install yt-dlp using [the binaries](#release-files), [pip](https://pypi.
File|Description
:---|:---
[yt-dlp](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp)|Platform-independent [zipimport](https://docs.python.org/3/library/zipimport.html) binary. Needs Python (recommended for **Linux/BSD**)
[yt-dlp.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe)|Windows (Win8+) standalone x64 binary (recommended for **Windows**)
[yt-dlp.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp.exe)|Windows (Win10+) standalone x64 binary (recommended for **Windows**)
[yt-dlp_macos](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos)|Universal MacOS (10.15+) standalone executable (recommended for **MacOS**)
#### Alternatives
@@ -111,11 +111,11 @@ File|Description
[yt-dlp_musllinux.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_musllinux.zip)|Unpackaged Linux (musl 1.2+) x86_64 executable (no auto-update)
[yt-dlp_musllinux_aarch64](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_musllinux_aarch64)|Linux (musl 1.2+) standalone aarch64 binary
[yt-dlp_musllinux_aarch64.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_musllinux_aarch64.zip)|Unpackaged Linux (musl 1.2+) aarch64 executable (no auto-update)
[yt-dlp_x86.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_x86.exe)|Windows (Win8+) standalone x86 (32-bit) binary
[yt-dlp_win_x86.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_win_x86.zip)|Unpackaged Windows (Win8+) x86 (32-bit) executable (no auto-update)
[yt-dlp_x86.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_x86.exe)|Windows (Win10+) standalone x86 (32-bit) binary
[yt-dlp_win_x86.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_win_x86.zip)|Unpackaged Windows (Win10+) x86 (32-bit) executable (no auto-update)
[yt-dlp_arm64.exe](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_arm64.exe)|Windows (Win10+) standalone ARM64 binary
[yt-dlp_win_arm64.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_win_arm64.zip)|Unpackaged Windows (Win10+) ARM64 executable (no auto-update)
[yt-dlp_win.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_win.zip)|Unpackaged Windows (Win8+) x64 executable (no auto-update)
[yt-dlp_win.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_win.zip)|Unpackaged Windows (Win10+) x64 executable (no auto-update)
[yt-dlp_macos.zip](https://github.com/yt-dlp/yt-dlp/releases/latest/download/yt-dlp_macos.zip)|Unpackaged MacOS (10.15+) executable (no auto-update)
#### Misc
@@ -142,11 +142,11 @@ While yt-dlp is licensed under the [Unlicense](LICENSE), many of the release fil
Most notably, the PyInstaller-bundled executables include GPLv3+ licensed code, and as such the combined work is licensed under [GPLv3+](https://www.gnu.org/licenses/gpl-3.0.html).
The zipimport Unix executable (`yt-dlp`) contains [ISC](https://github.com/meriyah/meriyah/blob/main/LICENSE.md) licensed code from [`meriyah`](https://github.com/meriyah/meriyah) and [MIT](https://github.com/davidbonnet/astring/blob/main/LICENSE) licensed code from [`astring`](https://github.com/davidbonnet/astring).
The zipimport Unix executable (`yt-dlp`) and release tarball (`yt-dlp.tar.gz`) contain [ISC](https://github.com/meriyah/meriyah/blob/main/LICENSE.md) licensed code from [`meriyah`](https://github.com/meriyah/meriyah) and [MIT](https://github.com/davidbonnet/astring/blob/main/LICENSE) licensed code from [`astring`](https://github.com/davidbonnet/astring).
See [THIRD_PARTY_LICENSES.txt](THIRD_PARTY_LICENSES.txt) for more details.
The git repository, the source tarball (`yt-dlp.tar.gz`), the PyPI source distribution and the PyPI built distribution (wheel) only contain code licensed under the [Unlicense](LICENSE).
The git repository, the PyPI source distribution and the PyPI built distribution (wheel) only contain code licensed under the [Unlicense](LICENSE).
<!-- MANPAGE: END EXCLUDED SECTION -->
@@ -193,7 +193,7 @@ When running a yt-dlp version that is older than 90 days, you will see a warning
You can suppress this warning by adding `--no-update` to your command or configuration file.
## DEPENDENCIES
Python versions 3.10+ (CPython) and 3.11+ (PyPy) are supported. Other versions and implementations may or may not work correctly.
Python versions 3.11+ (CPython and PyPy) are supported. Other versions and implementations may or may not work correctly.
<!-- Python 3.5+ uses VC++14 and it is already embedded in the binary created
<!x-- https://www.microsoft.com/en-us/download/details.aspx?id=26999 --x>
@@ -275,7 +275,7 @@ On some systems, you may need to use `py` or `python3` instead of `python`.
**Important**: Running `pyinstaller` directly **instead of** using `python -m bundle.pyinstaller` is **not** officially supported. This may or may not work correctly.
### Platform-independent Binary (UNIX)
You will need the build tools `python` (3.10+), `zip`, `make` (GNU), `pandoc`\* and `pytest`\*.
You will need the build tools `python` (3.11+), `zip`, `make` (GNU), `pandoc`\* and `pytest`\*.
After installing these, simply run `make`.
@@ -1309,7 +1309,7 @@ To summarize, the general syntax for a field is:
%(name[.keys][addition][>strf][,alternate][&replacement][|default])[flags][width][.precision][length]type
```
Additionally, you can set different output templates for the various metadata files separately from the general output template by specifying the type of file followed by the template separated by a colon `:`. The different file types supported are `subtitle`, `thumbnail`, `description`, `annotation` (deprecated), `infojson`, `link`, `pl_thumbnail`, `pl_description`, `pl_infojson`, `chapter`, `pl_video`. E.g. `-o "%(title)s.%(ext)s" -o "thumbnail:%(title)s\%(title)s.%(ext)s"` will put the thumbnails in a folder with the same name as the video. If any of the templates is empty, that type of file will not be written. E.g. `--write-thumbnail -o "thumbnail:"` will write thumbnails only for playlists and not for video.
Additionally, you can set different output templates for the various metadata files separately from the general output template by specifying the type of file followed by the template separated by a colon `:`. The different file types supported are `subtitle`, `thumbnail`, `description`, `annotation` (deprecated), `infojson`, `link`, `pl_thumbnail`, `pl_description`, `pl_infojson`, `chapter`, `pl_video`. E.g. `-o "%(title)s.%(ext)s" -o "thumbnail:%(title)s/%(title)s.%(ext)s"` will put the thumbnails in a folder with the same name as the video. If any of the templates is empty, that type of file will not be written. E.g. `--write-thumbnail -o "thumbnail:"` will write thumbnails only for playlists and not for video.
<a id="outtmpl-postprocess-note"></a>
@@ -1598,7 +1598,7 @@ Any string comparison may be prefixed with negation `!` in order to produce an o
**Note**: None of the aforementioned meta fields are guaranteed to be present since this solely depends on the metadata obtained by the particular extractor, i.e. the metadata offered by the website. Any other field made available by the extractor can also be used for filtering.
Formats for which the value is not known are excluded unless you put a question mark (`?`) after the operator. You can combine format filters, so `-f "bv[height<=?720][tbr>500]"` selects up to 720p videos (or videos where the height is not known) with a bitrate of at least 500 kbps. You can also use the filters with `all` to download all formats that satisfy the filter, e.g. `-f "all[vcodec=none]"` selects all audio-only formats.
Formats for which the value is not known are excluded unless you put a question mark (`?`) after the operator. You can combine format filters, so `-f "bv[height<=?720][tbr>500]"` selects up to 720p videos (or videos where the height is not known) with a bitrate greater than 500 kbps. You can also use the filters with `all` to download all formats that satisfy the filter, e.g. `-f "all[vcodec=none]"` selects all audio-only formats.
Format selectors can also be grouped using parentheses; e.g. `-f "(mp4,webm)[height<480]"` will download the best pre-merged mp4 and webm formats with a height lower than 480.
@@ -1859,10 +1859,10 @@ The following extractors use this feature:
#### 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/_base.py](https://github.com/yt-dlp/yt-dlp/blob/415b4c9f955b1a0391204bd24a7132590e7b3bdb/yt_dlp/extractor/youtube/_base.py#L402-L409) for the 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 currently available clients are `web`, `web_safari`, `web_embedded`, `web_music`, `web_creator`, `mweb`, `ios`, `android`, `android_vr`, `tv`, `tv_downgraded`, and `tv_simply`. By default, `android_vr,web_safari` is used. If no JavaScript runtime/engine is available, then only `android_vr` is used. If logged-in cookies are passed to yt-dlp, then `tv_downgraded,web_safari` is used for free accounts and `tv_downgraded,web_creator` is used for premium accounts. The `web_music` client is added for `music.youtube.com` URLs when logged-in cookies are used. The `web_embedded` client is added for age-restricted videos but only successfully works around the age-restriction sometimes (e.g. if the video is embeddable), and may be added as a fallback if `android_vr` is unable to access a video. The `web_creator` client is added for age-restricted videos if account age-verification is required. Some clients, such as `web_creator` and `web_music`, require a `po_token` for their formats to be downloadable. Some clients, such as `web_creator`, will only work with authentication. Not all clients support authentication via cookies. You can use `default` for the default clients, or you can use `all` for all clients (not recommended). You can prefix a client with `-` to exclude it, e.g. `youtube:player_client=default,-web_safari`
* `player_client`: Clients to extract video data from. The currently available clients are `web`, `web_safari`, `web_embedded`, `web_music`, `web_creator`, `mweb`, `ios`, `visionos`, `android`, `android_vr`, `tv`, `tv_downgraded`, `tv_samsung`, and `tv_simply`. By default, `tv_samsung,visionos,web` is used. If no JavaScript runtime/engine is available, then `web` and `tv_samsung` are omitted. If logged-in cookies are passed to yt-dlp, then `web_embedded,tv_samsung,web` is used for free accounts and `web_creator,tv_samsung,web` is used for premium accounts. The `web_music` client is added for `music.youtube.com` URLs when logged-in cookies are used. The `web_embedded` client is added for age-restricted videos but only successfully works around the age-restriction sometimes (e.g. if the video is embeddable). The `web_embedded` client may be added as a fallback if `android_vr` or `visionos` is unable to access a video. The `web_creator` client is added for age-restricted videos if account age-verification is required. Some clients, such as `web_creator` and `web_music`, require a `po_token` for their formats to be downloadable. Some clients, such as `web_creator`, will only work with authentication. Not all clients support authentication via cookies. You can use `default` for the default clients, or you can use `all` for all clients (not recommended). You can prefix a client with `-` to exclude it, e.g. `youtube:player_client=default,-web`
* `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), `initial_data` (skip initial data/next ep request). While these options can help reduce the number of requests needed or avoid some rate-limiting, they could cause issues such as missing formats or metadata. See [#860](https://github.com/yt-dlp/yt-dlp/pull/860) and [#12826](https://github.com/yt-dlp/yt-dlp/issues/12826) for more details
* `webpage_skip`: Skip extraction of embedded webpage data. One or both of `player_response`, `initial_data`. These options are for testing purposes and don't skip any network requests. Neither is skipped by default; however, if a `player_js_version` value other than `actual` is used, then `webpage_skip=player_response` is implied
* `webpage_client`: Client to use for the video webpage request. One of `web` or `web_safari` (default)
* `webpage_client`: Client to use for the video webpage request. One of `web` (default) or `web_safari`
* `player_params`: YouTube player parameters to use for player requests. Will overwrite any default ones set by yt-dlp.
* `player_js_variant`: The player javascript variant to use for n/sig deciphering. The known variants are: `main`, `tcc`, `tce`, `es5`, `es6`, `es6_tcc`, `es6_tce`, `tv`, `tv_es6`, `phone`, `house`. The default is `main`, and the others are for debugging purposes. You can use `actual` to go with what is prescribed by the site
* `player_js_version`: The player javascript version to use for n/sig deciphering, in the format of `signature_timestamp@hash` (e.g. `20348@0004de42`). The default is to use what is prescribed by the site, and can be selected with `actual`. Using any other value will imply `webpage_skip=player_response`
@@ -1975,9 +1975,12 @@ The following extractors use this feature:
* `backend`: Backend API to use for extraction - one of `streaks` (default) or `brightcove` (deprecated)
#### vimeo
* `client`: Client to extract video data from. The currently available clients are `android`, `ios`, `macos` and `web`. Only one client can be used. The `macos` client is used by default, but the `web` client is used when logged-in. The `web` client only works with account cookies or login credentials. The `android` and `ios` clients only work with previously cached OAuth tokens
* `client`: Client to extract video data from. The currently available clients are `android` and `web`. Only one client can be used. The `web` client is used by default, and it only works with account cookies or login credentials. The `android` client only works with previously cached OAuth tokens
* `original_format_policy`: Policy for when to try extracting original formats. One of `always`, `never`, or `auto`. The default `auto` policy tries to avoid exceeding the web client's API rate-limit by only making an extra request when Vimeo publicizes the video's downloadability
#### adn
* `profile_id`: The numeric ID of the premium account profile that will be used to download videos (default: `1`)
#### zan
* `split_angles`: Split multi-angle streams into separate angle formats. Forces re-encoding of the video stream during download, and requires ffmpeg. Either `true` or `false` (default)
@@ -2310,8 +2313,8 @@ Features marked with a **\*** have been back-ported to youtube-dl
Some of yt-dlp's default options are different from that of youtube-dl and youtube-dlc:
* yt-dlp supports only [Python 3.10+](## "Windows 8"), and will remove support for more versions as they [become EOL](https://devguide.python.org/versions/#python-release-cycle); while [youtube-dl still supports Python 2.6+ and 3.2+](https://github.com/ytdl-org/youtube-dl/issues/30568#issue-1118238743)
* The options `--auto-number` (`-A`), `--title` (`-t`) and `--literal` (`-l`), no longer work. See [removed options](#Removed) for details
* yt-dlp supports only [Python 3.11+](#dependencies), and will remove support for more versions as they [become EOL](https://devguide.python.org/versions/#python-release-cycle); while [youtube-dl still supports Python 2.6+ and 3.2+](https://github.com/ytdl-org/youtube-dl/issues/30568#issue-1118238743)
* Some options no longer work. See [removed options](#removed) for details
* `avconv` is not supported as an alternative to `ffmpeg`
* yt-dlp stores config files in slightly different locations to youtube-dl. See [CONFIGURATION](#configuration) for a list of correct locations
* The default [output template](#output-template) is `%(title)s [%(id)s].%(ext)s`. There is no real reason for this change. This was changed before yt-dlp was ever made public and now there are no plans to change it back to `%(title)s-%(id)s.%(ext)s`. Instead, you may use `--compat-options filename`
@@ -2473,10 +2476,7 @@ These options may no longer work as intended
--no-include-ads Default
--write-annotations No supported site has annotations now
--no-write-annotations Default
--avconv-location Removed alias for --ffmpeg-location
--cn-verification-proxy URL Removed alias for --geo-verification-proxy URL
--dump-headers Removed alias for --print-traffic
--dump-intermediate-pages Removed alias for --dump-pages
--youtube-skip-dash-manifest Removed alias for --extractor-args "youtube:skip=dash" (Alias: --no-youtube-include-dash-manifest)
--youtube-skip-hls-manifest Removed alias for --extractor-args "youtube:skip=hls" (Alias: --no-youtube-include-hls-manifest)
--youtube-include-dash-manifest Default (Alias: --no-youtube-skip-dash-manifest)
@@ -2488,10 +2488,13 @@ These options may no longer work as intended
--compat-options no-youtube-prefer-utc-upload-date No longer supported
#### Removed
These options were deprecated since 2014 and have now been entirely removed
These aliases have been removed and may be reused. Please update your scripts and configuration files accordingly
-A, --auto-number -o "%(autonumber)s-%(id)s.%(ext)s"
-t, -l, --title, --literal -o "%(title)s-%(id)s.%(ext)s"
--avconv-location --ffmpeg-location
--dump-headers --print-traffic
--dump-intermediate-pages --dump-pages
# CONTRIBUTING
+763 -543
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -99,7 +99,7 @@ services:
platforms:
- "linux/arm/v7"
args:
VERIFYIMAGE: arm32v7/debian:bullseye@sha256:9d544bf6ff73e36b8df1b7e415f6c8ee40ed84a0f3a26970cac8ea88b0ccf2ac
VERIFYIMAGE: ghcr.io/yt-dlp/manylinux_2_31_armv7l-shared:latest
environment:
EXE_NAME: ${EXE_NAME:?}
UPDATE_TO:
+2
View File
@@ -9,6 +9,8 @@ if [ -n "${SKIP_ONEFILE_BUILD:-}" ]; then
echo "Extracting zip to verify onedir build"
if command -v python3 >/dev/null 2>&1; then
python3 -m zipfile -e "/build/${EXE_NAME}.zip" ./
elif command -v py3.14 >/dev/null 2>&1; then
py3.14 -m zipfile -e "/build/${EXE_NAME}.zip" ./
else
echo "Attempting to install unzip"
if command -v dnf >/dev/null 2>&1; then
+5
View File
@@ -38,11 +38,16 @@ def main():
f'--name={name}',
'--icon=devscripts/logo.ico',
'--upx-exclude=vcruntime140.dll',
# setuptools and packaging are PyInstaller runtime dependencies,
# but would be collected due to cffi's imports if we don't exclude
'--exclude-module=setuptools',
'--exclude-module=packaging',
# Ref: https://github.com/yt-dlp/yt-dlp/issues/13311
# https://github.com/pyinstaller/pyinstaller/issues/9149
'--exclude-module=pkg_resources',
'--noconfirm',
'--additional-hooks-dir=yt_dlp/__pyinstaller',
'--add-data=THIRD_PARTY_LICENSES.txt:.',
*opts,
'yt_dlp/__main__.py',
]
+22 -77
View File
@@ -1,20 +1,16 @@
build==1.5.0 \
--hash=sha256:13f3eecb844759ab66efec90ca17639bbf14dc06cb2fdf37a9010322d9c50a6f \
--hash=sha256:302c22c3ba2a0fd5f3911918651341ebb3896176cbdec15bd421f80b1afc7647
build==1.6.1 \
--hash=sha256:51cc11666391ab6f092070437ac747002ff46f3e4113a3622177ee6b488bfc53 \
--hash=sha256:ecd351a4be9d35a9eaaba244a7687143c9c7d4aea6ac964e7e7ddab20cbcf4e7
colorama==0.4.6 ; os_name == 'nt' \
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
# via build
hatchling==1.30.1 \
--hash=sha256:161eacafb3c6f91526e92116d21426369f2c36e98c36a864f11a96345ad4ee31 \
--hash=sha256:eee4fd45357f72ebb3d7a42e5d72cfb5e29ed426d79e8836288926c4258d5f2e
importlib-metadata==9.0.0 ; python_full_version < '3.10.2' \
--hash=sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7 \
--hash=sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc
# via build
packaging==26.2 \
--hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
--hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
hatchling==1.32.4 \
--hash=sha256:08ecf7548fb48205e7f213d70c71e67b8271b7242093dc3f1da578b42c734a2c \
--hash=sha256:c4468f73144c054d2aab4ef0f0378c43b9878bf07f8ffd6b79690e970d375f07
packaging==26.3 \
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
# via
# build
# hatchling
@@ -22,70 +18,19 @@ pathspec==1.1.1 \
--hash=sha256:17db5ecd524104a120e173814c90367a96a98d07c45b2e10c2f3919fff91bf5a \
--hash=sha256:a00ce642f577bf7f473932318056212bc4f8bfdf53128c78bbd5af0b9b20b189
# via hatchling
pluggy==1.6.0 \
--hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \
--hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746
pluggy==1.7.0 \
--hash=sha256:7dd7b0d8832ba3cb632c306926ded123429211b83641b35dc5c41ad2d34f9bec \
--hash=sha256:d1eaa46ebb595891b860ab086b4d09c8588af65ebd4361b8e8f4bb8920b90ba8
# via hatchling
pyproject-hooks==1.2.0 \
--hash=sha256:1e859bd5c40fae9448642dd871adf459e5e2084186e8d2c2a79a824c970da1f8 \
--hash=sha256:9e5c6bfa8dcc30091c74b0cf803c81fdd29d94f01992a7707bc97babb1141913
pyproject-hooks==1.3.3 \
--hash=sha256:5fc53fdac9f7bd63fbcdc868fb5f90b4784d78a53a3d3388cd738b807441a20b \
--hash=sha256:defda19b854fa0d3bd4f76ea4ddcba8abd7dcfcdd585a6690ade050744fc5f43
# via build
tomli==2.4.1 ; python_full_version < '3.11' \
--hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \
--hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \
--hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \
--hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \
--hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \
--hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \
--hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \
--hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \
--hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \
--hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \
--hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \
--hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \
--hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \
--hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \
--hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \
--hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \
--hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \
--hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \
--hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \
--hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \
--hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \
--hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \
--hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \
--hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \
--hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \
--hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \
--hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \
--hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \
--hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \
--hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \
--hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \
--hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \
--hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \
--hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \
--hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \
--hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \
--hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \
--hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \
--hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \
--hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \
--hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \
--hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \
--hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \
--hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \
--hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \
--hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \
--hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049
# via
# build
# hatchling
trove-classifiers==2026.6.1.19 \
--hash=sha256:ab4c4ec93cc4a4e7815fa759906e05e6bb3f2fbd92ea0f897288c6a43efd15b3 \
--hash=sha256:c5132b4b61a829d11cfbd2d72e97f20a45ed6edb95e45c5efdeb5e00836b2745
tomlkit==0.15.2 \
--hash=sha256:05562412163a3037b94497385fb7f9204c637bc605af7a48199e41cf2272f437 \
--hash=sha256:83e32755ba1d20d9340bd069ee97e9f6232ba2346b63ffcba425de01f7e327a6
# via hatchling
trove-classifiers==2026.9.21.13 \
--hash=sha256:0a9ebc8d4e2f3e8a22848c5258033035bec17a3012ac3fea16dbaa764489eb71 \
--hash=sha256:8b1ff4f9c191b1040b71c37f1e445ab99732911e3cd91de52838453a854d7a17
# via hatchling
zipp==4.1.0 ; python_full_version < '3.10.2' \
--hash=sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f \
--hash=sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602
# via importlib-metadata
+559 -381
View File
@@ -1,409 +1,587 @@
brotli==1.2.0 ; implementation_name == 'cpython' and sys_platform != 'ios' \
--hash=sha256:022426c9e99fd65d9475dce5c195526f04bb8be8907607e27e747893f6ee3e24 \
--hash=sha256:072e7624b1fc4d601036ab3f4f27942ef772887e876beff0301d261210bca97f \
--hash=sha256:0bbd5b5ccd157ae7913750476d48099aaf507a79841c0d04a9db4415b14842de \
--hash=sha256:0cf8c3b8ba93d496b2fae778039e2f5ecc7cff99df84df337ca31d8f2252896c \
--hash=sha256:15b33fe93cedc4caaff8a0bd1eb7e3dab1c61bb22a0bf5bdfdfd97cd7da79744 \
--hash=sha256:1b1d6a4efedd53671c793be6dd760fcf2107da3a52331ad9ea429edf0902f27a \
--hash=sha256:1b557b29782a643420e08d75aea889462a4a8796e9a6cf5621ab05a3f7da8ef2 \
--hash=sha256:260d3692396e1895c5034f204f0db022c056f9e2ac841593a4cf9426e2a3faca \
--hash=sha256:26e8d3ecb0ee458a9804f47f21b74845cc823fd1bb19f02272be70774f56e2a6 \
--hash=sha256:2a7f1d03727130fc875448b65b127a9ec5d06d19d0148e7554384229706f9d1b \
--hash=sha256:2e1ad3fda65ae0d93fec742a128d72e145c9c7a99ee2fcd667785d99eb25a7fe \
--hash=sha256:3219bd9e69868e57183316ee19c84e03e8f8b5a1d1f2667e1aa8c2f91cb061ac \
--hash=sha256:350c8348f0e76fff0a0fd6c26755d2653863279d086d3aa2c290a6a7251135dd \
--hash=sha256:35d382625778834a7f3061b15423919aa03e4f5da34ac8e02c074e4b75ab4f84 \
--hash=sha256:3b90b767916ac44e93a8e28ce6adf8d551e43affb512f2377c732d486ac6514e \
--hash=sha256:3e1b35d56856f3ed326b140d3c6d9db91740f22e14b06e840fe4bb1923439a18 \
--hash=sha256:3f3c908bcc404c90c77d5a073e55271a0a498f4e0756e48127c35d91cf155947 \
--hash=sha256:40d918bce2b427a0c4ba189df7a006ac0c7277c180aee4617d99e9ccaaf59e6a \
--hash=sha256:4ecdb3b6dc36e6d6e14d3a1bdc6c1057c8cbf80db04031d566eb6080ce283a48 \
--hash=sha256:54a50a9dad16b32136b2241ddea9e4df159b41247b2ce6aac0b3276a66a8f1e5 \
--hash=sha256:67a91c5187e1eec76a61625c77a6c8c785650f5b576ca732bd33ef58b0dff49c \
--hash=sha256:6be67c19e0b0c56365c6a76e393b932fb0e78b3b56b711d180dd7013cb1fd984 \
--hash=sha256:6c12dad5cd04530323e723787ff762bac749a7b256a5bece32b2243dd5c27b21 \
--hash=sha256:7547369c4392b47d30a3467fe8c3330b4f2e0f7730e45e3103d7d636678a808b \
--hash=sha256:7a47ce5c2288702e09dc22a44d0ee6152f2c7eda97b3c8482d826a1f3cfc7da7 \
--hash=sha256:7a61c06b334bd99bc5ae84f1eeb36bfe01400264b3c352f968c6e30a10f9d08b \
--hash=sha256:81da1b229b1889f25adadc929aeb9dbc4e922bd18561b65b08dd9343cfccca84 \
--hash=sha256:832c115a020e463c2f67664560449a7bea26b0c1fdd690352addad6d0a08714d \
--hash=sha256:844a8ceb8483fefafc412f85c14f2aae2fb69567bf2a0de53cdb88b73e7c43ae \
--hash=sha256:898be2be399c221d2671d29eed26b6b2713a02c2119168ed914e7d00ceadb56f \
--hash=sha256:9322b9f8656782414b37e6af884146869d46ab85158201d82bab9abbcb971dc7 \
--hash=sha256:963a08f3bebd8b75ac57661045402da15991468a621f014be54e50f53a58d19e \
--hash=sha256:9c79f57faa25d97900bfb119480806d783fba83cd09ee0b33c17623935b05fa3 \
--hash=sha256:9e5825ba2c9998375530504578fd4d5d1059d09621a02065d1b6bfc41a8e05ab \
--hash=sha256:a1778532b978d2536e79c05dac2d8cd857f6c55cd0c95ace5b03740824e0e2f1 \
--hash=sha256:aa47441fa3026543513139cb8926a92a8e305ee9c71a6209ef7a97d91640ea03 \
--hash=sha256:acec55bb7c90f1dfc476126f9711a8e81c9af7fb617409a9ee2953115343f08d \
--hash=sha256:adedc4a67e15327dfdd04884873c6d5a01d3e3b6f61406f99b1ed4865a2f6d28 \
--hash=sha256:af43b8711a8264bb4e7d6d9a6d004c3a2019c04c01127a868709ec29962b6036 \
--hash=sha256:b232029d100d393ae3c603c8ffd7e3fe6f798c5e28ddca5feabb8e8fdb732997 \
--hash=sha256:b35c13ce241abdd44cb8ca70683f20c0c079728a36a996297adb5334adfc1c44 \
--hash=sha256:b63daa43d82f0cdabf98dee215b375b4058cce72871fd07934f179885aad16e8 \
--hash=sha256:c8565e3cdc1808b1a34714b553b262c5de5fbda202285782173ec137fd13709f \
--hash=sha256:cf9cba6f5b78a2071ec6fb1e7bd39acf35071d90a81231d67e92d637776a6a63 \
--hash=sha256:d2d085ded05278d1c7f65560aae97b3160aeb2ea2c0b3e26204856beccb60888 \
--hash=sha256:e310f77e41941c13340a95976fe66a8a95b01e783d430eeaf7a2f87e0a57dd0a \
--hash=sha256:e7c0af964e0b4e3412a0ebf341ea26ec767fa0b4cf81abb5e897c9338b5ad6a3 \
--hash=sha256:e99befa0b48f3cd293dafeacdd0d191804d105d279e0b387a32054c1180f3161 \
--hash=sha256:ef87b8ab2704da227e83a246356a2b179ef826f550f794b2c52cddb4efbd0196 \
--hash=sha256:fc1530af5c3c275b8524f2e24841cbe2599d74462455e9bae5109e9ff42e9361 \
--hash=sha256:ff09cd8c5eec3b9d02d2408db41be150d8891c5566addce57513bf546e3d6c6d
brotli==1.2.1 ; implementation_name == 'cpython' and sys_platform != 'ios' \
--hash=sha256:00a50d063aae2e69c2eb28818ccf6dc3e51f2ea5b74e3c2082a47943ee23f399 \
--hash=sha256:02b2f7b5a83485efe448a44ddf7983def05c3bb1dcf917d4f7154070260e13de \
--hash=sha256:035f3bf861328d8b7fcb61f4a976f9913027158e5666116733d59ffc65f2745e \
--hash=sha256:06a22fcbcae059c0679098232779095fc50a735a3fea02db5c79cab10b84d877 \
--hash=sha256:09a2f112a638aca15a88f298571788795fc45d62f2bca7f3870c1152153ef399 \
--hash=sha256:0a30e5df5ba985b67f85e13dfd7e5a68e186d8d9b5cff7d9a8904832bb413e81 \
--hash=sha256:11aec6ea5c20cad61a33302e06baa48b0243bfa4d173bc2985dabd047e367d08 \
--hash=sha256:1329c80daa60752f1d94f507479504921e358e71746c5fce9b55b3d51ac038bc \
--hash=sha256:1880db6241276e191d3e34a6e4eea708c6629103c396f0ea21e75b0ce63a9a2c \
--hash=sha256:1f65a91f3576949793b8720b12a47e7ea06debc970a2da6d54ff8458053e2109 \
--hash=sha256:23f0d23995100458d17f3bf5ce1e959fe46df894b472063a74266f7adeb2e72e \
--hash=sha256:264fd5b200f6f6170cb551a4b9fcaabf8aa846ddaefe72db4d5f49f9d3743df9 \
--hash=sha256:2df1678c2c25db2f669c613fe8b4e587d0dd24c6acf7746bad13d6e87e4b051d \
--hash=sha256:338856ae9ff63af4fc3dbbd6184a7276a6ae83df2243562e86e5ee5cf980cce7 \
--hash=sha256:37de1818ce469b3c37324c89d4d4dbb5e64461d9dc01c16f8abb2a17c465b132 \
--hash=sha256:3975fb11f63e212b87a087e4a910187b522c6969a4989ca362d6f85f9dc36acd \
--hash=sha256:4b9dd0173ca5e01d1eb307d3c184fe8c09bdc168ede560889b1018d216d38c61 \
--hash=sha256:4d47a9f0ba5ee608f3f3a9c942dcd244443068ae5b0d90183dd396dea02236e4 \
--hash=sha256:59ca34c7a83d7a3b842247183c426f891a95a8f57db41b7aac92195c51e8a83a \
--hash=sha256:59ec359a56f44277ad424fb4b7cf1a0ae2fd855b35ba8f15dcfbcabb3fb51aeb \
--hash=sha256:5f3da70516b1bd1b2aa183ec4ab5c02dfc6ad5c1184d47bb65ade25e710439b6 \
--hash=sha256:6532d2c58018121a9eb5882656cf862cdbbd853600cb5fbccac59bcff14f66b0 \
--hash=sha256:67f4dceb22ce3a742751cee849644449b169684699aa548e77d771de304e963c \
--hash=sha256:6b3c3d5794212a54434b4856f808f7bdf7ad48eacadaadb5b2346fc9a639365a \
--hash=sha256:6bd29ab84bb8972370cacd310e8a91651f54476d01de1cd1a4cf0bece5eb25e1 \
--hash=sha256:7248c282d7d6aef4ae89363da5fc3df7b9250eb04b252622955296eb5d0ea82f \
--hash=sha256:761db18dc32b24d00fbedca1013089eb3470053cefa8492bd9c07b11102d72bf \
--hash=sha256:77ef5882c5318ffc3dd94c6abc6a8f1ec2af75d66522319f1a250a07d53d0546 \
--hash=sha256:7ec678c52c3ef5e37482a094d109c04cf9e4a0e2923dd1e0fbddb4bf133a976e \
--hash=sha256:810aea5958d6a2d92593fd27218df528644aeb72cc7f6d401e650752d6c98949 \
--hash=sha256:87492842770cd772fce25e9cd279913eaea6c55a91a960b6302aedfa2ec7b152 \
--hash=sha256:875975f91870682cca4371260522ad3f22d636e845b5c5355c52bc045c0f75c8 \
--hash=sha256:90bd49511341dd7c40bb3acaa97cd8b9e5df4821a5714b842117e7069c7cc03e \
--hash=sha256:91097d66ebb8ca8d23372081a33405a44e2239445614888e38929bd7f5879dae \
--hash=sha256:9307679936e86d7773eadfa444a4a4ee80f6f45230e93379875f4a6897a09a2b \
--hash=sha256:93269f11303fc9a3e3990b57e0533f41949546156d9f0e535571f313032563cc \
--hash=sha256:96e6966edcfae74ffac2522d2dd1a304450d18807a9791f5ed0a3232192c9437 \
--hash=sha256:970a3dbce807a3f5c2b8232036052bade01e4bc92ade37d73ea3750418307fa1 \
--hash=sha256:972a2e19dbaab47d0aa77c1d07f71c930bdc53538f2b33decc905e92a4be5cbd \
--hash=sha256:972e34c5cbbfe6c90358bfae38edae1a29d3456e920da5a4664c98f221ee4df8 \
--hash=sha256:a3942e2d365f009e5e7839114fa315e1a2bcfea12b52064a28f1a7281862a2a7 \
--hash=sha256:a3dea7e1ac49e29306500a8627fa3eacabcc9e238d22495eea2d8e61de77065b \
--hash=sha256:a84e0ae14d1efe782a9f143021c4e01d5ed986a140fe5070505cc5978eaf0592 \
--hash=sha256:a998857af4fcd19920bdf5f30f0f1a23f38472a703d33e49168cd4fd32438377 \
--hash=sha256:aa32b51702a0b6e9fddc0d1dc66cb6ed6af112f1bba0cac2be9039546a862b5c \
--hash=sha256:b0c32f0660bb21e810ffc1d3d04b6ea682e118b8141c6e12522a3dacadeb70ee \
--hash=sha256:b0faa0b9af9367748388345d5b12f6add2a9cf896481e72910e88fbfe14ecd54 \
--hash=sha256:b5b458950312830913f837e179ce9221000ab7a20b4e42d7b48c1fcd79140de1 \
--hash=sha256:b8b2fc7901b31d5885f26521cf2d74feccdc126a272ba1d879b7545bb25468bc \
--hash=sha256:be371af72af54b6e508b68a7a87768e05b7e13023f6c82a3e3f5e4d0e829e186 \
--hash=sha256:c3f667dc60a875b12a5ecd7828062ccd97c0fb79c4adc6c8699d23d5ff2af7e1 \
--hash=sha256:c4b68ce579b05c66bb18a16356a4f713bebac2446ee498dd8bb1ecab3da77b89 \
--hash=sha256:c5302747f969d5ec925810176f7697712a3fa2ea0fae0c7a85aa4ad9325247fd \
--hash=sha256:c788fdab2eeeab671f5ab375ad010ef743f6c95be67f60f878e8876a51f6c671 \
--hash=sha256:cfa54e7f5bd5ef482e7f5336f7cf3c30ae608d9767e514dd930b7c30a03fa977 \
--hash=sha256:d6ef0035b6ae338a46951c144081c61fb044f4c1eb6d20acc5ba6277f666a4c0 \
--hash=sha256:dafaeb38712f99e5c31ad7f02c366f1ddd3792921b94066015f8c49f197163b0 \
--hash=sha256:dca1bf90b3a6a7440904f128464eb95bf46ac9da7ad3c85912483dd83128fd95 \
--hash=sha256:de1bf30d819809a964060356032e6670c9923644666afaaf3d1719d05ddb844e \
--hash=sha256:de499e2492c8106a5e163d3cf5b6726e2797f9234cfbc6055fbb5f9d8f198f39 \
--hash=sha256:e4a7be59d374c445766fa4ac066a04d19a757365ae00a950053d0ab7388d1039 \
--hash=sha256:e6c4fa55eab6b5684b33239597876a18a35ce1280b63ab960164032afbb8783f \
--hash=sha256:eaa5178a4c1fe619eff9cbe93b57919d426332e219870301d4ef5fc09a522ae9 \
--hash=sha256:ed62c15ce5e8b975b2710a0f7c8bb953cbffb472fccb05055be6afcba9520c19 \
--hash=sha256:ed8e452f5cb34f59f4861d50d029c6203b5f8f11c13d4186264392a64b4def8d \
--hash=sha256:eea17e3cdc6f9aecffe15fe9a9eeba8e8c049a5d347de1561eed2240cdf35a79 \
--hash=sha256:f00ff4b56caf151365c77988eb85a4a71eb26fe63047d4084d5614e06d65e3cf \
--hash=sha256:f06dd6a30438692d48c0d54de4b659cd55a57c2c2f6591c969c98d0a5523ab07 \
--hash=sha256:f34405292fca45cd77419005c1ea35ba1c03eaff9042afe76d6fe189fe474669 \
--hash=sha256:f352f797b1477c46a20e45f4cbc3a0e258e61963c8ae8f79f84a7bfb4195b37e \
--hash=sha256:f37ccd159dae35d4914651d57142c8077aa67ab7e3ffef690b00bcb7a7dbd8e6 \
--hash=sha256:f51bca8fcac4266519533698c316f3d23340768a8e57c4796c9f6e0a4f353807 \
--hash=sha256:f5342b8256476554b4045db8b7bf4dc4044d0405485f220f0cd80764bc0d7faf \
--hash=sha256:f5fbda9703bce94a976e1a6bbdbbe0af25fb613a593a56091991359928b66c05 \
--hash=sha256:fb5df75d1b1c42d997adbb39eac61f2cdb48efa26304a0cb9c0b757c9bc20732 \
--hash=sha256:fb6a4d400aa531c73a718b337116fad77ba8dc6df34fa615c808bfc55ffb19ca
# via yt-dlp
brotlicffi==1.2.0.1 ; implementation_name != 'cpython' \
--hash=sha256:2c85e65913cf2b79c57a3fdd05b98d9731d9255dc0cb696b09376cc091b9cddd \
--hash=sha256:37cb587d32bf7168e2218c455e22e409ad1f3157c6c71945879a311f3e6b6abf \
--hash=sha256:3c9544f83cb715d95d7eab3af4adbbef8b2093ad6382288a83b3a25feb1a57ec \
--hash=sha256:535f2d05d0273408abc13fc0eebb467afac17b0ad85090c8913690d40207dac5 \
--hash=sha256:625f8115d32ae9c0740d01ea51518437c3fbaa3e78d41cb18459f6f7ac326000 \
--hash=sha256:6f3314a3476f59e5443f9f72a6dff16edc0c3463c9b318feaef04ae3e4683f5a \
--hash=sha256:82ea52e2b5d3145b6c406ebd3efb0d55db718b7ad996bd70c62cec0439de1187 \
--hash=sha256:91ba5f0ccc040f6ff8f7efaf839f797723d03ed46acb8ae9408f99ffd2572cf4 \
--hash=sha256:9d6ba65dd528892b4d9960beba2ae011a753620bcfc66cf6fa3cee18d7b0baa4 \
--hash=sha256:be9a670c6811af30a4bd42d7116dc5895d3b41beaa8ed8a89050447a0181f5ce \
--hash=sha256:c20d5c596278307ad06414a6d95a892377ea274a5c6b790c2548c009385d621c \
--hash=sha256:ce17eb798ca59ecec67a9bb3fd7a4304e120d1cd02953ce522d959b9a84d58ac \
--hash=sha256:da2e82a08e7778b8bc539d27ca03cdd684113e81394bfaaad8d0dfc6a17ddede \
--hash=sha256:e015af99584c6db1490a69a210c765953e473e63adc2d891ac3062a737c9e851 \
--hash=sha256:f2a5575653b0672638ba039b82fda56854934d7a6a24d4b8b5033f73ab43cbc1
brotlicffi==1.2.1.0 ; implementation_name != 'cpython' \
--hash=sha256:00a6e8df24c2f48744bbdca8694a2b50bb26d1d0b6360c3a7c5caeaf4ad83373 \
--hash=sha256:0a7281a39de91432e90c27ab9c4f9feb3a9cf33fda3873534c2a88270d9f60a2 \
--hash=sha256:0cb591da62db91dddd701a28def82f39e0f7943321ac7d0814a1d2a1625095d1 \
--hash=sha256:1563024a25dd2c357457f49f4e03d4354d0660ae41ed1983d86c5817a754a539 \
--hash=sha256:2182d9af39ff06efce62a783d9429bf01f10cdedafc8b6ba696f75b52fc39eef \
--hash=sha256:25ab19c47b88438b5d00a2074b86fe37ab5c176aef90de1ae0f5e1ae52300462 \
--hash=sha256:30a52a620564ef3c6a34cd1e09d699b92ba68a3447a28915b77a17eb5d2c8f71 \
--hash=sha256:421ba24ee6568c6baa3c83e0f584fe9e3941bf86401122942c5ed085f8114c09 \
--hash=sha256:52b99120543ffa3b0667e922c6a7dc6b6e01350f7fd38f21aaca511bb9f8b4f2 \
--hash=sha256:54ccae9a0ff09c7f007aa247dc62b6ca7666ecf1358568e6f2eb8683ceed1d01 \
--hash=sha256:5d0b89e959f643aab4c58c15c06e1e87b6f6605e5e88c3c1c28f5ce1c58c4e5f \
--hash=sha256:602e87ecc8fd2c72b13ba6dced2e0d5aefc18a262523e82795ed0f47f5a13903 \
--hash=sha256:6f5ff7c8f62eaa3e6feb2b4d06a6001bb08cc346c9de7608786de99387255e94 \
--hash=sha256:75e54388f06cd7edf5354f526d0386553db441b7574a22a2bcb19a2149e48eb7 \
--hash=sha256:ac2d63c8f3c1fd000286315027a013008c7c9a3009c7415c24ee48dde1b207db \
--hash=sha256:b77704eb33e345e00d0a2854abf7966b86e1709a1f89bcc143b6c8437256d7c7 \
--hash=sha256:cc882e1ab3f81d262cc002132476dab7667f8f41ead3de8609b163cb64409f8a \
--hash=sha256:ed7c8311209853c9d78e2f6cff1f57e4df2541e4d67e3677dc1f4c88539db907 \
--hash=sha256:fea6f5450a6bd73ec222e92282d4db25030943946190697c1f2cd41087c59bc6
# via yt-dlp
certifi==2026.6.17 \
--hash=sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432 \
--hash=sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db
certifi==2026.10.23 \
--hash=sha256:a9895e6e2758b371e0545e321a3a8fd1fcfd9829ada8824a936dfb16aaaf36cd \
--hash=sha256:e9b54de76e530bb6cf0ccd036787103acb58fd42ba930ea8bf948ddbaa2f61d1
# via
# curl-cffi
# requests
# yt-dlp
cffi==2.0.0 \
--hash=sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb \
--hash=sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b \
--hash=sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f \
--hash=sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9 \
--hash=sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44 \
--hash=sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c \
--hash=sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75 \
--hash=sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e \
--hash=sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a \
--hash=sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e \
--hash=sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25 \
--hash=sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe \
--hash=sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b \
--hash=sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91 \
--hash=sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592 \
--hash=sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187 \
--hash=sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c \
--hash=sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1 \
--hash=sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94 \
--hash=sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba \
--hash=sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb \
--hash=sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529 \
--hash=sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca \
--hash=sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6 \
--hash=sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c \
--hash=sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0 \
--hash=sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743 \
--hash=sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5 \
--hash=sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5 \
--hash=sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4 \
--hash=sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d \
--hash=sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b \
--hash=sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93 \
--hash=sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205 \
--hash=sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27 \
--hash=sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512 \
--hash=sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d \
--hash=sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c \
--hash=sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037 \
--hash=sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26 \
--hash=sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb \
--hash=sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c \
--hash=sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8 \
--hash=sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4 \
--hash=sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414 \
--hash=sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9 \
--hash=sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664 \
--hash=sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9 \
--hash=sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775 \
--hash=sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739 \
--hash=sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc \
--hash=sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062 \
--hash=sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe \
--hash=sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92 \
--hash=sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5 \
--hash=sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13 \
--hash=sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d \
--hash=sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26 \
--hash=sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495 \
--hash=sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b \
--hash=sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6 \
--hash=sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c \
--hash=sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef \
--hash=sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5 \
--hash=sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18 \
--hash=sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad \
--hash=sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3 \
--hash=sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5 \
--hash=sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49 \
--hash=sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2 \
--hash=sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5 \
--hash=sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453
cffi==2.1.1 \
--hash=sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e \
--hash=sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66 \
--hash=sha256:0beceaabe56af686895136a2de78db54ecd8e4046b236b8fd6d6cb61389e9bf2 \
--hash=sha256:154852545011f779917b11c78db2358d095da62a9a172b78ad0a583ee5adc0d0 \
--hash=sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971 \
--hash=sha256:1a18a57b58cfb21fc28d72e876acf10eaed67a1ed96226f92af4df681d571c4c \
--hash=sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d \
--hash=sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517 \
--hash=sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735 \
--hash=sha256:246fa40ce8645a614ff682e0b70f37134e460eaf93a775e0cbe3cca585a67a80 \
--hash=sha256:25792eac27877609e7bb06d42ff88278a6624fff2ba9bbb523c09616b117e80f \
--hash=sha256:27350daa11d4f10c540e6e89dada4c54feb7256ad03e9a4dc075ebad7ba360d1 \
--hash=sha256:28907ab9bfb6aa13184cfc17c6b8e1023c5ab6fd7076d8c20a35e59fe04f8f29 \
--hash=sha256:2ae64be792b8966f2c69538199728b290e34726562896df1e5dc8ffd8d8188e8 \
--hash=sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c \
--hash=sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e \
--hash=sha256:3222ba5d678f80a030e6afbcc33dc1ae5cb45facabb61cee2c7016b8432fde48 \
--hash=sha256:3311ed60d36f83378794e1009ac6258bafbf81f7888b4caa7b35a521e3f95813 \
--hash=sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac \
--hash=sha256:34e261f78cb6ceaaa36f42f2613f4380d94d9c759a9c73c769ee6e0247364632 \
--hash=sha256:363e05fa78e15116c3c32c210ee36884fd6b9afa6d440e47112c3bd511d64cb6 \
--hash=sha256:398aff33cee2767e3e781d2554c54bd0dff386bb437581e0d8011fde1a942ec1 \
--hash=sha256:42a494cee34437f05546455144f2b5d9ac09b1face62bcfce597d2e521066688 \
--hash=sha256:42f6930c31dc7f50732c9ae793c2786c7b6b044195967bbdde40bb9be81c4cc0 \
--hash=sha256:456a61fa52d579ebf9df2e9552ead5129855dbaff6c1e5a9b1bc408809bdc062 \
--hash=sha256:471cee653ae88de62096552e6d24ccb4a5adb8c8c9f10b5054d0122c15bf2779 \
--hash=sha256:49cbc70e6542d4ccccb936558d1064a8012541e78f821f955cff24e357776c94 \
--hash=sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50 \
--hash=sha256:4be96343e422f2dfcd12ab5c9f5aebe03f82f737c6bffeca6830b3875cb44aab \
--hash=sha256:4f42141fc14250de6dde5ee7ea4432be017252d91f19c5ad043c084cea629cac \
--hash=sha256:507a24c282e0f42f8ed737cf048572cbf580468da5555764a8331735e9c736b6 \
--hash=sha256:51b31d1c98274844cfd7838ce00bfc27c7423a4dc00fc0772fc3331c2cc90676 \
--hash=sha256:58acb8ab8e295e6c5ea12f888cbb13cf21511ef2a3303a23f4325c29d17fe5c1 \
--hash=sha256:5c58fe613dc5e5336357eff555824a314d8e43282600435c8d1cb6a7a2fedd13 \
--hash=sha256:5e7cecbaadb83884793e05828cee59b210b24583b9c7425d0ba6a754fe22eb4e \
--hash=sha256:616f097f2fe415bc92a247f02e11f634e1f9e9a83d327e3c915c15089c87869e \
--hash=sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973 \
--hash=sha256:64faea20f4e2613363a1a9b9c7dd73058f3ecd00133a511e72ad7c511658f527 \
--hash=sha256:661c298b4821edebead0c91edd2b00374d67ad7c5a1f7a91d4442633b79d6a72 \
--hash=sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890 \
--hash=sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c \
--hash=sha256:6e192623c49c94421616a5778fba35cf0d5a8d000650c1967ef4448ee5cdd990 \
--hash=sha256:7225e4514edb64eb6740324353e0da0711954fd8d7da4576755b1c6e09b697cd \
--hash=sha256:770de9db11e84213beec501cfcaa013b019820ca881e03344dea5844f7876d94 \
--hash=sha256:7750c6449dff7864bb9bb27ddfb0267756189201a3afc911d82b3caacd70dfc3 \
--hash=sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80 \
--hash=sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5 \
--hash=sha256:7dbb61fe3a7699468030f71bbe5f8a0e326a151daa91beb11a6fc1f980c55e1c \
--hash=sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a \
--hash=sha256:8ef53b2de9bcb9197d31854256575d59dbac0cba72ac627bb291ef5eceb74be4 \
--hash=sha256:937c0052c05a31ca1daf18de3158eed4dbfcb9cc107adbea227728d647be701e \
--hash=sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6 \
--hash=sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b \
--hash=sha256:a4f00aa42f75d6e4595e8866e748cc1705adc0cddfeb2ca86d0d03993d63ba03 \
--hash=sha256:a6e721d4b0e45d5b65e87534470e67b18dcd092c83f68fba09f152b9cbc061af \
--hash=sha256:a730a083190634c65cca36ba5f489531576ebd79bcd5c8e172130f6453127231 \
--hash=sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2 \
--hash=sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3 \
--hash=sha256:ab36d55f9ed2d067327667c2fea18dda018eb628dd6347aa01dda6cf1f5d3836 \
--hash=sha256:ad2c86c495b899d862ea0f4b42891b8713a3bd45dd4105c7fd51c2a72f39f3a5 \
--hash=sha256:aeae0e330c9f6acd681f647d46cefd30c29f93e3392882e792e82080c9691399 \
--hash=sha256:b0431303acaea1089ad4b3e9ce4e6518193def1118d4073ca848635ee4ea2e96 \
--hash=sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e \
--hash=sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf \
--hash=sha256:c26608d2222fb1e94487e4a387d85f13eb55d5ed725cb25a0c589ac4ee60e7bc \
--hash=sha256:c7659f22557c5a0bc4855cd635f55edec690cc008a40768527762cb9fb263455 \
--hash=sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0 \
--hash=sha256:c8d2c9fd1f2d16f780d15127abb050d13d1a76c03a4bd87d7e4980e45e511e12 \
--hash=sha256:cc572dace3f60ef98d7b12ff411d20f5362feb31a0439eab0085bbfd349982d7 \
--hash=sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692 \
--hash=sha256:d28630f5854ab07ab1fd4aba756de52326c82e6be15d414b12793f1975048b54 \
--hash=sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3 \
--hash=sha256:da0e573f9f97159390c89d9f1a9e41908b66d408cc5b58d08cf3847d844c531b \
--hash=sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be \
--hash=sha256:dddad92b554513a31f272570678ba307fb9f618f05e3d4a5eacafff9eae03e1d \
--hash=sha256:df423d40ee8654634421812bc3b196da3f9bd7d32929da813f8394c4348a5358 \
--hash=sha256:df913725b79db7bcf03448f36b7bf8815363417d5b58deecf9305e3e30f0f21a \
--hash=sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7 \
--hash=sha256:e2d65b31f36619cda3999b78b2aa9632e76b78448e7a56fc4240824200e7c4fc \
--hash=sha256:e6e8cff14d6fb0be70a09c0bdc58096f501952d04624ebf867e0e56da2df8960 \
--hash=sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125 \
--hash=sha256:f24fb43132a4c6b4cb4eb029492919b2db645be6808d738f244fd146c03c32cb \
--hash=sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a \
--hash=sha256:f5cfbc5fe74540d335175b656c725d74d90e3730c626d92575eea35029d9afaa \
--hash=sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf \
--hash=sha256:f8ec5e643a9a937f64e1999eb9f75d072263751912dc5cd06d3c85f8f44be7c3 \
--hash=sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4 \
--hash=sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264
# via
# brotlicffi
# curl-cffi
charset-normalizer==3.4.7 \
--hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \
--hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \
--hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \
--hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \
--hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \
--hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \
--hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \
--hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \
--hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \
--hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \
--hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \
--hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \
--hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \
--hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \
--hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \
--hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \
--hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \
--hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \
--hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \
--hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \
--hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \
--hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \
--hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \
--hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \
--hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \
--hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \
--hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \
--hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \
--hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \
--hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \
--hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \
--hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \
--hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \
--hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \
--hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \
--hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \
--hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \
--hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \
--hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \
--hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \
--hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \
--hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \
--hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \
--hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \
--hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \
--hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \
--hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \
--hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \
--hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \
--hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \
--hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \
--hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \
--hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \
--hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \
--hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \
--hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \
--hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \
--hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \
--hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \
--hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \
--hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \
--hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \
--hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \
--hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \
--hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \
--hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \
--hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \
--hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \
--hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \
--hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \
--hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \
--hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \
--hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \
--hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \
--hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \
--hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \
--hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \
--hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \
--hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \
--hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \
--hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \
--hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \
--hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \
--hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \
--hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \
--hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \
--hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \
--hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \
--hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \
--hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \
--hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \
--hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \
--hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \
--hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \
--hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \
--hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \
--hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \
--hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464
charset-normalizer==3.5.2 \
--hash=sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e \
--hash=sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf \
--hash=sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5 \
--hash=sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56 \
--hash=sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26 \
--hash=sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718 \
--hash=sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93 \
--hash=sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640 \
--hash=sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3 \
--hash=sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875 \
--hash=sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e \
--hash=sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204 \
--hash=sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234 \
--hash=sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3 \
--hash=sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98 \
--hash=sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187 \
--hash=sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d \
--hash=sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f \
--hash=sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7 \
--hash=sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011 \
--hash=sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f \
--hash=sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869 \
--hash=sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1 \
--hash=sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d \
--hash=sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847 \
--hash=sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9 \
--hash=sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93 \
--hash=sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd \
--hash=sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00 \
--hash=sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0 \
--hash=sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09 \
--hash=sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac \
--hash=sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621 \
--hash=sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8 \
--hash=sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a \
--hash=sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51 \
--hash=sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0 \
--hash=sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef \
--hash=sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6 \
--hash=sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649 \
--hash=sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229 \
--hash=sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e \
--hash=sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd \
--hash=sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115 \
--hash=sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c \
--hash=sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab \
--hash=sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253 \
--hash=sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995 \
--hash=sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438 \
--hash=sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0 \
--hash=sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b \
--hash=sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7 \
--hash=sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a \
--hash=sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a \
--hash=sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c \
--hash=sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5 \
--hash=sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37 \
--hash=sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e \
--hash=sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4 \
--hash=sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800 \
--hash=sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055 \
--hash=sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c \
--hash=sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b \
--hash=sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80 \
--hash=sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a \
--hash=sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4 \
--hash=sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2 \
--hash=sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58 \
--hash=sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc \
--hash=sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639 \
--hash=sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf \
--hash=sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d \
--hash=sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f \
--hash=sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c \
--hash=sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc \
--hash=sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4 \
--hash=sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253 \
--hash=sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade \
--hash=sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858 \
--hash=sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26 \
--hash=sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96 \
--hash=sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8 \
--hash=sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13 \
--hash=sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1 \
--hash=sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03 \
--hash=sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364 \
--hash=sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4 \
--hash=sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0 \
--hash=sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a \
--hash=sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036 \
--hash=sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3 \
--hash=sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21 \
--hash=sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3 \
--hash=sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e \
--hash=sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413 \
--hash=sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21 \
--hash=sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346 \
--hash=sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429 \
--hash=sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685 \
--hash=sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f \
--hash=sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c \
--hash=sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d \
--hash=sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad \
--hash=sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400 \
--hash=sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb \
--hash=sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc \
--hash=sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c \
--hash=sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74 \
--hash=sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf \
--hash=sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604 \
--hash=sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f \
--hash=sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105 \
--hash=sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a \
--hash=sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d \
--hash=sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1 \
--hash=sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5 \
--hash=sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e \
--hash=sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709 \
--hash=sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874 \
--hash=sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc \
--hash=sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95 \
--hash=sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd \
--hash=sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0 \
--hash=sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d \
--hash=sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3 \
--hash=sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c \
--hash=sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3 \
--hash=sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491 \
--hash=sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5 \
--hash=sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5 \
--hash=sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655 \
--hash=sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288 \
--hash=sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd \
--hash=sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084 \
--hash=sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d \
--hash=sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915 \
--hash=sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1 \
--hash=sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd \
--hash=sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424 \
--hash=sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f
# via requests
curl-cffi==0.15.0 ; implementation_name == 'cpython' \
--hash=sha256:08c799b89740b9bc49c09fbc3d5907f13ac1f845ca52620507ef9466d4639dd5 \
--hash=sha256:0b6c0543b993996670e9e4b78e305a2d60809d5681903ffb5568e21a387434d3 \
--hash=sha256:1977e1e12cfb5c11352cbb74acef1bed24eb7d226dab61ca57c168c21acd4d61 \
--hash=sha256:2b6c847d86283b07ae69bb72c82eb8a59242277142aa35b89850f89e792a02fc \
--hash=sha256:408d6f14e346841cd889c2e0962832bb235ba3b6749ebf609f347f747da5e60f \
--hash=sha256:41f80170ba844009273b2660da1964ec31e99e5719d16b3422ada87177e32e13 \
--hash=sha256:4682dc38d4336e0eb0b185374db90a760efde63cbea994b4e63f3521d44c4c92 \
--hash=sha256:582e570aa2586b96ed47cf4a17586b9a3c462cbe43f780487c3dc245c6ef1527 \
--hash=sha256:5a0c1896a0d5a5ac1eb89cd24b008d2b718dd1df6fd2f75451b59ca66e49e572 \
--hash=sha256:7b7a92767a888ee90147e18964b396d8435ff42737030d6fb00824ffd6094805 \
--hash=sha256:7e63539d0d839d0a8c5eacf86229bc68c57803547f35e0db7ee0986328b478c3 \
--hash=sha256:829cc357061ecb99cc2d406301f609a039e05665322f5c025ec67c38b0dc49ce \
--hash=sha256:838e48212447d9c81364b04707a5c861daf08f8320f9ecb3406a8919d1d5c3b3 \
--hash=sha256:967ad7355bd8e9586f8c2d02eaa99953747549e7ea4a9b25cd53353e6b67fe6d \
--hash=sha256:9e5e69eee735f659287e2c84444319d68a1fa68dd37abf228943a4074864283a \
--hash=sha256:a25620d9bf989c9c029a7d1642999c4c265abb0bad811deb2f77b0b5b2b12e5b \
--hash=sha256:a6d57f8389273a3a1f94370473c74897467bcc36af0a17336989780c507fa43d \
--hash=sha256:aa1323950224db24f4c510d010b3affa02196ca853fb424191fa917a513d3f4b \
--hash=sha256:b624c7ce087bfda967a013ed0a64702a525444e5b6e97d23534d567ccc6525aa \
--hash=sha256:bda66404010e9ed743b1b83c20c86f24fe21a9a6873e17479d6e67e29d8ded28 \
--hash=sha256:ea0c67652bf6893d34ee0f82c944f37e488f6147e9421bef1771cc6545b02ded
curl-cffi==0.17.0 ; implementation_name == 'cpython' \
--hash=sha256:0d85bec9648bf7c14c3b43056ba82521740f72cd96ed7700a0e1973e7fc93f74 \
--hash=sha256:0e70d25d88adc66818d831805e460704088f445269eaabbf884ab05d437c2f99 \
--hash=sha256:2cc7d939014953223c96e78098bb24c336e7268eb6529c0d5fa9a53805a4acee \
--hash=sha256:2dac9c915a0ee7d7cc4285203d210816bb187c8deb5c20ee21e0613639c2a8bf \
--hash=sha256:31ee8500d06d6502ce1ec0b7ded1c5aa8e8f3401bbe37ccd78d6153d859d8f3c \
--hash=sha256:32f9508a92adaa8c9c35fd4cda786c9e697643afc2eda8dc4c3d426a910b453a \
--hash=sha256:3f737d386e77d4e5ac64998fac8b494b35d37e8cbda22f675b0126913e0e4d6d \
--hash=sha256:4c3993c7df155d622869b82a56adb018440587fd3faffeaf8d01cc016d2e1357 \
--hash=sha256:4f3413b62c780f2a5c7f8a0f6a1d8114f055043a273981b9732abedb5367202b \
--hash=sha256:51199328450e07c8ef8430a7ccce1acfb199b5cd7595e8f958e84f2faedccdac \
--hash=sha256:539eb6708c46433cd61745fda756f2754807f4774b31255d8ee56db0e97068fe \
--hash=sha256:56d622930eac5cee4cc6ebe63eaba3ecca65a2c73aa6bdf099c2ffae55ee988c \
--hash=sha256:5ca006230676c7c2f2e5708d02e5852a09caee49d82f1f2a469d5d6537a11baa \
--hash=sha256:7e126f4675d100f1ad6247a0d8e0b3ebe3fa2f4a123e2b9b78e4880b40f5bedd \
--hash=sha256:88cb5e34eb23eb2106711b06df68027209c72be709df239c6029345551e0acfd \
--hash=sha256:8a08236aac049468d83fc19699102a3d953769ccbfe2b31b63e1d26c5bb07af3 \
--hash=sha256:918a493717da703bc10507b811e347f4ad94132e30c6709fc1e85daf79979565 \
--hash=sha256:93f706c46370cf83c53ffe08cf33892e657c21a6597802f67f1559e4c642ee65 \
--hash=sha256:9426fa386a0f299ab043f64e59689d52e6ee2370f19238aa0bb42e6bf3620aaf \
--hash=sha256:a055f709029d2deaafed6a3a2a58c219d7ee2776a1d2357272d3ef230fb30c5c \
--hash=sha256:a93d3cd83aed4307001ca560b931317e0690ddf3c17e86c2d5b6e0722780b40c \
--hash=sha256:aa91d26234516ddb9eb97310d5fe1705aa6f677f101d57ffdb76d5f75439506e \
--hash=sha256:ad88837e627896f794ab77c5d61245f5fbc0da1e86a39043404b94bef45e98ef \
--hash=sha256:ae0442e45d6e0c987f84cb88bd6a99d7b91c8e2b017c18048a6c4fed63847c80 \
--hash=sha256:af0782d5e340b65fd76701630f0284a8f8243d77df5f2637efd09a4b009f4e24 \
--hash=sha256:b09f03f1aafcbbf6175610005e4e0192413148fe44c65b789a2aadfff9384a7d \
--hash=sha256:c11b405fa10530cec589349c1cc8d60a3a4fac20fb7be0b2713e7271a2737f57 \
--hash=sha256:e8cfb7eee2019fe879ab3304b33e84ba60dbcec148c34c343c49b8c67f9ddad5 \
--hash=sha256:f7e0817633948a8b00e65ef3662bf139cef3fb4d3847e29a720f8072c3d76a18 \
--hash=sha256:f8cf840646d3e57637b8caae7d0d93334dfed0bfbf6f160b36479a7d6069d547 \
--hash=sha256:fc33ca76371bc96df3c4e8593449a1e0e28086bf8016addb851905090069178c
# via yt-dlp
idna==3.18 \
--hash=sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2 \
--hash=sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848
idna==3.20 \
--hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \
--hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c
# via requests
markdown-it-py==4.2.0 ; implementation_name == 'cpython' \
--hash=sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49 \
--hash=sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a
# via rich
mdurl==0.1.2 ; implementation_name == 'cpython' \
--hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
--hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
# via markdown-it-py
mutagen==1.48.1 \
--hash=sha256:4f077fe87d3fc7fba259aa63d8c026b18382ca6a42ef37c61e16f1b1b5b82fe7 \
--hash=sha256:8f95637ab9f6f305cec6bd1294e197debe207998e3e068596563c74f86b0a173
# via yt-dlp
pycparser==3.0 ; implementation_name != 'PyPy' \
--hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \
--hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992
pycparser==3.11 ; implementation_name != 'PyPy' \
--hash=sha256:51d5a8ba2be0bbe440b99d2112604c95bbbc3c2748a64260186c541e1729cd80 \
--hash=sha256:d875f09c3507d00e1aba0eecc6dcadc1352f30fff09dc6bff2f1c2935e97c2bc
# via cffi
pycryptodomex==3.23.0 \
--hash=sha256:02d87b80778c171445d67e23d1caef279bf4b25c3597050ccd2e13970b57fd51 \
--hash=sha256:06698f957fe1ab229a99ba2defeeae1c09af185baa909a31a5d1f9d42b1aaed6 \
--hash=sha256:14c37aaece158d0ace436f76a7bb19093db3b4deade9797abfc39ec6cd6cc2fe \
--hash=sha256:189afbc87f0b9f158386bf051f720e20fa6145975f1e76369303d0f31d1a8d7c \
--hash=sha256:43c446e2ba8df8889e0e16f02211c25b4934898384c1ec1ec04d7889c0333587 \
--hash=sha256:4f2596e643d4365e14d0879dc5aafe6355616c61c2176009270f3048f6d9a61f \
--hash=sha256:52e5ca58c3a0b0bd5e100a9fbc8015059b05cffc6c66ce9d98b4b45e023443b9 \
--hash=sha256:55ccbe27f049743a4caf4f4221b166560d3438d0b1e5ab929e07ae1702a4d6fd \
--hash=sha256:58b851b9effd0d072d4ca2e4542bf2a4abcf13c82a29fd2c93ce27ee2a2e9462 \
--hash=sha256:6b8962204c47464d5c1c4038abeadd4514a133b28748bcd9fa5b6d62e3cec6fa \
--hash=sha256:6bbcb1dd0f646484939e142462d9e532482bc74475cecf9c4903d4e1cd21f003 \
--hash=sha256:71909758f010c82bc99b0abf4ea12012c98962fbf0583c2164f8b84533c2e4da \
--hash=sha256:7b37e08e3871efe2187bc1fd9320cc81d87caf19816c648f24443483005ff886 \
--hash=sha256:8a4fcd42ccb04c31268d1efeecfccfd1249612b4de6374205376b8f280321744 \
--hash=sha256:91979028227543010d7b2ba2471cf1d1e398b3f183cb105ac584df0c36dac28d \
--hash=sha256:a33986a0066860f7fcf7c7bd2bc804fa90e434183645595ae7b33d01f3c91ed8 \
--hash=sha256:a9d446e844f08299236780f2efa9898c818fe7e02f17263866b8550c7d5fb328 \
--hash=sha256:b2c2537863eccef2d41061e82a881dcabb04944c5c06c5aa7110b577cc487545 \
--hash=sha256:bc65bdd9fc8de7a35a74cab1c898cab391a4add33a8fe740bda00f5976ca4708 \
--hash=sha256:bdc69d0d3d989a1029df0eed67cc5e8e5d968f3724f4519bd03e0ec68df7543c \
--hash=sha256:c25e30a20e1b426e1f0fa00131c516f16e474204eee1139d1603e132acffc314 \
--hash=sha256:c7947ab8d589e3178da3d7cdeabe14f841b391e17046954f2fbcd941705762b5 \
--hash=sha256:c885da45e70139464f082018ac527fdaad26f1657a99ee13eecdce0f0ca24ab4 \
--hash=sha256:da4fa650cef02db88c2b98acc5434461e027dce0ae8c22dd5a69013eaf510006 \
--hash=sha256:ebfff755c360d674306e5891c564a274a47953562b42fb74a5c25b8fc1fb1cb5 \
--hash=sha256:eca54f4bb349d45afc17e3011ed4264ef1cc9e266699874cdd1349c504e64798 \
--hash=sha256:f489c4765093fb60e2edafdf223397bc716491b2b69fe74367b70d6999257a5c \
--hash=sha256:fdfac7cda115bca3a5abb2f9e43bc2fb66c2b65ab074913643803ca7083a79ea
pycryptodomex==3.24.1 \
--hash=sha256:03e2027f81fe6b700e7ff614d79111559bfb05ed8c4a9de9d2152d1a0a0768de \
--hash=sha256:09081666ffc599976c0b8b29caf2cf82212c0f05bed233c8f8ed53e4f6e1d356 \
--hash=sha256:147c742f73bbe8791d8c454b9972330d7ea501de94e8172957af375f9bdb4a7f \
--hash=sha256:3bbcc1807502da4b5d66c94357a99589c8547aa9ad2f9ecfa537b2e9a347538b \
--hash=sha256:48d9058dd4c8f3af83e048b6ff83d9c6300841c42579f77fdfab19e49156a512 \
--hash=sha256:514d685de4b0227d35d7114047fbd575bf162bff373e07af665aa41eee089dd0 \
--hash=sha256:569fdbeff936cbd5beb852b3969dc2f58fb255bd221b3f7a8999c035c30ec958 \
--hash=sha256:5966f829f64c833cc72a8694cfee05ad50446a44167842c92dec4ebf6b84d72c \
--hash=sha256:5b37b86a3771d6aa21cccf9f8448460e4be11e68bb8e699133ce632cb986f521 \
--hash=sha256:6159dc74824c591b4c294f8f96b74a71c3b5e9f637dab2f2da14cfa32dc24d47 \
--hash=sha256:77ef934c2b2eab3c57a431daf858fcbf272134691bcc8d729787d17ad4cbf758 \
--hash=sha256:794f32227a480ab3b39971ac4a53dfa8ed444e28c0ddecbdc35f26d038bb46da \
--hash=sha256:7a81e9be7084af3591912475b22c5d0646a9160f3974b6b7300138781fffdc0d \
--hash=sha256:7f30261641dac5ae60e0af2fb11ad7c87200575b0ce403f7531576b0f38a52be \
--hash=sha256:82eb0dd8a95be97f03527b108ee49f9b86a7c534fa47fa7a510be3eab8ea9acd \
--hash=sha256:8321c315c4418dfe45a811b792380438ec81185deaaf202dbcd77711b4f51796 \
--hash=sha256:9a732b9f5603b153dcdc071d6b342f192981907519827f2c1e4aeac41e2b34c2 \
--hash=sha256:9b94a8c647c1f80b4c82c7ac9642dda94a71abbb4efa29ad652c410ad7a39879 \
--hash=sha256:9bb353c764c144a9fc03302ef3763ad0c3e75bc7ca41f445cc98455f36da6c59 \
--hash=sha256:9dd5104a1d8ccf725a3c1b40b21d5ed47530b6499abba30955c174d895c1be2f \
--hash=sha256:a692d2484ca8fa2c69f45c63f2b30cd00b8512834e3a522fc297d981dde5b34c \
--hash=sha256:b1c7a61b0b644e9780aa9f6eee301fb77c813b1e41262f6f4f387de0558e8926 \
--hash=sha256:b299a1c10e45e1b71b34b048d555d3a8f366240942af89be5db379f88edb9542 \
--hash=sha256:bd06ab1d9cf90e8b198daae3b364e9ac23a640d210bb8faddad6627cf2e33be7 \
--hash=sha256:c20fb5e8cf874dc182091d6df122b8b588501d23e7b500acf662c49899afdd0f \
--hash=sha256:cc64f4e1fc07a155ef31eb9815183a6a8eb13dfd6876ab049c01125223aa0c40 \
--hash=sha256:cdec09935db4cbd74da5b577ea7d9959c73374060b22abf7d505429c0da7ed63 \
--hash=sha256:e87928d8f37952ba53d215836cb3d89c63c1367f037d055c3a5b3f4403f4c6b6 \
--hash=sha256:edc1deb28fceab6b78e12bae506eaef62ee2fc1b3cabc96f7932f0d51e368acd \
--hash=sha256:eeac2c9acbd2d9f0ca493fdf692ce8245ca37cbebee08c496025868d4b8ef70f \
--hash=sha256:f3ed97cdde1d96894057778095238bad3dd94d3e46dc07d6d618e6d4b7700cce \
--hash=sha256:f87d74a804ca949f46a6babe70247a789f6401f229566e90174c4b7033b87cc5
# via yt-dlp
pygments==2.20.0 ; implementation_name == 'cpython' \
--hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \
--hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176
# via rich
requests==2.34.2 \
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \
--hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed
# via yt-dlp
rich==15.0.0 ; implementation_name == 'cpython' \
--hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb \
--hash=sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36
# via curl-cffi
urllib3==2.7.0 \
--hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \
--hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897
urllib3==2.8.0 \
--hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 \
--hash=sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63
# via
# requests
# yt-dlp
websockets==16.0 \
--hash=sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c \
--hash=sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a \
--hash=sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe \
--hash=sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e \
--hash=sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec \
--hash=sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1 \
--hash=sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64 \
--hash=sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3 \
--hash=sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8 \
--hash=sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206 \
--hash=sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3 \
--hash=sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156 \
--hash=sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d \
--hash=sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9 \
--hash=sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad \
--hash=sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2 \
--hash=sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03 \
--hash=sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8 \
--hash=sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230 \
--hash=sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8 \
--hash=sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea \
--hash=sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641 \
--hash=sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957 \
--hash=sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6 \
--hash=sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6 \
--hash=sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5 \
--hash=sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f \
--hash=sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00 \
--hash=sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e \
--hash=sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b \
--hash=sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72 \
--hash=sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39 \
--hash=sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9 \
--hash=sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79 \
--hash=sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0 \
--hash=sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac \
--hash=sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35 \
--hash=sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0 \
--hash=sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5 \
--hash=sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c \
--hash=sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8 \
--hash=sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1 \
--hash=sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244 \
--hash=sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3 \
--hash=sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767 \
--hash=sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a \
--hash=sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d \
--hash=sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd \
--hash=sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e \
--hash=sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944 \
--hash=sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82 \
--hash=sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d \
--hash=sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4 \
--hash=sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5 \
--hash=sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904 \
--hash=sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde \
--hash=sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f \
--hash=sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c \
--hash=sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89 \
--hash=sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da \
--hash=sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4
websockets==17.3 \
--hash=sha256:018fab26140ce221c3853454a608e4e7004f4f10641cb97819dcd5b917bb2e99 \
--hash=sha256:07246d4f0293ef0b87eff3d7dd88c1f03dd9f678fa39f6de87b2af8504e7e0de \
--hash=sha256:078d1d41f45ee34eed5a4f3bbe7c588caecbdd6e12dfca73e8c1b0e803773793 \
--hash=sha256:0824e6ecee838cc28e6481062574c7fde49f9a2cedfacd36f0e91cb4b37fd6fe \
--hash=sha256:09f007b2150eff015b2109f006e2ac2012d376f41486defa88ae78a776b00cff \
--hash=sha256:0a0bcf66289b9d017c175562c35c5304b5cc3ed56aded994ae30b0a9654ba405 \
--hash=sha256:0a657b51e4a5f4ac577c11e706ff9a884ea5aaf3e2666bae283a251c63e66acb \
--hash=sha256:0c63ad657695e8f1a48624754cb6b464118ac50d4c1d477c26461c98390f0a62 \
--hash=sha256:0d20d6ea5aabbeba2e054d33e405192ef75dc12947bbd00ec97d23b14969d325 \
--hash=sha256:0e65260a1b1d7b81651f47343d836de70b88b02358ae3658efa6382104ec37b1 \
--hash=sha256:0f78bb2e82fe88912c9d7b25c98e57a9b08655579af89f164fd4c0657a075d62 \
--hash=sha256:10b24e836ee0233ca078e1244f6ba40343a22127a9a736f46a7e7b18de2cc711 \
--hash=sha256:13cffaedde6e06183860fc92d88fe1d190abda73837fe4c14f5d4803c472f5dd \
--hash=sha256:13eace1b315345ebac5b27821f5dcce24e5cf9976ab18f79e00a59bdd67e5d19 \
--hash=sha256:15decc0fe293d9e3f924bd483f3d76f3d0ff26845112a470e3f8842fec2c82a1 \
--hash=sha256:1c7dd93a1c9f89297471493674b1fc1d9467cafd45374f2172213046bdb3a329 \
--hash=sha256:1dae5cd6c92d4440b15f20aa2987baa73c47ea14baa0fec8536a542e82e0ab33 \
--hash=sha256:1db2604e6aedb7a2cb2f6e0575d6c9a852ccac8239703a930ac83b63309177a5 \
--hash=sha256:2129c9a5fc05a230ce088745a790af073e582b584badc7b05db067ee326f56d7 \
--hash=sha256:23046098ebf844753cfd211033624a8247520e5bf2194c24cb1a8c222917acff \
--hash=sha256:23cb6f6d64e3a389bb8ba150f947f9a6c8c0aca383e814ca3c5cffab738d5646 \
--hash=sha256:26838e2d95d7004c52e8c7b6b51676c872093a3b55a497824f899116a15a8a55 \
--hash=sha256:2789d203babb6ceb2770aadc2394c1f99263ec37fba57a93064f9a8ad899e8ff \
--hash=sha256:28d1935c16782a1e3650c9baa79069b016fff739e292e4cb14bbb830d6930491 \
--hash=sha256:29b01520c39ef2f23c88b002f11e6ef4165675f6c92f5f3578fd587d69b5a5fc \
--hash=sha256:2a377c7132b1e69be7a50d7434d7f26f69e93c70166ebb6d8f8cabf802ac4506 \
--hash=sha256:2b06213c8e1ce93b18d0476d7a5e647436c8f23d099888c9065e930e80f4bed5 \
--hash=sha256:2c460aeb12c2bd1c204944d9e9199595bf9e505eb542018d304bf9e63cb60cad \
--hash=sha256:2d08ca4bf5a9cdb6fd81b86b51bd5cfb10527d3a1199888f2b02cc6c6a3d5f80 \
--hash=sha256:2d875224bac1a05a20acade268a7a0e3498e7f8cf890acb7c2b23bacd2bd3659 \
--hash=sha256:2e99440ef446c7833690c1754e23b0188d440f3cb89812b0764c697a7880cb33 \
--hash=sha256:2fa79b9a48ae59744316c71a34cb9f76f30c93e117338522c5135cb7eac10351 \
--hash=sha256:32029441af953e980b9940f042b337fe4ad9a97fa8b17a4ed878ec67b5b89ef4 \
--hash=sha256:33221e49be79d7bfe6d12bc52ef9458b256ab74fa8ac5660acfa3065de1c7870 \
--hash=sha256:34c78052277053bcb09810ac8e9ba4029f9e3e277833fc18ec1c928a6246ac91 \
--hash=sha256:35381b575f70a08d4241e73c0cde4672bb9b2a9aae8767ca6b7fb61305a052c8 \
--hash=sha256:35fe35d20baa661cef4a12ee7bc42eaf2376d43ef9816ab29dd47ca957f7a73a \
--hash=sha256:39f532fa0d9026de4b9315a175998646112776baad54d55348435c11b05d034e \
--hash=sha256:3c4f631dc8d00e470cde3ec0a35d4b58a817bea592411956f1cf4099dbb306b3 \
--hash=sha256:3d78d93846eddc990551c1c31914d90d71957ca3af468969826f7ed0d7d1d51c \
--hash=sha256:411aa0fb234f42a1444dea1e177890ddfc577b36ffdfafec25cb0d2c818e1af8 \
--hash=sha256:41665c7ea01d3ae497a0c61fd22d3424230d18782a5fceb79f04db9ccb2042c9 \
--hash=sha256:4170556762c6fd2913d99dfdd8dbb4c927584899df7facb1034627e355263c45 \
--hash=sha256:43f270a5f21e12db08c73d83849a877c02ab7b7d0fb6e2718b5101d9c810212f \
--hash=sha256:443fa28652682d2a3ec3eca49af1b87cb2523561257683e62e03a98967b22138 \
--hash=sha256:45cc1ccb12ced6d242335159e8221733c8696da5ad0b6ceef6debb0f5ce89110 \
--hash=sha256:46ae05aa1aecd47d4d7de0f05ce2d1d2eb418f8de614964d754cc3b9a409c400 \
--hash=sha256:49fb5b4960ebe1bc557b435da8687deef1302a08f030a33c5606fa6fb11b773b \
--hash=sha256:4a9133dbaedc6f1af358127275676171d9a1bb3e61f47ee62b2ff9acb78af3d0 \
--hash=sha256:4aa85b34c21cf97b3470793d0bf0763d32bfd1e67b83067a0a3ba8dc3474dacf \
--hash=sha256:4d5f2492cb2192aab2d42e57f2caa2159b4fd20fde06f859ec13354f524b176c \
--hash=sha256:4e7b5d23ef144b32645d97bd99f382c4394c443395f45fe1576786838d26e308 \
--hash=sha256:4f7431e71072962d3ed1768038200aa4f1e76d9c2d7bedd554d57a55faaf6644 \
--hash=sha256:508775efa11d26aec186d10154359f52276e2baf9ca201b52356330883276dfd \
--hash=sha256:5142798871a248b422f353e0684d51dfa119de3403a6fa0904b7cb806d9790ce \
--hash=sha256:52a2ca6f401fb49a8d5d9e0e48ade5f58f1bdda33132907b0e4e3b702628fa4e \
--hash=sha256:53209dffd91b0aefed9ea630fa6ad5c2944d6210ba3a8a3a8664dc1575289b14 \
--hash=sha256:534ed583fd4323de45d196535a444cebd1af2105e6e4e0cdcbf8cea266a8747a \
--hash=sha256:54fcd24944e6d127d198c28dc363967b7131ff0c97833962c2ef2048018de02d \
--hash=sha256:55494475206113dbaf731dc8c5ffd5e1094175b753b7bbaad09fe3d7df61165c \
--hash=sha256:5670a762c7ae388bf8aa04199fd436180a4d28318dca9c1eae7b38604676dbfd \
--hash=sha256:56a76556ab04ab54a675acce2cac8b4e74ea2cec558a7c9ed37e0367b04b5d50 \
--hash=sha256:56d43c311f3519fb1057b6114dc24e9060bc3fb6aedf4aa11160484154b66b63 \
--hash=sha256:5868a02c4f6d698ddd19b4c9742748c03dec045289915806845189d96bc3d314 \
--hash=sha256:58e5d1e935a90878a935c7d2737a25c71cf4f1c13b6e6bef454ab722c4f338bb \
--hash=sha256:5ad409b7ea102339041281117cf2dadfe71edbb653dc48037cc55d516fb7f448 \
--hash=sha256:5af7070d80d278832cbca9c3c3dd44b30a26dcfa3ae1e0f6f19ff34edc27b689 \
--hash=sha256:5d0c871efc696ef5eb8514df64b86ab28736db753ebb42a2101f3b562f4849c0 \
--hash=sha256:5e0c0ed37472c4729f3001066510a656486f08f149dda1ebfd3dfe4450c9756e \
--hash=sha256:5e1c174b366565e101f903f9d1cc96d5508f805759dd37d012743f1c73ec0d7b \
--hash=sha256:62059d739af7fc035ed6e63c5390118a60a5e9aa5a5541cd0486a83e741842c7 \
--hash=sha256:623d4b44f64efdf235b1e8dce266057073d93cde6197e7d7684f20c297f67f30 \
--hash=sha256:628efe13630ac3397e7d1278b6be6f22f37a86d638a324334b4cd43c1daf9928 \
--hash=sha256:6342f79d6f50e680c8aa59e0615d745e867e51ffd59c77093be60b7c433067af \
--hash=sha256:63b87c93e28957e6dc2bb92d31727a863c9bf4a4daa080f0995fdcb0242c9166 \
--hash=sha256:65e937576141ac50fac32fa9736dbb3e0e4a7769f91be004011a09216c6ab05f \
--hash=sha256:66027e401c70d0cf55021b91b8a7ec2cd5810e20602f945b4fe6ae8b37ed232b \
--hash=sha256:6644eecd99c4e8cdf72e646e17b391bb70b054f44becde37dcdc48cbec7e1527 \
--hash=sha256:6705af9d1005127302c04d9f1533ba56e289336c465923ef878430e99295a0b9 \
--hash=sha256:6a8248b1ba8861e48e4c7ced3895a1264d2a3b617de72ec94172ce6e64bf16c7 \
--hash=sha256:6b14914e67044724c31a9360c7b89e9d070117c630746eefdc1620d967545acd \
--hash=sha256:6b7b540bb321f7f0a7b8f5d107f941bb361e3a154c0b594dae0394997b91b743 \
--hash=sha256:71250e010eede33c1d638e2c7a98288520d67f782fd5eceecaeca3129233a09a \
--hash=sha256:722ab747ff5dc28070b1a8c020dba6466f13f2ab56bc251ad301fefa2454aa1e \
--hash=sha256:724224d4c457207271239114bf43afafc3eca4a1b4661ccdd428d11869a03bbd \
--hash=sha256:729989759feb81ff6493879a0d60a0bd7d2eee41001bbec0381a080318439382 \
--hash=sha256:740bba4223fa5216d4d6c5dcd29e697f37229b8a61b69e1a50527b0ea993ab2c \
--hash=sha256:7bdc658c9474864893e0b6b94f1390bf6a912952df1870dd93bb7d1a902b5628 \
--hash=sha256:7d53fc4b90ef6e11de639dc18744d9be8cbd70ccb5ce80027aaffe7b1ab0215a \
--hash=sha256:7fa69212ea60ea24e2d8aff23fe102b1f87f1b27a320f92d2e7b3468997a496a \
--hash=sha256:80326bc571164bbbb6bead2e35d0c943b23b24fde629032197c58151529d24d8 \
--hash=sha256:80578e91764bfca297ddca322c00a3136d993b829e9839e7fa378a19c1fcc25d \
--hash=sha256:80a6e37e235780f189558ab804f3cbc01c18f5c578995739b49613d544d34ebf \
--hash=sha256:8135a549e27e9941a70e2d2156676ef2ffeff4b06e9d564dbaaae963482afdef \
--hash=sha256:82e60c00cfb8493a5ba27cdf9b3695fdd153f666f73e11f18968f78ead1d8705 \
--hash=sha256:856bbb24f2ee6436af7609267e73309e4bb0a0f9982f79f1c2e01019279c6671 \
--hash=sha256:85d6daa3a7ca404570ae130babbeb347ef9d3faca5300fb13cfa4bb48c3d30d1 \
--hash=sha256:8879b6a4040ee925c638548238ab7fe612cf5fa8752fe847346da0da8be81c3f \
--hash=sha256:8b3bede7d583bc9f47d8693a29984882e59077db1a5238ad977fc70ae8169741 \
--hash=sha256:8dbb3862aa649de95660b6337d97101977f160b5b354d07b82fe309874d2c8bc \
--hash=sha256:8f244dfee05ea29b8064701880865eb1684f3a704a5665bd10b64694444dbbd4 \
--hash=sha256:8f7469408740cf06a79b01605f2ae0b2acc8839c03fcbbf05da49baee12d3302 \
--hash=sha256:90cc9973c51811918247a78d9ab2f54871296e4e37e69a98aba4d3c9acedbf62 \
--hash=sha256:90d8c4fa5ba293cf92de351fbc292cdaadb1a1d58d031a1a97ff9b8fb6250ec7 \
--hash=sha256:94c02b0702656f083c098bdbd93bce22a7aa7a2b34ba56d2472efb67dab7cf58 \
--hash=sha256:9662a9fe457820c60365b3209e03cbd8e4a817195d55de65a80fa680b4bea136 \
--hash=sha256:997617dd7856c5dad742bf6893b872319156dd43f47587541a59e4a852d52bbc \
--hash=sha256:99c5637b74e2805ee4de9e2a43c8b45f678e50abb1c2da9880f0372f6498ba2f \
--hash=sha256:9a215749c9a88ef2842e880215193e56ae60b856773c99702b078236bc6d4adb \
--hash=sha256:9bde5d82d7ac4859e0cb3a35e148f537a8d4e56aa43f42582b5f263982f095ae \
--hash=sha256:a004c1fe5a72c496f28c6c1d8c2dc5cfe3278d99478e18f8b838c70a912b366f \
--hash=sha256:a0e2e7c2c1a4f25db7b6596738d810c10732e77f852247300a1bc49e364d6dc9 \
--hash=sha256:a22c4956a4d858200dba83f0691bb692d77b0eeddfca80157820d20b85dea4f1 \
--hash=sha256:a7f391838e8adcf1f2fe71561d9e5a9f74ea7ffa5052eb2db329aac677383136 \
--hash=sha256:a9eacb382f400bb5865e7e6d24bbe709a84510291e707f169dd4a24ee4a5ac6a \
--hash=sha256:ace8dd1efa5f44c482d091aa38322e20e3ffe5adcdba6b67ad9f4e7da58f3f68 \
--hash=sha256:ade76f8c84ade325bbed96806357fffd353fcc29a5166d6dc6d39381f6d9f76c \
--hash=sha256:af37a1e6b6bd506b597d5fb4cf111fb527d1b2223608a5d441d4738827cfd166 \
--hash=sha256:af7c474f0d8f4d2a196370e85033873c7b063a0b5da9a4f143aa023e3bd25407 \
--hash=sha256:b225c656efa2dedecc81651d2290170af25887b7de4f38c5efc7c5ae2b9442ab \
--hash=sha256:b459d29c8b82a420a98fa0ce8e9cf787ce0062d98cc90604ef9574fb3cc26ff8 \
--hash=sha256:bc6f87d03e3691154673aaa8f08991723d6e3394c83ef2875c7a9049eac9595c \
--hash=sha256:bc8fd230ef013951900c1fda100eebe4a4b1b407dde2a44186995042dda2c628 \
--hash=sha256:bd645b5d2f810a181c44f4a71135e7c365b44f4be9ed3d1892635be13a857553 \
--hash=sha256:be7be57097a65a8fab3d0f0a10d12931deb626a7d8082eb732b1ae41f3a202e3 \
--hash=sha256:c15a165673bb3fb57facbf040edf5c0556d20ccd2e0ccc5f23ebb69fb715fdc1 \
--hash=sha256:c4b3f2c7d84f303da873b634d0beef83b5e1137294c3de4e23102841dac0cf4a \
--hash=sha256:c534c9524a2acd0b97b7022074bec3784ac273c683cf9535087e437672ea8531 \
--hash=sha256:c95d25b5382ee0e6191ecafdeabefdc1f7bff8dfee29239b9b79e760ef3b04bd \
--hash=sha256:c9d06edfd974e918b40e0662a7e76dac13125529ee5ec9fbe42dc0d6faa209c3 \
--hash=sha256:cdb8e4b0f6a41b857c74c03116e8ffbef59ef8e533e934b532843178990d01d5 \
--hash=sha256:ce39283ef08b0f28478e920d4d89a1fc169176e568e8a6a821332673145522eb \
--hash=sha256:cfef7f7aa434a1e632e0ebda14b39f4f1d7975e0fce5c77ea7b43156fabf9bd8 \
--hash=sha256:d2605a3b2af8d66f8b75312d223642c065ec773446c04566d9030ad5e2db13c9 \
--hash=sha256:d338813a440bf6d2f0df55140d3f3080284410b1ebfe9df50e3847bcdb1a17bb \
--hash=sha256:d355b22270be8062360b9df2ee0b10277590789a1059257916fb9e256a0cff80 \
--hash=sha256:d68da281ac208b6236ffa8beef23fe7c7c956d8bf09b421d447232fd94441b35 \
--hash=sha256:dafbb58a149d1ebd5767b3f064f911c5ee0897608005e51c3904b0ada2a8d99c \
--hash=sha256:dc2b495a92b3971966bf102e73589f950db3ec1ca6713265355ce7771d97b199 \
--hash=sha256:dd0f3037d501178a761fd2814370aca547f79e99a200a61a1f6e7b79ec3d78b9 \
--hash=sha256:de2c12555bf05546f3ee75733f2c81de70aab7f530e86d0d2162b0ddcb3c39ae \
--hash=sha256:e164c4a6868d11988c7f2386e3278ccff21c665cd7d08279b62709dd37a3167c \
--hash=sha256:ed59cb4ee258674a6ed9b8515e42079db02cb3be94f133fdd3f200183a40c49d \
--hash=sha256:ef07e0b6b879f699a16fc7a513b974246fdeaef44908a021130cf4afe6a1c89c \
--hash=sha256:ef2950896673a9809e8e5ab857525924fbcacfc98b858b0509ccf50d341f80f4 \
--hash=sha256:f09f145b89ea292cf6c25fd7c8c0d90207fd6a9e54c7828499669996a1e5bdcc \
--hash=sha256:f27e7e8a85512b6a4b490d5756edde8e6772883a5800e1476172e44eda3f7d7c \
--hash=sha256:f300f28dff74ff4148c21e6971e4de6ca0c34e0086a3d95c017c5174ebf85ca5 \
--hash=sha256:f3ed747b7651668131029c720fbc32c7ee2d129bdad200e6c8f4037b20f7913a \
--hash=sha256:f87f02afe05c1c246012e3de100a77cfbabd17db709fe93cf074271ab239b312 \
--hash=sha256:fa87ea2ad64e59fe5622c1dc5716106b6d6e7e4b26b848cb5f5710a75c292ef5 \
--hash=sha256:fc23e72bd7f8a8e540fed2244524d0a9aeb6ae3325f3d56f04a7a3debe5b04c2 \
--hash=sha256:fdd00937f15f5f93c8e53d8060a8c4c010431ab595a9b5b50ddd569a04603944 \
--hash=sha256:fe7a168d805c8a7bf1c2de55b7ab2bc958586bfd88d0e87235a92cac66b590a7
# via yt-dlp
yt-dlp-ejs==0.8.0 \
--hash=sha256:79300e5fca7f937a1eeede11f0456862c1b41107ce1d726871e0207424f4bdb4 \
+439 -267
View File
@@ -1,289 +1,461 @@
brotli==1.2.0 ; implementation_name == 'cpython' and sys_platform != 'ios' \
--hash=sha256:022426c9e99fd65d9475dce5c195526f04bb8be8907607e27e747893f6ee3e24 \
--hash=sha256:072e7624b1fc4d601036ab3f4f27942ef772887e876beff0301d261210bca97f \
--hash=sha256:0bbd5b5ccd157ae7913750476d48099aaf507a79841c0d04a9db4415b14842de \
--hash=sha256:0cf8c3b8ba93d496b2fae778039e2f5ecc7cff99df84df337ca31d8f2252896c \
--hash=sha256:15b33fe93cedc4caaff8a0bd1eb7e3dab1c61bb22a0bf5bdfdfd97cd7da79744 \
--hash=sha256:1b1d6a4efedd53671c793be6dd760fcf2107da3a52331ad9ea429edf0902f27a \
--hash=sha256:1b557b29782a643420e08d75aea889462a4a8796e9a6cf5621ab05a3f7da8ef2 \
--hash=sha256:260d3692396e1895c5034f204f0db022c056f9e2ac841593a4cf9426e2a3faca \
--hash=sha256:26e8d3ecb0ee458a9804f47f21b74845cc823fd1bb19f02272be70774f56e2a6 \
--hash=sha256:2a7f1d03727130fc875448b65b127a9ec5d06d19d0148e7554384229706f9d1b \
--hash=sha256:2e1ad3fda65ae0d93fec742a128d72e145c9c7a99ee2fcd667785d99eb25a7fe \
--hash=sha256:3219bd9e69868e57183316ee19c84e03e8f8b5a1d1f2667e1aa8c2f91cb061ac \
--hash=sha256:350c8348f0e76fff0a0fd6c26755d2653863279d086d3aa2c290a6a7251135dd \
--hash=sha256:35d382625778834a7f3061b15423919aa03e4f5da34ac8e02c074e4b75ab4f84 \
--hash=sha256:3b90b767916ac44e93a8e28ce6adf8d551e43affb512f2377c732d486ac6514e \
--hash=sha256:3e1b35d56856f3ed326b140d3c6d9db91740f22e14b06e840fe4bb1923439a18 \
--hash=sha256:3f3c908bcc404c90c77d5a073e55271a0a498f4e0756e48127c35d91cf155947 \
--hash=sha256:40d918bce2b427a0c4ba189df7a006ac0c7277c180aee4617d99e9ccaaf59e6a \
--hash=sha256:4ecdb3b6dc36e6d6e14d3a1bdc6c1057c8cbf80db04031d566eb6080ce283a48 \
--hash=sha256:54a50a9dad16b32136b2241ddea9e4df159b41247b2ce6aac0b3276a66a8f1e5 \
--hash=sha256:67a91c5187e1eec76a61625c77a6c8c785650f5b576ca732bd33ef58b0dff49c \
--hash=sha256:6be67c19e0b0c56365c6a76e393b932fb0e78b3b56b711d180dd7013cb1fd984 \
--hash=sha256:6c12dad5cd04530323e723787ff762bac749a7b256a5bece32b2243dd5c27b21 \
--hash=sha256:7547369c4392b47d30a3467fe8c3330b4f2e0f7730e45e3103d7d636678a808b \
--hash=sha256:7a47ce5c2288702e09dc22a44d0ee6152f2c7eda97b3c8482d826a1f3cfc7da7 \
--hash=sha256:7a61c06b334bd99bc5ae84f1eeb36bfe01400264b3c352f968c6e30a10f9d08b \
--hash=sha256:81da1b229b1889f25adadc929aeb9dbc4e922bd18561b65b08dd9343cfccca84 \
--hash=sha256:832c115a020e463c2f67664560449a7bea26b0c1fdd690352addad6d0a08714d \
--hash=sha256:844a8ceb8483fefafc412f85c14f2aae2fb69567bf2a0de53cdb88b73e7c43ae \
--hash=sha256:898be2be399c221d2671d29eed26b6b2713a02c2119168ed914e7d00ceadb56f \
--hash=sha256:9322b9f8656782414b37e6af884146869d46ab85158201d82bab9abbcb971dc7 \
--hash=sha256:963a08f3bebd8b75ac57661045402da15991468a621f014be54e50f53a58d19e \
--hash=sha256:9c79f57faa25d97900bfb119480806d783fba83cd09ee0b33c17623935b05fa3 \
--hash=sha256:9e5825ba2c9998375530504578fd4d5d1059d09621a02065d1b6bfc41a8e05ab \
--hash=sha256:a1778532b978d2536e79c05dac2d8cd857f6c55cd0c95ace5b03740824e0e2f1 \
--hash=sha256:aa47441fa3026543513139cb8926a92a8e305ee9c71a6209ef7a97d91640ea03 \
--hash=sha256:acec55bb7c90f1dfc476126f9711a8e81c9af7fb617409a9ee2953115343f08d \
--hash=sha256:adedc4a67e15327dfdd04884873c6d5a01d3e3b6f61406f99b1ed4865a2f6d28 \
--hash=sha256:af43b8711a8264bb4e7d6d9a6d004c3a2019c04c01127a868709ec29962b6036 \
--hash=sha256:b232029d100d393ae3c603c8ffd7e3fe6f798c5e28ddca5feabb8e8fdb732997 \
--hash=sha256:b35c13ce241abdd44cb8ca70683f20c0c079728a36a996297adb5334adfc1c44 \
--hash=sha256:b63daa43d82f0cdabf98dee215b375b4058cce72871fd07934f179885aad16e8 \
--hash=sha256:c8565e3cdc1808b1a34714b553b262c5de5fbda202285782173ec137fd13709f \
--hash=sha256:cf9cba6f5b78a2071ec6fb1e7bd39acf35071d90a81231d67e92d637776a6a63 \
--hash=sha256:d2d085ded05278d1c7f65560aae97b3160aeb2ea2c0b3e26204856beccb60888 \
--hash=sha256:e310f77e41941c13340a95976fe66a8a95b01e783d430eeaf7a2f87e0a57dd0a \
--hash=sha256:e7c0af964e0b4e3412a0ebf341ea26ec767fa0b4cf81abb5e897c9338b5ad6a3 \
--hash=sha256:e99befa0b48f3cd293dafeacdd0d191804d105d279e0b387a32054c1180f3161 \
--hash=sha256:ef87b8ab2704da227e83a246356a2b179ef826f550f794b2c52cddb4efbd0196 \
--hash=sha256:fc1530af5c3c275b8524f2e24841cbe2599d74462455e9bae5109e9ff42e9361 \
--hash=sha256:ff09cd8c5eec3b9d02d2408db41be150d8891c5566addce57513bf546e3d6c6d
brotli==1.2.1 ; implementation_name == 'cpython' and sys_platform != 'ios' \
--hash=sha256:00a50d063aae2e69c2eb28818ccf6dc3e51f2ea5b74e3c2082a47943ee23f399 \
--hash=sha256:02b2f7b5a83485efe448a44ddf7983def05c3bb1dcf917d4f7154070260e13de \
--hash=sha256:035f3bf861328d8b7fcb61f4a976f9913027158e5666116733d59ffc65f2745e \
--hash=sha256:06a22fcbcae059c0679098232779095fc50a735a3fea02db5c79cab10b84d877 \
--hash=sha256:09a2f112a638aca15a88f298571788795fc45d62f2bca7f3870c1152153ef399 \
--hash=sha256:0a30e5df5ba985b67f85e13dfd7e5a68e186d8d9b5cff7d9a8904832bb413e81 \
--hash=sha256:11aec6ea5c20cad61a33302e06baa48b0243bfa4d173bc2985dabd047e367d08 \
--hash=sha256:1329c80daa60752f1d94f507479504921e358e71746c5fce9b55b3d51ac038bc \
--hash=sha256:1880db6241276e191d3e34a6e4eea708c6629103c396f0ea21e75b0ce63a9a2c \
--hash=sha256:1f65a91f3576949793b8720b12a47e7ea06debc970a2da6d54ff8458053e2109 \
--hash=sha256:23f0d23995100458d17f3bf5ce1e959fe46df894b472063a74266f7adeb2e72e \
--hash=sha256:264fd5b200f6f6170cb551a4b9fcaabf8aa846ddaefe72db4d5f49f9d3743df9 \
--hash=sha256:2df1678c2c25db2f669c613fe8b4e587d0dd24c6acf7746bad13d6e87e4b051d \
--hash=sha256:338856ae9ff63af4fc3dbbd6184a7276a6ae83df2243562e86e5ee5cf980cce7 \
--hash=sha256:37de1818ce469b3c37324c89d4d4dbb5e64461d9dc01c16f8abb2a17c465b132 \
--hash=sha256:3975fb11f63e212b87a087e4a910187b522c6969a4989ca362d6f85f9dc36acd \
--hash=sha256:4b9dd0173ca5e01d1eb307d3c184fe8c09bdc168ede560889b1018d216d38c61 \
--hash=sha256:4d47a9f0ba5ee608f3f3a9c942dcd244443068ae5b0d90183dd396dea02236e4 \
--hash=sha256:59ca34c7a83d7a3b842247183c426f891a95a8f57db41b7aac92195c51e8a83a \
--hash=sha256:59ec359a56f44277ad424fb4b7cf1a0ae2fd855b35ba8f15dcfbcabb3fb51aeb \
--hash=sha256:5f3da70516b1bd1b2aa183ec4ab5c02dfc6ad5c1184d47bb65ade25e710439b6 \
--hash=sha256:6532d2c58018121a9eb5882656cf862cdbbd853600cb5fbccac59bcff14f66b0 \
--hash=sha256:67f4dceb22ce3a742751cee849644449b169684699aa548e77d771de304e963c \
--hash=sha256:6b3c3d5794212a54434b4856f808f7bdf7ad48eacadaadb5b2346fc9a639365a \
--hash=sha256:6bd29ab84bb8972370cacd310e8a91651f54476d01de1cd1a4cf0bece5eb25e1 \
--hash=sha256:7248c282d7d6aef4ae89363da5fc3df7b9250eb04b252622955296eb5d0ea82f \
--hash=sha256:761db18dc32b24d00fbedca1013089eb3470053cefa8492bd9c07b11102d72bf \
--hash=sha256:77ef5882c5318ffc3dd94c6abc6a8f1ec2af75d66522319f1a250a07d53d0546 \
--hash=sha256:7ec678c52c3ef5e37482a094d109c04cf9e4a0e2923dd1e0fbddb4bf133a976e \
--hash=sha256:810aea5958d6a2d92593fd27218df528644aeb72cc7f6d401e650752d6c98949 \
--hash=sha256:87492842770cd772fce25e9cd279913eaea6c55a91a960b6302aedfa2ec7b152 \
--hash=sha256:875975f91870682cca4371260522ad3f22d636e845b5c5355c52bc045c0f75c8 \
--hash=sha256:90bd49511341dd7c40bb3acaa97cd8b9e5df4821a5714b842117e7069c7cc03e \
--hash=sha256:91097d66ebb8ca8d23372081a33405a44e2239445614888e38929bd7f5879dae \
--hash=sha256:9307679936e86d7773eadfa444a4a4ee80f6f45230e93379875f4a6897a09a2b \
--hash=sha256:93269f11303fc9a3e3990b57e0533f41949546156d9f0e535571f313032563cc \
--hash=sha256:96e6966edcfae74ffac2522d2dd1a304450d18807a9791f5ed0a3232192c9437 \
--hash=sha256:970a3dbce807a3f5c2b8232036052bade01e4bc92ade37d73ea3750418307fa1 \
--hash=sha256:972a2e19dbaab47d0aa77c1d07f71c930bdc53538f2b33decc905e92a4be5cbd \
--hash=sha256:972e34c5cbbfe6c90358bfae38edae1a29d3456e920da5a4664c98f221ee4df8 \
--hash=sha256:a3942e2d365f009e5e7839114fa315e1a2bcfea12b52064a28f1a7281862a2a7 \
--hash=sha256:a3dea7e1ac49e29306500a8627fa3eacabcc9e238d22495eea2d8e61de77065b \
--hash=sha256:a84e0ae14d1efe782a9f143021c4e01d5ed986a140fe5070505cc5978eaf0592 \
--hash=sha256:a998857af4fcd19920bdf5f30f0f1a23f38472a703d33e49168cd4fd32438377 \
--hash=sha256:aa32b51702a0b6e9fddc0d1dc66cb6ed6af112f1bba0cac2be9039546a862b5c \
--hash=sha256:b0c32f0660bb21e810ffc1d3d04b6ea682e118b8141c6e12522a3dacadeb70ee \
--hash=sha256:b0faa0b9af9367748388345d5b12f6add2a9cf896481e72910e88fbfe14ecd54 \
--hash=sha256:b5b458950312830913f837e179ce9221000ab7a20b4e42d7b48c1fcd79140de1 \
--hash=sha256:b8b2fc7901b31d5885f26521cf2d74feccdc126a272ba1d879b7545bb25468bc \
--hash=sha256:be371af72af54b6e508b68a7a87768e05b7e13023f6c82a3e3f5e4d0e829e186 \
--hash=sha256:c3f667dc60a875b12a5ecd7828062ccd97c0fb79c4adc6c8699d23d5ff2af7e1 \
--hash=sha256:c4b68ce579b05c66bb18a16356a4f713bebac2446ee498dd8bb1ecab3da77b89 \
--hash=sha256:c5302747f969d5ec925810176f7697712a3fa2ea0fae0c7a85aa4ad9325247fd \
--hash=sha256:c788fdab2eeeab671f5ab375ad010ef743f6c95be67f60f878e8876a51f6c671 \
--hash=sha256:cfa54e7f5bd5ef482e7f5336f7cf3c30ae608d9767e514dd930b7c30a03fa977 \
--hash=sha256:d6ef0035b6ae338a46951c144081c61fb044f4c1eb6d20acc5ba6277f666a4c0 \
--hash=sha256:dafaeb38712f99e5c31ad7f02c366f1ddd3792921b94066015f8c49f197163b0 \
--hash=sha256:dca1bf90b3a6a7440904f128464eb95bf46ac9da7ad3c85912483dd83128fd95 \
--hash=sha256:de1bf30d819809a964060356032e6670c9923644666afaaf3d1719d05ddb844e \
--hash=sha256:de499e2492c8106a5e163d3cf5b6726e2797f9234cfbc6055fbb5f9d8f198f39 \
--hash=sha256:e4a7be59d374c445766fa4ac066a04d19a757365ae00a950053d0ab7388d1039 \
--hash=sha256:e6c4fa55eab6b5684b33239597876a18a35ce1280b63ab960164032afbb8783f \
--hash=sha256:eaa5178a4c1fe619eff9cbe93b57919d426332e219870301d4ef5fc09a522ae9 \
--hash=sha256:ed62c15ce5e8b975b2710a0f7c8bb953cbffb472fccb05055be6afcba9520c19 \
--hash=sha256:ed8e452f5cb34f59f4861d50d029c6203b5f8f11c13d4186264392a64b4def8d \
--hash=sha256:eea17e3cdc6f9aecffe15fe9a9eeba8e8c049a5d347de1561eed2240cdf35a79 \
--hash=sha256:f00ff4b56caf151365c77988eb85a4a71eb26fe63047d4084d5614e06d65e3cf \
--hash=sha256:f06dd6a30438692d48c0d54de4b659cd55a57c2c2f6591c969c98d0a5523ab07 \
--hash=sha256:f34405292fca45cd77419005c1ea35ba1c03eaff9042afe76d6fe189fe474669 \
--hash=sha256:f352f797b1477c46a20e45f4cbc3a0e258e61963c8ae8f79f84a7bfb4195b37e \
--hash=sha256:f37ccd159dae35d4914651d57142c8077aa67ab7e3ffef690b00bcb7a7dbd8e6 \
--hash=sha256:f51bca8fcac4266519533698c316f3d23340768a8e57c4796c9f6e0a4f353807 \
--hash=sha256:f5342b8256476554b4045db8b7bf4dc4044d0405485f220f0cd80764bc0d7faf \
--hash=sha256:f5fbda9703bce94a976e1a6bbdbbe0af25fb613a593a56091991359928b66c05 \
--hash=sha256:fb5df75d1b1c42d997adbb39eac61f2cdb48efa26304a0cb9c0b757c9bc20732 \
--hash=sha256:fb6a4d400aa531c73a718b337116fad77ba8dc6df34fa615c808bfc55ffb19ca
# via yt-dlp
brotlicffi==1.2.0.1 ; implementation_name != 'cpython' \
--hash=sha256:2c85e65913cf2b79c57a3fdd05b98d9731d9255dc0cb696b09376cc091b9cddd \
--hash=sha256:37cb587d32bf7168e2218c455e22e409ad1f3157c6c71945879a311f3e6b6abf \
--hash=sha256:3c9544f83cb715d95d7eab3af4adbbef8b2093ad6382288a83b3a25feb1a57ec \
--hash=sha256:535f2d05d0273408abc13fc0eebb467afac17b0ad85090c8913690d40207dac5 \
--hash=sha256:625f8115d32ae9c0740d01ea51518437c3fbaa3e78d41cb18459f6f7ac326000 \
--hash=sha256:6f3314a3476f59e5443f9f72a6dff16edc0c3463c9b318feaef04ae3e4683f5a \
--hash=sha256:82ea52e2b5d3145b6c406ebd3efb0d55db718b7ad996bd70c62cec0439de1187 \
--hash=sha256:91ba5f0ccc040f6ff8f7efaf839f797723d03ed46acb8ae9408f99ffd2572cf4 \
--hash=sha256:9d6ba65dd528892b4d9960beba2ae011a753620bcfc66cf6fa3cee18d7b0baa4 \
--hash=sha256:be9a670c6811af30a4bd42d7116dc5895d3b41beaa8ed8a89050447a0181f5ce \
--hash=sha256:c20d5c596278307ad06414a6d95a892377ea274a5c6b790c2548c009385d621c \
--hash=sha256:ce17eb798ca59ecec67a9bb3fd7a4304e120d1cd02953ce522d959b9a84d58ac \
--hash=sha256:da2e82a08e7778b8bc539d27ca03cdd684113e81394bfaaad8d0dfc6a17ddede \
--hash=sha256:e015af99584c6db1490a69a210c765953e473e63adc2d891ac3062a737c9e851 \
--hash=sha256:f2a5575653b0672638ba039b82fda56854934d7a6a24d4b8b5033f73ab43cbc1
brotlicffi==1.2.1.0 ; implementation_name != 'cpython' \
--hash=sha256:00a6e8df24c2f48744bbdca8694a2b50bb26d1d0b6360c3a7c5caeaf4ad83373 \
--hash=sha256:0a7281a39de91432e90c27ab9c4f9feb3a9cf33fda3873534c2a88270d9f60a2 \
--hash=sha256:0cb591da62db91dddd701a28def82f39e0f7943321ac7d0814a1d2a1625095d1 \
--hash=sha256:1563024a25dd2c357457f49f4e03d4354d0660ae41ed1983d86c5817a754a539 \
--hash=sha256:2182d9af39ff06efce62a783d9429bf01f10cdedafc8b6ba696f75b52fc39eef \
--hash=sha256:25ab19c47b88438b5d00a2074b86fe37ab5c176aef90de1ae0f5e1ae52300462 \
--hash=sha256:30a52a620564ef3c6a34cd1e09d699b92ba68a3447a28915b77a17eb5d2c8f71 \
--hash=sha256:421ba24ee6568c6baa3c83e0f584fe9e3941bf86401122942c5ed085f8114c09 \
--hash=sha256:52b99120543ffa3b0667e922c6a7dc6b6e01350f7fd38f21aaca511bb9f8b4f2 \
--hash=sha256:54ccae9a0ff09c7f007aa247dc62b6ca7666ecf1358568e6f2eb8683ceed1d01 \
--hash=sha256:5d0b89e959f643aab4c58c15c06e1e87b6f6605e5e88c3c1c28f5ce1c58c4e5f \
--hash=sha256:602e87ecc8fd2c72b13ba6dced2e0d5aefc18a262523e82795ed0f47f5a13903 \
--hash=sha256:6f5ff7c8f62eaa3e6feb2b4d06a6001bb08cc346c9de7608786de99387255e94 \
--hash=sha256:75e54388f06cd7edf5354f526d0386553db441b7574a22a2bcb19a2149e48eb7 \
--hash=sha256:ac2d63c8f3c1fd000286315027a013008c7c9a3009c7415c24ee48dde1b207db \
--hash=sha256:b77704eb33e345e00d0a2854abf7966b86e1709a1f89bcc143b6c8437256d7c7 \
--hash=sha256:cc882e1ab3f81d262cc002132476dab7667f8f41ead3de8609b163cb64409f8a \
--hash=sha256:ed7c8311209853c9d78e2f6cff1f57e4df2541e4d67e3677dc1f4c88539db907 \
--hash=sha256:fea6f5450a6bd73ec222e92282d4db25030943946190697c1f2cd41087c59bc6
# via yt-dlp
certifi==2026.6.17 \
--hash=sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432 \
--hash=sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db
certifi==2026.10.23 \
--hash=sha256:a9895e6e2758b371e0545e321a3a8fd1fcfd9829ada8824a936dfb16aaaf36cd \
--hash=sha256:e9b54de76e530bb6cf0ccd036787103acb58fd42ba930ea8bf948ddbaa2f61d1
# via
# requests
# yt-dlp
charset-normalizer==3.4.7 \
--hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \
--hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \
--hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \
--hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \
--hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \
--hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \
--hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \
--hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \
--hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \
--hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \
--hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \
--hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \
--hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \
--hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \
--hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \
--hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \
--hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \
--hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \
--hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \
--hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \
--hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \
--hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \
--hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \
--hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \
--hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \
--hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \
--hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \
--hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \
--hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \
--hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \
--hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \
--hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \
--hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \
--hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \
--hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \
--hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \
--hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \
--hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \
--hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \
--hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \
--hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \
--hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \
--hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \
--hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \
--hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \
--hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \
--hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \
--hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \
--hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \
--hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \
--hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \
--hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \
--hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \
--hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \
--hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \
--hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \
--hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \
--hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \
--hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \
--hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \
--hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \
--hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \
--hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \
--hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \
--hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \
--hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \
--hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \
--hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \
--hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \
--hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \
--hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \
--hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \
--hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \
--hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \
--hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \
--hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \
--hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \
--hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \
--hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \
--hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \
--hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \
--hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \
--hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \
--hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \
--hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \
--hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \
--hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \
--hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \
--hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \
--hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \
--hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \
--hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \
--hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \
--hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \
--hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \
--hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \
--hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \
--hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464
charset-normalizer==3.5.2 \
--hash=sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e \
--hash=sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf \
--hash=sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5 \
--hash=sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56 \
--hash=sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26 \
--hash=sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718 \
--hash=sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93 \
--hash=sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640 \
--hash=sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3 \
--hash=sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875 \
--hash=sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e \
--hash=sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204 \
--hash=sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234 \
--hash=sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3 \
--hash=sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98 \
--hash=sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187 \
--hash=sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d \
--hash=sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f \
--hash=sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7 \
--hash=sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011 \
--hash=sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f \
--hash=sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869 \
--hash=sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1 \
--hash=sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d \
--hash=sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847 \
--hash=sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9 \
--hash=sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93 \
--hash=sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd \
--hash=sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00 \
--hash=sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0 \
--hash=sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09 \
--hash=sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac \
--hash=sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621 \
--hash=sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8 \
--hash=sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a \
--hash=sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51 \
--hash=sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0 \
--hash=sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef \
--hash=sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6 \
--hash=sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649 \
--hash=sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229 \
--hash=sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e \
--hash=sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd \
--hash=sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115 \
--hash=sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c \
--hash=sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab \
--hash=sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253 \
--hash=sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995 \
--hash=sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438 \
--hash=sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0 \
--hash=sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b \
--hash=sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7 \
--hash=sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a \
--hash=sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a \
--hash=sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c \
--hash=sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5 \
--hash=sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37 \
--hash=sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e \
--hash=sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4 \
--hash=sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800 \
--hash=sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055 \
--hash=sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c \
--hash=sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b \
--hash=sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80 \
--hash=sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a \
--hash=sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4 \
--hash=sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2 \
--hash=sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58 \
--hash=sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc \
--hash=sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639 \
--hash=sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf \
--hash=sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d \
--hash=sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f \
--hash=sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c \
--hash=sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc \
--hash=sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4 \
--hash=sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253 \
--hash=sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade \
--hash=sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858 \
--hash=sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26 \
--hash=sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96 \
--hash=sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8 \
--hash=sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13 \
--hash=sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1 \
--hash=sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03 \
--hash=sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364 \
--hash=sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4 \
--hash=sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0 \
--hash=sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a \
--hash=sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036 \
--hash=sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3 \
--hash=sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21 \
--hash=sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3 \
--hash=sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e \
--hash=sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413 \
--hash=sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21 \
--hash=sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346 \
--hash=sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429 \
--hash=sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685 \
--hash=sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f \
--hash=sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c \
--hash=sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d \
--hash=sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad \
--hash=sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400 \
--hash=sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb \
--hash=sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc \
--hash=sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c \
--hash=sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74 \
--hash=sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf \
--hash=sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604 \
--hash=sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f \
--hash=sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105 \
--hash=sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a \
--hash=sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d \
--hash=sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1 \
--hash=sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5 \
--hash=sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e \
--hash=sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709 \
--hash=sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874 \
--hash=sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc \
--hash=sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95 \
--hash=sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd \
--hash=sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0 \
--hash=sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d \
--hash=sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3 \
--hash=sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c \
--hash=sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3 \
--hash=sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491 \
--hash=sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5 \
--hash=sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5 \
--hash=sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655 \
--hash=sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288 \
--hash=sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd \
--hash=sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084 \
--hash=sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d \
--hash=sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915 \
--hash=sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1 \
--hash=sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd \
--hash=sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424 \
--hash=sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f
# via requests
idna==3.18 \
--hash=sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2 \
--hash=sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848
idna==3.20 \
--hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \
--hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c
# via requests
mutagen==1.48.1 \
--hash=sha256:4f077fe87d3fc7fba259aa63d8c026b18382ca6a42ef37c61e16f1b1b5b82fe7 \
--hash=sha256:8f95637ab9f6f305cec6bd1294e197debe207998e3e068596563c74f86b0a173
# via yt-dlp
pycryptodomex==3.23.0 \
--hash=sha256:02d87b80778c171445d67e23d1caef279bf4b25c3597050ccd2e13970b57fd51 \
--hash=sha256:06698f957fe1ab229a99ba2defeeae1c09af185baa909a31a5d1f9d42b1aaed6 \
--hash=sha256:14c37aaece158d0ace436f76a7bb19093db3b4deade9797abfc39ec6cd6cc2fe \
--hash=sha256:189afbc87f0b9f158386bf051f720e20fa6145975f1e76369303d0f31d1a8d7c \
--hash=sha256:43c446e2ba8df8889e0e16f02211c25b4934898384c1ec1ec04d7889c0333587 \
--hash=sha256:4f2596e643d4365e14d0879dc5aafe6355616c61c2176009270f3048f6d9a61f \
--hash=sha256:52e5ca58c3a0b0bd5e100a9fbc8015059b05cffc6c66ce9d98b4b45e023443b9 \
--hash=sha256:55ccbe27f049743a4caf4f4221b166560d3438d0b1e5ab929e07ae1702a4d6fd \
--hash=sha256:58b851b9effd0d072d4ca2e4542bf2a4abcf13c82a29fd2c93ce27ee2a2e9462 \
--hash=sha256:6b8962204c47464d5c1c4038abeadd4514a133b28748bcd9fa5b6d62e3cec6fa \
--hash=sha256:6bbcb1dd0f646484939e142462d9e532482bc74475cecf9c4903d4e1cd21f003 \
--hash=sha256:71909758f010c82bc99b0abf4ea12012c98962fbf0583c2164f8b84533c2e4da \
--hash=sha256:7b37e08e3871efe2187bc1fd9320cc81d87caf19816c648f24443483005ff886 \
--hash=sha256:8a4fcd42ccb04c31268d1efeecfccfd1249612b4de6374205376b8f280321744 \
--hash=sha256:91979028227543010d7b2ba2471cf1d1e398b3f183cb105ac584df0c36dac28d \
--hash=sha256:a33986a0066860f7fcf7c7bd2bc804fa90e434183645595ae7b33d01f3c91ed8 \
--hash=sha256:a9d446e844f08299236780f2efa9898c818fe7e02f17263866b8550c7d5fb328 \
--hash=sha256:b2c2537863eccef2d41061e82a881dcabb04944c5c06c5aa7110b577cc487545 \
--hash=sha256:bc65bdd9fc8de7a35a74cab1c898cab391a4add33a8fe740bda00f5976ca4708 \
--hash=sha256:bdc69d0d3d989a1029df0eed67cc5e8e5d968f3724f4519bd03e0ec68df7543c \
--hash=sha256:c25e30a20e1b426e1f0fa00131c516f16e474204eee1139d1603e132acffc314 \
--hash=sha256:c7947ab8d589e3178da3d7cdeabe14f841b391e17046954f2fbcd941705762b5 \
--hash=sha256:c885da45e70139464f082018ac527fdaad26f1657a99ee13eecdce0f0ca24ab4 \
--hash=sha256:da4fa650cef02db88c2b98acc5434461e027dce0ae8c22dd5a69013eaf510006 \
--hash=sha256:ebfff755c360d674306e5891c564a274a47953562b42fb74a5c25b8fc1fb1cb5 \
--hash=sha256:eca54f4bb349d45afc17e3011ed4264ef1cc9e266699874cdd1349c504e64798 \
--hash=sha256:f489c4765093fb60e2edafdf223397bc716491b2b69fe74367b70d6999257a5c \
--hash=sha256:fdfac7cda115bca3a5abb2f9e43bc2fb66c2b65ab074913643803ca7083a79ea
pycparser==3.11 ; implementation_name != 'PyPy' and implementation_name != 'cpython' \
--hash=sha256:51d5a8ba2be0bbe440b99d2112604c95bbbc3c2748a64260186c541e1729cd80 \
--hash=sha256:d875f09c3507d00e1aba0eecc6dcadc1352f30fff09dc6bff2f1c2935e97c2bc
# via cffi
pycryptodomex==3.24.1 \
--hash=sha256:03e2027f81fe6b700e7ff614d79111559bfb05ed8c4a9de9d2152d1a0a0768de \
--hash=sha256:09081666ffc599976c0b8b29caf2cf82212c0f05bed233c8f8ed53e4f6e1d356 \
--hash=sha256:147c742f73bbe8791d8c454b9972330d7ea501de94e8172957af375f9bdb4a7f \
--hash=sha256:3bbcc1807502da4b5d66c94357a99589c8547aa9ad2f9ecfa537b2e9a347538b \
--hash=sha256:48d9058dd4c8f3af83e048b6ff83d9c6300841c42579f77fdfab19e49156a512 \
--hash=sha256:514d685de4b0227d35d7114047fbd575bf162bff373e07af665aa41eee089dd0 \
--hash=sha256:569fdbeff936cbd5beb852b3969dc2f58fb255bd221b3f7a8999c035c30ec958 \
--hash=sha256:5966f829f64c833cc72a8694cfee05ad50446a44167842c92dec4ebf6b84d72c \
--hash=sha256:5b37b86a3771d6aa21cccf9f8448460e4be11e68bb8e699133ce632cb986f521 \
--hash=sha256:6159dc74824c591b4c294f8f96b74a71c3b5e9f637dab2f2da14cfa32dc24d47 \
--hash=sha256:77ef934c2b2eab3c57a431daf858fcbf272134691bcc8d729787d17ad4cbf758 \
--hash=sha256:794f32227a480ab3b39971ac4a53dfa8ed444e28c0ddecbdc35f26d038bb46da \
--hash=sha256:7a81e9be7084af3591912475b22c5d0646a9160f3974b6b7300138781fffdc0d \
--hash=sha256:7f30261641dac5ae60e0af2fb11ad7c87200575b0ce403f7531576b0f38a52be \
--hash=sha256:82eb0dd8a95be97f03527b108ee49f9b86a7c534fa47fa7a510be3eab8ea9acd \
--hash=sha256:8321c315c4418dfe45a811b792380438ec81185deaaf202dbcd77711b4f51796 \
--hash=sha256:9a732b9f5603b153dcdc071d6b342f192981907519827f2c1e4aeac41e2b34c2 \
--hash=sha256:9b94a8c647c1f80b4c82c7ac9642dda94a71abbb4efa29ad652c410ad7a39879 \
--hash=sha256:9bb353c764c144a9fc03302ef3763ad0c3e75bc7ca41f445cc98455f36da6c59 \
--hash=sha256:9dd5104a1d8ccf725a3c1b40b21d5ed47530b6499abba30955c174d895c1be2f \
--hash=sha256:a692d2484ca8fa2c69f45c63f2b30cd00b8512834e3a522fc297d981dde5b34c \
--hash=sha256:b1c7a61b0b644e9780aa9f6eee301fb77c813b1e41262f6f4f387de0558e8926 \
--hash=sha256:b299a1c10e45e1b71b34b048d555d3a8f366240942af89be5db379f88edb9542 \
--hash=sha256:bd06ab1d9cf90e8b198daae3b364e9ac23a640d210bb8faddad6627cf2e33be7 \
--hash=sha256:c20fb5e8cf874dc182091d6df122b8b588501d23e7b500acf662c49899afdd0f \
--hash=sha256:cc64f4e1fc07a155ef31eb9815183a6a8eb13dfd6876ab049c01125223aa0c40 \
--hash=sha256:cdec09935db4cbd74da5b577ea7d9959c73374060b22abf7d505429c0da7ed63 \
--hash=sha256:e87928d8f37952ba53d215836cb3d89c63c1367f037d055c3a5b3f4403f4c6b6 \
--hash=sha256:edc1deb28fceab6b78e12bae506eaef62ee2fc1b3cabc96f7932f0d51e368acd \
--hash=sha256:eeac2c9acbd2d9f0ca493fdf692ce8245ca37cbebee08c496025868d4b8ef70f \
--hash=sha256:f3ed97cdde1d96894057778095238bad3dd94d3e46dc07d6d618e6d4b7700cce \
--hash=sha256:f87d74a804ca949f46a6babe70247a789f6401f229566e90174c4b7033b87cc5
# via yt-dlp
requests==2.34.2 \
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \
--hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed
# via yt-dlp
urllib3==2.7.0 \
--hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \
--hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897
urllib3==2.8.0 \
--hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 \
--hash=sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63
# via
# requests
# yt-dlp
websockets==16.0 \
--hash=sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c \
--hash=sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a \
--hash=sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe \
--hash=sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e \
--hash=sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec \
--hash=sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1 \
--hash=sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64 \
--hash=sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3 \
--hash=sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8 \
--hash=sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206 \
--hash=sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3 \
--hash=sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156 \
--hash=sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d \
--hash=sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9 \
--hash=sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad \
--hash=sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2 \
--hash=sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03 \
--hash=sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8 \
--hash=sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230 \
--hash=sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8 \
--hash=sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea \
--hash=sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641 \
--hash=sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957 \
--hash=sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6 \
--hash=sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6 \
--hash=sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5 \
--hash=sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f \
--hash=sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00 \
--hash=sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e \
--hash=sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b \
--hash=sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72 \
--hash=sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39 \
--hash=sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9 \
--hash=sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79 \
--hash=sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0 \
--hash=sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac \
--hash=sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35 \
--hash=sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0 \
--hash=sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5 \
--hash=sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c \
--hash=sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8 \
--hash=sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1 \
--hash=sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244 \
--hash=sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3 \
--hash=sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767 \
--hash=sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a \
--hash=sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d \
--hash=sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd \
--hash=sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e \
--hash=sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944 \
--hash=sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82 \
--hash=sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d \
--hash=sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4 \
--hash=sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5 \
--hash=sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904 \
--hash=sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde \
--hash=sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f \
--hash=sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c \
--hash=sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89 \
--hash=sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da \
--hash=sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4
websockets==17.3 \
--hash=sha256:018fab26140ce221c3853454a608e4e7004f4f10641cb97819dcd5b917bb2e99 \
--hash=sha256:07246d4f0293ef0b87eff3d7dd88c1f03dd9f678fa39f6de87b2af8504e7e0de \
--hash=sha256:078d1d41f45ee34eed5a4f3bbe7c588caecbdd6e12dfca73e8c1b0e803773793 \
--hash=sha256:0824e6ecee838cc28e6481062574c7fde49f9a2cedfacd36f0e91cb4b37fd6fe \
--hash=sha256:09f007b2150eff015b2109f006e2ac2012d376f41486defa88ae78a776b00cff \
--hash=sha256:0a0bcf66289b9d017c175562c35c5304b5cc3ed56aded994ae30b0a9654ba405 \
--hash=sha256:0a657b51e4a5f4ac577c11e706ff9a884ea5aaf3e2666bae283a251c63e66acb \
--hash=sha256:0c63ad657695e8f1a48624754cb6b464118ac50d4c1d477c26461c98390f0a62 \
--hash=sha256:0d20d6ea5aabbeba2e054d33e405192ef75dc12947bbd00ec97d23b14969d325 \
--hash=sha256:0e65260a1b1d7b81651f47343d836de70b88b02358ae3658efa6382104ec37b1 \
--hash=sha256:0f78bb2e82fe88912c9d7b25c98e57a9b08655579af89f164fd4c0657a075d62 \
--hash=sha256:10b24e836ee0233ca078e1244f6ba40343a22127a9a736f46a7e7b18de2cc711 \
--hash=sha256:13cffaedde6e06183860fc92d88fe1d190abda73837fe4c14f5d4803c472f5dd \
--hash=sha256:13eace1b315345ebac5b27821f5dcce24e5cf9976ab18f79e00a59bdd67e5d19 \
--hash=sha256:15decc0fe293d9e3f924bd483f3d76f3d0ff26845112a470e3f8842fec2c82a1 \
--hash=sha256:1c7dd93a1c9f89297471493674b1fc1d9467cafd45374f2172213046bdb3a329 \
--hash=sha256:1dae5cd6c92d4440b15f20aa2987baa73c47ea14baa0fec8536a542e82e0ab33 \
--hash=sha256:1db2604e6aedb7a2cb2f6e0575d6c9a852ccac8239703a930ac83b63309177a5 \
--hash=sha256:2129c9a5fc05a230ce088745a790af073e582b584badc7b05db067ee326f56d7 \
--hash=sha256:23046098ebf844753cfd211033624a8247520e5bf2194c24cb1a8c222917acff \
--hash=sha256:23cb6f6d64e3a389bb8ba150f947f9a6c8c0aca383e814ca3c5cffab738d5646 \
--hash=sha256:26838e2d95d7004c52e8c7b6b51676c872093a3b55a497824f899116a15a8a55 \
--hash=sha256:2789d203babb6ceb2770aadc2394c1f99263ec37fba57a93064f9a8ad899e8ff \
--hash=sha256:28d1935c16782a1e3650c9baa79069b016fff739e292e4cb14bbb830d6930491 \
--hash=sha256:29b01520c39ef2f23c88b002f11e6ef4165675f6c92f5f3578fd587d69b5a5fc \
--hash=sha256:2a377c7132b1e69be7a50d7434d7f26f69e93c70166ebb6d8f8cabf802ac4506 \
--hash=sha256:2b06213c8e1ce93b18d0476d7a5e647436c8f23d099888c9065e930e80f4bed5 \
--hash=sha256:2c460aeb12c2bd1c204944d9e9199595bf9e505eb542018d304bf9e63cb60cad \
--hash=sha256:2d08ca4bf5a9cdb6fd81b86b51bd5cfb10527d3a1199888f2b02cc6c6a3d5f80 \
--hash=sha256:2d875224bac1a05a20acade268a7a0e3498e7f8cf890acb7c2b23bacd2bd3659 \
--hash=sha256:2e99440ef446c7833690c1754e23b0188d440f3cb89812b0764c697a7880cb33 \
--hash=sha256:2fa79b9a48ae59744316c71a34cb9f76f30c93e117338522c5135cb7eac10351 \
--hash=sha256:32029441af953e980b9940f042b337fe4ad9a97fa8b17a4ed878ec67b5b89ef4 \
--hash=sha256:33221e49be79d7bfe6d12bc52ef9458b256ab74fa8ac5660acfa3065de1c7870 \
--hash=sha256:34c78052277053bcb09810ac8e9ba4029f9e3e277833fc18ec1c928a6246ac91 \
--hash=sha256:35381b575f70a08d4241e73c0cde4672bb9b2a9aae8767ca6b7fb61305a052c8 \
--hash=sha256:35fe35d20baa661cef4a12ee7bc42eaf2376d43ef9816ab29dd47ca957f7a73a \
--hash=sha256:39f532fa0d9026de4b9315a175998646112776baad54d55348435c11b05d034e \
--hash=sha256:3c4f631dc8d00e470cde3ec0a35d4b58a817bea592411956f1cf4099dbb306b3 \
--hash=sha256:3d78d93846eddc990551c1c31914d90d71957ca3af468969826f7ed0d7d1d51c \
--hash=sha256:411aa0fb234f42a1444dea1e177890ddfc577b36ffdfafec25cb0d2c818e1af8 \
--hash=sha256:41665c7ea01d3ae497a0c61fd22d3424230d18782a5fceb79f04db9ccb2042c9 \
--hash=sha256:4170556762c6fd2913d99dfdd8dbb4c927584899df7facb1034627e355263c45 \
--hash=sha256:43f270a5f21e12db08c73d83849a877c02ab7b7d0fb6e2718b5101d9c810212f \
--hash=sha256:443fa28652682d2a3ec3eca49af1b87cb2523561257683e62e03a98967b22138 \
--hash=sha256:45cc1ccb12ced6d242335159e8221733c8696da5ad0b6ceef6debb0f5ce89110 \
--hash=sha256:46ae05aa1aecd47d4d7de0f05ce2d1d2eb418f8de614964d754cc3b9a409c400 \
--hash=sha256:49fb5b4960ebe1bc557b435da8687deef1302a08f030a33c5606fa6fb11b773b \
--hash=sha256:4a9133dbaedc6f1af358127275676171d9a1bb3e61f47ee62b2ff9acb78af3d0 \
--hash=sha256:4aa85b34c21cf97b3470793d0bf0763d32bfd1e67b83067a0a3ba8dc3474dacf \
--hash=sha256:4d5f2492cb2192aab2d42e57f2caa2159b4fd20fde06f859ec13354f524b176c \
--hash=sha256:4e7b5d23ef144b32645d97bd99f382c4394c443395f45fe1576786838d26e308 \
--hash=sha256:4f7431e71072962d3ed1768038200aa4f1e76d9c2d7bedd554d57a55faaf6644 \
--hash=sha256:508775efa11d26aec186d10154359f52276e2baf9ca201b52356330883276dfd \
--hash=sha256:5142798871a248b422f353e0684d51dfa119de3403a6fa0904b7cb806d9790ce \
--hash=sha256:52a2ca6f401fb49a8d5d9e0e48ade5f58f1bdda33132907b0e4e3b702628fa4e \
--hash=sha256:53209dffd91b0aefed9ea630fa6ad5c2944d6210ba3a8a3a8664dc1575289b14 \
--hash=sha256:534ed583fd4323de45d196535a444cebd1af2105e6e4e0cdcbf8cea266a8747a \
--hash=sha256:54fcd24944e6d127d198c28dc363967b7131ff0c97833962c2ef2048018de02d \
--hash=sha256:55494475206113dbaf731dc8c5ffd5e1094175b753b7bbaad09fe3d7df61165c \
--hash=sha256:5670a762c7ae388bf8aa04199fd436180a4d28318dca9c1eae7b38604676dbfd \
--hash=sha256:56a76556ab04ab54a675acce2cac8b4e74ea2cec558a7c9ed37e0367b04b5d50 \
--hash=sha256:56d43c311f3519fb1057b6114dc24e9060bc3fb6aedf4aa11160484154b66b63 \
--hash=sha256:5868a02c4f6d698ddd19b4c9742748c03dec045289915806845189d96bc3d314 \
--hash=sha256:58e5d1e935a90878a935c7d2737a25c71cf4f1c13b6e6bef454ab722c4f338bb \
--hash=sha256:5ad409b7ea102339041281117cf2dadfe71edbb653dc48037cc55d516fb7f448 \
--hash=sha256:5af7070d80d278832cbca9c3c3dd44b30a26dcfa3ae1e0f6f19ff34edc27b689 \
--hash=sha256:5d0c871efc696ef5eb8514df64b86ab28736db753ebb42a2101f3b562f4849c0 \
--hash=sha256:5e0c0ed37472c4729f3001066510a656486f08f149dda1ebfd3dfe4450c9756e \
--hash=sha256:5e1c174b366565e101f903f9d1cc96d5508f805759dd37d012743f1c73ec0d7b \
--hash=sha256:62059d739af7fc035ed6e63c5390118a60a5e9aa5a5541cd0486a83e741842c7 \
--hash=sha256:623d4b44f64efdf235b1e8dce266057073d93cde6197e7d7684f20c297f67f30 \
--hash=sha256:628efe13630ac3397e7d1278b6be6f22f37a86d638a324334b4cd43c1daf9928 \
--hash=sha256:6342f79d6f50e680c8aa59e0615d745e867e51ffd59c77093be60b7c433067af \
--hash=sha256:63b87c93e28957e6dc2bb92d31727a863c9bf4a4daa080f0995fdcb0242c9166 \
--hash=sha256:65e937576141ac50fac32fa9736dbb3e0e4a7769f91be004011a09216c6ab05f \
--hash=sha256:66027e401c70d0cf55021b91b8a7ec2cd5810e20602f945b4fe6ae8b37ed232b \
--hash=sha256:6644eecd99c4e8cdf72e646e17b391bb70b054f44becde37dcdc48cbec7e1527 \
--hash=sha256:6705af9d1005127302c04d9f1533ba56e289336c465923ef878430e99295a0b9 \
--hash=sha256:6a8248b1ba8861e48e4c7ced3895a1264d2a3b617de72ec94172ce6e64bf16c7 \
--hash=sha256:6b14914e67044724c31a9360c7b89e9d070117c630746eefdc1620d967545acd \
--hash=sha256:6b7b540bb321f7f0a7b8f5d107f941bb361e3a154c0b594dae0394997b91b743 \
--hash=sha256:71250e010eede33c1d638e2c7a98288520d67f782fd5eceecaeca3129233a09a \
--hash=sha256:722ab747ff5dc28070b1a8c020dba6466f13f2ab56bc251ad301fefa2454aa1e \
--hash=sha256:724224d4c457207271239114bf43afafc3eca4a1b4661ccdd428d11869a03bbd \
--hash=sha256:729989759feb81ff6493879a0d60a0bd7d2eee41001bbec0381a080318439382 \
--hash=sha256:740bba4223fa5216d4d6c5dcd29e697f37229b8a61b69e1a50527b0ea993ab2c \
--hash=sha256:7bdc658c9474864893e0b6b94f1390bf6a912952df1870dd93bb7d1a902b5628 \
--hash=sha256:7d53fc4b90ef6e11de639dc18744d9be8cbd70ccb5ce80027aaffe7b1ab0215a \
--hash=sha256:7fa69212ea60ea24e2d8aff23fe102b1f87f1b27a320f92d2e7b3468997a496a \
--hash=sha256:80326bc571164bbbb6bead2e35d0c943b23b24fde629032197c58151529d24d8 \
--hash=sha256:80578e91764bfca297ddca322c00a3136d993b829e9839e7fa378a19c1fcc25d \
--hash=sha256:80a6e37e235780f189558ab804f3cbc01c18f5c578995739b49613d544d34ebf \
--hash=sha256:8135a549e27e9941a70e2d2156676ef2ffeff4b06e9d564dbaaae963482afdef \
--hash=sha256:82e60c00cfb8493a5ba27cdf9b3695fdd153f666f73e11f18968f78ead1d8705 \
--hash=sha256:856bbb24f2ee6436af7609267e73309e4bb0a0f9982f79f1c2e01019279c6671 \
--hash=sha256:85d6daa3a7ca404570ae130babbeb347ef9d3faca5300fb13cfa4bb48c3d30d1 \
--hash=sha256:8879b6a4040ee925c638548238ab7fe612cf5fa8752fe847346da0da8be81c3f \
--hash=sha256:8b3bede7d583bc9f47d8693a29984882e59077db1a5238ad977fc70ae8169741 \
--hash=sha256:8dbb3862aa649de95660b6337d97101977f160b5b354d07b82fe309874d2c8bc \
--hash=sha256:8f244dfee05ea29b8064701880865eb1684f3a704a5665bd10b64694444dbbd4 \
--hash=sha256:8f7469408740cf06a79b01605f2ae0b2acc8839c03fcbbf05da49baee12d3302 \
--hash=sha256:90cc9973c51811918247a78d9ab2f54871296e4e37e69a98aba4d3c9acedbf62 \
--hash=sha256:90d8c4fa5ba293cf92de351fbc292cdaadb1a1d58d031a1a97ff9b8fb6250ec7 \
--hash=sha256:94c02b0702656f083c098bdbd93bce22a7aa7a2b34ba56d2472efb67dab7cf58 \
--hash=sha256:9662a9fe457820c60365b3209e03cbd8e4a817195d55de65a80fa680b4bea136 \
--hash=sha256:997617dd7856c5dad742bf6893b872319156dd43f47587541a59e4a852d52bbc \
--hash=sha256:99c5637b74e2805ee4de9e2a43c8b45f678e50abb1c2da9880f0372f6498ba2f \
--hash=sha256:9a215749c9a88ef2842e880215193e56ae60b856773c99702b078236bc6d4adb \
--hash=sha256:9bde5d82d7ac4859e0cb3a35e148f537a8d4e56aa43f42582b5f263982f095ae \
--hash=sha256:a004c1fe5a72c496f28c6c1d8c2dc5cfe3278d99478e18f8b838c70a912b366f \
--hash=sha256:a0e2e7c2c1a4f25db7b6596738d810c10732e77f852247300a1bc49e364d6dc9 \
--hash=sha256:a22c4956a4d858200dba83f0691bb692d77b0eeddfca80157820d20b85dea4f1 \
--hash=sha256:a7f391838e8adcf1f2fe71561d9e5a9f74ea7ffa5052eb2db329aac677383136 \
--hash=sha256:a9eacb382f400bb5865e7e6d24bbe709a84510291e707f169dd4a24ee4a5ac6a \
--hash=sha256:ace8dd1efa5f44c482d091aa38322e20e3ffe5adcdba6b67ad9f4e7da58f3f68 \
--hash=sha256:ade76f8c84ade325bbed96806357fffd353fcc29a5166d6dc6d39381f6d9f76c \
--hash=sha256:af37a1e6b6bd506b597d5fb4cf111fb527d1b2223608a5d441d4738827cfd166 \
--hash=sha256:af7c474f0d8f4d2a196370e85033873c7b063a0b5da9a4f143aa023e3bd25407 \
--hash=sha256:b225c656efa2dedecc81651d2290170af25887b7de4f38c5efc7c5ae2b9442ab \
--hash=sha256:b459d29c8b82a420a98fa0ce8e9cf787ce0062d98cc90604ef9574fb3cc26ff8 \
--hash=sha256:bc6f87d03e3691154673aaa8f08991723d6e3394c83ef2875c7a9049eac9595c \
--hash=sha256:bc8fd230ef013951900c1fda100eebe4a4b1b407dde2a44186995042dda2c628 \
--hash=sha256:bd645b5d2f810a181c44f4a71135e7c365b44f4be9ed3d1892635be13a857553 \
--hash=sha256:be7be57097a65a8fab3d0f0a10d12931deb626a7d8082eb732b1ae41f3a202e3 \
--hash=sha256:c15a165673bb3fb57facbf040edf5c0556d20ccd2e0ccc5f23ebb69fb715fdc1 \
--hash=sha256:c4b3f2c7d84f303da873b634d0beef83b5e1137294c3de4e23102841dac0cf4a \
--hash=sha256:c534c9524a2acd0b97b7022074bec3784ac273c683cf9535087e437672ea8531 \
--hash=sha256:c95d25b5382ee0e6191ecafdeabefdc1f7bff8dfee29239b9b79e760ef3b04bd \
--hash=sha256:c9d06edfd974e918b40e0662a7e76dac13125529ee5ec9fbe42dc0d6faa209c3 \
--hash=sha256:cdb8e4b0f6a41b857c74c03116e8ffbef59ef8e533e934b532843178990d01d5 \
--hash=sha256:ce39283ef08b0f28478e920d4d89a1fc169176e568e8a6a821332673145522eb \
--hash=sha256:cfef7f7aa434a1e632e0ebda14b39f4f1d7975e0fce5c77ea7b43156fabf9bd8 \
--hash=sha256:d2605a3b2af8d66f8b75312d223642c065ec773446c04566d9030ad5e2db13c9 \
--hash=sha256:d338813a440bf6d2f0df55140d3f3080284410b1ebfe9df50e3847bcdb1a17bb \
--hash=sha256:d355b22270be8062360b9df2ee0b10277590789a1059257916fb9e256a0cff80 \
--hash=sha256:d68da281ac208b6236ffa8beef23fe7c7c956d8bf09b421d447232fd94441b35 \
--hash=sha256:dafbb58a149d1ebd5767b3f064f911c5ee0897608005e51c3904b0ada2a8d99c \
--hash=sha256:dc2b495a92b3971966bf102e73589f950db3ec1ca6713265355ce7771d97b199 \
--hash=sha256:dd0f3037d501178a761fd2814370aca547f79e99a200a61a1f6e7b79ec3d78b9 \
--hash=sha256:de2c12555bf05546f3ee75733f2c81de70aab7f530e86d0d2162b0ddcb3c39ae \
--hash=sha256:e164c4a6868d11988c7f2386e3278ccff21c665cd7d08279b62709dd37a3167c \
--hash=sha256:ed59cb4ee258674a6ed9b8515e42079db02cb3be94f133fdd3f200183a40c49d \
--hash=sha256:ef07e0b6b879f699a16fc7a513b974246fdeaef44908a021130cf4afe6a1c89c \
--hash=sha256:ef2950896673a9809e8e5ab857525924fbcacfc98b858b0509ccf50d341f80f4 \
--hash=sha256:f09f145b89ea292cf6c25fd7c8c0d90207fd6a9e54c7828499669996a1e5bdcc \
--hash=sha256:f27e7e8a85512b6a4b490d5756edde8e6772883a5800e1476172e44eda3f7d7c \
--hash=sha256:f300f28dff74ff4148c21e6971e4de6ca0c34e0086a3d95c017c5174ebf85ca5 \
--hash=sha256:f3ed747b7651668131029c720fbc32c7ee2d129bdad200e6c8f4037b20f7913a \
--hash=sha256:f87f02afe05c1c246012e3de100a77cfbabd17db709fe93cf074271ab239b312 \
--hash=sha256:fa87ea2ad64e59fe5622c1dc5716106b6d6e7e4b26b848cb5f5710a75c292ef5 \
--hash=sha256:fc23e72bd7f8a8e540fed2244524d0a9aeb6ae3325f3d56f04a7a3debe5b04c2 \
--hash=sha256:fdd00937f15f5f93c8e53d8060a8c4c010431ab595a9b5b50ddd569a04603944 \
--hash=sha256:fe7a168d805c8a7bf1c2de55b7ab2bc958586bfd88d0e87235a92cac66b590a7
# via yt-dlp
yt-dlp-ejs==0.8.0 \
--hash=sha256:79300e5fca7f937a1eeede11f0456862c1b41107ce1d726871e0207424f4bdb4 \
+6 -6
View File
@@ -9,11 +9,11 @@ macholib==1.16.4 ; sys_platform == 'darwin' \
--hash=sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea \
--hash=sha256:f408c93ab2e995cd2c46e34fe328b130404be143469e41bc366c807448979362
# via delocate
packaging==26.2 ; sys_platform == 'darwin' \
--hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
--hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
packaging==26.3 ; sys_platform == 'darwin' \
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
# via delocate
typing-extensions==4.15.0 ; sys_platform == 'darwin' \
--hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
typing-extensions==4.16.0 ; sys_platform == 'darwin' \
--hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \
--hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5
# via delocate
+62 -133
View File
@@ -9,97 +9,86 @@ colorama==0.4.6 ; sys_platform == 'win32' \
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
# via pytest
distlib==0.4.3 \
--hash=sha256:4b0ce306c966eb73bc3a7b6abad017c556dadd92c44701562cd528ac7fde4d5b \
--hash=sha256:f152097224a0ae24be5a0f6bae1b9359af82133bce63f98a95f86cae1aede9ed
distlib==0.4.4 \
--hash=sha256:ca4175b4ac7f71223cc30ed7248c45d2b38c2439d8ee6e498ab67ed63cf3508d \
--hash=sha256:cf09d55b1e85a89576b036aeb71550bfd68320f3f21761ca329eadadad918638
# via virtualenv
exceptiongroup==1.3.1 ; python_full_version < '3.11' \
--hash=sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219 \
--hash=sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598
# via pytest
filelock==3.29.4 \
--hash=sha256:10cdb3656fc44541cdf30652a93fb10ec6b05325620eb316bd26893e4201538a \
--hash=sha256:dac1648087d5115554850d113e7dd8c83ab2d38e3435dde2d4f163847e57b767
filelock==4.2.4 \
--hash=sha256:301241438c57936ef93f4243a94f2559022268bfcf9b375a9a72eb0f8db8358e \
--hash=sha256:c6d8663535e1650ee430507b4ffbac7b464dd64b7647ea0112a9f406499d163d
# via
# python-discovery
# virtualenv
identify==2.6.19 \
--hash=sha256:20e6a87f786f768c092a721ad107fc9df0eb89347be9396cadf3f4abbd1fb78a \
--hash=sha256:6be5020c38fcb07da56c53733538a3081ea5aa70d36a156f83044bfbf9173842
identify==2.6.20 \
--hash=sha256:6a16b69b93187244e0548cbfd25b3e4a6f9a7a2ad784625c3bec2b8d27b81aaa \
--hash=sha256:ad729860a923858d26917c2f4fb0a1d83d27a75b1e090c06440c573f048f3285
# via pre-commit
iniconfig==2.3.0 \
--hash=sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730 \
--hash=sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12
iniconfig==2.3.1 \
--hash=sha256:67f4b9c50da0dedf52af349e7749a80a9057a5031199791b906c3bb3ae878960 \
--hash=sha256:9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7
# via pytest
nodeenv==1.10.0 \
--hash=sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827 \
--hash=sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb
nodeenv==1.11.0 \
--hash=sha256:3ce8fe5b71d16e8af7039ca65257354100bc772965d6bc549070649e53b1b146 \
--hash=sha256:edaa16e6c14d7cf395d75d4bbd5a26390f4dc06501a33b4e76282b02cc688a25
# via pre-commit
packaging==26.2 \
--hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
--hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
packaging==26.3 \
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
# via
# pytest
# pytest-rerunfailures
platformdirs==4.10.0 \
--hash=sha256:31e761a6a0ca04faf7353ea759bdba55652be214725111e5aac52dfa29d4bef7 \
--hash=sha256:fb516cdb12eb0d857d0cd85a7c57cea4d060bee4578d6cf5a14dfdf8cbf8784a
# via
# python-discovery
# virtualenv
pluggy==1.6.0 \
--hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \
--hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746
platformdirs==4.13.5 \
--hash=sha256:05831adf87d392760f4b5c3a0a95579ab5a10b18b9b9bd43680dcb47544788a0 \
--hash=sha256:53d3ec4280b815c1e0b02edad7f9ee8fda1ba9c0865dd9c2e6e63849ce82fc1e
# via virtualenv
pluggy==1.7.0 \
--hash=sha256:7dd7b0d8832ba3cb632c306926ded123429211b83641b35dc5c41ad2d34f9bec \
--hash=sha256:d1eaa46ebb595891b860ab086b4d09c8588af65ebd4361b8e8f4bb8920b90ba8
# via pytest
pre-commit==4.6.0 \
--hash=sha256:718d2208cef53fdc38206e40524a6d4d9576d103eb16f0fec11c875e7716e9d9 \
--hash=sha256:e2cf246f7299edcabcf15f9b0571fdce06058527f0a06535068a86d38089f29b
pycodestyle==2.14.0 \
--hash=sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783 \
--hash=sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d
pre-commit==4.7.0 \
--hash=sha256:1f3deee12b914c8fa184bd2b5953391c2e4f36763e403d4a23dc9983fa7c6e86 \
--hash=sha256:2e229038ad3656081b70c27913157e4b636ef306f643f024a8a8e3f0f7b2f877
pycodestyle==2.15.0 \
--hash=sha256:12fd2f73c7b8ee8845a0431111df8faf4c1a07d6e64e2ee7f0c74014dab14181 \
--hash=sha256:318f5db083869b4c4dad922d0b11124fb27ab181b6730b93371da671e31bd50e
# via autopep8
pygments==2.20.0 \
--hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \
--hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176
pygments==2.21.0 \
--hash=sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9 \
--hash=sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c
# via pytest
pytest==9.1.1 \
--hash=sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313 \
--hash=sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c
# via pytest-rerunfailures
pytest-rerunfailures==16.3 \
--hash=sha256:37c9b1231c8083e9f4e724f50f7a21241822f9516c15c700ebbf218d6452355c \
--hash=sha256:6bdfb8ffb46c46072e6c16bdedee38b6c13eac620d9415ed5b63152cbf283170
python-discovery==1.4.2 \
--hash=sha256:475803f53b7b2ed6e490e27373f9d8340f7d2eebf9acdaf645d7d714c97bb500 \
--hash=sha256:8f3746c4b4968d22afbb97d36e1a0e5b66e6c0f297290f2e95f05b9b8bf18690
pytest-rerunfailures==16.7 \
--hash=sha256:6956ddfb65ca1d07e7e3d99e2c5359d82300f4cb062e6049563bd2c106f72d5c \
--hash=sha256:edf1886209c2b7dafe35b5bf1708d6ec40ccf6c6b357f0f02807efcec0204c99
python-discovery==1.6.4 \
--hash=sha256:530179cc51a1816d512b15635b3dc931295ae12efb183783ad31190a5d425d2b \
--hash=sha256:bc70d31f0ec5de11eda13d4d64c16e24b3506a65984684f2b6c98cb83b2ea9df
# via virtualenv
pyyaml==6.0.3 \
--hash=sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c \
--hash=sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3 \
--hash=sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956 \
--hash=sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6 \
--hash=sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c \
--hash=sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65 \
--hash=sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a \
--hash=sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b \
--hash=sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1 \
--hash=sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e \
--hash=sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310 \
--hash=sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4 \
--hash=sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea \
--hash=sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0 \
--hash=sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e \
--hash=sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac \
--hash=sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9 \
--hash=sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7 \
--hash=sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35 \
--hash=sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb \
--hash=sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69 \
--hash=sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b \
--hash=sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c \
--hash=sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd \
--hash=sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824 \
--hash=sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198 \
--hash=sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065 \
--hash=sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c \
--hash=sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c \
@@ -113,15 +102,12 @@ pyyaml==6.0.3 \
--hash=sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28 \
--hash=sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3 \
--hash=sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5 \
--hash=sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b \
--hash=sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf \
--hash=sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5 \
--hash=sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702 \
--hash=sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8 \
--hash=sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788 \
--hash=sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d \
--hash=sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc \
--hash=sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c \
--hash=sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba \
--hash=sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5 \
--hash=sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26 \
@@ -132,83 +118,26 @@ pyyaml==6.0.3 \
--hash=sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6 \
--hash=sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0
# via pre-commit
ruff==0.15.19 \
--hash=sha256:08143f0685ae278b30727ea72e90c61e5bd9c31b91aac4f5bb989538f73d24b8 \
--hash=sha256:27c15b2a241dd4d995557949a094fe78b8ad99122a38ccae1595849bcc947b3f \
--hash=sha256:4171b6613effa9363cd46dd4f75bd1827b6d1b946b5e278ed0c600d305379445 \
--hash=sha256:4d190d8f62a0b94aba8f721116538a9ee29b1e74d26650846ba9b99f0ae21c40 \
--hash=sha256:5a2c86ba6870dd415a9d9eb8be94d7924ebec6a26ffc7958ec7ca29d4bff967d \
--hash=sha256:6a498f82e0f4d8904c4e0aea5139cdfac1f39d19a3c51d491292f63a36e83b2e \
--hash=sha256:6c6b607466e47349332eb1d9be52fb1467423fc07c217341af41cd0f3f0573be \
--hash=sha256:82b432bc087264aea70fd25ac198918b70bd9e2aa0db4297b0bb91bbfbbc63ce \
--hash=sha256:8530a09d03b3a8c994f8b559a7dcdabc690bcd3f78ef276c38c83166798ebf56 \
--hash=sha256:87bf21fb3875fe69f0eacc825411657e2e85589cce633c35c0adf1113649c62b \
--hash=sha256:8f47f0f92952af2557212bb10cf3e695cd4cf28b2c6e42cdb18ec6c9ebfa19da \
--hash=sha256:922d1eb283161564759bd49f507e91dc6112c15da8bd5b84ed714e086243cf86 \
--hash=sha256:c6c754515be7b76afe6e7e62df7776709571bcfc1631183828afcf3bafa869e3 \
--hash=sha256:d48caa34488fb521fd0ef4aea2b0e8fe758298df044138f0d67b687a6a0d07ed \
--hash=sha256:ed03b7862d68f0a8771d50ee129980cbf1b113f96e250b73954bc292f689e0bb \
--hash=sha256:edc27f7172a93b32b102687009d6a588508815072141543ae603a8b9b0823063 \
--hash=sha256:efeca47ee3f9d4a7162655a3b8e6ee4a878646044233978d4d2c1ff8cdd914f0 \
--hash=sha256:f9b229cb3ef56ecc2c1c8ebeca64b7a7740ccaef40a9eb097e78dde5a8560b83
tomli==2.4.1 ; python_full_version < '3.11' \
--hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \
--hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \
--hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \
--hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \
--hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \
--hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \
--hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \
--hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \
--hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \
--hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \
--hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \
--hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \
--hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \
--hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \
--hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \
--hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \
--hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \
--hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \
--hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \
--hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \
--hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \
--hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \
--hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \
--hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \
--hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \
--hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \
--hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \
--hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \
--hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \
--hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \
--hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \
--hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \
--hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \
--hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \
--hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \
--hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \
--hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \
--hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \
--hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \
--hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \
--hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \
--hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \
--hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \
--hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \
--hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \
--hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \
--hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049
# via
# autopep8
# pytest
typing-extensions==4.15.0 ; python_full_version < '3.11' \
--hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
# via
# exceptiongroup
# virtualenv
virtualenv==21.5.1 \
--hash=sha256:55aa670b67bbfb991b03fda39bd3276d92c419d702376e98c5df1c9989a26783 \
--hash=sha256:dca3bf98275a59c652b69d68e73433e597d977c2da9198882479d1a7188009c8
ruff==0.17.1 \
--hash=sha256:056c5d5fa0ac790051ae165d7035c7bf956d02de2db557f2e9b31d877a505fca \
--hash=sha256:1796c41eafec66f4635125dd1e074a7aa27b8d20c187d484360acf11d247fc4a \
--hash=sha256:1de0030a8aa78c65c5fecb84b2e5c390ac684c0452875a02afc7c083d49a496a \
--hash=sha256:29b454f18ca3eeaf37fbf140841dcf27d36109e29dee9aae8acecb68c26c6f74 \
--hash=sha256:42400b9a6ff8515ff27796f07f92e0195be011c86e81e381606f58ea5502fef4 \
--hash=sha256:4c0d6cb5f8fbac77eec9af49f4fc0eaf856b05545e372b0694d24b4e76b1c640 \
--hash=sha256:5bb796c5112e9fb9527f2ef2faa0a130d6312d19de92bcfaddd70dbb2d41020f \
--hash=sha256:5df76f16580fab58d0f6c98a3ac254a4abceb7b2489b8b678335869cff77b3d7 \
--hash=sha256:684154861a819bf1f433669d2a0ce9c3e54677c65b8ebb866cc2a7ec86345785 \
--hash=sha256:78beced4a3c94dfedbee4b999b95b6a27b35820fdc0afbacc6d37a8da26c1cd1 \
--hash=sha256:7feefc63921202894f0e158b0e32f45a5950d70a7fb693ccb9264816c25b1c05 \
--hash=sha256:80e53b0e5faa3c5667f035daaa032893ae42b7cfe708c886d39ed131e54688ab \
--hash=sha256:872e03dd231744d6c5ec5c8af6be52b71323fc6ee096e4c8b34d9f844ee3b978 \
--hash=sha256:8eadb09a788010be29c895418bdfa513e4e1c65e64b94e5b19e4cd381f6cc7fb \
--hash=sha256:8f9aa5b5bd5fa1937803ea609c8f153b8de39bf3e0e149897ae34b0c5b52f467 \
--hash=sha256:a6ef98e51de8ef38082f90653ceeb84944bd7673783eea13e1647c5b9b064189 \
--hash=sha256:bd8f5a55b10f371642eacd0e8665a42a8b97da15c9a7187c79e697b77b5e0ce4 \
--hash=sha256:ce05e6f3973611d9550a600e04bb531061e368baba31610eb57c1509a8f21a0a
virtualenv==21.14.13 \
--hash=sha256:5fbb04138a4861580b78ba9110d529a26bc48fcc93c8ec36bc0202eeed96a788 \
--hash=sha256:de5307ba4b9a0001d9c8ea02832d38f63ca432880f416c1bface61c4323fd905
# via pre-commit
File diff suppressed because it is too large Load Diff
+121 -95
View File
@@ -1,97 +1,123 @@
cffi==2.0.0 ; implementation_name == 'cpython' \
--hash=sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb \
--hash=sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b \
--hash=sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f \
--hash=sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9 \
--hash=sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44 \
--hash=sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c \
--hash=sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75 \
--hash=sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e \
--hash=sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a \
--hash=sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e \
--hash=sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25 \
--hash=sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe \
--hash=sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b \
--hash=sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91 \
--hash=sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592 \
--hash=sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187 \
--hash=sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c \
--hash=sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1 \
--hash=sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94 \
--hash=sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba \
--hash=sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb \
--hash=sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529 \
--hash=sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca \
--hash=sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6 \
--hash=sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c \
--hash=sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0 \
--hash=sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743 \
--hash=sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5 \
--hash=sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5 \
--hash=sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4 \
--hash=sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d \
--hash=sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b \
--hash=sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93 \
--hash=sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205 \
--hash=sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27 \
--hash=sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512 \
--hash=sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d \
--hash=sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c \
--hash=sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037 \
--hash=sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26 \
--hash=sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb \
--hash=sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c \
--hash=sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8 \
--hash=sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4 \
--hash=sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414 \
--hash=sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9 \
--hash=sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664 \
--hash=sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9 \
--hash=sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775 \
--hash=sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739 \
--hash=sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc \
--hash=sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062 \
--hash=sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe \
--hash=sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92 \
--hash=sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5 \
--hash=sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13 \
--hash=sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d \
--hash=sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26 \
--hash=sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495 \
--hash=sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b \
--hash=sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6 \
--hash=sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c \
--hash=sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef \
--hash=sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5 \
--hash=sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18 \
--hash=sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad \
--hash=sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3 \
--hash=sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5 \
--hash=sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49 \
--hash=sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2 \
--hash=sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5 \
--hash=sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453
cffi==2.1.1 ; implementation_name == 'cpython' \
--hash=sha256:046bfc24911b37851ee1b51aab8bffe713d89c68c6a057b09484ce9fd5f69b4e \
--hash=sha256:06c72bb76605a4b0cd0aad6930b69d4baf7dd5d806cfc409b824191099700e66 \
--hash=sha256:0beceaabe56af686895136a2de78db54ecd8e4046b236b8fd6d6cb61389e9bf2 \
--hash=sha256:154852545011f779917b11c78db2358d095da62a9a172b78ad0a583ee5adc0d0 \
--hash=sha256:19ee6127ee34de7d83ce3d371ebc5ed91addbdcc39f9ab15ce4eb35a4e534971 \
--hash=sha256:1a18a57b58cfb21fc28d72e876acf10eaed67a1ed96226f92af4df681d571c4c \
--hash=sha256:1aa5645c30469b09530c4ebca77ebf8f17618293c58f8549cb1a543a50236e7d \
--hash=sha256:208f941bb9d18e768138677f0a6d2ce01f590df56043dda1df1535ac57c88517 \
--hash=sha256:210019b6c7cf07f081b4c54635c8cf744377001350e29cc0f81c4377b4797735 \
--hash=sha256:246fa40ce8645a614ff682e0b70f37134e460eaf93a775e0cbe3cca585a67a80 \
--hash=sha256:25792eac27877609e7bb06d42ff88278a6624fff2ba9bbb523c09616b117e80f \
--hash=sha256:27350daa11d4f10c540e6e89dada4c54feb7256ad03e9a4dc075ebad7ba360d1 \
--hash=sha256:28907ab9bfb6aa13184cfc17c6b8e1023c5ab6fd7076d8c20a35e59fe04f8f29 \
--hash=sha256:2ae64be792b8966f2c69538199728b290e34726562896df1e5dc8ffd8d8188e8 \
--hash=sha256:31348097ff5bbe827ccc41795d4dd099d9f0625e7def00ee653c137a490c2a6c \
--hash=sha256:3143d81e29e1e20a9ce10901ec369012947876596f75a222235965f2b7ae832e \
--hash=sha256:3222ba5d678f80a030e6afbcc33dc1ae5cb45facabb61cee2c7016b8432fde48 \
--hash=sha256:3311ed60d36f83378794e1009ac6258bafbf81f7888b4caa7b35a521e3f95813 \
--hash=sha256:334644fbac4eff73d985a17a91226df55d0f394160c4cfb880e084c8f7161cac \
--hash=sha256:34e261f78cb6ceaaa36f42f2613f4380d94d9c759a9c73c769ee6e0247364632 \
--hash=sha256:363e05fa78e15116c3c32c210ee36884fd6b9afa6d440e47112c3bd511d64cb6 \
--hash=sha256:398aff33cee2767e3e781d2554c54bd0dff386bb437581e0d8011fde1a942ec1 \
--hash=sha256:42a494cee34437f05546455144f2b5d9ac09b1face62bcfce597d2e521066688 \
--hash=sha256:42f6930c31dc7f50732c9ae793c2786c7b6b044195967bbdde40bb9be81c4cc0 \
--hash=sha256:456a61fa52d579ebf9df2e9552ead5129855dbaff6c1e5a9b1bc408809bdc062 \
--hash=sha256:471cee653ae88de62096552e6d24ccb4a5adb8c8c9f10b5054d0122c15bf2779 \
--hash=sha256:49cbc70e6542d4ccccb936558d1064a8012541e78f821f955cff24e357776c94 \
--hash=sha256:4a7c934f7360e8cd64fe9efadcbd10c7c6364f531e432b9a4bf5ccbc9e0e8b50 \
--hash=sha256:4be96343e422f2dfcd12ab5c9f5aebe03f82f737c6bffeca6830b3875cb44aab \
--hash=sha256:4f42141fc14250de6dde5ee7ea4432be017252d91f19c5ad043c084cea629cac \
--hash=sha256:507a24c282e0f42f8ed737cf048572cbf580468da5555764a8331735e9c736b6 \
--hash=sha256:51b31d1c98274844cfd7838ce00bfc27c7423a4dc00fc0772fc3331c2cc90676 \
--hash=sha256:58acb8ab8e295e6c5ea12f888cbb13cf21511ef2a3303a23f4325c29d17fe5c1 \
--hash=sha256:5c58fe613dc5e5336357eff555824a314d8e43282600435c8d1cb6a7a2fedd13 \
--hash=sha256:5e7cecbaadb83884793e05828cee59b210b24583b9c7425d0ba6a754fe22eb4e \
--hash=sha256:616f097f2fe415bc92a247f02e11f634e1f9e9a83d327e3c915c15089c87869e \
--hash=sha256:63bbfd5ded17c4840ac07cd8f1c21ba9d9708141f840b324f422f41b207e3973 \
--hash=sha256:64faea20f4e2613363a1a9b9c7dd73058f3ecd00133a511e72ad7c511658f527 \
--hash=sha256:661c298b4821edebead0c91edd2b00374d67ad7c5a1f7a91d4442633b79d6a72 \
--hash=sha256:68e62fe11f30d5ca8289242866f0a5291402d8529ca2178ab8afc5c9694ae890 \
--hash=sha256:6a8dddef476fab96d066d578fc88526767b836ab5ab21754e1d5bf3879c31c7c \
--hash=sha256:6e192623c49c94421616a5778fba35cf0d5a8d000650c1967ef4448ee5cdd990 \
--hash=sha256:7225e4514edb64eb6740324353e0da0711954fd8d7da4576755b1c6e09b697cd \
--hash=sha256:770de9db11e84213beec501cfcaa013b019820ca881e03344dea5844f7876d94 \
--hash=sha256:7750c6449dff7864bb9bb27ddfb0267756189201a3afc911d82b3caacd70dfc3 \
--hash=sha256:7bde5e4cc5c10140859842b9d383af292b22639a4dffb725314baf45968cef80 \
--hash=sha256:7da0c5eff80f0197f3b3d1232ec5a682a9325f4ae9016a78f5f5ca35f9ced1f5 \
--hash=sha256:7dbb61fe3a7699468030f71bbe5f8a0e326a151daa91beb11a6fc1f980c55e1c \
--hash=sha256:811bd1e21d32de12efca32393a0ab3f5133b54fce9bd44b8bd77ab07da14bf6a \
--hash=sha256:8ef53b2de9bcb9197d31854256575d59dbac0cba72ac627bb291ef5eceb74be4 \
--hash=sha256:937c0052c05a31ca1daf18de3158eed4dbfcb9cc107adbea227728d647be701e \
--hash=sha256:9d2055050ea716bd38b7f7f1579c275386646b4894c155a3e2f3cd62ed41b7c6 \
--hash=sha256:a2d7755bef5a12ed488f4ef1f1b69ee9191d7396083b755a5d2295f6edb4768b \
--hash=sha256:a4f00aa42f75d6e4595e8866e748cc1705adc0cddfeb2ca86d0d03993d63ba03 \
--hash=sha256:a6e721d4b0e45d5b65e87534470e67b18dcd092c83f68fba09f152b9cbc061af \
--hash=sha256:a730a083190634c65cca36ba5f489531576ebd79bcd5c8e172130f6453127231 \
--hash=sha256:a931079504ecc49efed7744c476a5c343a92fabf66dec2db95edb1b2fdc770e2 \
--hash=sha256:aa9511c62d14da7aacc9b4bf51f3f697a621e83b2d6919008243c3aad168eea3 \
--hash=sha256:ab36d55f9ed2d067327667c2fea18dda018eb628dd6347aa01dda6cf1f5d3836 \
--hash=sha256:ad2c86c495b899d862ea0f4b42891b8713a3bd45dd4105c7fd51c2a72f39f3a5 \
--hash=sha256:aeae0e330c9f6acd681f647d46cefd30c29f93e3392882e792e82080c9691399 \
--hash=sha256:b0431303acaea1089ad4b3e9ce4e6518193def1118d4073ca848635ee4ea2e96 \
--hash=sha256:b5bdfd1c873d4e093aabc0ca84c4ca6dbc4f752afb5c86f146d9742580c9da2e \
--hash=sha256:c1453022f490d2459a11819d83ad1d586e9ff65a12ac3e705ffebd46d3685dcf \
--hash=sha256:c26608d2222fb1e94487e4a387d85f13eb55d5ed725cb25a0c589ac4ee60e7bc \
--hash=sha256:c7659f22557c5a0bc4855cd635f55edec690cc008a40768527762cb9fb263455 \
--hash=sha256:c8c69575568085ba0b1b10c0249d779a214aea6f6522e949a0fc9fb0fcb449d0 \
--hash=sha256:c8d2c9fd1f2d16f780d15127abb050d13d1a76c03a4bd87d7e4980e45e511e12 \
--hash=sha256:cc572dace3f60ef98d7b12ff411d20f5362feb31a0439eab0085bbfd349982d7 \
--hash=sha256:d18e5ac0f2f03f4f518d3e23db0f0cad7faa1da8620e9c09461d443bbf6e6692 \
--hash=sha256:d28630f5854ab07ab1fd4aba756de52326c82e6be15d414b12793f1975048b54 \
--hash=sha256:d9c275eaacd24aa73f94ffd6de08fc3f932424d8b6c376f4bed7cde376fe7bc3 \
--hash=sha256:da0e573f9f97159390c89d9f1a9e41908b66d408cc5b58d08cf3847d844c531b \
--hash=sha256:dd31f52ea1086513bb9df30f8fcee9b8918323ae067a3d5b78bc826a000712be \
--hash=sha256:dddad92b554513a31f272570678ba307fb9f618f05e3d4a5eacafff9eae03e1d \
--hash=sha256:df423d40ee8654634421812bc3b196da3f9bd7d32929da813f8394c4348a5358 \
--hash=sha256:df913725b79db7bcf03448f36b7bf8815363417d5b58deecf9305e3e30f0f21a \
--hash=sha256:e0bcb7e0f677f543555d2adff3bf19c05f66cdb4796e5ff602442ab2fe3c4ef7 \
--hash=sha256:e2d65b31f36619cda3999b78b2aa9632e76b78448e7a56fc4240824200e7c4fc \
--hash=sha256:e6e8cff14d6fb0be70a09c0bdc58096f501952d04624ebf867e0e56da2df8960 \
--hash=sha256:f16c709686a78c727bbbf059f92b0bf41c6fc60deec706d2dc19f529175a6125 \
--hash=sha256:f24fb43132a4c6b4cb4eb029492919b2db645be6808d738f244fd146c03c32cb \
--hash=sha256:f53e442b08449d42821fa4a4fba000095af9f62742a500f978a9f557ec44339a \
--hash=sha256:f5cfbc5fe74540d335175b656c725d74d90e3730c626d92575eea35029d9afaa \
--hash=sha256:f81b3b8f3d4e343550fa4baa0e479bba9f2d29ce9c2e9b51d1ce1718d7442fcf \
--hash=sha256:f8ec5e643a9a937f64e1999eb9f75d072263751912dc5cd06d3c85f8f44be7c3 \
--hash=sha256:fb92203a88b3d3053034db775110081c49d28be6551923805e039924093761e4 \
--hash=sha256:fcd22650c908d7b7da162bbfaab594a1227a15d1643a98c68b122ac642fa2264
# via curl-cffi
curl-cffi==0.15.0 ; implementation_name == 'cpython' \
--hash=sha256:08c799b89740b9bc49c09fbc3d5907f13ac1f845ca52620507ef9466d4639dd5 \
--hash=sha256:0b6c0543b993996670e9e4b78e305a2d60809d5681903ffb5568e21a387434d3 \
--hash=sha256:1977e1e12cfb5c11352cbb74acef1bed24eb7d226dab61ca57c168c21acd4d61 \
--hash=sha256:2b6c847d86283b07ae69bb72c82eb8a59242277142aa35b89850f89e792a02fc \
--hash=sha256:408d6f14e346841cd889c2e0962832bb235ba3b6749ebf609f347f747da5e60f \
--hash=sha256:41f80170ba844009273b2660da1964ec31e99e5719d16b3422ada87177e32e13 \
--hash=sha256:4682dc38d4336e0eb0b185374db90a760efde63cbea994b4e63f3521d44c4c92 \
--hash=sha256:582e570aa2586b96ed47cf4a17586b9a3c462cbe43f780487c3dc245c6ef1527 \
--hash=sha256:5a0c1896a0d5a5ac1eb89cd24b008d2b718dd1df6fd2f75451b59ca66e49e572 \
--hash=sha256:7b7a92767a888ee90147e18964b396d8435ff42737030d6fb00824ffd6094805 \
--hash=sha256:7e63539d0d839d0a8c5eacf86229bc68c57803547f35e0db7ee0986328b478c3 \
--hash=sha256:829cc357061ecb99cc2d406301f609a039e05665322f5c025ec67c38b0dc49ce \
--hash=sha256:838e48212447d9c81364b04707a5c861daf08f8320f9ecb3406a8919d1d5c3b3 \
--hash=sha256:967ad7355bd8e9586f8c2d02eaa99953747549e7ea4a9b25cd53353e6b67fe6d \
--hash=sha256:9e5e69eee735f659287e2c84444319d68a1fa68dd37abf228943a4074864283a \
--hash=sha256:a25620d9bf989c9c029a7d1642999c4c265abb0bad811deb2f77b0b5b2b12e5b \
--hash=sha256:a6d57f8389273a3a1f94370473c74897467bcc36af0a17336989780c507fa43d \
--hash=sha256:aa1323950224db24f4c510d010b3affa02196ca853fb424191fa917a513d3f4b \
--hash=sha256:b624c7ce087bfda967a013ed0a64702a525444e5b6e97d23534d567ccc6525aa \
--hash=sha256:bda66404010e9ed743b1b83c20c86f24fe21a9a6873e17479d6e67e29d8ded28 \
--hash=sha256:ea0c67652bf6893d34ee0f82c944f37e488f6147e9421bef1771cc6545b02ded
curl-cffi==0.17.0 ; implementation_name == 'cpython' \
--hash=sha256:0d85bec9648bf7c14c3b43056ba82521740f72cd96ed7700a0e1973e7fc93f74 \
--hash=sha256:0e70d25d88adc66818d831805e460704088f445269eaabbf884ab05d437c2f99 \
--hash=sha256:2cc7d939014953223c96e78098bb24c336e7268eb6529c0d5fa9a53805a4acee \
--hash=sha256:2dac9c915a0ee7d7cc4285203d210816bb187c8deb5c20ee21e0613639c2a8bf \
--hash=sha256:31ee8500d06d6502ce1ec0b7ded1c5aa8e8f3401bbe37ccd78d6153d859d8f3c \
--hash=sha256:32f9508a92adaa8c9c35fd4cda786c9e697643afc2eda8dc4c3d426a910b453a \
--hash=sha256:3f737d386e77d4e5ac64998fac8b494b35d37e8cbda22f675b0126913e0e4d6d \
--hash=sha256:4c3993c7df155d622869b82a56adb018440587fd3faffeaf8d01cc016d2e1357 \
--hash=sha256:4f3413b62c780f2a5c7f8a0f6a1d8114f055043a273981b9732abedb5367202b \
--hash=sha256:51199328450e07c8ef8430a7ccce1acfb199b5cd7595e8f958e84f2faedccdac \
--hash=sha256:539eb6708c46433cd61745fda756f2754807f4774b31255d8ee56db0e97068fe \
--hash=sha256:56d622930eac5cee4cc6ebe63eaba3ecca65a2c73aa6bdf099c2ffae55ee988c \
--hash=sha256:5ca006230676c7c2f2e5708d02e5852a09caee49d82f1f2a469d5d6537a11baa \
--hash=sha256:7e126f4675d100f1ad6247a0d8e0b3ebe3fa2f4a123e2b9b78e4880b40f5bedd \
--hash=sha256:88cb5e34eb23eb2106711b06df68027209c72be709df239c6029345551e0acfd \
--hash=sha256:8a08236aac049468d83fc19699102a3d953769ccbfe2b31b63e1d26c5bb07af3 \
--hash=sha256:918a493717da703bc10507b811e347f4ad94132e30c6709fc1e85daf79979565 \
--hash=sha256:93f706c46370cf83c53ffe08cf33892e657c21a6597802f67f1559e4c642ee65 \
--hash=sha256:9426fa386a0f299ab043f64e59689d52e6ee2370f19238aa0bb42e6bf3620aaf \
--hash=sha256:a055f709029d2deaafed6a3a2a58c219d7ee2776a1d2357272d3ef230fb30c5c \
--hash=sha256:a93d3cd83aed4307001ca560b931317e0690ddf3c17e86c2d5b6e0722780b40c \
--hash=sha256:aa91d26234516ddb9eb97310d5fe1705aa6f677f101d57ffdb76d5f75439506e \
--hash=sha256:ad88837e627896f794ab77c5d61245f5fbc0da1e86a39043404b94bef45e98ef \
--hash=sha256:ae0442e45d6e0c987f84cb88bd6a99d7b91c8e2b017c18048a6c4fed63847c80 \
--hash=sha256:af0782d5e340b65fd76701630f0284a8f8243d77df5f2637efd09a4b009f4e24 \
--hash=sha256:b09f03f1aafcbbf6175610005e4e0192413148fe44c65b789a2aadfff9384a7d \
--hash=sha256:c11b405fa10530cec589349c1cc8d60a3a4fac20fb7be0b2713e7271a2737f57 \
--hash=sha256:e8cfb7eee2019fe879ab3304b33e84ba60dbcec148c34c343c49b8c67f9ddad5 \
--hash=sha256:f7e0817633948a8b00e65ef3662bf139cef3fb4d3847e29a720f8072c3d76a18 \
--hash=sha256:f8cf840646d3e57637b8caae7d0d93334dfed0bfbf6f160b36479a7d6069d547 \
--hash=sha256:fc33ca76371bc96df3c4e8593449a1e0e28086bf8016addb851905090069178c
# via yt-dlp
+463 -311
View File
@@ -4,189 +4,260 @@ altgraph==0.17.5 \
# via
# macholib
# pyinstaller
brotli==1.2.0 ; implementation_name == 'cpython' and sys_platform != 'ios' \
--hash=sha256:022426c9e99fd65d9475dce5c195526f04bb8be8907607e27e747893f6ee3e24 \
--hash=sha256:072e7624b1fc4d601036ab3f4f27942ef772887e876beff0301d261210bca97f \
--hash=sha256:0bbd5b5ccd157ae7913750476d48099aaf507a79841c0d04a9db4415b14842de \
--hash=sha256:0cf8c3b8ba93d496b2fae778039e2f5ecc7cff99df84df337ca31d8f2252896c \
--hash=sha256:15b33fe93cedc4caaff8a0bd1eb7e3dab1c61bb22a0bf5bdfdfd97cd7da79744 \
--hash=sha256:1b1d6a4efedd53671c793be6dd760fcf2107da3a52331ad9ea429edf0902f27a \
--hash=sha256:1b557b29782a643420e08d75aea889462a4a8796e9a6cf5621ab05a3f7da8ef2 \
--hash=sha256:260d3692396e1895c5034f204f0db022c056f9e2ac841593a4cf9426e2a3faca \
--hash=sha256:26e8d3ecb0ee458a9804f47f21b74845cc823fd1bb19f02272be70774f56e2a6 \
--hash=sha256:2a7f1d03727130fc875448b65b127a9ec5d06d19d0148e7554384229706f9d1b \
--hash=sha256:2e1ad3fda65ae0d93fec742a128d72e145c9c7a99ee2fcd667785d99eb25a7fe \
--hash=sha256:3219bd9e69868e57183316ee19c84e03e8f8b5a1d1f2667e1aa8c2f91cb061ac \
--hash=sha256:350c8348f0e76fff0a0fd6c26755d2653863279d086d3aa2c290a6a7251135dd \
--hash=sha256:35d382625778834a7f3061b15423919aa03e4f5da34ac8e02c074e4b75ab4f84 \
--hash=sha256:3b90b767916ac44e93a8e28ce6adf8d551e43affb512f2377c732d486ac6514e \
--hash=sha256:3e1b35d56856f3ed326b140d3c6d9db91740f22e14b06e840fe4bb1923439a18 \
--hash=sha256:3f3c908bcc404c90c77d5a073e55271a0a498f4e0756e48127c35d91cf155947 \
--hash=sha256:40d918bce2b427a0c4ba189df7a006ac0c7277c180aee4617d99e9ccaaf59e6a \
--hash=sha256:4ecdb3b6dc36e6d6e14d3a1bdc6c1057c8cbf80db04031d566eb6080ce283a48 \
--hash=sha256:54a50a9dad16b32136b2241ddea9e4df159b41247b2ce6aac0b3276a66a8f1e5 \
--hash=sha256:67a91c5187e1eec76a61625c77a6c8c785650f5b576ca732bd33ef58b0dff49c \
--hash=sha256:6be67c19e0b0c56365c6a76e393b932fb0e78b3b56b711d180dd7013cb1fd984 \
--hash=sha256:6c12dad5cd04530323e723787ff762bac749a7b256a5bece32b2243dd5c27b21 \
--hash=sha256:7547369c4392b47d30a3467fe8c3330b4f2e0f7730e45e3103d7d636678a808b \
--hash=sha256:7a47ce5c2288702e09dc22a44d0ee6152f2c7eda97b3c8482d826a1f3cfc7da7 \
--hash=sha256:7a61c06b334bd99bc5ae84f1eeb36bfe01400264b3c352f968c6e30a10f9d08b \
--hash=sha256:81da1b229b1889f25adadc929aeb9dbc4e922bd18561b65b08dd9343cfccca84 \
--hash=sha256:832c115a020e463c2f67664560449a7bea26b0c1fdd690352addad6d0a08714d \
--hash=sha256:844a8ceb8483fefafc412f85c14f2aae2fb69567bf2a0de53cdb88b73e7c43ae \
--hash=sha256:898be2be399c221d2671d29eed26b6b2713a02c2119168ed914e7d00ceadb56f \
--hash=sha256:9322b9f8656782414b37e6af884146869d46ab85158201d82bab9abbcb971dc7 \
--hash=sha256:963a08f3bebd8b75ac57661045402da15991468a621f014be54e50f53a58d19e \
--hash=sha256:9c79f57faa25d97900bfb119480806d783fba83cd09ee0b33c17623935b05fa3 \
--hash=sha256:9e5825ba2c9998375530504578fd4d5d1059d09621a02065d1b6bfc41a8e05ab \
--hash=sha256:a1778532b978d2536e79c05dac2d8cd857f6c55cd0c95ace5b03740824e0e2f1 \
--hash=sha256:aa47441fa3026543513139cb8926a92a8e305ee9c71a6209ef7a97d91640ea03 \
--hash=sha256:acec55bb7c90f1dfc476126f9711a8e81c9af7fb617409a9ee2953115343f08d \
--hash=sha256:adedc4a67e15327dfdd04884873c6d5a01d3e3b6f61406f99b1ed4865a2f6d28 \
--hash=sha256:af43b8711a8264bb4e7d6d9a6d004c3a2019c04c01127a868709ec29962b6036 \
--hash=sha256:b232029d100d393ae3c603c8ffd7e3fe6f798c5e28ddca5feabb8e8fdb732997 \
--hash=sha256:b35c13ce241abdd44cb8ca70683f20c0c079728a36a996297adb5334adfc1c44 \
--hash=sha256:b63daa43d82f0cdabf98dee215b375b4058cce72871fd07934f179885aad16e8 \
--hash=sha256:c8565e3cdc1808b1a34714b553b262c5de5fbda202285782173ec137fd13709f \
--hash=sha256:cf9cba6f5b78a2071ec6fb1e7bd39acf35071d90a81231d67e92d637776a6a63 \
--hash=sha256:d2d085ded05278d1c7f65560aae97b3160aeb2ea2c0b3e26204856beccb60888 \
--hash=sha256:e310f77e41941c13340a95976fe66a8a95b01e783d430eeaf7a2f87e0a57dd0a \
--hash=sha256:e7c0af964e0b4e3412a0ebf341ea26ec767fa0b4cf81abb5e897c9338b5ad6a3 \
--hash=sha256:e99befa0b48f3cd293dafeacdd0d191804d105d279e0b387a32054c1180f3161 \
--hash=sha256:ef87b8ab2704da227e83a246356a2b179ef826f550f794b2c52cddb4efbd0196 \
--hash=sha256:fc1530af5c3c275b8524f2e24841cbe2599d74462455e9bae5109e9ff42e9361 \
--hash=sha256:ff09cd8c5eec3b9d02d2408db41be150d8891c5566addce57513bf546e3d6c6d
brotli==1.2.1 ; implementation_name == 'cpython' and sys_platform != 'ios' \
--hash=sha256:00a50d063aae2e69c2eb28818ccf6dc3e51f2ea5b74e3c2082a47943ee23f399 \
--hash=sha256:02b2f7b5a83485efe448a44ddf7983def05c3bb1dcf917d4f7154070260e13de \
--hash=sha256:035f3bf861328d8b7fcb61f4a976f9913027158e5666116733d59ffc65f2745e \
--hash=sha256:06a22fcbcae059c0679098232779095fc50a735a3fea02db5c79cab10b84d877 \
--hash=sha256:09a2f112a638aca15a88f298571788795fc45d62f2bca7f3870c1152153ef399 \
--hash=sha256:0a30e5df5ba985b67f85e13dfd7e5a68e186d8d9b5cff7d9a8904832bb413e81 \
--hash=sha256:11aec6ea5c20cad61a33302e06baa48b0243bfa4d173bc2985dabd047e367d08 \
--hash=sha256:1329c80daa60752f1d94f507479504921e358e71746c5fce9b55b3d51ac038bc \
--hash=sha256:1880db6241276e191d3e34a6e4eea708c6629103c396f0ea21e75b0ce63a9a2c \
--hash=sha256:1f65a91f3576949793b8720b12a47e7ea06debc970a2da6d54ff8458053e2109 \
--hash=sha256:23f0d23995100458d17f3bf5ce1e959fe46df894b472063a74266f7adeb2e72e \
--hash=sha256:264fd5b200f6f6170cb551a4b9fcaabf8aa846ddaefe72db4d5f49f9d3743df9 \
--hash=sha256:2df1678c2c25db2f669c613fe8b4e587d0dd24c6acf7746bad13d6e87e4b051d \
--hash=sha256:338856ae9ff63af4fc3dbbd6184a7276a6ae83df2243562e86e5ee5cf980cce7 \
--hash=sha256:37de1818ce469b3c37324c89d4d4dbb5e64461d9dc01c16f8abb2a17c465b132 \
--hash=sha256:3975fb11f63e212b87a087e4a910187b522c6969a4989ca362d6f85f9dc36acd \
--hash=sha256:4b9dd0173ca5e01d1eb307d3c184fe8c09bdc168ede560889b1018d216d38c61 \
--hash=sha256:4d47a9f0ba5ee608f3f3a9c942dcd244443068ae5b0d90183dd396dea02236e4 \
--hash=sha256:59ca34c7a83d7a3b842247183c426f891a95a8f57db41b7aac92195c51e8a83a \
--hash=sha256:59ec359a56f44277ad424fb4b7cf1a0ae2fd855b35ba8f15dcfbcabb3fb51aeb \
--hash=sha256:5f3da70516b1bd1b2aa183ec4ab5c02dfc6ad5c1184d47bb65ade25e710439b6 \
--hash=sha256:6532d2c58018121a9eb5882656cf862cdbbd853600cb5fbccac59bcff14f66b0 \
--hash=sha256:67f4dceb22ce3a742751cee849644449b169684699aa548e77d771de304e963c \
--hash=sha256:6b3c3d5794212a54434b4856f808f7bdf7ad48eacadaadb5b2346fc9a639365a \
--hash=sha256:6bd29ab84bb8972370cacd310e8a91651f54476d01de1cd1a4cf0bece5eb25e1 \
--hash=sha256:7248c282d7d6aef4ae89363da5fc3df7b9250eb04b252622955296eb5d0ea82f \
--hash=sha256:761db18dc32b24d00fbedca1013089eb3470053cefa8492bd9c07b11102d72bf \
--hash=sha256:77ef5882c5318ffc3dd94c6abc6a8f1ec2af75d66522319f1a250a07d53d0546 \
--hash=sha256:7ec678c52c3ef5e37482a094d109c04cf9e4a0e2923dd1e0fbddb4bf133a976e \
--hash=sha256:810aea5958d6a2d92593fd27218df528644aeb72cc7f6d401e650752d6c98949 \
--hash=sha256:87492842770cd772fce25e9cd279913eaea6c55a91a960b6302aedfa2ec7b152 \
--hash=sha256:875975f91870682cca4371260522ad3f22d636e845b5c5355c52bc045c0f75c8 \
--hash=sha256:90bd49511341dd7c40bb3acaa97cd8b9e5df4821a5714b842117e7069c7cc03e \
--hash=sha256:91097d66ebb8ca8d23372081a33405a44e2239445614888e38929bd7f5879dae \
--hash=sha256:9307679936e86d7773eadfa444a4a4ee80f6f45230e93379875f4a6897a09a2b \
--hash=sha256:93269f11303fc9a3e3990b57e0533f41949546156d9f0e535571f313032563cc \
--hash=sha256:96e6966edcfae74ffac2522d2dd1a304450d18807a9791f5ed0a3232192c9437 \
--hash=sha256:970a3dbce807a3f5c2b8232036052bade01e4bc92ade37d73ea3750418307fa1 \
--hash=sha256:972a2e19dbaab47d0aa77c1d07f71c930bdc53538f2b33decc905e92a4be5cbd \
--hash=sha256:972e34c5cbbfe6c90358bfae38edae1a29d3456e920da5a4664c98f221ee4df8 \
--hash=sha256:a3942e2d365f009e5e7839114fa315e1a2bcfea12b52064a28f1a7281862a2a7 \
--hash=sha256:a3dea7e1ac49e29306500a8627fa3eacabcc9e238d22495eea2d8e61de77065b \
--hash=sha256:a84e0ae14d1efe782a9f143021c4e01d5ed986a140fe5070505cc5978eaf0592 \
--hash=sha256:a998857af4fcd19920bdf5f30f0f1a23f38472a703d33e49168cd4fd32438377 \
--hash=sha256:aa32b51702a0b6e9fddc0d1dc66cb6ed6af112f1bba0cac2be9039546a862b5c \
--hash=sha256:b0c32f0660bb21e810ffc1d3d04b6ea682e118b8141c6e12522a3dacadeb70ee \
--hash=sha256:b0faa0b9af9367748388345d5b12f6add2a9cf896481e72910e88fbfe14ecd54 \
--hash=sha256:b5b458950312830913f837e179ce9221000ab7a20b4e42d7b48c1fcd79140de1 \
--hash=sha256:b8b2fc7901b31d5885f26521cf2d74feccdc126a272ba1d879b7545bb25468bc \
--hash=sha256:be371af72af54b6e508b68a7a87768e05b7e13023f6c82a3e3f5e4d0e829e186 \
--hash=sha256:c3f667dc60a875b12a5ecd7828062ccd97c0fb79c4adc6c8699d23d5ff2af7e1 \
--hash=sha256:c4b68ce579b05c66bb18a16356a4f713bebac2446ee498dd8bb1ecab3da77b89 \
--hash=sha256:c5302747f969d5ec925810176f7697712a3fa2ea0fae0c7a85aa4ad9325247fd \
--hash=sha256:c788fdab2eeeab671f5ab375ad010ef743f6c95be67f60f878e8876a51f6c671 \
--hash=sha256:cfa54e7f5bd5ef482e7f5336f7cf3c30ae608d9767e514dd930b7c30a03fa977 \
--hash=sha256:d6ef0035b6ae338a46951c144081c61fb044f4c1eb6d20acc5ba6277f666a4c0 \
--hash=sha256:dafaeb38712f99e5c31ad7f02c366f1ddd3792921b94066015f8c49f197163b0 \
--hash=sha256:dca1bf90b3a6a7440904f128464eb95bf46ac9da7ad3c85912483dd83128fd95 \
--hash=sha256:de1bf30d819809a964060356032e6670c9923644666afaaf3d1719d05ddb844e \
--hash=sha256:de499e2492c8106a5e163d3cf5b6726e2797f9234cfbc6055fbb5f9d8f198f39 \
--hash=sha256:e4a7be59d374c445766fa4ac066a04d19a757365ae00a950053d0ab7388d1039 \
--hash=sha256:e6c4fa55eab6b5684b33239597876a18a35ce1280b63ab960164032afbb8783f \
--hash=sha256:eaa5178a4c1fe619eff9cbe93b57919d426332e219870301d4ef5fc09a522ae9 \
--hash=sha256:ed62c15ce5e8b975b2710a0f7c8bb953cbffb472fccb05055be6afcba9520c19 \
--hash=sha256:ed8e452f5cb34f59f4861d50d029c6203b5f8f11c13d4186264392a64b4def8d \
--hash=sha256:eea17e3cdc6f9aecffe15fe9a9eeba8e8c049a5d347de1561eed2240cdf35a79 \
--hash=sha256:f00ff4b56caf151365c77988eb85a4a71eb26fe63047d4084d5614e06d65e3cf \
--hash=sha256:f06dd6a30438692d48c0d54de4b659cd55a57c2c2f6591c969c98d0a5523ab07 \
--hash=sha256:f34405292fca45cd77419005c1ea35ba1c03eaff9042afe76d6fe189fe474669 \
--hash=sha256:f352f797b1477c46a20e45f4cbc3a0e258e61963c8ae8f79f84a7bfb4195b37e \
--hash=sha256:f37ccd159dae35d4914651d57142c8077aa67ab7e3ffef690b00bcb7a7dbd8e6 \
--hash=sha256:f51bca8fcac4266519533698c316f3d23340768a8e57c4796c9f6e0a4f353807 \
--hash=sha256:f5342b8256476554b4045db8b7bf4dc4044d0405485f220f0cd80764bc0d7faf \
--hash=sha256:f5fbda9703bce94a976e1a6bbdbbe0af25fb613a593a56091991359928b66c05 \
--hash=sha256:fb5df75d1b1c42d997adbb39eac61f2cdb48efa26304a0cb9c0b757c9bc20732 \
--hash=sha256:fb6a4d400aa531c73a718b337116fad77ba8dc6df34fa615c808bfc55ffb19ca
# via yt-dlp
brotlicffi==1.2.0.1 ; implementation_name != 'cpython' \
--hash=sha256:2c85e65913cf2b79c57a3fdd05b98d9731d9255dc0cb696b09376cc091b9cddd \
--hash=sha256:37cb587d32bf7168e2218c455e22e409ad1f3157c6c71945879a311f3e6b6abf \
--hash=sha256:3c9544f83cb715d95d7eab3af4adbbef8b2093ad6382288a83b3a25feb1a57ec \
--hash=sha256:535f2d05d0273408abc13fc0eebb467afac17b0ad85090c8913690d40207dac5 \
--hash=sha256:625f8115d32ae9c0740d01ea51518437c3fbaa3e78d41cb18459f6f7ac326000 \
--hash=sha256:6f3314a3476f59e5443f9f72a6dff16edc0c3463c9b318feaef04ae3e4683f5a \
--hash=sha256:82ea52e2b5d3145b6c406ebd3efb0d55db718b7ad996bd70c62cec0439de1187 \
--hash=sha256:91ba5f0ccc040f6ff8f7efaf839f797723d03ed46acb8ae9408f99ffd2572cf4 \
--hash=sha256:9d6ba65dd528892b4d9960beba2ae011a753620bcfc66cf6fa3cee18d7b0baa4 \
--hash=sha256:be9a670c6811af30a4bd42d7116dc5895d3b41beaa8ed8a89050447a0181f5ce \
--hash=sha256:c20d5c596278307ad06414a6d95a892377ea274a5c6b790c2548c009385d621c \
--hash=sha256:ce17eb798ca59ecec67a9bb3fd7a4304e120d1cd02953ce522d959b9a84d58ac \
--hash=sha256:da2e82a08e7778b8bc539d27ca03cdd684113e81394bfaaad8d0dfc6a17ddede \
--hash=sha256:e015af99584c6db1490a69a210c765953e473e63adc2d891ac3062a737c9e851 \
--hash=sha256:f2a5575653b0672638ba039b82fda56854934d7a6a24d4b8b5033f73ab43cbc1
brotlicffi==1.2.1.0 ; implementation_name != 'cpython' \
--hash=sha256:00a6e8df24c2f48744bbdca8694a2b50bb26d1d0b6360c3a7c5caeaf4ad83373 \
--hash=sha256:0a7281a39de91432e90c27ab9c4f9feb3a9cf33fda3873534c2a88270d9f60a2 \
--hash=sha256:0cb591da62db91dddd701a28def82f39e0f7943321ac7d0814a1d2a1625095d1 \
--hash=sha256:1563024a25dd2c357457f49f4e03d4354d0660ae41ed1983d86c5817a754a539 \
--hash=sha256:2182d9af39ff06efce62a783d9429bf01f10cdedafc8b6ba696f75b52fc39eef \
--hash=sha256:25ab19c47b88438b5d00a2074b86fe37ab5c176aef90de1ae0f5e1ae52300462 \
--hash=sha256:30a52a620564ef3c6a34cd1e09d699b92ba68a3447a28915b77a17eb5d2c8f71 \
--hash=sha256:421ba24ee6568c6baa3c83e0f584fe9e3941bf86401122942c5ed085f8114c09 \
--hash=sha256:52b99120543ffa3b0667e922c6a7dc6b6e01350f7fd38f21aaca511bb9f8b4f2 \
--hash=sha256:54ccae9a0ff09c7f007aa247dc62b6ca7666ecf1358568e6f2eb8683ceed1d01 \
--hash=sha256:5d0b89e959f643aab4c58c15c06e1e87b6f6605e5e88c3c1c28f5ce1c58c4e5f \
--hash=sha256:602e87ecc8fd2c72b13ba6dced2e0d5aefc18a262523e82795ed0f47f5a13903 \
--hash=sha256:6f5ff7c8f62eaa3e6feb2b4d06a6001bb08cc346c9de7608786de99387255e94 \
--hash=sha256:75e54388f06cd7edf5354f526d0386553db441b7574a22a2bcb19a2149e48eb7 \
--hash=sha256:ac2d63c8f3c1fd000286315027a013008c7c9a3009c7415c24ee48dde1b207db \
--hash=sha256:b77704eb33e345e00d0a2854abf7966b86e1709a1f89bcc143b6c8437256d7c7 \
--hash=sha256:cc882e1ab3f81d262cc002132476dab7667f8f41ead3de8609b163cb64409f8a \
--hash=sha256:ed7c8311209853c9d78e2f6cff1f57e4df2541e4d67e3677dc1f4c88539db907 \
--hash=sha256:fea6f5450a6bd73ec222e92282d4db25030943946190697c1f2cd41087c59bc6
# via yt-dlp
certifi==2026.6.17 \
--hash=sha256:024c88eeec92ca068db80f02b8b07c9cef7b9fe261d1d535abfd5abd6f6af432 \
--hash=sha256:2227dcbaafe0d2f59279d1762ddddc37783ed4354594f194ffc31d20f41fc3db
certifi==2026.10.23 \
--hash=sha256:a9895e6e2758b371e0545e321a3a8fd1fcfd9829ada8824a936dfb16aaaf36cd \
--hash=sha256:e9b54de76e530bb6cf0ccd036787103acb58fd42ba930ea8bf948ddbaa2f61d1
# via
# curl-cffi
# requests
# yt-dlp
charset-normalizer==3.4.7 \
--hash=sha256:007d05ec7321d12a40227aae9e2bc6dca73f3cb21058999a1df9e193555a9dcc \
--hash=sha256:03853ed82eeebbce3c2abfdbc98c96dc205f32a79627688ac9a27370ea61a49c \
--hash=sha256:08e721811161356f97b4059a9ba7bafb23ea5ee2255402c42881c214e173c6b4 \
--hash=sha256:0c96c3b819b5c3e9e165495db84d41914d6894d55181d2d108cc1a69bfc9cce0 \
--hash=sha256:0ea948db76d31190bf08bd371623927ee1339d5f2a0b4b1b4a4439a65298703c \
--hash=sha256:0f7eb884681e3938906ed0434f20c63046eacd0111c4ba96f27b76084cd679f5 \
--hash=sha256:12d8baf840cc7889b37c7c770f478adea7adce3dcb3944d02ec87508e2dcf153 \
--hash=sha256:1a87ca9d5df6fe460483d9a5bbf2b18f620cbed41b432e2bddb686228282d10b \
--hash=sha256:1c2a768fdd44ee4a9339a9b0b130049139b8ce3c01d2ce09f67f5a68048d477c \
--hash=sha256:1c2aed2e5e41f24ea8ef1590b8e848a79b56f3a5564a65ceec43c9d692dc7d8a \
--hash=sha256:202389074300232baeb53ae2569a60901f7efadd4245cf3a3bf0617d60b439d7 \
--hash=sha256:203104ed3e428044fd943bc4bf45fa73c0730391f9621e37fe39ecf477b128cb \
--hash=sha256:2257141f39fe65a3fdf38aeccae4b953e5f3b3324f4ff0daf9f15b8518666a2c \
--hash=sha256:298930cec56029e05497a76988377cbd7457ba864beeea92ad7e844fe74cd1f1 \
--hash=sha256:2d6eb928e13016cea4f1f21d1e10c1cebd5a421bc57ddf5b1142ae3f86824fab \
--hash=sha256:2fe249cb4651fd12605b7288b24751d8bfd46d35f12a20b1ba33dea122e690df \
--hash=sha256:30b8d1d8c52a48c2c5690e152c169b673487a2a58de1ec7393196753063fcd5e \
--hash=sha256:3534e7dcbdcf757da6b85a0bbf5b6868786d5982dd959b065e65481644817a18 \
--hash=sha256:38c0109396c4cfc574d502df99742a45c72c08eff0a36158b6f04000043dbf38 \
--hash=sha256:3946fa46a0cf3e4c8cb1cc52f56bb536310d34f25f01ca9b6c16afa767dab110 \
--hash=sha256:3bec022aec2c514d9cf199522a802bd007cd588ab17ab2525f20f9c34d067c18 \
--hash=sha256:3c9a494bc5ec77d43cea229c4f6db1e4d8fe7e1bbffa8b6f0f0032430ff8ab44 \
--hash=sha256:3dce51d0f5e7951f8bb4900c257dad282f49190fdbebecd4ba99bcc41fef404d \
--hash=sha256:3dedcc22d73ec993f42055eff4fcfed9318d1eeb9a6606c55892a26964964e48 \
--hash=sha256:4042d5c8f957e15221d423ba781e85d553722fc4113f523f2feb7b188cc34c5e \
--hash=sha256:481551899c856c704d58119b5025793fa6730adda3571971af568f66d2424bb5 \
--hash=sha256:4dc1e73c36828f982bfe79fadf5919923f8a6f4df2860804db9a98c48824ce8d \
--hash=sha256:4e5163c14bffd570ef2affbfdd77bba66383890797df43dc8b4cc7d6f500bf53 \
--hash=sha256:511ef87c8aec0783e08ac18565a16d435372bc1ac25a91e6ac7f5ef2b0bff790 \
--hash=sha256:532bc9bf33a68613fd7d65e4b1c71a6a38d7d42604ecf239c77392e9b4e8998c \
--hash=sha256:54523e136b8948060c0fa0bc7b1b50c32c186f2fceee897a495406bb6e311d2b \
--hash=sha256:5649fd1c7bade02f320a462fdefd0b4bd3ce036065836d4f42e0de958038e116 \
--hash=sha256:56be790f86bfb2c98fb742ce566dfb4816e5a83384616ab59c49e0604d49c51d \
--hash=sha256:5b77459df20e08151cd6f8b9ef8ef1f961ef73d85c21a555c7eed5b79410ec10 \
--hash=sha256:5ed6ab538499c8644b8a3e18debabcd7ce684f3fa91cf867521a7a0279cab2d6 \
--hash=sha256:6178f72c5508bfc5fd446a5905e698c6212932f25bcdd4b47a757a50605a90e2 \
--hash=sha256:64f02c6841d7d83f832cd97ccf8eb8a906d06eb95d5276069175c696b024b60a \
--hash=sha256:65bcd23054beab4d166035cabbc868a09c1a49d1efe458fe8e4361215df40265 \
--hash=sha256:66671f93accb62ed07da56613636f3641f1a12c13046ce91ffc923721f23c008 \
--hash=sha256:6696b7688f54f5af4462118f0bfa7c1621eeb87154f77fa04b9295ce7a8f2943 \
--hash=sha256:6785f414ae0f3c733c437e0f3929197934f526d19dfaa75e18fdb4f94c6fb374 \
--hash=sha256:67f6279d125ca0046a7fd386d01b311c6363844deac3e5b069b514ba3e63c246 \
--hash=sha256:6c114670c45346afedc0d947faf3c7f701051d2518b943679c8ff88befe14f8e \
--hash=sha256:6ed74185b2db44f41ef35fd1617c5888e59792da9bbc9190d6c7300617182616 \
--hash=sha256:708838739abf24b2ceb208d0e22403dd018faeef86ddac04319a62ae884c4f15 \
--hash=sha256:715479b9a2802ecac752a3b0efa2b0b60285cf962ee38414211abdfccc233b41 \
--hash=sha256:733784b6d6def852c814bce5f318d25da2ee65dd4839a0718641c696e09a2960 \
--hash=sha256:750e02e074872a3fad7f233b47734166440af3cdea0add3e95163110816d6752 \
--hash=sha256:752a45dc4a6934060b3b0dab47e04edc3326575f82be64bc4fc293914566503e \
--hash=sha256:7579e913a5339fb8fa133f6bbcfd8e6749696206cf05acdbdca71a1b436d8e72 \
--hash=sha256:7641bb8895e77f921102f72833904dcd9901df5d6d72a2ab8f31d04b7e51e4e7 \
--hash=sha256:7804338df6fcc08105c7745f1502ba68d900f45fd770d5bdd5288ddccb8a42d8 \
--hash=sha256:80d04837f55fc81da168b98de4f4b797ef007fc8a79ab71c6ec9bc4dd662b15b \
--hash=sha256:8778f0c7a52e56f75d12dae53ae320fae900a8b9b4164b981b9c5ce059cd1fcb \
--hash=sha256:8d828b6667a32a728a1ad1d93957cdf37489c57b97ae6c4de2860fa749b8fc1e \
--hash=sha256:8e385e4267ab76874ae30db04c627faaaf0b509e1ccc11a95b3fc3e83f855c00 \
--hash=sha256:92a0a01ead5e668468e952e4238cccd7c537364eb7d851ab144ab6627dbbe12f \
--hash=sha256:94e1885b270625a9a828c9793b4d52a64445299baa1fea5a173bf1d3dd9a1a5a \
--hash=sha256:a180c5e59792af262bf263b21a3c49353f25945d8d9f70628e73de370d55e1e1 \
--hash=sha256:a277ab8928b9f299723bc1a2dabb1265911b1a76341f90a510368ca44ad9ab66 \
--hash=sha256:a5fe03b42827c13cdccd08e6c0247b6a6d4b5e3cdc53fd1749f5896adcdc2356 \
--hash=sha256:a89c23ef8d2c6b27fd200a42aa4ac72786e7c60d40efdc76e6011260b6e949c4 \
--hash=sha256:adb2597b428735679446b46c8badf467b4ca5f5056aae4d51a19f9570301b1ad \
--hash=sha256:ae196f021b5e7c78e918242d217db021ed2a6ace2bc6ae94c0fc596221c7f58d \
--hash=sha256:ae89db9e5f98a11a4bf50407d4363e7b09b31e55bc117b4f7d80aab97ba009e5 \
--hash=sha256:aed52fea0513bac0ccde438c188c8a471c4e0f457c2dd20cdbf6ea7a450046c7 \
--hash=sha256:b14b2d9dac08e28bb8046a1a0434b1750eb221c8f5b87a68f4fa11a6f97b5e34 \
--hash=sha256:bb6d88045545b26da47aa879dd4a89a71d1dce0f0e549b1abcb31dfe4a8eac49 \
--hash=sha256:bc17a677b21b3502a21f66a8cc64f5bfad4df8a0b8434d661666f8ce90ac3af1 \
--hash=sha256:bd6c2a1c7573c64738d716488d2cdd3c00e340e4835707d8fdb8dc1a66ef164e \
--hash=sha256:c03a41a8784091e67a39648f70c5f97b5b6a37f216896d44d2cdcb82615339a0 \
--hash=sha256:c35abb8bfff0185efac5878da64c45dafd2b37fb0383add1be155a763c1f083d \
--hash=sha256:c36c333c39be2dbca264d7803333c896ab8fa7d4d6f0ab7edb7dfd7aea6e98c0 \
--hash=sha256:c45e9440fb78f8ddabcf714b68f936737a121355bf59f3907f4e17721b9d1aae \
--hash=sha256:cdd68a1fb318e290a2077696b7eb7a21a49163c455979c639bf5a5dcdc46617d \
--hash=sha256:ce3412fbe1e31eb81ea42f4169ed94861c56e643189e1e75f0041f3fe7020abe \
--hash=sha256:cf1493cd8607bec4d8a7b9b004e699fcf8f9103a9284cc94962cb73d20f9d4a3 \
--hash=sha256:cf29836da5119f3c8a8a70667b0ef5fdca3bb12f80fd06487cfa575b3909b393 \
--hash=sha256:d4a48e5b3c2a489fae013b7589308a40146ee081f6f509e047e0e096084ceca1 \
--hash=sha256:d560742f3c0d62afaccf9f41fe485ed69bd7661a241f86a3ef0f0fb8b1a397af \
--hash=sha256:d6038d37043bced98a66e68d3aa2b6a35505dc01328cd65217cefe82f25def44 \
--hash=sha256:d635aab80466bc95771bb78d5370e74d36d1fe31467b6b29b8b57b2a3cd7d22c \
--hash=sha256:e044c39e41b92c845bc815e5ae4230804e8e7bc29e399b0437d64222d92809dd \
--hash=sha256:e060d01aec0a910bdccb8be71faf34e7799ce36950f8294c8bf612cba65a2c9e \
--hash=sha256:e1421b502d83040e6d7fb2fb18dff63957f720da3d77b2fbd3187ceb63755d7b \
--hash=sha256:e17b8d5d6a8c47c85e68ca8379def1303fd360c3e22093a807cd34a71cd082b8 \
--hash=sha256:e712b419df8ba5e42b226c510472b37bd57b38e897d3eca5e8cfd410a29fa859 \
--hash=sha256:e74327fb75de8986940def6e8dee4f127cc9752bee7355bb323cc5b2659b6d46 \
--hash=sha256:e8ac484bf18ce6975760921bb6148041faa8fef0547200386ea0b52b5d27bf7b \
--hash=sha256:eca9705049ad3c7345d574e3510665cb2cf844c2f2dcfe675332677f081cbd46 \
--hash=sha256:edac0f1ab77644605be2cbba52e6b7f630731fc42b34cb0f634be1a6eface56a \
--hash=sha256:effc3f449787117233702311a1b7d8f59cba9ced946ba727bdc329ec69028e24 \
--hash=sha256:f495a1652cf3fbab2eb0639776dad966c2fb874d79d87ca07f9d5f059b8bd215 \
--hash=sha256:f496c9c3cc02230093d8330875c4c3cdfc3b73612a5fd921c65d39cbcef08063 \
--hash=sha256:f59099f9b66f0d7145115e6f80dd8b1d847176df89b234a5a6b3f00437aa0832 \
--hash=sha256:f59ad4c0e8f6bba240a9bb85504faa1ab438237199d4cce5f622761507b8f6a6 \
--hash=sha256:fbccdc05410c9ee21bbf16a35f4c1d16123dcdeb8a1d38f33654fa21d0234f79 \
--hash=sha256:fea24543955a6a729c45a73fe90e08c743f0b3334bbf3201e6c4bc1b0c7fa464
charset-normalizer==3.5.2 \
--hash=sha256:01077390b03f7988f11d700a2194e69b119741a86b1a638b1db88891e3eced8e \
--hash=sha256:01b0c0d2262a9e28e8484a278c7e1b5d650e3ac8cf2683d2967e25899f208bdf \
--hash=sha256:04851f73ae72b8413dddadb16a49dfee95263553741fd42d546f7d66907e6be5 \
--hash=sha256:0521c5665880b33d603717defa76c094048900010897909952397feb3039da56 \
--hash=sha256:0774bf9bf620249fee3e0b8b9fd3065de213be30f3aa94ce2494b3b638949e26 \
--hash=sha256:0c951d5e6dd9c2ff60609476752bee49da4206adde960ebc247766937f72e718 \
--hash=sha256:0fed1d06615f022ee3b13caf5e8b180cfea32bb2c5aded8a9d44277afc040f93 \
--hash=sha256:114e4d0c92d618409ed82a99e22b5c5e768fe995f2973f78265f4524f49d4640 \
--hash=sha256:11912e4bb14baae7c5d8791aa55ba0a3a03ec6729073307b0f57270abaa713d3 \
--hash=sha256:11a4d68a6ecda3292cb1e50239e111543ba5d709bb62a6b4ea1afcfa729d8875 \
--hash=sha256:124fbf1a8ff966d87ae05bb8bd45a71f966055ed8bba320d0c7cf450bc5f4d0e \
--hash=sha256:1503bccbeb36d5527790c3930327704c39af22de3112f1b1666a9f3ce15ee204 \
--hash=sha256:15c44f7edfd477b06f517a5cc317fc1707edb9de2c865f43d4b6513907473234 \
--hash=sha256:16fa0eccf81304b79c5cd87f9271c3b85dd9dd99245e4422ae9c0dd45e0f99d3 \
--hash=sha256:183b88127acdb4fabe59d951ab424faf1af7b63cdbb5f776186c1ea2ffcaed98 \
--hash=sha256:1afb975bd5d68d5ce9f6b6d44fdf2f7e34b895a35e95708a7a91b20a3b51d187 \
--hash=sha256:1b4cbc7c3491ccb4aa17fcd8165649d01cf39f76de1696da8631b5f71b85401d \
--hash=sha256:1bc0baf5ef96b6ede57d47f4b8fe4d9d84019c3bfcbeb20a41edc6a6ee341f1f \
--hash=sha256:1c50fe28bbc2ced33386f298650d91218076c05420e6cbd790b913adc41659e7 \
--hash=sha256:1db38f4c5496827c1a501846d64d14c3b80c7e6714e406cd7dc36a9899fa1011 \
--hash=sha256:211d5a3eb6af8f513b8d4ca19a8c1b7accab1b5f0d3175f9826b03c1a920dc1f \
--hash=sha256:23851fb4e1b85ed3f6c2a27b777cdfe2e19fb5b38429a8faf38c7542b7665869 \
--hash=sha256:254eb48b9fa5ee9898a3c445825a1f340fe53712a098904b39b0bddba8ea3cb1 \
--hash=sha256:2625388c6c754520c37abaf3b41eb34d1cc4a373f457898f08606c8e362b891d \
--hash=sha256:281cb91036248400f4cc957495cccd44c275c2e0c5854f7e45ac5cf7dc193847 \
--hash=sha256:28b4f0d66fb834ff90f28209ac7bce77868c45d8c93e26f906709d9b7c2e1af9 \
--hash=sha256:2a925889534b3748302dae5dead07cc13480de1dac3aea80a941b729b471ef93 \
--hash=sha256:2b7b3bbfb4fe8ef40600792d762fbaa9057559f9d3fad209525b7a22b99e91fd \
--hash=sha256:2c9ad19a6cfcd5ea5c0d41161d22f9df1dcc277e9bef2751391334546a314c00 \
--hash=sha256:2ce45c6627b22c47e390bc91a41c3d13032192e699fa0bea96e9671b373d69b0 \
--hash=sha256:2e06a3a98f916dd41d27f3105e02e7a40181c98c94b9158733d03a6f80506c09 \
--hash=sha256:304d5463e65a35d7bb0850550e0780395395f6fcf452f04db7d5ca7cecc425ac \
--hash=sha256:304d8e4d493af723536393eee0c689eb7813f4a474c8b479dee63f1fdd98f621 \
--hash=sha256:31f3930700408d211f13378ccbe1c40845d8da54bd0681fac3a9b5aae81c7aa8 \
--hash=sha256:34276fd796040bf0993ab33a369aa572e6979c7aab225a88893667ad8eac8f7a \
--hash=sha256:355ad8011081dec5412240c087a9a0c9d4d5039f3ed11a3f13e18c2b29b56c51 \
--hash=sha256:38a873987f3be698494da8b2e3085e29da02da7b633dce73e79c699a113d7bf0 \
--hash=sha256:39de2a259fc954455c57274dc94c79d5842774e1247a016aff30bc0efed0f4ef \
--hash=sha256:3d21b8b13c7592db2ac5e544a6d83187b995257472b0c9e8351b6d507ae37ed6 \
--hash=sha256:3d31298449090ab8d47b7b1b2a555ff73cac7ed438a08b7ac160980c7ebed649 \
--hash=sha256:3df041de8887954562c9b261cba85ca0e9ded74048daf125f45edcfaa4832229 \
--hash=sha256:40ab6bffa02ae10a0581e6c198be7d2d8ca5c2a0c64e4ed3465d766df457573e \
--hash=sha256:4275811936e2f06feff5e598fb42a1b7ae852da8e39605211892b56b81a34efd \
--hash=sha256:443eae2bf318abeaf6f15d785138f71fd6de770e99a92158b8b814265e079115 \
--hash=sha256:4495c5002a7b28557e7e222e77e0b661183e432b7d6d2e788101e3f240e05b8c \
--hash=sha256:4685902cf26edf013ed7a3da0f426ebba7a00ebb9541386d835afbf002c11cab \
--hash=sha256:498dc3188ca05a68231ac3fdbfc7f57eb67e1343c30e0fea17f8218c1599b253 \
--hash=sha256:4c2b5031f63e331e3839b40aed2dd6f191e9c07edbde303e7876846ea1946995 \
--hash=sha256:4d48f2d08b9de5864e2c8744d4461b862fb149a18274abc8b698c45975573438 \
--hash=sha256:4f87960d57feabfb618e4e0af6e7371645fa26a277860739d6e5d6e0012c92f0 \
--hash=sha256:51cf45226a9b588d0d2b4880c62d686934b63ab0bd79ca23ab0e9762eb27441b \
--hash=sha256:52aa6992700996af31f375de0c6bacd402b0097fe40b53c426b9f51a90ebabc7 \
--hash=sha256:56bc200a365efb37383b7852e4cc5898d3b2da5987289b543956cf8cad71018a \
--hash=sha256:58ca3755ee7ff7f59b57789ec9833c9de9ea275405cdd240eda1f193112e398a \
--hash=sha256:58f361dcbab699cf8f42db3f47c8e7fd1036f138c23a5d08de9fde5f425a730c \
--hash=sha256:598a11a2c7ebaa5334bf698bf29568c9c390abac6a154d8170fedecd1cea38c5 \
--hash=sha256:59f63901b0031c3136cf64704dcb21de0bbae62ce2c9529bc39d27665463de37 \
--hash=sha256:5cde776b7cc66e4f6c99612cea4aa7269aa65863f7a15841b2c264f103822f4e \
--hash=sha256:5e2b6b57e9733d39f0c9fd3185efa6b8e29652c4cd8fe94180272cf6ed9a78c4 \
--hash=sha256:5fb29fb8cd1a46c27a1bf9613ad5ec2599310d46b4025d9556404a6b6a292800 \
--hash=sha256:6045373d5a89a5ec71afde535db987ca28e76dfa276c2d4c818265b375d4b055 \
--hash=sha256:62603db9a7caa0802eaa28c1c46fecd7b3a263a774069c24c3c28c302448721c \
--hash=sha256:65cd72beeeca9d3aaea1201e5923859f308f952f9c71de93f06063c79f0f7a3b \
--hash=sha256:6bd128f206a7752ae1f2ab6c61bf8a24ba28913a10df8b14c2637b973ff97a80 \
--hash=sha256:6be488a102b8cf28d0391d8c4ba7748938ae28b78ad901f8585520fca33ead1a \
--hash=sha256:7218e8f32b0956cfcd048fd42d9d5779809745ca1d86113ca56f66e7ae1549c4 \
--hash=sha256:7441d755b7ab94f8d4eb3e43ec05482d760842fd263d003a99102d742cd835e2 \
--hash=sha256:749e97e1b32313717a565abbe321bc2190bc8b35f1a67e4cdbc7c56c8d8ffe58 \
--hash=sha256:780fbe7cab297b81dad9fb8dc5eb003c0468ffb0d9e5f65068c53a34661a96bc \
--hash=sha256:78456a747de8dc58360ffa581f30a002baf5aa28cb262536545e91f113ed7639 \
--hash=sha256:7967d08cf06dee78443b874f98c98036f624f3a4e73e11f9f64f5be4d25393cf \
--hash=sha256:7a881931aa470808df94a8c380eed2bbbc76cd9dc622310f99665658c821eb6d \
--hash=sha256:7dcd882da75ef9adf94903b1e3b9419e8aa8fb4c7396822b834b9ef7fb96954f \
--hash=sha256:7e841fb9010836c992c9f12fcbd43a831de93a5f726fc1ccd8ca1d0268c5014c \
--hash=sha256:7fdde2c9fd9e3eca40631e024664cf2584272cc8f96308cbe5fdfc930f51d8bc \
--hash=sha256:8024d00c3faf3fc0c16e07a69f4405e8eac7cc0ab15f65fe6cf43827c4cf72b4 \
--hash=sha256:80d02b6f04e92601a081dd97b23d3128033098bff5d35d392ddcc0476ea11253 \
--hash=sha256:838dcc90063569a0448120554591a1d6c4a4ffe11babf048908793154ab86ade \
--hash=sha256:849df64e889b2e17230d58410a03dba311a65b163508fd33679b2b737d4b7858 \
--hash=sha256:87475fabc8d9996fd9c27debb395e642e8c838d78a00b6e932227a0e06b81e26 \
--hash=sha256:87e50a3e7cb90af586b6c5faf23e302a970415ac73bd7bd90a515a04b427ef96 \
--hash=sha256:89b53f3cda69831909888e0494f4fa0bcd3537e3e138dabeb620bd6ad946bae8 \
--hash=sha256:8d86d6fc60743dc916eb79e2eb1ec4818e21e427731543af40a3021851174a13 \
--hash=sha256:915563965d418f986e7e145accc592eae9e1a1be3566ff98a05d7a9ec42a76e1 \
--hash=sha256:92888bb3187c5ba50500b00b3b310c9f2c651709d28036077680cb5255450a03 \
--hash=sha256:9409a8bf35cf78353942504b24a57de3d75b708997a1e4bd8db71ac8633ce364 \
--hash=sha256:9b7f416ff0978e2f2249330527f0ad6fa02f4932e6199692d3b52da2048c19e4 \
--hash=sha256:9cae88599c7219005d879f98e5ed53341e9a122af585e1091200358a3003d2a0 \
--hash=sha256:9cf9b1a857e25c4baceeb3624e92a56df3668f398c4acba74e174d81fb4d1d3a \
--hash=sha256:9f56f72050826f63dcee7a7f55b0a77168cb3bfc553fd405e7f8f9ece75a4036 \
--hash=sha256:a090bb2c68df85450502e3e20d665e3a5af9c65a84d6508ed477badd49166fd3 \
--hash=sha256:a192e2c40070d92c3ccf777e3a5c4ff515573cd2bb7ed0c537fdadbbec5bbf21 \
--hash=sha256:a19a731138fc27d5682277d3b9df22855cea1239bce7fcec5f78f42ef2d1f3c3 \
--hash=sha256:a66c3bc5ab1f0ff2164fc9965ddd611ff0802173f4b9d24554c563f6ab7e1d6e \
--hash=sha256:a815775b6c38d4e0ff7bcffbeba67feded90202bb6a226b8dd35f1c855217413 \
--hash=sha256:a89012d6d5476ee112d20d998570ed58df2260a852afb1758809cd6900411d21 \
--hash=sha256:ae4f5fea5b8b8ccff88238cc8569303e5ee95efae67fa62922a311397a71f346 \
--hash=sha256:b6856554c4f44d79fc2307d5768854310a8f0096e501c75637542c82292b0429 \
--hash=sha256:b6b751274acb69d77b3323d6b7dbaa3c7fdfc1eb829b7eb61d262f32e1af9685 \
--hash=sha256:b7fd005a73d9e657273b7a10dc71a9e03c8fb9ee6999798d6918ce095b81ac7f \
--hash=sha256:b91363207bd9dc966a691e959bb47f64b30f7ac4b072be9968b366982f7db77c \
--hash=sha256:ba0b1d2620edf869789c3879223f52bf2afc5d31b3cb47cc57b3a12c05e2aa9d \
--hash=sha256:bbbfc8e28816f19d7c0f1816664980c0a9875d01b27cdf8eedddb639d9e108ad \
--hash=sha256:bd16aabe4a02a297c23417aa17ac6299dbd8c49f673bcd645b4929b11f5a4400 \
--hash=sha256:c0afc6800ba57ccc350374c5bd6150419915d95ce93cdbab2d783d75eaf30ecb \
--hash=sha256:c7c9ab723cde841fefb34efbad91e87f00a674b1fe1cd0784fde742bf2c154dc \
--hash=sha256:c8f3d67aeaf55f017982b73683f0e7342ba2f6635a78f69ce89ebb26aa411e5c \
--hash=sha256:c9790464842f85f437dbbb54417eda1e0e6bfc52dd8d22d6fd1c994b73b2dc74 \
--hash=sha256:ca403d7e4798f525fdfc78e258820419cbbd0f0ecbab9de7840e3c017cf6b8cf \
--hash=sha256:d008d90a7f2471519aef0c90dfbe73b3e6e4d5e66ac48e19154c17e89e98b604 \
--hash=sha256:d19fbd981a488e22cd04883659ca6b08f50b5974f9fd7c95655ef6a043e5893f \
--hash=sha256:d1befeed746d247c81127bb14de9dc3d30edb6e5976d34f83f86ed262b1d9105 \
--hash=sha256:d2374b62878abb00cd8309b32af6c0b715cd02dec0ca74ef12e5069bdc64144a \
--hash=sha256:d376bbd28b3a8999db1a103b3b388aee6f1ddeb3e51bc2172993efdcd86e064d \
--hash=sha256:d6734d2ef8a50fbf8445c139477da401f50d62a0606bf00e20ec6d87773fefb1 \
--hash=sha256:d760fe2a4d7c3b226cb9026d6a842868d52a7901bd98420e1baf14e80da85cf5 \
--hash=sha256:db19d07e2e0129e974a0e65d0064fc222a446cd5122c2fd4184d2af9fc734a9e \
--hash=sha256:dca9ab98072a5a54ebacebdc45f53e645336b320c667410b061be1ca588ae709 \
--hash=sha256:ddc7dacc8ece3a182e7f15cb862d1fd616b46d076cb1ae9dd232b2c38b655874 \
--hash=sha256:def79fa35ef0cef8d2accec024f4fdc7ead3012ff02f5215c783f39f03ef8cfc \
--hash=sha256:df29a0a7107f7011e77f4eebdddec4c7331e24d787a0b21a46d63bdf7445da95 \
--hash=sha256:e09a3942ecbdee5cce73ea9d42da82b81b72ac1bf031ce069b93b5adf4eac8cd \
--hash=sha256:e242bb1c5e76e97dfa9e7f209a71e93a01d7f19ffdd5cfbb2e2d55b4f08f8ab0 \
--hash=sha256:e243bd13217235fc7290c621941c3f5cc8b66e4872495be821d7436ba2fb838d \
--hash=sha256:e2af3aad578aa6bd1384bcf4750fc285e5a9de53f40b7d41e5a0bf748edeb2b3 \
--hash=sha256:e4e81e09c1578b8df602e3db08b0b3ea0a6947ad612f52bf8dc5ea8d47691f0c \
--hash=sha256:e54da4baf05720032d527874d40b65fa4d7e5c6c6a43d0c3adbeffcaf275a2b3 \
--hash=sha256:ed2a239c0ea213acc1908150a3037257083c7c083128f1a4cec2ec4b97dca491 \
--hash=sha256:ed905975ab14056a2e5eb1c376cb2e1ebc5396baf84163939c518556fccde9f5 \
--hash=sha256:ee21e28f0430bd6dc9086c6e525d5e818a44a5ad19720c8a0ef766792f3eb5e5 \
--hash=sha256:ee43c17b173d46a3212baa6ead3ae258eeabdae48c263a01ccf0218c366dd655 \
--hash=sha256:ef4fcbf3327382cd4c9f540babd61248208af7b93eec4de397b4d5f58a09e288 \
--hash=sha256:eff0ac9dbe711a4aee69bf04a83896aa9b85f19641264053a9f6d48573abb7dd \
--hash=sha256:f0aa869112ef88429ae17820d99c3dd9504c9e9c671d3c246f3d7442cb051084 \
--hash=sha256:f3c96f633825733f735c5a9cf21d21a257d8e1edf0b1cee0a064b9c424ca0f7d \
--hash=sha256:f5ec61164adcec446f8969a3358ec3f9b26bbda3b9213e5586d219afa8df2915 \
--hash=sha256:f7d486c83842422badd511868fd8a9a20e9407ace71564b6af47ce7e60a336c1 \
--hash=sha256:fb9e68df06293761f9fe66ade60a9bc6d0f5e42b8acf2939a9158af86ab0e5bd \
--hash=sha256:fcff63213e8e6e47770541a4607175404f47cbb3ebea7b6058cc82d524a0e424 \
--hash=sha256:fe9753dfee015c570d73df76f899f18444d41388bffcde097deba51c4fadbb9f
# via requests
delocate==0.13.0 ; sys_platform == 'darwin' \
--hash=sha256:11f7596f88984c33f76b27fe2eea7637d1ce369a9e0b6737bbc706b6426e862c \
--hash=sha256:a93e67a9f56ee01a3f7096a042231d4ac37fecac873cd5ea34ea2b4f43a8fa13
idna==3.18 \
--hash=sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2 \
--hash=sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848
idna==3.20 \
--hash=sha256:a7db850025b95ded1eae8a46181a1a6c56c92c96f0e2b005d9ff8dc0210cab44 \
--hash=sha256:ab7ae7122974553370f0bdb919e1a960b2cd1bc1ef0276416d896db81c14582c
# via requests
macholib==1.16.4 ; sys_platform == 'darwin' \
--hash=sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea \
@@ -194,21 +265,13 @@ macholib==1.16.4 ; sys_platform == 'darwin' \
# via
# delocate
# pyinstaller
markdown-it-py==4.2.0 ; implementation_name == 'cpython' \
--hash=sha256:04a21681d6fbb623de53f6f364d352309d4094dd4194040a10fd51833e418d49 \
--hash=sha256:9f7ebbcd14fe59494226453aed97c1070d83f8d24b6fc3a3bcf9a38092641c4a
# via rich
mdurl==0.1.2 ; implementation_name == 'cpython' \
--hash=sha256:84008a41e51615a49fc9966191ff91509e3c40b939176e643fd50a5c2196b8f8 \
--hash=sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba
# via markdown-it-py
mutagen==1.48.1 \
--hash=sha256:4f077fe87d3fc7fba259aa63d8c026b18382ca6a42ef37c61e16f1b1b5b82fe7 \
--hash=sha256:8f95637ab9f6f305cec6bd1294e197debe207998e3e068596563c74f86b0a173
# via yt-dlp
packaging==26.2 \
--hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
--hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
packaging==26.3 \
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
# via
# delocate
# pyinstaller
@@ -217,60 +280,60 @@ pefile==2024.8.26 ; sys_platform == 'win32' \
--hash=sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632 \
--hash=sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f
# via pyinstaller
pycparser==3.0 ; implementation_name != 'PyPy' \
--hash=sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29 \
--hash=sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992
pycparser==3.11 ; implementation_name != 'PyPy' \
--hash=sha256:51d5a8ba2be0bbe440b99d2112604c95bbbc3c2748a64260186c541e1729cd80 \
--hash=sha256:d875f09c3507d00e1aba0eecc6dcadc1352f30fff09dc6bff2f1c2935e97c2bc
# via cffi
pycryptodomex==3.23.0 \
--hash=sha256:02d87b80778c171445d67e23d1caef279bf4b25c3597050ccd2e13970b57fd51 \
--hash=sha256:06698f957fe1ab229a99ba2defeeae1c09af185baa909a31a5d1f9d42b1aaed6 \
--hash=sha256:14c37aaece158d0ace436f76a7bb19093db3b4deade9797abfc39ec6cd6cc2fe \
--hash=sha256:189afbc87f0b9f158386bf051f720e20fa6145975f1e76369303d0f31d1a8d7c \
--hash=sha256:43c446e2ba8df8889e0e16f02211c25b4934898384c1ec1ec04d7889c0333587 \
--hash=sha256:4f2596e643d4365e14d0879dc5aafe6355616c61c2176009270f3048f6d9a61f \
--hash=sha256:52e5ca58c3a0b0bd5e100a9fbc8015059b05cffc6c66ce9d98b4b45e023443b9 \
--hash=sha256:55ccbe27f049743a4caf4f4221b166560d3438d0b1e5ab929e07ae1702a4d6fd \
--hash=sha256:58b851b9effd0d072d4ca2e4542bf2a4abcf13c82a29fd2c93ce27ee2a2e9462 \
--hash=sha256:6b8962204c47464d5c1c4038abeadd4514a133b28748bcd9fa5b6d62e3cec6fa \
--hash=sha256:6bbcb1dd0f646484939e142462d9e532482bc74475cecf9c4903d4e1cd21f003 \
--hash=sha256:71909758f010c82bc99b0abf4ea12012c98962fbf0583c2164f8b84533c2e4da \
--hash=sha256:7b37e08e3871efe2187bc1fd9320cc81d87caf19816c648f24443483005ff886 \
--hash=sha256:8a4fcd42ccb04c31268d1efeecfccfd1249612b4de6374205376b8f280321744 \
--hash=sha256:91979028227543010d7b2ba2471cf1d1e398b3f183cb105ac584df0c36dac28d \
--hash=sha256:a33986a0066860f7fcf7c7bd2bc804fa90e434183645595ae7b33d01f3c91ed8 \
--hash=sha256:a9d446e844f08299236780f2efa9898c818fe7e02f17263866b8550c7d5fb328 \
--hash=sha256:b2c2537863eccef2d41061e82a881dcabb04944c5c06c5aa7110b577cc487545 \
--hash=sha256:bc65bdd9fc8de7a35a74cab1c898cab391a4add33a8fe740bda00f5976ca4708 \
--hash=sha256:bdc69d0d3d989a1029df0eed67cc5e8e5d968f3724f4519bd03e0ec68df7543c \
--hash=sha256:c25e30a20e1b426e1f0fa00131c516f16e474204eee1139d1603e132acffc314 \
--hash=sha256:c7947ab8d589e3178da3d7cdeabe14f841b391e17046954f2fbcd941705762b5 \
--hash=sha256:c885da45e70139464f082018ac527fdaad26f1657a99ee13eecdce0f0ca24ab4 \
--hash=sha256:da4fa650cef02db88c2b98acc5434461e027dce0ae8c22dd5a69013eaf510006 \
--hash=sha256:ebfff755c360d674306e5891c564a274a47953562b42fb74a5c25b8fc1fb1cb5 \
--hash=sha256:eca54f4bb349d45afc17e3011ed4264ef1cc9e266699874cdd1349c504e64798 \
--hash=sha256:f489c4765093fb60e2edafdf223397bc716491b2b69fe74367b70d6999257a5c \
--hash=sha256:fdfac7cda115bca3a5abb2f9e43bc2fb66c2b65ab074913643803ca7083a79ea
pycryptodomex==3.24.1 \
--hash=sha256:03e2027f81fe6b700e7ff614d79111559bfb05ed8c4a9de9d2152d1a0a0768de \
--hash=sha256:09081666ffc599976c0b8b29caf2cf82212c0f05bed233c8f8ed53e4f6e1d356 \
--hash=sha256:147c742f73bbe8791d8c454b9972330d7ea501de94e8172957af375f9bdb4a7f \
--hash=sha256:3bbcc1807502da4b5d66c94357a99589c8547aa9ad2f9ecfa537b2e9a347538b \
--hash=sha256:48d9058dd4c8f3af83e048b6ff83d9c6300841c42579f77fdfab19e49156a512 \
--hash=sha256:514d685de4b0227d35d7114047fbd575bf162bff373e07af665aa41eee089dd0 \
--hash=sha256:569fdbeff936cbd5beb852b3969dc2f58fb255bd221b3f7a8999c035c30ec958 \
--hash=sha256:5966f829f64c833cc72a8694cfee05ad50446a44167842c92dec4ebf6b84d72c \
--hash=sha256:5b37b86a3771d6aa21cccf9f8448460e4be11e68bb8e699133ce632cb986f521 \
--hash=sha256:6159dc74824c591b4c294f8f96b74a71c3b5e9f637dab2f2da14cfa32dc24d47 \
--hash=sha256:77ef934c2b2eab3c57a431daf858fcbf272134691bcc8d729787d17ad4cbf758 \
--hash=sha256:794f32227a480ab3b39971ac4a53dfa8ed444e28c0ddecbdc35f26d038bb46da \
--hash=sha256:7a81e9be7084af3591912475b22c5d0646a9160f3974b6b7300138781fffdc0d \
--hash=sha256:7f30261641dac5ae60e0af2fb11ad7c87200575b0ce403f7531576b0f38a52be \
--hash=sha256:82eb0dd8a95be97f03527b108ee49f9b86a7c534fa47fa7a510be3eab8ea9acd \
--hash=sha256:8321c315c4418dfe45a811b792380438ec81185deaaf202dbcd77711b4f51796 \
--hash=sha256:9a732b9f5603b153dcdc071d6b342f192981907519827f2c1e4aeac41e2b34c2 \
--hash=sha256:9b94a8c647c1f80b4c82c7ac9642dda94a71abbb4efa29ad652c410ad7a39879 \
--hash=sha256:9bb353c764c144a9fc03302ef3763ad0c3e75bc7ca41f445cc98455f36da6c59 \
--hash=sha256:9dd5104a1d8ccf725a3c1b40b21d5ed47530b6499abba30955c174d895c1be2f \
--hash=sha256:a692d2484ca8fa2c69f45c63f2b30cd00b8512834e3a522fc297d981dde5b34c \
--hash=sha256:b1c7a61b0b644e9780aa9f6eee301fb77c813b1e41262f6f4f387de0558e8926 \
--hash=sha256:b299a1c10e45e1b71b34b048d555d3a8f366240942af89be5db379f88edb9542 \
--hash=sha256:bd06ab1d9cf90e8b198daae3b364e9ac23a640d210bb8faddad6627cf2e33be7 \
--hash=sha256:c20fb5e8cf874dc182091d6df122b8b588501d23e7b500acf662c49899afdd0f \
--hash=sha256:cc64f4e1fc07a155ef31eb9815183a6a8eb13dfd6876ab049c01125223aa0c40 \
--hash=sha256:cdec09935db4cbd74da5b577ea7d9959c73374060b22abf7d505429c0da7ed63 \
--hash=sha256:e87928d8f37952ba53d215836cb3d89c63c1367f037d055c3a5b3f4403f4c6b6 \
--hash=sha256:edc1deb28fceab6b78e12bae506eaef62ee2fc1b3cabc96f7932f0d51e368acd \
--hash=sha256:eeac2c9acbd2d9f0ca493fdf692ce8245ca37cbebee08c496025868d4b8ef70f \
--hash=sha256:f3ed97cdde1d96894057778095238bad3dd94d3e46dc07d6d618e6d4b7700cce \
--hash=sha256:f87d74a804ca949f46a6babe70247a789f6401f229566e90174c4b7033b87cc5
# via yt-dlp
pygments==2.20.0 ; implementation_name == 'cpython' \
--hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \
--hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176
# via rich
pyinstaller==6.21.0 \
--hash=sha256:327d132389f37912609e01be62810cf96b5aa95b613903e4b8692e0d12fb0eda \
--hash=sha256:42395ec76df8e8120c36b13339d9db8cab83e316a12839ee303cc00fc941bb74 \
--hash=sha256:4e3108b3f02384560da70e39b8bf22b0ad597d02bd68a40d76ea91c1cfa00cad \
--hash=sha256:5fa56746c1e76f93634d018502301378a2d0c382553d37d8c3c34ff436c12dd1 \
--hash=sha256:605169523a6b5ace39f13dfbff21add9f2bc43df99c7daf9394fefb2c45e8b6f \
--hash=sha256:697532279f535ad572bda613db4f821540e235c7854ca6da4d3bf0373f4415ee \
--hash=sha256:6b6374d652107dd4a2eeece903ff82bb4045bb5e1006c5a158a6dcdbefe84bf2 \
--hash=sha256:7071d4b094d5b40deeef5fa3d3b98a1b846087f7562b49209663d5f9281fe251 \
--hash=sha256:7fae06c494ce0ebfe6bd3055c0e409def884f63af2e3705d06bd431ad9237fc7 \
--hash=sha256:bb9fab705983e393a2d1cac77d6972513057ad800215fd861dc15ff5272e98fd \
--hash=sha256:c6b28d30d8fd99ce162ff3aab5013ed44dbfb747566b1f01b9bed7964d7c14e9 \
--hash=sha256:f13c95c9c03fb567217135919f93815c305813126780b0ed6e0123cb8acaf025
pyinstaller-hooks-contrib==2026.6 \
--hash=sha256:bef5002c32f4f50bd55b005da12cff64eca8783e7eaf86a06a62410164bab725 \
--hash=sha256:fd13b8ac126b35361175edacd41a0d97080b75dd5f4b594ecefefff969509dd3
pyinstaller==6.22.0 \
--hash=sha256:0a20c37761851100f422ec261f513f46d8e57100ea22886b9ff7a6c346104bd8 \
--hash=sha256:6e5f3656de100954bf5db25536c43e097e46d482843a96d03a0852bf266e4853 \
--hash=sha256:6f527c1345d5010682587aebc2f0c1cc34a9b1f200424969c7bfda723cddc074 \
--hash=sha256:7885de3c830356b0990b27fe164f2b008fb4a18560bac884cf33985f61469f44 \
--hash=sha256:81dc305c16510c1f9ead6d115b66f381e3d3453ecb96653099c51aa3050420d1 \
--hash=sha256:8b0166fff4583b374bbe7fa044bf03ddc33cab0f792a665807d96048e63f060e \
--hash=sha256:b07ac9fd1d661ae4d0af6752c3941e4e5576a16cfe7e2d6504a32d57e17d0acc \
--hash=sha256:b1233da63926be213cdfbfbb314735bc7762136ed772b1082e1b0a2d7ed896b5 \
--hash=sha256:d7c7c5b149f7f9b37585b37e2376f774038b6a5633ba34db0de2698f75391e13 \
--hash=sha256:e6859e80b9c7dccb8a1687c5ed4644a722b370c2aa13e8a9ca5ebf5f9bb842ce \
--hash=sha256:f6c750c8ae999cc5520ddbce4263ac3ece96db04ba359ef20acacd81bccc201b \
--hash=sha256:f92f78a9c463b884d57f90c7459c0cb263ccd26a499356bbfac7a5f41fd5b93f
pyinstaller-hooks-contrib==2026.8 \
--hash=sha256:4d825786ad7a9b7dbcc52d612748a34562fe273461bcfd88f4d549c594bbf8f9 \
--hash=sha256:6d21d65323ea4467753afc21f52d7d0e69416ae8101dd88269bf273ad48db084
# via pyinstaller
pywin32-ctypes==0.2.3 ; sys_platform == 'win32' \
--hash=sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8 \
@@ -280,86 +343,175 @@ requests==2.34.2 \
--hash=sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0 \
--hash=sha256:f288924cae4e29463698d6d60bc6a4da69c89185ad1e0bcc4104f584e960b9ed
# via yt-dlp
rich==15.0.0 ; implementation_name == 'cpython' \
--hash=sha256:33bd4ef74232fb73fe9279a257718407f169c09b78a87ad3d296f548e27de0bb \
--hash=sha256:edd07a4824c6b40189fb7ac9bc4c52536e9780fbbfbddf6f1e2502c31b068c36
# via curl-cffi
setuptools==82.0.1 \
--hash=sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9 \
--hash=sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb
setuptools==84.2.1 \
--hash=sha256:3ff8b3b5492a0aa66960f4419365a86b84e013070d4313e4d4a6894f5d64d6bc \
--hash=sha256:ca140b45d5325a9478f880e351484f62fef15f336462e449ca0c03c873d589c2
# via pyinstaller
typing-extensions==4.15.0 ; sys_platform == 'darwin' \
--hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
typing-extensions==4.16.0 ; sys_platform == 'darwin' \
--hash=sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8 \
--hash=sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5
# via delocate
urllib3==2.7.0 \
--hash=sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c \
--hash=sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897
urllib3==2.8.0 \
--hash=sha256:0cf3cae568d36aa9576b28dfb35f11328f1cb974ca7647d9475ebb86c75ac6e3 \
--hash=sha256:63bf2ead4c879426ebf22ef2a781eeb4aa3b4ae798a0435506f8687fd5bb9b63
# via
# requests
# yt-dlp
websockets==16.0 \
--hash=sha256:0298d07ee155e2e9fda5be8a9042200dd2e3bb0b8a38482156576f863a9d457c \
--hash=sha256:04cdd5d2d1dacbad0a7bf36ccbcd3ccd5a30ee188f2560b7a62a30d14107b31a \
--hash=sha256:08d7af67b64d29823fed316505a89b86705f2b7981c07848fb5e3ea3020c1abe \
--hash=sha256:152284a83a00c59b759697b7f9e9cddf4e3c7861dd0d964b472b70f78f89e80e \
--hash=sha256:1637db62fad1dc833276dded54215f2c7fa46912301a24bd94d45d46a011ceec \
--hash=sha256:19c4dc84098e523fd63711e563077d39e90ec6702aff4b5d9e344a60cb3c0cb1 \
--hash=sha256:1c1b30e4f497b0b354057f3467f56244c603a79c0d1dafce1d16c283c25f6e64 \
--hash=sha256:2b9f1e0d69bc60a4a87349d50c09a037a2607918746f07de04df9e43252c77a3 \
--hash=sha256:31a52addea25187bde0797a97d6fc3d2f92b6f72a9370792d65a6e84615ac8a8 \
--hash=sha256:32da954ffa2814258030e5a57bc73a3635463238e797c7375dc8091327434206 \
--hash=sha256:335c23addf3d5e6a8633f9f8eda77efad001671e80b95c491dd0924587ece0b3 \
--hash=sha256:3425ac5cf448801335d6fdc7ae1eb22072055417a96cc6b31b3861f455fbc156 \
--hash=sha256:349f83cd6c9a415428ee1005cadb5c2c56f4389bc06a9af16103c3bc3dcc8b7d \
--hash=sha256:37b31c1623c6605e4c00d466c9d633f9b812ea430c11c8a278774a1fde1acfa9 \
--hash=sha256:417b28978cdccab24f46400586d128366313e8a96312e4b9362a4af504f3bbad \
--hash=sha256:485c49116d0af10ac698623c513c1cc01c9446c058a4e61e3bf6c19dff7335a2 \
--hash=sha256:4a1aba3340a8dca8db6eb5a7986157f52eb9e436b74813764241981ca4888f03 \
--hash=sha256:50f23cdd8343b984957e4077839841146f67a3d31ab0d00e6b824e74c5b2f6e8 \
--hash=sha256:52a0fec0e6c8d9a784c2c78276a48a2bdf099e4ccc2a4cad53b27718dbfd0230 \
--hash=sha256:52ac480f44d32970d66763115edea932f1c5b1312de36df06d6b219f6741eed8 \
--hash=sha256:5569417dc80977fc8c2d43a86f78e0a5a22fee17565d78621b6bb264a115d4ea \
--hash=sha256:569d01a4e7fba956c5ae4fc988f0d4e187900f5497ce46339c996dbf24f17641 \
--hash=sha256:583b7c42688636f930688d712885cf1531326ee05effd982028212ccc13e5957 \
--hash=sha256:5a4b4cc550cb665dd8a47f868c8d04c8230f857363ad3c9caf7a0c3bf8c61ca6 \
--hash=sha256:5f451484aeb5cafee1ccf789b1b66f535409d038c56966d6101740c1614b86c6 \
--hash=sha256:5f6261a5e56e8d5c42a4497b364ea24d94d9563e8fbd44e78ac40879c60179b5 \
--hash=sha256:6e5a82b677f8f6f59e8dfc34ec06ca6b5b48bc4fcda346acd093694cc2c24d8f \
--hash=sha256:71c989cbf3254fbd5e84d3bff31e4da39c43f884e64f2551d14bb3c186230f00 \
--hash=sha256:781caf5e8eee67f663126490c2f96f40906594cb86b408a703630f95550a8c3e \
--hash=sha256:7be95cfb0a4dae143eaed2bcba8ac23f4892d8971311f1b06f3c6b78952ee70b \
--hash=sha256:7d837379b647c0c4c2355c2499723f82f1635fd2c26510e1f587d89bc2199e72 \
--hash=sha256:86890e837d61574c92a97496d590968b23c2ef0aeb8a9bc9421d174cd378ae39 \
--hash=sha256:878b336ac47938b474c8f982ac2f7266a540adc3fa4ad74ae96fea9823a02cc9 \
--hash=sha256:8b6e209ffee39ff1b6d0fa7bfef6de950c60dfb91b8fcead17da4ee539121a79 \
--hash=sha256:8cc451a50f2aee53042ac52d2d053d08bf89bcb31ae799cb4487587661c038a0 \
--hash=sha256:8d7f0659570eefb578dacde98e24fb60af35350193e4f56e11190787bee77dac \
--hash=sha256:8e1dab317b6e77424356e11e99a432b7cb2f3ec8c5ab4dabbcee6add48f72b35 \
--hash=sha256:8ff32bb86522a9e5e31439a58addbb0166f0204d64066fb955265c4e214160f0 \
--hash=sha256:95724e638f0f9c350bb1c2b0a7ad0e83d9cc0c9259f3ea94e40d7b02a2179ae5 \
--hash=sha256:9b5aca38b67492ef518a8ab76851862488a478602229112c4b0d58d63a7a4d5c \
--hash=sha256:a069d734c4a043182729edd3e9f247c3b2a4035415a9172fd0f1b71658a320a8 \
--hash=sha256:a0b31e0b424cc6b5a04b8838bbaec1688834b2383256688cf47eb97412531da1 \
--hash=sha256:a35539cacc3febb22b8f4d4a99cc79b104226a756aa7400adc722e83b0d03244 \
--hash=sha256:a5e18a238a2b2249c9a9235466b90e96ae4795672598a58772dd806edc7ac6d3 \
--hash=sha256:a653aea902e0324b52f1613332ddf50b00c06fdaf7e92624fbf8c77c78fa5767 \
--hash=sha256:abf050a199613f64c886ea10f38b47770a65154dc37181bfaff70c160f45315a \
--hash=sha256:af80d74d4edfa3cb9ed973a0a5ba2b2a549371f8a741e0800cb07becdd20f23d \
--hash=sha256:b14dc141ed6d2dde437cddb216004bcac6a1df0935d79656387bd41632ba0bbd \
--hash=sha256:b784ca5de850f4ce93ec85d3269d24d4c82f22b7212023c974c401d4980ebc5e \
--hash=sha256:bc59589ab64b0022385f429b94697348a6a234e8ce22544e3681b2e9331b5944 \
--hash=sha256:c0204dc62a89dc9d50d682412c10b3542d748260d743500a85c13cd1ee4bde82 \
--hash=sha256:c0ee0e63f23914732c6d7e0cce24915c48f3f1512ec1d079ed01fc629dab269d \
--hash=sha256:caab51a72c51973ca21fa8a18bd8165e1a0183f1ac7066a182ff27107b71e1a4 \
--hash=sha256:d6297ce39ce5c2e6feb13c1a996a2ded3b6832155fcfc920265c76f24c7cceb5 \
--hash=sha256:daa3b6ff70a9241cf6c7fc9e949d41232d9d7d26fd3522b1ad2b4d62487e9904 \
--hash=sha256:df57afc692e517a85e65b72e165356ed1df12386ecb879ad5693be08fac65dde \
--hash=sha256:e0334872c0a37b606418ac52f6ab9cfd17317ac26365f7f65e203e2d0d0d359f \
--hash=sha256:e6578ed5b6981005df1860a56e3617f14a6c307e6a71b4fff8c48fdc50f3ed2c \
--hash=sha256:eaded469f5e5b7294e2bdca0ab06becb6756ea86894a47806456089298813c89 \
--hash=sha256:f4a32d1bd841d4bcbffdcb3d2ce50c09c3909fbead375ab28d0181af89fd04da \
--hash=sha256:fd3cb4adb94a2a6e2b7c0d8d05cb94e6f1c81a0cf9dc2694fb65c7e8d94c42e4
websockets==17.3 \
--hash=sha256:018fab26140ce221c3853454a608e4e7004f4f10641cb97819dcd5b917bb2e99 \
--hash=sha256:07246d4f0293ef0b87eff3d7dd88c1f03dd9f678fa39f6de87b2af8504e7e0de \
--hash=sha256:078d1d41f45ee34eed5a4f3bbe7c588caecbdd6e12dfca73e8c1b0e803773793 \
--hash=sha256:0824e6ecee838cc28e6481062574c7fde49f9a2cedfacd36f0e91cb4b37fd6fe \
--hash=sha256:09f007b2150eff015b2109f006e2ac2012d376f41486defa88ae78a776b00cff \
--hash=sha256:0a0bcf66289b9d017c175562c35c5304b5cc3ed56aded994ae30b0a9654ba405 \
--hash=sha256:0a657b51e4a5f4ac577c11e706ff9a884ea5aaf3e2666bae283a251c63e66acb \
--hash=sha256:0c63ad657695e8f1a48624754cb6b464118ac50d4c1d477c26461c98390f0a62 \
--hash=sha256:0d20d6ea5aabbeba2e054d33e405192ef75dc12947bbd00ec97d23b14969d325 \
--hash=sha256:0e65260a1b1d7b81651f47343d836de70b88b02358ae3658efa6382104ec37b1 \
--hash=sha256:0f78bb2e82fe88912c9d7b25c98e57a9b08655579af89f164fd4c0657a075d62 \
--hash=sha256:10b24e836ee0233ca078e1244f6ba40343a22127a9a736f46a7e7b18de2cc711 \
--hash=sha256:13cffaedde6e06183860fc92d88fe1d190abda73837fe4c14f5d4803c472f5dd \
--hash=sha256:13eace1b315345ebac5b27821f5dcce24e5cf9976ab18f79e00a59bdd67e5d19 \
--hash=sha256:15decc0fe293d9e3f924bd483f3d76f3d0ff26845112a470e3f8842fec2c82a1 \
--hash=sha256:1c7dd93a1c9f89297471493674b1fc1d9467cafd45374f2172213046bdb3a329 \
--hash=sha256:1dae5cd6c92d4440b15f20aa2987baa73c47ea14baa0fec8536a542e82e0ab33 \
--hash=sha256:1db2604e6aedb7a2cb2f6e0575d6c9a852ccac8239703a930ac83b63309177a5 \
--hash=sha256:2129c9a5fc05a230ce088745a790af073e582b584badc7b05db067ee326f56d7 \
--hash=sha256:23046098ebf844753cfd211033624a8247520e5bf2194c24cb1a8c222917acff \
--hash=sha256:23cb6f6d64e3a389bb8ba150f947f9a6c8c0aca383e814ca3c5cffab738d5646 \
--hash=sha256:26838e2d95d7004c52e8c7b6b51676c872093a3b55a497824f899116a15a8a55 \
--hash=sha256:2789d203babb6ceb2770aadc2394c1f99263ec37fba57a93064f9a8ad899e8ff \
--hash=sha256:28d1935c16782a1e3650c9baa79069b016fff739e292e4cb14bbb830d6930491 \
--hash=sha256:29b01520c39ef2f23c88b002f11e6ef4165675f6c92f5f3578fd587d69b5a5fc \
--hash=sha256:2a377c7132b1e69be7a50d7434d7f26f69e93c70166ebb6d8f8cabf802ac4506 \
--hash=sha256:2b06213c8e1ce93b18d0476d7a5e647436c8f23d099888c9065e930e80f4bed5 \
--hash=sha256:2c460aeb12c2bd1c204944d9e9199595bf9e505eb542018d304bf9e63cb60cad \
--hash=sha256:2d08ca4bf5a9cdb6fd81b86b51bd5cfb10527d3a1199888f2b02cc6c6a3d5f80 \
--hash=sha256:2d875224bac1a05a20acade268a7a0e3498e7f8cf890acb7c2b23bacd2bd3659 \
--hash=sha256:2e99440ef446c7833690c1754e23b0188d440f3cb89812b0764c697a7880cb33 \
--hash=sha256:2fa79b9a48ae59744316c71a34cb9f76f30c93e117338522c5135cb7eac10351 \
--hash=sha256:32029441af953e980b9940f042b337fe4ad9a97fa8b17a4ed878ec67b5b89ef4 \
--hash=sha256:33221e49be79d7bfe6d12bc52ef9458b256ab74fa8ac5660acfa3065de1c7870 \
--hash=sha256:34c78052277053bcb09810ac8e9ba4029f9e3e277833fc18ec1c928a6246ac91 \
--hash=sha256:35381b575f70a08d4241e73c0cde4672bb9b2a9aae8767ca6b7fb61305a052c8 \
--hash=sha256:35fe35d20baa661cef4a12ee7bc42eaf2376d43ef9816ab29dd47ca957f7a73a \
--hash=sha256:39f532fa0d9026de4b9315a175998646112776baad54d55348435c11b05d034e \
--hash=sha256:3c4f631dc8d00e470cde3ec0a35d4b58a817bea592411956f1cf4099dbb306b3 \
--hash=sha256:3d78d93846eddc990551c1c31914d90d71957ca3af468969826f7ed0d7d1d51c \
--hash=sha256:411aa0fb234f42a1444dea1e177890ddfc577b36ffdfafec25cb0d2c818e1af8 \
--hash=sha256:41665c7ea01d3ae497a0c61fd22d3424230d18782a5fceb79f04db9ccb2042c9 \
--hash=sha256:4170556762c6fd2913d99dfdd8dbb4c927584899df7facb1034627e355263c45 \
--hash=sha256:43f270a5f21e12db08c73d83849a877c02ab7b7d0fb6e2718b5101d9c810212f \
--hash=sha256:443fa28652682d2a3ec3eca49af1b87cb2523561257683e62e03a98967b22138 \
--hash=sha256:45cc1ccb12ced6d242335159e8221733c8696da5ad0b6ceef6debb0f5ce89110 \
--hash=sha256:46ae05aa1aecd47d4d7de0f05ce2d1d2eb418f8de614964d754cc3b9a409c400 \
--hash=sha256:49fb5b4960ebe1bc557b435da8687deef1302a08f030a33c5606fa6fb11b773b \
--hash=sha256:4a9133dbaedc6f1af358127275676171d9a1bb3e61f47ee62b2ff9acb78af3d0 \
--hash=sha256:4aa85b34c21cf97b3470793d0bf0763d32bfd1e67b83067a0a3ba8dc3474dacf \
--hash=sha256:4d5f2492cb2192aab2d42e57f2caa2159b4fd20fde06f859ec13354f524b176c \
--hash=sha256:4e7b5d23ef144b32645d97bd99f382c4394c443395f45fe1576786838d26e308 \
--hash=sha256:4f7431e71072962d3ed1768038200aa4f1e76d9c2d7bedd554d57a55faaf6644 \
--hash=sha256:508775efa11d26aec186d10154359f52276e2baf9ca201b52356330883276dfd \
--hash=sha256:5142798871a248b422f353e0684d51dfa119de3403a6fa0904b7cb806d9790ce \
--hash=sha256:52a2ca6f401fb49a8d5d9e0e48ade5f58f1bdda33132907b0e4e3b702628fa4e \
--hash=sha256:53209dffd91b0aefed9ea630fa6ad5c2944d6210ba3a8a3a8664dc1575289b14 \
--hash=sha256:534ed583fd4323de45d196535a444cebd1af2105e6e4e0cdcbf8cea266a8747a \
--hash=sha256:54fcd24944e6d127d198c28dc363967b7131ff0c97833962c2ef2048018de02d \
--hash=sha256:55494475206113dbaf731dc8c5ffd5e1094175b753b7bbaad09fe3d7df61165c \
--hash=sha256:5670a762c7ae388bf8aa04199fd436180a4d28318dca9c1eae7b38604676dbfd \
--hash=sha256:56a76556ab04ab54a675acce2cac8b4e74ea2cec558a7c9ed37e0367b04b5d50 \
--hash=sha256:56d43c311f3519fb1057b6114dc24e9060bc3fb6aedf4aa11160484154b66b63 \
--hash=sha256:5868a02c4f6d698ddd19b4c9742748c03dec045289915806845189d96bc3d314 \
--hash=sha256:58e5d1e935a90878a935c7d2737a25c71cf4f1c13b6e6bef454ab722c4f338bb \
--hash=sha256:5ad409b7ea102339041281117cf2dadfe71edbb653dc48037cc55d516fb7f448 \
--hash=sha256:5af7070d80d278832cbca9c3c3dd44b30a26dcfa3ae1e0f6f19ff34edc27b689 \
--hash=sha256:5d0c871efc696ef5eb8514df64b86ab28736db753ebb42a2101f3b562f4849c0 \
--hash=sha256:5e0c0ed37472c4729f3001066510a656486f08f149dda1ebfd3dfe4450c9756e \
--hash=sha256:5e1c174b366565e101f903f9d1cc96d5508f805759dd37d012743f1c73ec0d7b \
--hash=sha256:62059d739af7fc035ed6e63c5390118a60a5e9aa5a5541cd0486a83e741842c7 \
--hash=sha256:623d4b44f64efdf235b1e8dce266057073d93cde6197e7d7684f20c297f67f30 \
--hash=sha256:628efe13630ac3397e7d1278b6be6f22f37a86d638a324334b4cd43c1daf9928 \
--hash=sha256:6342f79d6f50e680c8aa59e0615d745e867e51ffd59c77093be60b7c433067af \
--hash=sha256:63b87c93e28957e6dc2bb92d31727a863c9bf4a4daa080f0995fdcb0242c9166 \
--hash=sha256:65e937576141ac50fac32fa9736dbb3e0e4a7769f91be004011a09216c6ab05f \
--hash=sha256:66027e401c70d0cf55021b91b8a7ec2cd5810e20602f945b4fe6ae8b37ed232b \
--hash=sha256:6644eecd99c4e8cdf72e646e17b391bb70b054f44becde37dcdc48cbec7e1527 \
--hash=sha256:6705af9d1005127302c04d9f1533ba56e289336c465923ef878430e99295a0b9 \
--hash=sha256:6a8248b1ba8861e48e4c7ced3895a1264d2a3b617de72ec94172ce6e64bf16c7 \
--hash=sha256:6b14914e67044724c31a9360c7b89e9d070117c630746eefdc1620d967545acd \
--hash=sha256:6b7b540bb321f7f0a7b8f5d107f941bb361e3a154c0b594dae0394997b91b743 \
--hash=sha256:71250e010eede33c1d638e2c7a98288520d67f782fd5eceecaeca3129233a09a \
--hash=sha256:722ab747ff5dc28070b1a8c020dba6466f13f2ab56bc251ad301fefa2454aa1e \
--hash=sha256:724224d4c457207271239114bf43afafc3eca4a1b4661ccdd428d11869a03bbd \
--hash=sha256:729989759feb81ff6493879a0d60a0bd7d2eee41001bbec0381a080318439382 \
--hash=sha256:740bba4223fa5216d4d6c5dcd29e697f37229b8a61b69e1a50527b0ea993ab2c \
--hash=sha256:7bdc658c9474864893e0b6b94f1390bf6a912952df1870dd93bb7d1a902b5628 \
--hash=sha256:7d53fc4b90ef6e11de639dc18744d9be8cbd70ccb5ce80027aaffe7b1ab0215a \
--hash=sha256:7fa69212ea60ea24e2d8aff23fe102b1f87f1b27a320f92d2e7b3468997a496a \
--hash=sha256:80326bc571164bbbb6bead2e35d0c943b23b24fde629032197c58151529d24d8 \
--hash=sha256:80578e91764bfca297ddca322c00a3136d993b829e9839e7fa378a19c1fcc25d \
--hash=sha256:80a6e37e235780f189558ab804f3cbc01c18f5c578995739b49613d544d34ebf \
--hash=sha256:8135a549e27e9941a70e2d2156676ef2ffeff4b06e9d564dbaaae963482afdef \
--hash=sha256:82e60c00cfb8493a5ba27cdf9b3695fdd153f666f73e11f18968f78ead1d8705 \
--hash=sha256:856bbb24f2ee6436af7609267e73309e4bb0a0f9982f79f1c2e01019279c6671 \
--hash=sha256:85d6daa3a7ca404570ae130babbeb347ef9d3faca5300fb13cfa4bb48c3d30d1 \
--hash=sha256:8879b6a4040ee925c638548238ab7fe612cf5fa8752fe847346da0da8be81c3f \
--hash=sha256:8b3bede7d583bc9f47d8693a29984882e59077db1a5238ad977fc70ae8169741 \
--hash=sha256:8dbb3862aa649de95660b6337d97101977f160b5b354d07b82fe309874d2c8bc \
--hash=sha256:8f244dfee05ea29b8064701880865eb1684f3a704a5665bd10b64694444dbbd4 \
--hash=sha256:8f7469408740cf06a79b01605f2ae0b2acc8839c03fcbbf05da49baee12d3302 \
--hash=sha256:90cc9973c51811918247a78d9ab2f54871296e4e37e69a98aba4d3c9acedbf62 \
--hash=sha256:90d8c4fa5ba293cf92de351fbc292cdaadb1a1d58d031a1a97ff9b8fb6250ec7 \
--hash=sha256:94c02b0702656f083c098bdbd93bce22a7aa7a2b34ba56d2472efb67dab7cf58 \
--hash=sha256:9662a9fe457820c60365b3209e03cbd8e4a817195d55de65a80fa680b4bea136 \
--hash=sha256:997617dd7856c5dad742bf6893b872319156dd43f47587541a59e4a852d52bbc \
--hash=sha256:99c5637b74e2805ee4de9e2a43c8b45f678e50abb1c2da9880f0372f6498ba2f \
--hash=sha256:9a215749c9a88ef2842e880215193e56ae60b856773c99702b078236bc6d4adb \
--hash=sha256:9bde5d82d7ac4859e0cb3a35e148f537a8d4e56aa43f42582b5f263982f095ae \
--hash=sha256:a004c1fe5a72c496f28c6c1d8c2dc5cfe3278d99478e18f8b838c70a912b366f \
--hash=sha256:a0e2e7c2c1a4f25db7b6596738d810c10732e77f852247300a1bc49e364d6dc9 \
--hash=sha256:a22c4956a4d858200dba83f0691bb692d77b0eeddfca80157820d20b85dea4f1 \
--hash=sha256:a7f391838e8adcf1f2fe71561d9e5a9f74ea7ffa5052eb2db329aac677383136 \
--hash=sha256:a9eacb382f400bb5865e7e6d24bbe709a84510291e707f169dd4a24ee4a5ac6a \
--hash=sha256:ace8dd1efa5f44c482d091aa38322e20e3ffe5adcdba6b67ad9f4e7da58f3f68 \
--hash=sha256:ade76f8c84ade325bbed96806357fffd353fcc29a5166d6dc6d39381f6d9f76c \
--hash=sha256:af37a1e6b6bd506b597d5fb4cf111fb527d1b2223608a5d441d4738827cfd166 \
--hash=sha256:af7c474f0d8f4d2a196370e85033873c7b063a0b5da9a4f143aa023e3bd25407 \
--hash=sha256:b225c656efa2dedecc81651d2290170af25887b7de4f38c5efc7c5ae2b9442ab \
--hash=sha256:b459d29c8b82a420a98fa0ce8e9cf787ce0062d98cc90604ef9574fb3cc26ff8 \
--hash=sha256:bc6f87d03e3691154673aaa8f08991723d6e3394c83ef2875c7a9049eac9595c \
--hash=sha256:bc8fd230ef013951900c1fda100eebe4a4b1b407dde2a44186995042dda2c628 \
--hash=sha256:bd645b5d2f810a181c44f4a71135e7c365b44f4be9ed3d1892635be13a857553 \
--hash=sha256:be7be57097a65a8fab3d0f0a10d12931deb626a7d8082eb732b1ae41f3a202e3 \
--hash=sha256:c15a165673bb3fb57facbf040edf5c0556d20ccd2e0ccc5f23ebb69fb715fdc1 \
--hash=sha256:c4b3f2c7d84f303da873b634d0beef83b5e1137294c3de4e23102841dac0cf4a \
--hash=sha256:c534c9524a2acd0b97b7022074bec3784ac273c683cf9535087e437672ea8531 \
--hash=sha256:c95d25b5382ee0e6191ecafdeabefdc1f7bff8dfee29239b9b79e760ef3b04bd \
--hash=sha256:c9d06edfd974e918b40e0662a7e76dac13125529ee5ec9fbe42dc0d6faa209c3 \
--hash=sha256:cdb8e4b0f6a41b857c74c03116e8ffbef59ef8e533e934b532843178990d01d5 \
--hash=sha256:ce39283ef08b0f28478e920d4d89a1fc169176e568e8a6a821332673145522eb \
--hash=sha256:cfef7f7aa434a1e632e0ebda14b39f4f1d7975e0fce5c77ea7b43156fabf9bd8 \
--hash=sha256:d2605a3b2af8d66f8b75312d223642c065ec773446c04566d9030ad5e2db13c9 \
--hash=sha256:d338813a440bf6d2f0df55140d3f3080284410b1ebfe9df50e3847bcdb1a17bb \
--hash=sha256:d355b22270be8062360b9df2ee0b10277590789a1059257916fb9e256a0cff80 \
--hash=sha256:d68da281ac208b6236ffa8beef23fe7c7c956d8bf09b421d447232fd94441b35 \
--hash=sha256:dafbb58a149d1ebd5767b3f064f911c5ee0897608005e51c3904b0ada2a8d99c \
--hash=sha256:dc2b495a92b3971966bf102e73589f950db3ec1ca6713265355ce7771d97b199 \
--hash=sha256:dd0f3037d501178a761fd2814370aca547f79e99a200a61a1f6e7b79ec3d78b9 \
--hash=sha256:de2c12555bf05546f3ee75733f2c81de70aab7f530e86d0d2162b0ddcb3c39ae \
--hash=sha256:e164c4a6868d11988c7f2386e3278ccff21c665cd7d08279b62709dd37a3167c \
--hash=sha256:ed59cb4ee258674a6ed9b8515e42079db02cb3be94f133fdd3f200183a40c49d \
--hash=sha256:ef07e0b6b879f699a16fc7a513b974246fdeaef44908a021130cf4afe6a1c89c \
--hash=sha256:ef2950896673a9809e8e5ab857525924fbcacfc98b858b0509ccf50d341f80f4 \
--hash=sha256:f09f145b89ea292cf6c25fd7c8c0d90207fd6a9e54c7828499669996a1e5bdcc \
--hash=sha256:f27e7e8a85512b6a4b490d5756edde8e6772883a5800e1476172e44eda3f7d7c \
--hash=sha256:f300f28dff74ff4148c21e6971e4de6ca0c34e0086a3d95c017c5174ebf85ca5 \
--hash=sha256:f3ed747b7651668131029c720fbc32c7ee2d129bdad200e6c8f4037b20f7913a \
--hash=sha256:f87f02afe05c1c246012e3de100a77cfbabd17db709fe93cf074271ab239b312 \
--hash=sha256:fa87ea2ad64e59fe5622c1dc5716106b6d6e7e4b26b848cb5f5710a75c292ef5 \
--hash=sha256:fc23e72bd7f8a8e540fed2244524d0a9aeb6ae3325f3d56f04a7a3debe5b04c2 \
--hash=sha256:fdd00937f15f5f93c8e53d8060a8c4c010431ab595a9b5b50ddd569a04603944 \
--hash=sha256:fe7a168d805c8a7bf1c2de55b7ab2bc958586bfd88d0e87235a92cac66b590a7
# via yt-dlp
yt-dlp-ejs==0.8.0 \
--hash=sha256:79300e5fca7f937a1eeede11f0456862c1b41107ce1d726871e0207424f4bdb4 \
+3 -3
View File
@@ -1,3 +1,3 @@
pip==26.1.2 \
--hash=sha256:382ff9f685ee3bc25864f820aa50505825f10f5458ffff07e30a6d96e5715cab \
--hash=sha256:f49cd134c61cf2fd75e0ce2676db03e4054504a5a4986d00f8299ae632dc4605
pip==26.2.2 \
--hash=sha256:3a8e5c800492787f33a4114ef54444546c340df428974ebba17e0fd47e11af2f \
--hash=sha256:fd7f4dfa8190e014013b9f08f3e973f4e4c26ffd179a204895533a7254813a70
+22 -22
View File
@@ -8,9 +8,9 @@ macholib==1.16.4 ; sys_platform == 'darwin' \
--hash=sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea \
--hash=sha256:f408c93ab2e995cd2c46e34fe328b130404be143469e41bc366c807448979362
# via pyinstaller
packaging==26.2 \
--hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
--hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
packaging==26.3 \
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
# via
# pyinstaller
# pyinstaller-hooks-contrib
@@ -18,28 +18,28 @@ pefile==2024.8.26 ; sys_platform == 'win32' \
--hash=sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632 \
--hash=sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f
# via pyinstaller
pyinstaller==6.21.0 \
--hash=sha256:327d132389f37912609e01be62810cf96b5aa95b613903e4b8692e0d12fb0eda \
--hash=sha256:42395ec76df8e8120c36b13339d9db8cab83e316a12839ee303cc00fc941bb74 \
--hash=sha256:4e3108b3f02384560da70e39b8bf22b0ad597d02bd68a40d76ea91c1cfa00cad \
--hash=sha256:5fa56746c1e76f93634d018502301378a2d0c382553d37d8c3c34ff436c12dd1 \
--hash=sha256:605169523a6b5ace39f13dfbff21add9f2bc43df99c7daf9394fefb2c45e8b6f \
--hash=sha256:697532279f535ad572bda613db4f821540e235c7854ca6da4d3bf0373f4415ee \
--hash=sha256:6b6374d652107dd4a2eeece903ff82bb4045bb5e1006c5a158a6dcdbefe84bf2 \
--hash=sha256:7071d4b094d5b40deeef5fa3d3b98a1b846087f7562b49209663d5f9281fe251 \
--hash=sha256:7fae06c494ce0ebfe6bd3055c0e409def884f63af2e3705d06bd431ad9237fc7 \
--hash=sha256:bb9fab705983e393a2d1cac77d6972513057ad800215fd861dc15ff5272e98fd \
--hash=sha256:c6b28d30d8fd99ce162ff3aab5013ed44dbfb747566b1f01b9bed7964d7c14e9 \
--hash=sha256:f13c95c9c03fb567217135919f93815c305813126780b0ed6e0123cb8acaf025
pyinstaller-hooks-contrib==2026.6 \
--hash=sha256:bef5002c32f4f50bd55b005da12cff64eca8783e7eaf86a06a62410164bab725 \
--hash=sha256:fd13b8ac126b35361175edacd41a0d97080b75dd5f4b594ecefefff969509dd3
pyinstaller==6.22.0 \
--hash=sha256:0a20c37761851100f422ec261f513f46d8e57100ea22886b9ff7a6c346104bd8 \
--hash=sha256:6e5f3656de100954bf5db25536c43e097e46d482843a96d03a0852bf266e4853 \
--hash=sha256:6f527c1345d5010682587aebc2f0c1cc34a9b1f200424969c7bfda723cddc074 \
--hash=sha256:7885de3c830356b0990b27fe164f2b008fb4a18560bac884cf33985f61469f44 \
--hash=sha256:81dc305c16510c1f9ead6d115b66f381e3d3453ecb96653099c51aa3050420d1 \
--hash=sha256:8b0166fff4583b374bbe7fa044bf03ddc33cab0f792a665807d96048e63f060e \
--hash=sha256:b07ac9fd1d661ae4d0af6752c3941e4e5576a16cfe7e2d6504a32d57e17d0acc \
--hash=sha256:b1233da63926be213cdfbfbb314735bc7762136ed772b1082e1b0a2d7ed896b5 \
--hash=sha256:d7c7c5b149f7f9b37585b37e2376f774038b6a5633ba34db0de2698f75391e13 \
--hash=sha256:e6859e80b9c7dccb8a1687c5ed4644a722b370c2aa13e8a9ca5ebf5f9bb842ce \
--hash=sha256:f6c750c8ae999cc5520ddbce4263ac3ece96db04ba359ef20acacd81bccc201b \
--hash=sha256:f92f78a9c463b884d57f90c7459c0cb263ccd26a499356bbfac7a5f41fd5b93f
pyinstaller-hooks-contrib==2026.8 \
--hash=sha256:4d825786ad7a9b7dbcc52d612748a34562fe273461bcfd88f4d549c594bbf8f9 \
--hash=sha256:6d21d65323ea4467753afc21f52d7d0e69416ae8101dd88269bf273ad48db084
# via pyinstaller
pywin32-ctypes==0.2.3 ; sys_platform == 'win32' \
--hash=sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8 \
--hash=sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755
# via pyinstaller
setuptools==82.0.1 \
--hash=sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9 \
--hash=sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb
setuptools==84.2.1 \
--hash=sha256:3ff8b3b5492a0aa66960f4419365a86b84e013070d4313e4d4a6894f5d64d6bc \
--hash=sha256:ca140b45d5325a9478f880e351484f62fef15f336462e449ca0c03c873d589c2
# via pyinstaller
+22 -71
View File
@@ -1,75 +1,26 @@
autopep8==2.3.2 \
--hash=sha256:89440a4f969197b69a995e4ce0661b031f455a9f776d2c5ba3dbd83466931758 \
--hash=sha256:ce8ad498672c845a0c3de2629c15b635ec2b05ef8177a6e7c91c74f3e9b51128
pycodestyle==2.14.0 \
--hash=sha256:c4b5b517d278089ff9d0abdec919cd97262a3367449ea1c8b49b91529167b783 \
--hash=sha256:dd6bf7cb4ee77f8e016f9c8e74a35ddd9f67e1d5fd4184d86c3b98e07099f42d
# via autopep8
ruff==0.15.19 \
--hash=sha256:08143f0685ae278b30727ea72e90c61e5bd9c31b91aac4f5bb989538f73d24b8 \
--hash=sha256:27c15b2a241dd4d995557949a094fe78b8ad99122a38ccae1595849bcc947b3f \
--hash=sha256:4171b6613effa9363cd46dd4f75bd1827b6d1b946b5e278ed0c600d305379445 \
--hash=sha256:4d190d8f62a0b94aba8f721116538a9ee29b1e74d26650846ba9b99f0ae21c40 \
--hash=sha256:5a2c86ba6870dd415a9d9eb8be94d7924ebec6a26ffc7958ec7ca29d4bff967d \
--hash=sha256:6a498f82e0f4d8904c4e0aea5139cdfac1f39d19a3c51d491292f63a36e83b2e \
--hash=sha256:6c6b607466e47349332eb1d9be52fb1467423fc07c217341af41cd0f3f0573be \
--hash=sha256:82b432bc087264aea70fd25ac198918b70bd9e2aa0db4297b0bb91bbfbbc63ce \
--hash=sha256:8530a09d03b3a8c994f8b559a7dcdabc690bcd3f78ef276c38c83166798ebf56 \
--hash=sha256:87bf21fb3875fe69f0eacc825411657e2e85589cce633c35c0adf1113649c62b \
--hash=sha256:8f47f0f92952af2557212bb10cf3e695cd4cf28b2c6e42cdb18ec6c9ebfa19da \
--hash=sha256:922d1eb283161564759bd49f507e91dc6112c15da8bd5b84ed714e086243cf86 \
--hash=sha256:c6c754515be7b76afe6e7e62df7776709571bcfc1631183828afcf3bafa869e3 \
--hash=sha256:d48caa34488fb521fd0ef4aea2b0e8fe758298df044138f0d67b687a6a0d07ed \
--hash=sha256:ed03b7862d68f0a8771d50ee129980cbf1b113f96e250b73954bc292f689e0bb \
--hash=sha256:edc27f7172a93b32b102687009d6a588508815072141543ae603a8b9b0823063 \
--hash=sha256:efeca47ee3f9d4a7162655a3b8e6ee4a878646044233978d4d2c1ff8cdd914f0 \
--hash=sha256:f9b229cb3ef56ecc2c1c8ebeca64b7a7740ccaef40a9eb097e78dde5a8560b83
tomli==2.4.1 ; python_full_version < '3.11' \
--hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \
--hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \
--hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \
--hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \
--hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \
--hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \
--hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \
--hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \
--hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \
--hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \
--hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \
--hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \
--hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \
--hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \
--hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \
--hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \
--hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \
--hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \
--hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \
--hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \
--hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \
--hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \
--hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \
--hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \
--hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \
--hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \
--hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \
--hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \
--hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \
--hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \
--hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \
--hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \
--hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \
--hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \
--hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \
--hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \
--hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \
--hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \
--hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \
--hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \
--hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \
--hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \
--hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \
--hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \
--hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \
--hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \
--hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049
pycodestyle==2.15.0 \
--hash=sha256:12fd2f73c7b8ee8845a0431111df8faf4c1a07d6e64e2ee7f0c74014dab14181 \
--hash=sha256:318f5db083869b4c4dad922d0b11124fb27ab181b6730b93371da671e31bd50e
# via autopep8
ruff==0.17.1 \
--hash=sha256:056c5d5fa0ac790051ae165d7035c7bf956d02de2db557f2e9b31d877a505fca \
--hash=sha256:1796c41eafec66f4635125dd1e074a7aa27b8d20c187d484360acf11d247fc4a \
--hash=sha256:1de0030a8aa78c65c5fecb84b2e5c390ac684c0452875a02afc7c083d49a496a \
--hash=sha256:29b454f18ca3eeaf37fbf140841dcf27d36109e29dee9aae8acecb68c26c6f74 \
--hash=sha256:42400b9a6ff8515ff27796f07f92e0195be011c86e81e381606f58ea5502fef4 \
--hash=sha256:4c0d6cb5f8fbac77eec9af49f4fc0eaf856b05545e372b0694d24b4e76b1c640 \
--hash=sha256:5bb796c5112e9fb9527f2ef2faa0a130d6312d19de92bcfaddd70dbb2d41020f \
--hash=sha256:5df76f16580fab58d0f6c98a3ac254a4abceb7b2489b8b678335869cff77b3d7 \
--hash=sha256:684154861a819bf1f433669d2a0ce9c3e54677c65b8ebb866cc2a7ec86345785 \
--hash=sha256:78beced4a3c94dfedbee4b999b95b6a27b35820fdc0afbacc6d37a8da26c1cd1 \
--hash=sha256:7feefc63921202894f0e158b0e32f45a5950d70a7fb693ccb9264816c25b1c05 \
--hash=sha256:80e53b0e5faa3c5667f035daaa032893ae42b7cfe708c886d39ed131e54688ab \
--hash=sha256:872e03dd231744d6c5ec5c8af6be52b71323fc6ee096e4c8b34d9f844ee3b978 \
--hash=sha256:8eadb09a788010be29c895418bdfa513e4e1c65e64b94e5b19e4cd381f6cc7fb \
--hash=sha256:8f9aa5b5bd5fa1937803ea609c8f153b8de39bf3e0e149897ae34b0c5b52f467 \
--hash=sha256:a6ef98e51de8ef38082f90653ceeb84944bd7673783eea13e1647c5b9b064189 \
--hash=sha256:bd8f5a55b10f371642eacd0e8665a42a8b97da15c9a7187c79e697b77b5e0ce4 \
--hash=sha256:ce05e6f3973611d9550a600e04bb531061e368baba31610eb57c1509a8f21a0a
+15 -72
View File
@@ -2,85 +2,28 @@ colorama==0.4.6 ; sys_platform == 'win32' \
--hash=sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44 \
--hash=sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6
# via pytest
exceptiongroup==1.3.1 ; python_full_version < '3.11' \
--hash=sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219 \
--hash=sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598
iniconfig==2.3.1 \
--hash=sha256:67f4b9c50da0dedf52af349e7749a80a9057a5031199791b906c3bb3ae878960 \
--hash=sha256:9121e2c1fdb355232495be3194c8dfe87ccc2d5dee45947b78e68f499790d7a7
# via pytest
iniconfig==2.3.0 \
--hash=sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730 \
--hash=sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12
# via pytest
packaging==26.2 \
--hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
--hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
packaging==26.3 \
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
# via
# pytest
# pytest-rerunfailures
pluggy==1.6.0 \
--hash=sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3 \
--hash=sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746
pluggy==1.7.0 \
--hash=sha256:7dd7b0d8832ba3cb632c306926ded123429211b83641b35dc5c41ad2d34f9bec \
--hash=sha256:d1eaa46ebb595891b860ab086b4d09c8588af65ebd4361b8e8f4bb8920b90ba8
# via pytest
pygments==2.20.0 \
--hash=sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f \
--hash=sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176
pygments==2.21.0 \
--hash=sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9 \
--hash=sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c
# via pytest
pytest==9.1.1 \
--hash=sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313 \
--hash=sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c
# via pytest-rerunfailures
pytest-rerunfailures==16.3 \
--hash=sha256:37c9b1231c8083e9f4e724f50f7a21241822f9516c15c700ebbf218d6452355c \
--hash=sha256:6bdfb8ffb46c46072e6c16bdedee38b6c13eac620d9415ed5b63152cbf283170
tomli==2.4.1 ; python_full_version < '3.11' \
--hash=sha256:01f520d4f53ef97964a240a035ec2a869fe1a37dde002b57ebc4417a27ccd853 \
--hash=sha256:0d85819802132122da43cb86656f8d1f8c6587d54ae7dcaf30e90533028b49fe \
--hash=sha256:136443dbd7e1dee43c68ac2694fde36b2849865fa258d39bf822c10e8068eac5 \
--hash=sha256:1d8591993e228b0c930c4bb0db464bdad97b3289fb981255d6c9a41aedc84b2d \
--hash=sha256:2190f2e9dd7508d2a90ded5ed369255980a1bcdd58e52f7fe24b8162bf9fedbd \
--hash=sha256:2c1c351919aca02858f740c6d33adea0c5deea37f9ecca1cc1ef9e884a619d26 \
--hash=sha256:36d2bd2ad5fb9eaddba5226aa02c8ec3fa4f192631e347b3ed28186d43be6b54 \
--hash=sha256:3d48a93ee1c9b79c04bb38772ee1b64dcf18ff43085896ea460ca8dec96f35f6 \
--hash=sha256:47149d5bd38761ac8be13a84864bf0b7b70bc051806bc3669ab1cbc56216b23c \
--hash=sha256:4ab97e64ccda8756376892c53a72bd1f964e519c77236368527f758fbc36a53a \
--hash=sha256:4b605484e43cdc43f0954ddae319fb75f04cc10dd80d830540060ee7cd0243cd \
--hash=sha256:504aa796fe0569bb43171066009ead363de03675276d2d121ac1a4572397870f \
--hash=sha256:51529d40e3ca50046d7606fa99ce3956a617f9b36380da3b7f0dd3dd28e68cb5 \
--hash=sha256:52c8ef851d9a240f11a88c003eacb03c31fc1c9c4ec64a99a0f922b93874fda9 \
--hash=sha256:559db847dc486944896521f68d8190be1c9e719fced785720d2216fe7022b662 \
--hash=sha256:5a881ab208c0baf688221f8cecc5401bd291d67e38a1ac884d6736cbcd8247e9 \
--hash=sha256:5cb41aa38891e073ee49d55fbc7839cfdb2bc0e600add13874d048c94aadddd1 \
--hash=sha256:5e262d41726bc187e69af7825504c933b6794dc3fbd5945e41a79bb14c31f585 \
--hash=sha256:5ee18d9ebdb417e384b58fe414e8d6af9f4e7a0ae761519fb50f721de398dd4e \
--hash=sha256:7008df2e7655c495dd12d2a4ad038ff878d4ca4b81fccaf82b714e07eae4402c \
--hash=sha256:734e20b57ba95624ecf1841e72b53f6e186355e216e5412de414e3c51e5e3c41 \
--hash=sha256:7c7e1a961a0b2f2472c1ac5b69affa0ae1132c39adcb67aba98568702b9cc23f \
--hash=sha256:7f86fd587c4ed9dd76f318225e7d9b29cfc5a9d43de44e5754db8d1128487085 \
--hash=sha256:7f94b27a62cfad8496c8d2513e1a222dd446f095fca8987fceef261225538a15 \
--hash=sha256:88dceee75c2c63af144e456745e10101eb67361050196b0b6af5d717254dddf7 \
--hash=sha256:8a650c2dbafa08d42e51ba0b62740dae4ecb9338eefa093aa5c78ceb546fcd5c \
--hash=sha256:8d65a2fbf9d2f8352685bc1364177ee3923d6baf5e7f43ea4959d7d8bc326a36 \
--hash=sha256:96481a5786729fd470164b47cdb3e0e58062a496f455ee41b4403be77cb5a076 \
--hash=sha256:a120733b01c45e9a0c34aeef92bf0cf1d56cfe81ed9d47d562f9ed591a9828ac \
--hash=sha256:b1d22e6e9387bf4739fbe23bfa80e93f6b0373a7f1b96c6227c32bef95a4d7a8 \
--hash=sha256:b8c198f8c1805dc42708689ed6864951fd2494f924149d3e4bce7710f8eb5232 \
--hash=sha256:c2541745709bad0264b7d4705ad453b76ccd191e64aa6f0fc66b69a293a45ece \
--hash=sha256:c742f741d58a28940ce01d58f0ab2ea3ced8b12402f162f4d534dfe18ba1cd6a \
--hash=sha256:c7f2c7f2b9ca6bdeef8f0fa897f8e05085923eb091721675170254cbc5b02897 \
--hash=sha256:d312ef37c91508b0ab2cee7da26ec0b3ed2f03ce12bd87a588d771ae15dcf82d \
--hash=sha256:d4d8fe59808a54658fcc0160ecfb1b30f9089906c50b23bcb4c69eddc19ec2b4 \
--hash=sha256:da25dc3563bff5965356133435b757a795a17b17d01dbc0f42fb32447ddfd917 \
--hash=sha256:eab21f45c7f66c13f2a9e0e1535309cee140182a9cdae1e041d02e47291e8396 \
--hash=sha256:eb0dc4e38e6a1fd579e5d50369aa2e10acfc9cace504579b2faabb478e76941a \
--hash=sha256:ec9bfaf3ad2df51ace80688143a6a4ebc09a248f6ff781a9945e51937008fcbc \
--hash=sha256:ede3e6487c5ef5d28634ba3f31f989030ad6af71edfb0055cbbd14189ff240ba \
--hash=sha256:f3c6818a1a86dd6dca7ddcaaf76947d5ba31aecc28cb1b67009a5877c9a64f3f \
--hash=sha256:f758f1b9299d059cc3f6546ae2af89670cb1c4d48ea29c3cacc4fe7de3058257 \
--hash=sha256:f8f0fc26ec2cc2b965b7a3b87cd19c5c6b8c5e5f436b984e85f486d652285c30 \
--hash=sha256:fd0409a3653af6c147209d267a0e4243f0ae46b011aa978b1080359fddc9b6cf \
--hash=sha256:ff18e6a727ee0ab0388507b89d1bc6a22b138d1e2fa56d1ad494586d61d2eae9 \
--hash=sha256:ff2983983d34813c1aeb0fa89091e76c3a22889ee83ab27c5eeb45100560c049
# via pytest
typing-extensions==4.15.0 ; python_full_version < '3.11' \
--hash=sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466 \
--hash=sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548
# via exceptiongroup
pytest-rerunfailures==16.7 \
--hash=sha256:6956ddfb65ca1d07e7e3d99e2c5359d82300f4cb062e6049563bd2c106f72d5c \
--hash=sha256:edf1886209c2b7dafe35b5bf1708d6ec40ccf6c6b357f0f02807efcec0204c99
+20 -20
View File
@@ -1,20 +1,20 @@
uv==0.11.24 \
--hash=sha256:047d763d20d71968c00f4afec40b0e75d9da7e3693f725b9f502d84a25256893 \
--hash=sha256:0e100b9cbc59beff2730840ac989b1f100cc03c90514e7cab6992a1f3f13784e \
--hash=sha256:3176668ea8a2318d775c0d9188661c61ccc36790220724b1d360fcc8945d520e \
--hash=sha256:356435577fae11fafe7a067ee3269cccefd35b031b83a3a36c87fe9d192bffba \
--hash=sha256:38f38c9449aafd71dc0fa35e66a8a547ee48947b2f2f94084893c2afe6058cfa \
--hash=sha256:438f8291fb9daea30a4bd333299b82e6ef755578302745a021162f328cfcfc68 \
--hash=sha256:48a6123f71b801e0e0b8a38520b011632ad81e0a043445044ce5b1a7b1cec7b6 \
--hash=sha256:6ecdad43e870f88d3772d9d37e877259ae35ec374d51589805cdcf6196205829 \
--hash=sha256:79757f90b7765996366b80e77cad13555c7f7e1282ca8d8b686ee21773ab0b77 \
--hash=sha256:8346b0086d213b80430f3bb4477379a8a4fa550b03447d23c84eee85c2e52bc4 \
--hash=sha256:8602a1b6300a3a948afacc62e1cb933c8394c27966db85ed7e29483300b69dc4 \
--hash=sha256:9312b6fd44361674e9c847a828ded792493766697816261e05848a024fe34129 \
--hash=sha256:bf568c62dddd55ad9c85a16ffdfbcc7746be9c3159ed644e4f9e6f5e44905cbb \
--hash=sha256:c4ab221c0a949f8006a7582786dae384706b2f82016a0db60baa7cc696042705 \
--hash=sha256:c8ec3caf656645f58b53cb9aee9aa95cfc65c82ba2d7f1362bfd2660d1484307 \
--hash=sha256:d6a49543c659c0cf1ff4c944955d97e69dbce4b76e3d284f5a92cea19133ebb6 \
--hash=sha256:e499579f557abf17b8ffd1490d3e827748aea096f6eaa66737e729e046449f08 \
--hash=sha256:e7e78c18686202c8b8715bebb83bfaf58f82d7fb848b6a5ae4e925a9fac3de4c \
--hash=sha256:ed0c9a9d7909f0e48a9dafe666ca9ebefe2a1534e51ed05c0a7de7406465f868
uv==0.13.5 \
--hash=sha256:0548460d46c8667488b1f089e936f29f0edfb1cc753f9152ffbd8bc84a46aa20 \
--hash=sha256:0e03f5717bdaaf5ab4e2df361d2395e36b515946f56ef4bed88801aeb9959fb0 \
--hash=sha256:1fb29fc46ba12033e2ef95a95ac79d649e71bbb1358419bbbcbd19d86026ef2f \
--hash=sha256:2386c2dc9b59fc1d39b1c500e4319d71d3268232eb3b38e29cd6775d6269e8d4 \
--hash=sha256:2386e8dbfe110ff2f8ec8bd344dd18bf39eb9eb54e1edeeb87c3b85c34229cd3 \
--hash=sha256:309a74d3c488bfaa3ba7bff759da73193d8781729c0a01274f4940fd32bb5712 \
--hash=sha256:337a14829bb499e114989df4f908f134ff37f1fb6c33497541cfb05b28080e39 \
--hash=sha256:469cca66de1b17c75b9b9de806a64cffb57cba5e42b1e30d0bba6fa72a146f58 \
--hash=sha256:4f62680fe58c5a83fd539e38f1956c2b577b1f5939c9020aa4c7f0addda2f4ad \
--hash=sha256:8d092d07d2389909027c2ed4965ade1bd46bbcecceb26686ff40927684f8c457 \
--hash=sha256:91e58e304b63b6c91bac5561459ab0c3ea24f17bc01ea9359d69fed72142978f \
--hash=sha256:979409b8c9a78df140ffb19c53f511b7a73526da8d1d5e36558833055e371c6c \
--hash=sha256:a42c85fa8156e1e5e2cecdbc77bb818ea1dcf5f78b8e2a8f84c7fe4f16f0702e \
--hash=sha256:d162669e3a7811c584b03690eaa11e796ad1d309aa8229d5dfe3cbcd68a90400 \
--hash=sha256:d3fd5db55c20feb672ea457361aba29ab68b9ae69a14d98ad6c138b5f86dcca4 \
--hash=sha256:e01481ae5212e45ee7c85fad5fc67f06b0ee0329a7c3c289dc529da884b03881 \
--hash=sha256:f4e55a6e2a1089fe74ed50fbdf2df0f6f336ee148ad232b05932db5deee8007e \
--hash=sha256:f867c5ec24c563afaae730a13e46cdf74a1a0b64c134286ff99762a96e2abf40 \
--hash=sha256:fa8d26e08e34c29c0c4e820cf3181757086d547240b4f4d31ff1d8bd810ca946
+11 -11
View File
@@ -8,9 +8,9 @@ macholib==1.16.4 ; sys_platform == 'darwin' \
--hash=sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea \
--hash=sha256:f408c93ab2e995cd2c46e34fe328b130404be143469e41bc366c807448979362
# via pyinstaller
packaging==26.2 \
--hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
--hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
packaging==26.3 \
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
# via
# pyinstaller
# pyinstaller-hooks-contrib
@@ -18,17 +18,17 @@ pefile==2024.8.26 ; sys_platform == 'win32' \
--hash=sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632 \
--hash=sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f
# via pyinstaller
pyinstaller @ https://github.com/yt-dlp/Pyinstaller-Builds/releases/download/2026.06.20.202648/pyinstaller-6.21.0-py3-none-win_arm64.whl \
--hash=sha256:920d24804314db99c552950806fb355a286eb1e2244fe296efb46319b5a900c2
pyinstaller-hooks-contrib==2026.6 \
--hash=sha256:bef5002c32f4f50bd55b005da12cff64eca8783e7eaf86a06a62410164bab725 \
--hash=sha256:fd13b8ac126b35361175edacd41a0d97080b75dd5f4b594ecefefff969509dd3
pyinstaller @ https://github.com/yt-dlp/Pyinstaller-Builds/releases/download/2026.08.19.215425/pyinstaller-6.22.0-py3-none-win_arm64.whl \
--hash=sha256:cdb8599f3844825143d40b6dd3e193cb608e1820f90580b665b4f2b139b68cb8
pyinstaller-hooks-contrib==2026.8 \
--hash=sha256:4d825786ad7a9b7dbcc52d612748a34562fe273461bcfd88f4d549c594bbf8f9 \
--hash=sha256:6d21d65323ea4467753afc21f52d7d0e69416ae8101dd88269bf273ad48db084
# via pyinstaller
pywin32-ctypes==0.2.3 ; sys_platform == 'win32' \
--hash=sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8 \
--hash=sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755
# via pyinstaller
setuptools==82.0.1 \
--hash=sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9 \
--hash=sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb
setuptools==84.2.1 \
--hash=sha256:3ff8b3b5492a0aa66960f4419365a86b84e013070d4313e4d4a6894f5d64d6bc \
--hash=sha256:ca140b45d5325a9478f880e351484f62fef15f336462e449ca0c03c873d589c2
# via pyinstaller
+11 -11
View File
@@ -8,9 +8,9 @@ macholib==1.16.4 ; sys_platform == 'darwin' \
--hash=sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea \
--hash=sha256:f408c93ab2e995cd2c46e34fe328b130404be143469e41bc366c807448979362
# via pyinstaller
packaging==26.2 \
--hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
--hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
packaging==26.3 \
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
# via
# pyinstaller
# pyinstaller-hooks-contrib
@@ -18,17 +18,17 @@ pefile==2024.8.26 ; sys_platform == 'win32' \
--hash=sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632 \
--hash=sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f
# via pyinstaller
pyinstaller @ https://github.com/yt-dlp/Pyinstaller-Builds/releases/download/2026.06.20.202648/pyinstaller-6.21.0-py3-none-win_amd64.whl \
--hash=sha256:dce4e3c9c8b20a2c5292d8f90c034cd3a854df8fdd054cc05c2a375a2edd4220
pyinstaller-hooks-contrib==2026.6 \
--hash=sha256:bef5002c32f4f50bd55b005da12cff64eca8783e7eaf86a06a62410164bab725 \
--hash=sha256:fd13b8ac126b35361175edacd41a0d97080b75dd5f4b594ecefefff969509dd3
pyinstaller @ https://github.com/yt-dlp/Pyinstaller-Builds/releases/download/2026.08.19.215425/pyinstaller-6.22.0-py3-none-win_amd64.whl \
--hash=sha256:294099ecb5fdd2a13ae4c29006d4e335b697a63b6a16cf052b90ec2b40bef05a
pyinstaller-hooks-contrib==2026.8 \
--hash=sha256:4d825786ad7a9b7dbcc52d612748a34562fe273461bcfd88f4d549c594bbf8f9 \
--hash=sha256:6d21d65323ea4467753afc21f52d7d0e69416ae8101dd88269bf273ad48db084
# via pyinstaller
pywin32-ctypes==0.2.3 ; sys_platform == 'win32' \
--hash=sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8 \
--hash=sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755
# via pyinstaller
setuptools==82.0.1 \
--hash=sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9 \
--hash=sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb
setuptools==84.2.1 \
--hash=sha256:3ff8b3b5492a0aa66960f4419365a86b84e013070d4313e4d4a6894f5d64d6bc \
--hash=sha256:ca140b45d5325a9478f880e351484f62fef15f336462e449ca0c03c873d589c2
# via pyinstaller
+11 -11
View File
@@ -8,9 +8,9 @@ macholib==1.16.4 ; sys_platform == 'darwin' \
--hash=sha256:da1a3fa8266e30f0ce7e97c6a54eefaae8edd1e5f86f3eb8b95457cae90265ea \
--hash=sha256:f408c93ab2e995cd2c46e34fe328b130404be143469e41bc366c807448979362
# via pyinstaller
packaging==26.2 \
--hash=sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e \
--hash=sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661
packaging==26.3 \
--hash=sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79 \
--hash=sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c
# via
# pyinstaller
# pyinstaller-hooks-contrib
@@ -18,17 +18,17 @@ pefile==2024.8.26 ; sys_platform == 'win32' \
--hash=sha256:3ff6c5d8b43e8c37bb6e6dd5085658d658a7a0bdcd20b6a07b1fcfc1c4e9d632 \
--hash=sha256:76f8b485dcd3b1bb8166f1128d395fa3d87af26360c2358fb75b80019b957c6f
# via pyinstaller
pyinstaller @ https://github.com/yt-dlp/Pyinstaller-Builds/releases/download/2026.06.20.202648/pyinstaller-6.21.0-py3-none-win32.whl \
--hash=sha256:e495b51a5d17b1bc2201783384e20ecfd9f292460460f0dce486ca075bce8f61
pyinstaller-hooks-contrib==2026.6 \
--hash=sha256:bef5002c32f4f50bd55b005da12cff64eca8783e7eaf86a06a62410164bab725 \
--hash=sha256:fd13b8ac126b35361175edacd41a0d97080b75dd5f4b594ecefefff969509dd3
pyinstaller @ https://github.com/yt-dlp/Pyinstaller-Builds/releases/download/2026.08.19.215425/pyinstaller-6.22.0-py3-none-win32.whl \
--hash=sha256:c339eb81fb6158815b7d3c9d81dc6aaad1de974b81ddd91ecfced045f8b27f5e
pyinstaller-hooks-contrib==2026.8 \
--hash=sha256:4d825786ad7a9b7dbcc52d612748a34562fe273461bcfd88f4d549c594bbf8f9 \
--hash=sha256:6d21d65323ea4467753afc21f52d7d0e69416ae8101dd88269bf273ad48db084
# via pyinstaller
pywin32-ctypes==0.2.3 ; sys_platform == 'win32' \
--hash=sha256:8a1513379d709975552d202d942d9837758905c8d01eb82b8bcc30918929e7b8 \
--hash=sha256:d162dc04946d704503b2edc4d55f3dba5c1d539ead017afa00142c38b9885755
# via pyinstaller
setuptools==82.0.1 \
--hash=sha256:7d872682c5d01cfde07da7bccc7b65469d3dca203318515ada1de5eda35efbf9 \
--hash=sha256:a59e362652f08dcd477c78bb6e7bd9d80a7995bc73ce773050228a348ce2e5bb
setuptools==84.2.1 \
--hash=sha256:3ff8b3b5492a0aa66960f4419365a86b84e013070d4313e4d4a6894f5d64d6bc \
--hash=sha256:ca140b45d5325a9478f880e351484f62fef15f336462e449ca0c03c873d589c2
# via pyinstaller
+42
View File
@@ -382,5 +382,47 @@
"action": "add",
"when": "b6590aaa1e3808155d69c9a79a797ae484163789",
"short": "[priority] Security: [[CVE-2026-55404](https://nvd.nist.gov/vuln/detail/CVE-2026-55404)] [Downstream command injection via improper sanitization of --write-link output](https://github.com/yt-dlp/yt-dlp/security/advisories/GHSA-6v4j-43gg-vj32)\n - Shortcut file data is now properly validated and sanitized when the `--write-link` options are used"
},
{
"action": "remove",
"when": "a8be438aac1b90c3888e974056d967b8be90fa7e"
},
{
"action": "remove",
"when": "fdcc954df4955267ec1627cbeb347b661a110e7c"
},
{
"action": "remove",
"when": "370f7820ea187646cadc0985bc1ea45beac5be4a"
},
{
"action": "remove",
"when": "2bf72df3deaf3dc835d2ff1c99484f01723a5d13"
},
{
"action": "change",
"when": "f1df65d5d7a97bd81b3c70bf4bc41897b0616f6e",
"short": "[utils] `download_range_func`: Improve `__eq__` and `__repr__` (#16393)",
"authors": ["atsushi2965"]
},
{
"action": "add",
"when": "70279f2f0c576e23e1ec1406317d2cb85586af3f",
"short": "[priority] Security: Old yt-dlp executables are vulnerable to man-in-the-middle attacks\n - A man-in-the-middle/MITM attack is when your internet traffic is intercepted by an attacker that impersonates the website(s) you browse and sends you malicious data instead.\n - If you think you may be targeted by such an attack, it is strongly recommended to avoid using the self-updater (e.g. the `-U`, `--update`, `--update-to` command-line options), and instead manually download and install this release's executable.\n - For more details, see the [`certifi` security advisory](https://github.com/advisories/GHSA-6q48-6c7w-9gw2)"
},
{
"action": "add",
"when": "3d28cf4780fa88689fc50010d72cf2f40ce3a3b8",
"short": "[priority] **The minimum *required* Python version has been raised to 3.11**\n - Python 3.10 has reached its end-of-life as of October 2026, and yt-dlp has now removed support for it. [Read more](https://github.com/yt-dlp/yt-dlp/issues/16916)"
},
{
"action": "add",
"when": "3d28cf4780fa88689fc50010d72cf2f40ce3a3b8",
"short": "[priority] **The official Windows release binaries now require Windows 10 or later.** [Read more](https://github.com/yt-dlp/yt-dlp/issues/16917)"
},
{
"action": "add",
"when": "7747073a2b00ca4688637eef4e168af9d2a806cb",
"short": "[priority] Security: The recent `brotli` and `certifi` vulnerabilities have now been fully addressed in the executables\n - The `brotli` package bundled with the executables has been upgraded to version 1.2.1, and the `curl-cffi` package has been upgraded to version 0.17.0. These upgrades address the recent [`brotli` security vulnerability](https://github.com/advisories/GHSA-9v8h-qqgm-4m35)\n - `curl-cffi` 0.17.0 also fully addresses the recent [`certifi` security vulnerability](https://github.com/advisories/GHSA-6q48-6c7w-9gw2) that was already partially addressed by upgrading the `certifi` package bundled with the executables"
}
]
+79 -20
View File
@@ -10,7 +10,7 @@ HEADER = '''THIRD-PARTY LICENSES
This file aggregates license texts of third-party components included with the yt-dlp PyInstaller-bundled executables.
yt-dlp itself is licensed under the Unlicense (see LICENSE file).
Source code for bundled third-party components is available from the original projects.
If you cannot obtain it, the maintainers will provide it as per license obligation; maintainer emails are listed in pyproject.toml.'''
If you cannot obtain it, the maintainers will provide it as per license obligation: email maintainers@yt-dlp.org'''
@dataclass(frozen=True)
@@ -47,6 +47,13 @@ DEPENDENCIES: list[Dependency] = [
license_url='https://raw.githubusercontent.com/libffi/libffi/refs/heads/master/LICENSE',
project_url='https://sourceware.org/libffi/',
),
Dependency(
name='OpenSSL 1.x',
license='OpenSSL',
license_url='https://raw.githubusercontent.com/openssl/openssl/refs/tags/OpenSSL_1_1_1t/LICENSE',
comment='Only included in `yt-dlp.exe` and `yt-dlp_x86.exe` Windows builds',
project_url='https://www.openssl.org/',
),
Dependency(
name='OpenSSL 3.0+',
license='Apache-2.0',
@@ -123,43 +130,79 @@ DEPENDENCIES: list[Dependency] = [
name='libintl',
license='LGPL-2.1-or-later',
license_url='https://raw.githubusercontent.com/autotools-mirror/gettext/refs/heads/master/gettext-runtime/intl/COPYING.LIB',
comment='Only included in macOS builds',
comment='Only included in Linux builds',
project_url='https://www.gnu.org/software/gettext/',
),
Dependency(
name='libidn2',
license='LGPL-3.0-or-later',
license_url='https://gitlab.com/libidn/libidn2/-/raw/master/COPYING.LESSERv3',
comment='Only included in macOS builds',
comment='Only included in Linux builds',
project_url='https://www.gnu.org/software/libidn/',
),
Dependency(
name='libidn2 (Unicode character data files)',
license='Unicode-TOU AND Unicode-DFS-2016',
license_url='https://gitlab.com/libidn/libidn2/-/raw/master/COPYING.unicode',
comment='Only included in macOS builds',
comment='Only included in Linux builds',
project_url='https://www.gnu.org/software/libidn/',
),
Dependency(
name='libunistring',
license='LGPL-3.0-or-later',
license_url='https://gitweb.git.savannah.gnu.org/gitweb/?p=libunistring.git;a=blob_plain;f=COPYING.LIB;hb=HEAD',
comment='Only included in macOS builds',
comment='Only included in Linux builds',
project_url='https://www.gnu.org/software/libunistring/',
),
# Non-Python dependencies of curl_cffi
Dependency(
name='librtmp',
license='LGPL-2.1-or-later',
# No official repo URL
license_url='https://gist.githubusercontent.com/seproDev/31d8c691ccddebe37b8b379307cb232d/raw/053408e98547ea8c7d9ba3a80c965f33e163b881/librtmp_COPYING.txt',
comment='Only included in macOS builds',
project_url='https://rtmpdump.mplayerhq.hu/',
name='curl-impersonate',
license='MIT',
license_url='https://raw.githubusercontent.com/lexiforest/curl-impersonate/refs/heads/main/LICENSE',
comment='Not included in `yt-dlp_x86.exe` Windows builds',
project_url='https://github.com/lexiforest/curl-impersonate',
),
Dependency(
name='curl',
license='curl',
license_url='https://raw.githubusercontent.com/curl/curl/refs/heads/master/LICENSES/curl.txt',
comment='Not included in `yt-dlp_x86.exe` Windows builds',
project_url='https://curl.se/',
),
Dependency(
name='BoringSSL',
license='Apache-2.0',
license_url='https://raw.githubusercontent.com/google/boringssl/refs/heads/main/LICENSE',
comment='Not included in `yt-dlp_x86.exe` Windows builds',
project_url='https://boringssl.googlesource.com/boringssl',
),
Dependency(
name='nghttp2',
license='MIT',
license_url='https://raw.githubusercontent.com/nghttp2/nghttp2/refs/heads/master/COPYING',
comment='Not included in `yt-dlp_x86.exe` Windows builds',
project_url='https://nghttp2.org/',
),
Dependency(
name='ngtcp2',
license='MIT',
license_url='https://raw.githubusercontent.com/ngtcp2/ngtcp2/refs/heads/main/COPYING',
comment='Not included in `yt-dlp_x86.exe` Windows builds',
project_url='https://nghttp2.org/ngtcp2/',
),
Dependency(
name='nghttp3',
license='MIT',
license_url='https://raw.githubusercontent.com/ngtcp2/nghttp3/refs/heads/main/COPYING',
comment='Not included in `yt-dlp_x86.exe` Windows builds',
project_url='https://nghttp2.org/nghttp3/',
),
Dependency(
name='zstd',
license='BSD-3-Clause',
license_url='https://raw.githubusercontent.com/facebook/zstd/refs/heads/dev/LICENSE',
comment='Only included in macOS builds',
comment='Not included in `yt-dlp_x86.exe` Windows builds',
project_url='https://facebook.github.io/zstd/',
),
@@ -174,28 +217,42 @@ DEPENDENCIES: list[Dependency] = [
name='curl_cffi',
license='MIT',
license_url='https://raw.githubusercontent.com/lexiforest/curl_cffi/refs/heads/main/LICENSE',
comment='Not included in `yt-dlp_x86` and `yt-dlp_musllinux_aarch64` builds',
comment='Not included in `yt-dlp_x86.exe` Windows builds',
project_url='https://curl-cffi.readthedocs.io/',
),
# Dependency of curl_cffi
# curl_cffi vendored code:
# - https://github.com/lexiforest/curl_cffi/blob/v0.15.0/curl_cffi/_asyncio_selector.py
Dependency(
name='curl-impersonate',
license='MIT',
license_url='https://raw.githubusercontent.com/lexiforest/curl-impersonate/refs/heads/main/LICENSE',
comment='Not included in `yt-dlp_x86` and `yt-dlp_musllinux_aarch64` builds',
project_url='https://github.com/lexiforest/curl-impersonate',
name='Tornado',
license='Apache-2.0',
license_url='https://raw.githubusercontent.com/tornadoweb/tornado/master/LICENSE',
comment='Not included in `yt-dlp_x86.exe` Windows builds',
project_url='http://www.tornadoweb.org/',
),
# curl_cffi vendored code:
# - https://github.com/lexiforest/curl_cffi/blob/v0.15.0/curl_cffi/requests/cookies.py
# - https://github.com/lexiforest/curl_cffi/blob/v0.15.0/curl_cffi/requests/headers.py
Dependency(
name='httpx',
license='BSD-3-Clause',
license_url='https://github.com/encode/httpx/raw/master/LICENSE.md',
comment='Not included in `yt-dlp_x86.exe` Windows builds',
project_url='https://www.python-httpx.org/',
),
# Dependency of cryptography and curl_cffi
Dependency(
name='cffi',
license='MIT-0', # Technically does not need to be included
license_url='https://raw.githubusercontent.com/python-cffi/cffi/refs/heads/main/LICENSE',
comment='Not included in `yt-dlp_x86.exe` Windows builds',
project_url='https://cffi.readthedocs.io/',
),
# Dependecy of cffi
# Dependency of cffi
Dependency(
name='pycparser',
license='BSD-3-Clause',
license_url='https://raw.githubusercontent.com/eliben/pycparser/refs/heads/main/LICENSE',
comment='Not included in `yt-dlp_x86.exe` Windows builds',
project_url='https://github.com/eliben/pycparser',
),
Dependency(
@@ -276,12 +333,14 @@ DEPENDENCIES: list[Dependency] = [
name='Meriyah',
license='ISC',
license_url='https://raw.githubusercontent.com/meriyah/meriyah/refs/heads/main/LICENSE.md',
comment='Also included in `yt-dlp` zipimport Unix executables and `yt-dlp.tar.gz` release tarballs',
project_url='https://github.com/meriyah/meriyah',
),
Dependency(
name='Astring',
license='MIT',
license_url='https://raw.githubusercontent.com/davidbonnet/astring/refs/heads/main/LICENSE',
comment='Also included in `yt-dlp` zipimport Unix executables and `yt-dlp.tar.gz` release tarballs',
project_url='https://github.com/davidbonnet/astring/',
),
]
+5 -11
View File
@@ -1,25 +1,18 @@
#!/usr/bin/env python3
# Allow execution from anywhere
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import argparse
import re
import subprocess
import sys
import tomllib
from pathlib import Path
from devscripts.tomlparse import parse_toml
from devscripts.utils import read_file
def parse_args():
parser = argparse.ArgumentParser(description='Install dependencies for yt-dlp')
parser.add_argument(
'input', nargs='?', metavar='TOMLFILE', default=Path(__file__).parent.parent / 'pyproject.toml',
'input', nargs='?', type=Path, metavar='TOMLFILE', default=Path(__file__).parent.parent / 'pyproject.toml',
help='input file (default: %(default)s)')
parser.add_argument(
'-e', '--exclude-dependency', metavar='DEPENDENCY', action='append',
@@ -50,7 +43,8 @@ def uniq(arg) -> dict[str, None]:
def main():
args = parse_args()
toml_data = parse_toml(read_file(args.input))
with args.input.open('rb') as file:
toml_data = tomllib.load(file)
project_table = toml_data['project']
recursive_pattern = re.compile(rf'{project_table["name"]}\[(?P<extra_name>[\w-]+)\]')
extras = project_table['optional-dependencies']
+1 -1
View File
@@ -35,7 +35,7 @@ VERBOSE = '''
[debug] Command-line config: ['-vU', 'https://www.youtube.com/watch?v=YE7VzlLtp-4']
[debug] Encodings: locale cp65001, fs utf-8, pref cp65001, out utf-8, error utf-8, screen utf-8
[debug] yt-dlp version nightly@... from yt-dlp/yt-dlp-nightly-builds [1a176d874] (win_exe)
[debug] Python 3.10.11 (CPython AMD64 64bit) - Windows-10-10.0.20348-SP0 (OpenSSL 1.1.1t 7 Feb 2023)
[debug] Python 3.14.x (CPython AMD64 64bit) - Windows-10-... (OpenSSL 3.y ...)
[debug] exe versions: ffmpeg 7.0.2 (setts), ffprobe 7.0.2
[debug] Optional libraries: Cryptodome-3.21.0, brotli-1.1.0, certifi-2024.08.30, curl_cffi-0.5.10, mutagen-1.47.0, requests-2.32.3, sqlite3-3.40.1, urllib3-2.2.3, websockets-13.1
[debug] Proxy map: {}
+1 -2
View File
@@ -66,8 +66,7 @@ def convert_code_blocks(readme):
def move_sections(readme):
MOVE_TAG_TEMPLATE = '<!-- MANPAGE: MOVE "%s" SECTION HERE -->'
sections = re.findall(r'(?m)^%s$' % (
re.escape(MOVE_TAG_TEMPLATE).replace(r'\%', '%') % '(.+)'), readme)
sections = re.findall(r'(?m)^%s$' % (re.escape(MOVE_TAG_TEMPLATE) % '(.+)'), readme)
for section_name in sections:
move_tag = MOVE_TAG_TEMPLATE % section_name
+1 -1
View File
@@ -57,7 +57,7 @@ def setup_variables(environment):
revision = None
if INPUTS['prerelease'] or not json.loads(environment['HAS_RELEASE_KEY']):
revision = dt.datetime.now(tz=dt.timezone.utc).strftime('%H%M%S')
revision = dt.datetime.now(tz=dt.UTC).strftime('%H%M%S')
version = calculate_version(INPUTS.get('version') or revision)
+1 -1
View File
@@ -60,7 +60,7 @@ def _test(github_repository, note, repo_vars, repo_secrets, inputs, expected, ig
def test_setup_variables():
DEFAULT_VERSION_WITH_REVISION = dt.datetime.now(tz=dt.timezone.utc).strftime('%Y.%m.%d.%H%M%S')
DEFAULT_VERSION_WITH_REVISION = dt.datetime.now(tz=dt.UTC).strftime('%Y.%m.%d.%H%M%S')
DEFAULT_VERSION = calculate_version()
BASE_REPO_VARS = {
'MASTER_ARCHIVE_REPO': 'yt-dlp/yt-dlp-master-builds',
-192
View File
@@ -1,192 +0,0 @@
#!/usr/bin/env python3
"""
Simple parser for spec compliant toml files
A simple toml parser for files that comply with the spec.
Should only be used to parse `pyproject.toml` for `install_deps.py`.
IMPORTANT: INVALID FILES OR MULTILINE STRINGS ARE NOT SUPPORTED!
"""
from __future__ import annotations
import datetime as dt
import json
import re
import typing
WS = r'(?:[\ \t]*)'
STRING_RE = re.compile(r'"(?:\\.|[^\\"\n])*"|\'[^\'\n]*\'')
SINGLE_KEY_RE = re.compile(rf'{STRING_RE.pattern}|[A-Za-z0-9_-]+')
KEY_RE = re.compile(rf'{WS}(?:{SINGLE_KEY_RE.pattern}){WS}(?:\.{WS}(?:{SINGLE_KEY_RE.pattern}){WS})*')
EQUALS_RE = re.compile(rf'={WS}')
WS_RE = re.compile(WS)
_SUBTABLE = rf'(?P<subtable>^\[(?P<is_list>\[)?(?P<path>{KEY_RE.pattern})\]\]?)'
EXPRESSION_RE = re.compile(rf'^(?:{_SUBTABLE}|{KEY_RE.pattern}=)', re.MULTILINE)
LIST_WS_RE = re.compile(rf'{WS}((#[^\n]*)?\n{WS})*')
LEFTOVER_VALUE_RE = re.compile(r'[^,}\]\t\n#]+')
def parse_key(value: str):
for match in SINGLE_KEY_RE.finditer(value):
if match[0][0] == '"':
yield json.loads(match[0])
elif match[0][0] == '\'':
yield match[0][1:-1]
else:
yield match[0]
def get_target(root: dict, paths: list[str], is_list=False):
target = root
for index, key in enumerate(paths, 1):
use_list = is_list and index == len(paths)
result = target.get(key)
if result is None:
result = [] if use_list else {}
target[key] = result
if isinstance(result, dict):
target = result
elif use_list:
target = {}
result.append(target)
else:
target = result[-1]
assert isinstance(target, dict)
return target
def parse_enclosed(data: str, index: int, end: str, ws_re: re.Pattern):
index += 1
if match := ws_re.match(data, index):
index = match.end()
while data[index] != end:
index = yield True, index
if match := ws_re.match(data, index):
index = match.end()
if data[index] == ',':
index += 1
if match := ws_re.match(data, index):
index = match.end()
assert data[index] == end
yield False, index + 1
def parse_value(data: str, index: int):
result: dict[str, typing.Any] | list[typing.Any]
if data[index] == '[':
result = []
indices = parse_enclosed(data, index, ']', LIST_WS_RE)
valid, index = next(indices)
while valid:
index, value = parse_value(data, index)
result.append(value)
valid, index = indices.send(index)
return index, result
if data[index] == '{':
result = {}
indices = parse_enclosed(data, index, '}', WS_RE)
valid, index = next(indices)
while valid:
valid, index = indices.send(parse_kv_pair(data, index, result))
return index, result
if match := STRING_RE.match(data, index):
return match.end(), json.loads(match[0]) if match[0][0] == '"' else match[0][1:-1]
match = LEFTOVER_VALUE_RE.match(data, index)
assert match
value = match[0].strip()
for func in [
int,
float,
dt.time.fromisoformat,
dt.date.fromisoformat,
dt.datetime.fromisoformat,
{'true': True, 'false': False}.get,
]:
try:
value = func(value) # type: ignore[operator]
break
except Exception:
pass
return match.end(), value
def parse_kv_pair(data: str, index: int, target: dict):
match = KEY_RE.match(data, index)
if not match:
return None
*keys, key = parse_key(match[0])
match = EQUALS_RE.match(data, match.end())
assert match
index = match.end()
index, value = parse_value(data, index)
get_target(target, keys)[key] = value
return index
def parse_toml(data: str):
root: dict[str, typing.Any] = {}
target = root
index = 0
while True:
match = EXPRESSION_RE.search(data, index)
if not match:
break
if match.group('subtable'):
index = match.end()
path, is_list = match.group('path', 'is_list')
target = get_target(root, list(parse_key(path)), bool(is_list))
continue
index = parse_kv_pair(data, match.start(), target)
assert index is not None
return root
def main():
import argparse
from pathlib import Path
parser = argparse.ArgumentParser()
parser.add_argument('infile', type=Path, help='The TOML file to read as input')
args = parser.parse_args()
with args.infile.open('r', encoding='utf-8') as file:
data = file.read()
def default(obj):
if isinstance(obj, (dt.date, dt.time, dt.datetime)):
return obj.isoformat()
print(json.dumps(parse_toml(data), default=default))
if __name__ == '__main__':
main()
-835
View File
@@ -1,835 +0,0 @@
#!/usr/bin/env python3
from __future__ import annotations
# Allow direct execution
import os
import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import collections.abc
import contextlib
import dataclasses
import hashlib
import io
import itertools
import json
import pathlib
import re
import typing
import urllib.parse
import zipfile
from devscripts.tomlparse import parse_toml
from devscripts.utils import (
call_github_api,
request,
run_process,
zipf_files_and_folders,
)
BASE_PATH = pathlib.Path(__file__).parent.parent
PYPROJECT_PATH = BASE_PATH / 'pyproject.toml'
MAKEFILE_PATH = BASE_PATH / 'Makefile'
LOCKFILE_PATH = BASE_PATH / 'uv.lock'
REQUIREMENTS_PATH = BASE_PATH / 'bundle/requirements'
REQS_OUTPUT_TMPL = '{}.txt'
EXTRAS_TABLE = 'project.optional-dependencies'
GROUPS_TABLE = 'dependency-groups'
PINNED_EXTRAS = {
'pin': 'default',
'pin-curl-cffi': 'curl-cffi',
'pin-secretstorage': 'secretstorage',
'pin-deno': 'deno',
}
EJS_ASSETS = {
'yt.solver.lib.js': False,
'yt.solver.lib.min.js': False,
'yt.solver.deno.lib.js': True,
'yt.solver.bun.lib.js': True,
'yt.solver.core.min.js': False,
'yt.solver.core.js': True,
}
EJS_TEMPLATE = '''\
# This file is generated by devscripts/update_requirements.py. DO NOT MODIFY!
VERSION = {version!r}
HASHES = {{
{hash_mapping}
}}
'''
@dataclasses.dataclass
class Target:
extras: list[str] = dataclasses.field(default_factory=list)
groups: list[str] = dataclasses.field(default_factory=list)
prune_packages: list[str] = dataclasses.field(default_factory=list)
omit_packages: list[str] = dataclasses.field(default_factory=list)
BUNDLE_TARGETS = {
'default': Target(
extras=['default'],
# PyPy bundles cffi, which is a transitive dep of brotlicffi, which is only required for PyPy
prune_packages=['cffi'],
),
'curl-cffi': Target(
extras=['default', 'curl-cffi'],
),
'linux': Target(
extras=['default', 'curl-cffi', 'secretstorage'],
),
'macos': Target(
extras=['default', 'curl-cffi'],
# NB: Resolve delocate and PyInstaller together since they share dependencies
groups=['delocate', 'pyinstaller'],
# curl-cffi and cffi don't provide universal2 wheels, so only directly install their deps
omit_packages=['curl-cffi', 'cffi'],
),
# We fuse our own universal2 wheels for curl-cffi+cffi, so we need a separate requirements file
'macos-curl_cffi': Target(
extras=['curl-cffi'],
# Only need curl-cffi+cffi in this requirements file; their deps are installed directly
# XXX: Try to keep these in sync with curl-cffi's and cffi's transitive dependencies
prune_packages=['rich'],
omit_packages=['certifi', 'pycparser'],
),
}
PYINSTALLER_BUILDS_TARGETS = {
'win-x64-pyinstaller': 'win_amd64',
'win-x86-pyinstaller': 'win32',
'win-arm64-pyinstaller': 'win_arm64',
}
WELLKNOWN_PACKAGES = {
'deno': {'owner': 'denoland', 'repo': 'deno'},
'protobug': {'owner': 'yt-dlp', 'repo': 'protobug'},
'yt-dlp-ejs': {'owner': 'yt-dlp', 'repo': 'ejs'},
**{
f'pyinstaller[{asset_tag}]': {'owner': 'pyinstaller', 'repo': 'pyinstaller'}
for asset_tag in PYINSTALLER_BUILDS_TARGETS.values()
},
}
def get_extras(pyproject_toml: dict[str, typing.Any], *, resolve: bool = True) -> dict[str, typing.Any]:
project_table = pyproject_toml['project']
extras = project_table.get('optional-dependencies', {})
if not resolve:
return extras
project_name = project_table['name']
recursive_pattern = re.compile(rf'{project_name}\[(?P<extra_name>[^]]+)\]')
def yield_deps_from_extra(extra):
for dep in extra:
if mobj := recursive_pattern.fullmatch(dep):
yield from extras[mobj.group('extra_name')]
else:
yield dep
return {extra_name: list(yield_deps_from_extra(extra)) for extra_name, extra in extras.items()}
def get_groups(pyproject_toml: dict[str, typing.Any], *, resolve: bool = True) -> dict[str, typing.Any]:
groups = pyproject_toml.get('dependency-groups', {})
if not resolve:
return groups
def yield_deps_from_group(group):
for dep in group:
if isinstance(dep, dict):
yield from yield_deps_from_group(groups[dep['include-group']])
else:
yield dep
return {group_name: list(yield_deps_from_group(group)) for group_name, group in groups.items()}
def call_pypi_api(project: str):
print(f'Fetching package info from PyPI API: {project}', file=sys.stderr)
headers = {
'Accept': 'application/json',
'User-Agent': 'yt-dlp',
}
with request(f'https://pypi.org/pypi/{project}/json', headers=headers) as resp:
return json.load(resp)
def fetch_latest_github_release(owner: str, repo: str):
print(f'Fetching latest release from Github API: {owner}/{repo}', file=sys.stderr)
return call_github_api(f'/repos/{owner}/{repo}/releases/latest')
def fetch_github_tags(
owner: str,
repo: str,
*,
fetch_tags: list[str] | None = None,
):
needed_tags = set(fetch_tags or [])
results = {}
for page in itertools.count(1):
print(f'Fetching tags list page {page} from Github API: {owner}/{repo}', file=sys.stderr)
tags = call_github_api(
f'/repos/{owner}/{repo}/tags',
query={'per_page': '100', 'page': page})
if not tags:
break
if not fetch_tags:
# Fetch all tags
results.update({tag['name']: tag for tag in tags})
continue
for tag in tags:
clean_tag = tag['name'].removeprefix('v')
possible_matches = {tag['name'], clean_tag}
# Normalize calver tags like 2024.01.01 to 2024.1.1
with contextlib.suppress(ValueError):
possible_matches.add('.'.join(map(str, map(int, clean_tag.split('.')))))
for name in possible_matches:
if name in needed_tags:
needed_tags.remove(name)
results[name] = tag
break # from inner loop
if not needed_tags:
break
if not needed_tags:
break
return results
def generate_table_lines(
table_name: str,
table: dict[str, str | bool | int | float | list[str | dict[str, str]]],
) -> collections.abc.Iterator[str]:
SUPPORTED_TYPES = (str, bool, int, float, list)
yield f'[{table_name}]\n'
for name, value in table.items():
if not isinstance(value, SUPPORTED_TYPES):
raise TypeError(
f'expected {"/".join(t.__name__ for t in SUPPORTED_TYPES)} value, '
f'got {type(value).__name__}')
if not isinstance(value, list):
yield f'{name} = {json.dumps(value)}\n'
continue
yield f'{name} = ['
if value:
yield '\n'
for element in value:
yield ' '
if isinstance(element, dict):
yield '{ ' + ', '.join(f'{k} = {json.dumps(v)}' for k, v in element.items()) + ' }'
else:
yield f'"{element}"'
yield ',\n'
yield ']\n'
yield '\n'
def replace_table_in_pyproject(
pyproject_text: str,
table_name: str,
table: dict[str, str | bool | int | float | list[str | dict[str, str]]],
) -> collections.abc.Iterator[str]:
INSIDE = 1
BEYOND = 2
state = 0
for line in pyproject_text.splitlines(True):
if state == INSIDE:
if line == '\n':
state = BEYOND
continue
if line != f'[{table_name}]\n' or state == BEYOND:
yield line
continue
yield from generate_table_lines(table_name, table)
state = INSIDE
def modify_and_write_pyproject(
pyproject_text: str,
table_name: str,
table: dict[str, str | bool | int | float | list[str | dict[str, str]]],
) -> None:
with PYPROJECT_PATH.open(mode='w') as f:
f.writelines(replace_table_in_pyproject(pyproject_text, table_name, table))
def run_uv_export(
*,
extras: list[str] | None = None,
groups: list[str] | None = None,
prune_packages: list[str] | None = None,
omit_packages: list[str] | None = None,
bare: bool = False,
output_file: pathlib.Path | None = None,
) -> str:
return run_process(
'uv', 'export',
'--no-python-downloads',
'--quiet',
'--no-progress',
'--color=never',
'--format=requirements.txt',
'--frozen',
'--refresh',
'--no-emit-project',
'--no-default-groups',
'--no-header',
*(f'--extra={extra}' for extra in (extras or [])),
*(f'--group={group}' for group in (groups or [])),
*(f'--prune={package}' for package in (prune_packages or [])),
*(f'--no-emit-package={package}' for package in (omit_packages or [])),
*(['--no-annotate', '--no-hashes'] if bare else []),
*([f'--output-file={output_file.relative_to(BASE_PATH)}'] if output_file else []),
).stdout
def run_pip_compile(
*args: str,
input_line: str,
output_file: pathlib.Path | None = None,
env: dict[str, str] | None = None,
) -> str:
return run_process(
'uv', 'pip', 'compile',
'--no-python-downloads',
'--quiet',
'--no-progress',
'--color=never',
'--format=requirements.txt',
'--refresh',
'--generate-hashes',
'--no-strip-markers',
'--no-header',
'--universal',
*args,
*([f'--output-file={output_file.relative_to(BASE_PATH)}'] if output_file else []),
'-', # Read from stdin
input=f'{input_line}\n',
env=env,
).stdout
def makefile_variables(
prefix: str,
filetypes: list[str] | None = None,
*,
version: str | None = None,
name: str | None = None,
digest: str | None = None,
data: bytes = b'',
keys_only: bool = False,
) -> dict[str, str | None]:
variables = {
f'{prefix}_VERSION': version,
f'{prefix}_WHEEL_NAME': name,
f'{prefix}_WHEEL_HASH': digest,
}
for ft in filetypes or []:
variables.update({
f'{prefix}_{ft.upper()}_FOLDERS': None,
f'{prefix}_{ft.upper()}_FILES': None,
})
if keys_only:
return variables
if not all(arg is not None for arg in (version, name, digest, not filetypes or data)):
raise ValueError(
f'makefile_variables requires version, name, digest, {"and data, " if filetypes else ""}OR keys_only=True')
if filetypes:
with io.BytesIO(data) as buf, zipfile.ZipFile(buf) as zipf:
for ft in filetypes:
files, folders = zipf_files_and_folders(zipf, f'*.{ft.lower()}')
variables[f'{prefix}_{ft.upper()}_FOLDERS'] = ' '.join(folders)
variables[f'{prefix}_{ft.upper()}_FILES'] = ' '.join(files)
return variables
def ejs_makefile_variables(**kwargs) -> dict[str, str | None]:
return makefile_variables('EJS', filetypes=['PY', 'JS'], **kwargs)
def update_ejs(
verify: bool = False,
) -> dict[str, tuple[str, str] | tuple[str, None] | tuple[None, str]] | None:
PACKAGE_NAME = 'yt-dlp-ejs'
PREFIX = f' "{PACKAGE_NAME}=='
LIBRARY_NAME = PACKAGE_NAME.replace('-', '_')
PACKAGE_PATH = BASE_PATH / 'yt_dlp/extractor/youtube/jsc/_builtin/vendor'
current_version = None
with PYPROJECT_PATH.open() as file:
for line in file:
if not line.startswith(PREFIX):
continue
current_version, _, _ = line.removeprefix(PREFIX).partition('"')
if not current_version:
raise ValueError(f'{PACKAGE_NAME} dependency line could not be found')
makefile_info = ejs_makefile_variables(keys_only=True)
prefixes = tuple(f'{key} = ' for key in makefile_info)
with MAKEFILE_PATH.open() as file:
for line in file:
if not line.startswith(prefixes):
continue
key, _, val = line.partition(' = ')
makefile_info[key] = val.rstrip()
info = fetch_latest_github_release('yt-dlp', 'ejs')
version = info['tag_name']
if version == current_version:
print(f'{PACKAGE_NAME} is up to date! ({version})', file=sys.stderr)
return None
print(f'Updating {PACKAGE_NAME} from {current_version} to {version}', file=sys.stderr)
hashes = []
wheel_info = {}
for asset in info['assets']:
name = asset['name']
digest = asset['digest']
is_wheel = name.startswith(f'{LIBRARY_NAME}-') and name.endswith('.whl')
if not is_wheel and name not in EJS_ASSETS:
continue
with request(asset['browser_download_url']) as resp:
data = resp.read()
# verify digest from github
algo, _, expected = digest.partition(':')
hexdigest = hashlib.new(algo, data).hexdigest()
if hexdigest != expected:
raise ValueError(f'downloaded attest mismatch ({hexdigest!r} != {expected!r})')
if is_wheel:
wheel_info = ejs_makefile_variables(version=version, name=name, digest=digest, data=data)
continue
# calculate sha3-512 digest
asset_hash = hashlib.sha3_512(data).hexdigest()
hashes.append(f' {name!r}: {asset_hash!r},')
if EJS_ASSETS[name]:
(PACKAGE_PATH / name).write_bytes(data)
hash_mapping = '\n'.join(hashes)
if missing_assets := [asset_name for asset_name in EJS_ASSETS if asset_name not in hash_mapping]:
raise ValueError(f'asset(s) not found in release: {", ".join(missing_assets)}')
if missing_fields := [key for key in makefile_info if not wheel_info.get(key)]:
raise ValueError(f'wheel info not found in release: {", ".join(missing_fields)}')
(PACKAGE_PATH / '_info.py').write_text(EJS_TEMPLATE.format(
version=version,
hash_mapping=hash_mapping,
))
content = PYPROJECT_PATH.read_text()
updated = content.replace(PREFIX + current_version, PREFIX + version)
PYPROJECT_PATH.write_text(updated)
makefile = MAKEFILE_PATH.read_text()
for key in wheel_info:
makefile = makefile.replace(f'{key} = {makefile_info[key]}', f'{key} = {wheel_info[key]}')
MAKEFILE_PATH.write_text(makefile)
return update_requirements(upgrade_only=PACKAGE_NAME, verify=verify)
@dataclasses.dataclass(frozen=True)
class PythonDependency:
name: str
exact_version: str
direct_reference: str | None
specifier: str | None
markers: str | None
def parse_version_from_dist(filename: str, name: str) -> str:
# Ref: https://packaging.python.org/en/latest/specifications/binary-distribution-format/#escaping-and-unicode
normalized_name = re.sub(r'[-_.]+', '-', name).lower().replace('-', '_')
# Ref: https://packaging.python.org/en/latest/specifications/version-specifiers/#version-specifiers
if mobj := re.fullmatch(rf'{normalized_name}-(?P<version>[^-]+)(?:-.+\.whl|\.tar\.gz)', filename):
return mobj.group('version')
raise ValueError(f'unable to parse version from distribution filename: {filename}')
def parse_dependency(line: str) -> PythonDependency:
# Ref: https://packaging.python.org/en/latest/specifications/name-normalization/
NAME_RE = re.compile(r'^(?P<name>[A-Z0-9](?:[A-Z0-9._-]*[A-Z0-9])?)', re.IGNORECASE)
line = line.rstrip().removesuffix('\\')
mobj = NAME_RE.match(line)
if not mobj:
raise ValueError(f'unable to parse PythonDependency.name from line:\n {line}')
name = mobj.group('name')
rest = line[len(name):].lstrip()
specifier_or_direct_reference, _, markers = map(str.strip, rest.partition(';'))
specifier, _, direct_reference = map(str.strip, specifier_or_direct_reference.partition('@'))
exact_version = None
if ',' not in specifier and specifier.startswith('=='):
exact_version = specifier[2:]
# Ref: https://packaging.python.org/en/latest/specifications/binary-distribution-format/
if direct_reference and not exact_version:
filename = urllib.parse.urlparse(direct_reference).path.rpartition('/')[2]
if filename.endswith(('.tar.gz', '.whl')):
exact_version = parse_version_from_dist(filename, name)
if not exact_version:
raise ValueError(f'unable to parse PythonDependency.exact_version from line:\n {line}')
return PythonDependency(
name=name,
exact_version=exact_version,
direct_reference=direct_reference or None,
specifier=specifier or None,
markers=markers or None,
)
def package_diff_dict(
old_dict: dict[str, str],
new_dict: dict[str, str],
) -> dict[str, tuple[str, str] | tuple[str, None] | tuple[None, str]]:
"""
@param old_dict: Dictionary w/ package names as keys and old package versions as values
@param new_dict: Dictionary w/ package names as keys and new package versions as values
@returns Dictionary w/ package names as keys and tuples of (old_ver, new_ver) as values
"""
ret_dict: dict[str, tuple[str, str] | tuple[str, None] | tuple[None, str]] = {}
for name, new_version in new_dict.items():
if name not in old_dict:
ret_dict[name] = (None, new_version)
continue
old_version = old_dict[name]
if new_version != old_version:
ret_dict[name] = (old_version, new_version)
for name, old_version in old_dict.items():
if name not in new_dict:
ret_dict[name] = (old_version, None)
return ret_dict
def get_lock_packages(lock: dict[str, typing.Any], ignore_names: list[str] | None = None) -> dict[str, str]:
return {
package['name']: package['version']
for package in lock['package']
if package.get('version') and package['name'] not in (ignore_names or [])
}
def evaluate_requirements_txt(
old_txt: str,
new_txt: str,
) -> dict[str, tuple[str, str] | tuple[str, None] | tuple[None, str]]:
old_dict: dict[str, str] = {}
new_dict: dict[str, str] = {}
for txt, dct in [(old_txt, old_dict), (new_txt, new_dict)]:
for line in txt.splitlines():
if not line.strip() or line.startswith(('#', ' ')):
continue
dep = parse_dependency(line)
dct.update({dep.name: dep.exact_version})
return package_diff_dict(old_dict, new_dict)
def update_requirements(
upgrade_only: str | None = None,
verify: bool = False,
) -> dict[str, tuple[str, str] | tuple[str, None] | tuple[None, str]]:
# Are we upgrading all packages or only one (e.g. 'yt-dlp-ejs' or 'protobug')?
upgrade_arg = f'--upgrade-package={upgrade_only}' if upgrade_only else '--upgrade'
pyproject_text = PYPROJECT_PATH.read_text()
pyproject_toml = parse_toml(pyproject_text)
package_name = pyproject_toml['project']['name']
extras = get_extras(pyproject_toml)
# Remove pinned extras so they don't muck up the lockfile during generation/upgrade
for pinned_extra_name in PINNED_EXTRAS:
extras.pop(pinned_extra_name, None)
# Write an intermediate pyproject.toml to use for generating lockfile and bundle requirements
modify_and_write_pyproject(pyproject_text, table_name=EXTRAS_TABLE, table=extras)
old_lock = None
if LOCKFILE_PATH.is_file():
old_lock = parse_toml(LOCKFILE_PATH.read_text())
# If verifying, set UV_EXCLUDE_NEWER env var with the last timestamp recorded in uv.lock
env = None
if verify or upgrade_only in pyproject_toml['tool']['uv']['exclude-newer-package']:
env = os.environ.copy()
env['UV_EXCLUDE_NEWER'] = old_lock['options']['exclude-newer'] # type: ignore[index]
print(f'Setting UV_EXCLUDE_NEWER={env["UV_EXCLUDE_NEWER"]}', file=sys.stderr)
# Generate/upgrade lockfile
print(f'Running: uv lock {upgrade_arg}', file=sys.stderr)
run_process('uv', 'lock', upgrade_arg, env=env)
# Record diff in uv.lock packages
old_packages = get_lock_packages(old_lock, [package_name]) if old_lock else {}
new_packages = get_lock_packages(parse_toml(LOCKFILE_PATH.read_text()), [package_name])
all_updates = package_diff_dict(old_packages, new_packages)
# Update Windows PyInstaller requirements; need to compare before & after .txt's for reporting
if not upgrade_only:
info = fetch_latest_github_release('yt-dlp', 'Pyinstaller-Builds')
for target_suffix, asset_tag in PYINSTALLER_BUILDS_TARGETS.items():
asset_info = next(asset for asset in info['assets'] if asset_tag in asset['name'])
requirements_path = REQUIREMENTS_PATH / REQS_OUTPUT_TMPL.format(target_suffix)
if requirements_path.is_file():
old_requirements_txt = requirements_path.read_text()
else:
old_requirements_txt = ''
run_pip_compile(
upgrade_arg,
input_line=f'pyinstaller @ {asset_info["browser_download_url"]}',
output_file=requirements_path,
env=env)
new_requirements_txt = requirements_path.read_text()
if asset_info['digest'] not in new_requirements_txt:
raise ValueError(
f'expected pyinstaller wheel hash {asset_info["digest"]} '
f'not found in {requirements_path}')
diff_dict = evaluate_requirements_txt(old_requirements_txt, new_requirements_txt)
if pyinstaller_diff := diff_dict.get('pyinstaller'):
# NB: this depends on 'pyinstaller[asset_tag]' keys in WELLKNOWN_PACKAGES
all_updates.update({f'pyinstaller[{asset_tag}]': pyinstaller_diff})
# Generate new pinned extras; any updates to these are already recorded w/ uv.lock package diff
for pinned_name, extra_name in PINNED_EXTRAS.items():
extras[pinned_name] = run_uv_export(
extras=[extra_name],
bare=True,
# PyPy bundles cffi, which is a transitive dep of brotlicffi, which is only required for PyPy
prune_packages=['cffi'] if extra_name == 'default' else [],
).splitlines()
# Write the finalized pyproject.toml
modify_and_write_pyproject(pyproject_text, table_name=EXTRAS_TABLE, table=extras)
# Generate/upgrade final lockfile that includes pinned extras
print('Running: uv lock', file=sys.stderr)
run_process('uv', 'lock', env=env)
# Export bundle requirements; any updates to these are already recorded w/ uv.lock package diff
for target_suffix, target in BUNDLE_TARGETS.items():
run_uv_export(
extras=target.extras,
groups=target.groups,
prune_packages=target.prune_packages,
omit_packages=target.omit_packages,
output_file=REQUIREMENTS_PATH / REQS_OUTPUT_TMPL.format(target_suffix))
# Export group requirements; any updates to these are already recorded w/ uv.lock package diff
for group in get_groups(pyproject_toml, resolve=False):
run_uv_export(
groups=[group],
output_file=REQUIREMENTS_PATH / REQS_OUTPUT_TMPL.format(group))
return all_updates
def generate_report(
all_updates: dict[str, tuple[str | None, str | None]],
) -> collections.abc.Iterator[str]:
GITHUB_RE = re.compile(r'https://github\.com/(?P<owner>[0-9a-zA-Z_-]+)/(?P<repo>[0-9a-zA-Z_-]+)')
yield 'package | old | new | diff | changelog'
yield '--------|-----|-----|------|----------'
for package, (old, new) in sorted(all_updates.items()):
if package in WELLKNOWN_PACKAGES:
github_info = WELLKNOWN_PACKAGES[package]
changelog = ''
else:
project_urls = call_pypi_api(package)['info']['project_urls']
github_info = next((
mobj.groupdict() for url in project_urls.values()
if (mobj := GITHUB_RE.match(url))), {})
changelog = next((
url for key, url in project_urls.items()
if key.lower().startswith(('change', 'history', 'release '))), '')
if changelog:
name = urllib.parse.urlparse(changelog).path.rstrip('/').rpartition('/')[2] or 'changelog'
changelog = f'[{name}](<{changelog}>)'
md_old = old = old or ''
md_new = new = new or ''
if old and new:
# bolden and italicize the differing parts
old_parts = old.split('.')
new_parts = new.split('.')
offset = None
for index, (old_part, new_part) in enumerate(zip(old_parts, new_parts, strict=False)):
if old_part != new_part:
offset = index
break
if offset is not None:
md_old = '.'.join(old_parts[:offset]) + '.***' + '.'.join(old_parts[offset:]) + '***'
md_old = md_old.lstrip('.')
md_new = '.'.join(new_parts[:offset]) + '.***' + '.'.join(new_parts[offset:]) + '***'
md_new = md_new.lstrip('.')
compare = ''
if github_info:
tags_info = fetch_github_tags(
github_info['owner'], github_info['repo'], fetch_tags=[old, new])
old_tag = tags_info.get(old) and tags_info[old]['name']
new_tag = tags_info.get(new) and tags_info[new]['name']
github_url = 'https://github.com/{owner}/{repo}'.format(**github_info)
if new_tag:
md_new = f'[{md_new}](<{github_url}/releases/tag/{new_tag}>)'
if old_tag:
md_old = f'[{md_old}](<{github_url}/releases/tag/{old_tag}>)'
if new_tag and old_tag:
compare = f'[`{old_tag}...{new_tag}`](<{github_url}/compare/{old_tag}...{new_tag}>)'
yield ' | '.join((
# Strip the [win*] tag from package in the URL (e.g. pyinstaller[win32])
f'[**`{package}`**](<https://pypi.org/project/{package.split("[")[0]}/>)',
md_old,
md_new,
compare,
changelog,
))
def make_pull_request_description(all_updates: dict[str, tuple[str | None, str | None]]) -> str:
return '\n'.join((
'<!-- BEGIN update_requirements generated section -->\n',
*generate_report(all_updates),
'\n<!-- END update_requirements generated section -->\n\n',
))
def make_commit_message(all_updates: dict[str, tuple[str | None, str | None]]) -> str:
return '\n\n'.join((
make_commit_title(all_updates),
make_commit_body(all_updates),
))
def make_commit_title(all_updates: dict[str, tuple[str | None, str | None]]) -> str:
count = len(all_updates)
return f'[build] Update {count} dependenc{"ies" if count > 1 else "y"}'
def make_commit_body(all_updates: dict[str, tuple[str | None, str | None]]) -> str:
return '\n'.join(make_commit_line(package, old, new) for package, (old, new) in all_updates.items())
def make_commit_line(package: str, old: str | None, new: str | None) -> str:
if old is None:
return f'* Add {package} {new}'
if new is None:
return f'* Remove {package} {old}'
return f'* Bump {package} {old} => {new}'
def table_a_raza(header: tuple[str, ...], rows: list[tuple[str, ...]]) -> collections.abc.Generator[str]:
widths = [len(col) for col in header]
for row in rows:
for index, (width, col) in enumerate(zip(widths, row, strict=True)):
if len(col) > width:
widths[index] = len(col)
yield ' | '.join(col.ljust(width) for width, col in zip(widths, header, strict=True))
yield '-|-'.join(''.ljust(width, '-') for width in widths)
for row in rows:
yield ' | '.join(col.ljust(width) for width, col in zip(widths, row, strict=True))
def parse_args():
import argparse
parser = argparse.ArgumentParser(description='generate/update lockfile and requirements')
parser.add_argument(
'upgrade_only', nargs='?', metavar='PACKAGE',
help='only upgrade this package. (by default, all packages will be upgraded)')
parser.add_argument(
'--verify', action='store_true',
help='only verify the update(s) using the previously recorded cooldown timestamp')
parser.add_argument(
'--no-markdown-reports', action='store_true',
help='do not generate markdown PR descriptions; avoids optional PyPI/GitHub API calls')
return parser.parse_args()
def main():
args = parse_args()
if args.upgrade_only in ('ejs', 'yt-dlp-ejs'):
all_updates = update_ejs(verify=args.verify)
else:
all_updates = update_requirements(upgrade_only=args.upgrade_only, verify=args.verify)
if all_updates is None:
return 1
elif not all_updates:
print('All requirements are up-to-date', file=sys.stderr)
return 0
if args.verify:
print('Verification failed! Updates were made:', file=sys.stderr)
for row in table_a_raza(('package', 'old', 'new'), [
(package, old or '', new or '')
for package, (old, new) in all_updates.items()
]):
print(row)
return 1
else:
if not args.no_markdown_reports:
print(make_pull_request_description(all_updates))
print(make_commit_message(all_updates))
return 0
if __name__ == '__main__':
sys.exit(main())
+1 -53
View File
@@ -1,17 +1,8 @@
from __future__ import annotations
import argparse
import contextlib
import datetime as dt
import functools
import itertools
import json
import os
import re
import subprocess
import urllib.parse
import urllib.request
import zipfile
def read_file(fname):
@@ -36,7 +27,7 @@ def calculate_version(version=None, fname='yt_dlp/version.py'):
return version
revision = version
version = dt.datetime.now(dt.timezone.utc).strftime('%Y.%m.%d')
version = dt.datetime.now(dt.UTC).strftime('%Y.%m.%d')
if revision:
assert re.fullmatch(r'[0-9]+', revision), 'Revision must be numeric'
@@ -73,46 +64,3 @@ def run_process(*args, **kwargs):
kwargs.setdefault('encoding', 'utf-8')
kwargs.setdefault('errors', 'replace')
return subprocess.run(args, **kwargs)
def request(url: str, *, headers: dict | None = None):
req = urllib.request.Request(url, headers=headers or {})
return contextlib.closing(urllib.request.urlopen(req))
def call_github_api(path: str, *, query: dict | None = None) -> dict | list:
API_BASE_URL = 'https://api.github.com/'
assert not path.startswith(('https://', 'http://')) or path.startswith(API_BASE_URL)
url = urllib.parse.urlparse(urllib.parse.urljoin(API_BASE_URL, path))
qs = urllib.parse.urlencode({
**urllib.parse.parse_qs(url.query),
**(query or {}),
}, True)
headers = {
'Accept': 'application/vnd.github+json',
'User-Agent': 'yt-dlp',
'X-GitHub-Api-Version': '2026-03-10',
}
if gh_token := os.getenv('GH_TOKEN'):
headers['Authorization'] = f'Bearer {gh_token}'
with request(urllib.parse.urlunparse(url._replace(query=qs)), headers=headers) as resp:
return json.load(resp)
def zipf_files_and_folders(zipf: zipfile.ZipFile, glob: str = '*') -> tuple[list[str], list[str]]:
files = []
folders = []
path = zipfile.Path(zipf)
for f in itertools.chain(path.glob(glob), path.rglob(glob)):
if not f.is_file():
continue
files.append(f.at) # type: ignore[attr-defined]
folder = f.parent.at.rstrip('/') # type: ignore[attr-defined]
if folder and folder not in folders:
folders.append(folder)
return files, folders
+37 -29
View File
@@ -15,7 +15,7 @@ maintainers = [
]
description = "A feature-rich command-line audio/video downloader"
readme = "README.md"
requires-python = ">=3.10"
requires-python = ">=3.11"
keywords = [
"cli",
"downloader",
@@ -32,11 +32,11 @@ classifiers = [
"Environment :: Console",
"Programming Language :: Python",
"Programming Language :: Python :: 3 :: Only",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
"Programming Language :: Python :: 3.14",
"Programming Language :: Python :: 3.15",
"Programming Language :: Python :: Implementation",
"Programming Language :: Python :: Implementation :: CPython",
"Programming Language :: Python :: Implementation :: PyPy",
@@ -49,7 +49,7 @@ dependencies = []
default = [
"brotli ; implementation_name == 'cpython' and sys_platform != 'ios'",
"brotlicffi ; implementation_name != 'cpython'",
"certifi",
"certifi>=2026.10.19",
"mutagen",
"pycryptodomex",
"requests>=2.32.2,<3",
@@ -58,47 +58,43 @@ default = [
"yt-dlp-ejs==0.8.0",
]
curl-cffi = [
"curl-cffi>=0.5.10,!=0.6.*,!=0.7.*,!=0.8.*,!=0.9.*,<0.16 ; implementation_name == 'cpython'",
"curl-cffi>=0.5.10,!=0.6.*,!=0.7.*,!=0.8.*,!=0.9.*,<0.18 ; implementation_name == 'cpython'",
]
secretstorage = [
"secretstorage",
]
deno = [
"deno>=2.6.6",
"deno>=2.9.8",
]
pin = [
"brotli==1.2.0 ; implementation_name == 'cpython' and sys_platform != 'ios'",
"brotlicffi==1.2.0.1 ; implementation_name != 'cpython'",
"certifi==2026.6.17",
"charset-normalizer==3.4.7",
"idna==3.18",
"brotli==1.2.1 ; implementation_name == 'cpython' and sys_platform != 'ios'",
"brotlicffi==1.2.1.0 ; implementation_name != 'cpython'",
"certifi==2026.10.23",
"charset-normalizer==3.5.2",
"idna==3.20",
"mutagen==1.48.1",
"pycryptodomex==3.23.0",
"pycparser==3.11 ; implementation_name != 'PyPy' and implementation_name != 'cpython'",
"pycryptodomex==3.24.1",
"requests==2.34.2",
"urllib3==2.7.0",
"websockets==16.0",
"urllib3==2.8.0",
"websockets==17.3",
"yt-dlp-ejs==0.8.0",
]
pin-curl-cffi = [
"certifi==2026.6.17 ; implementation_name == 'cpython'",
"cffi==2.0.0 ; implementation_name == 'cpython'",
"curl-cffi==0.15.0 ; implementation_name == 'cpython'",
"markdown-it-py==4.2.0 ; implementation_name == 'cpython'",
"mdurl==0.1.2 ; implementation_name == 'cpython'",
"pycparser==3.0 ; implementation_name == 'cpython'",
"pygments==2.20.0 ; implementation_name == 'cpython'",
"rich==15.0.0 ; implementation_name == 'cpython'",
"certifi==2026.10.23 ; implementation_name == 'cpython'",
"cffi==2.1.1 ; implementation_name == 'cpython'",
"curl-cffi==0.17.0 ; implementation_name == 'cpython'",
"pycparser==3.11 ; implementation_name == 'cpython'",
]
pin-secretstorage = [
"cffi==2.0.0 ; platform_python_implementation != 'PyPy'",
"cryptography==49.0.0",
"cffi==2.1.1 ; platform_python_implementation != 'PyPy'",
"cryptography==50.0.2",
"jeepney==0.9.0",
"pycparser==3.0 ; implementation_name != 'PyPy' and platform_python_implementation != 'PyPy'",
"pycparser==3.11 ; implementation_name != 'PyPy' and platform_python_implementation != 'PyPy'",
"secretstorage==3.5.0",
"typing-extensions==4.15.0 ; python_full_version < '3.11'",
]
pin-deno = [
"deno==2.8.3",
"deno==2.9.8",
]
[dependency-groups]
@@ -108,7 +104,7 @@ build = [
]
static-analysis = [
"autopep8~=2.0",
"ruff~=0.15.0",
"ruff~=0.17.0",
]
test = [
"pytest~=9.0",
@@ -120,7 +116,7 @@ dev = [
{include-group = "test"},
]
pyinstaller = [
"pyinstaller>=6.17.0",
"pyinstaller==6.22.0",
]
delocate = [
"delocate>=0.13.0 ; sys_platform == 'darwin'",
@@ -240,11 +236,11 @@ run-cov = "echo Code coverage not implemented && exit 1"
[[tool.hatch.envs.hatch-test.matrix]]
python = [
"3.10",
"3.11",
"3.12",
"3.13",
"3.14",
"3.15",
"pypy3.11",
]
@@ -252,7 +248,17 @@ python = [
exclude-newer = "7 days"
[tool.uv.exclude-newer-package]
brotli = false # temporary
brotlicffi = false # temporary
certifi = false # temporary
curl-cffi = false # temporary
deno = false # temporary
pip = false
protobug = false
pyinstaller = false
setuptools = false # temporary
uv = false
virtualenv = false # temporary
yt-dlp-ejs = false
[tool.ruff]
@@ -396,6 +402,8 @@ banned-from = [
"yt_dlp.utils.intlist_to_bytes".msg = "Use `bytes` instead."
"yt_dlp.utils.jwt_encode_hs256".msg = "Use `yt_dlp.utils.jwt_encode` instead."
"yt_dlp.utils.make_dir".msg = "Use `yt_dlp.utils.make_parent_dirs` instead."
"yt_dlp.utils.number_of_digits".msg = "Do not use"
"yt_dlp.utils.random_uuidv4".msg = "Use `str(uuid.uuid4())` instead."
"yt_dlp.utils.decodeArgument".msg = "Do not use"
"yt_dlp.utils.decodeFilename".msg = "Do not use"
"yt_dlp.utils.encodeFilename".msg = "Do not use"
+7 -4
View File
@@ -84,10 +84,9 @@ The only reliable way to check if a site is supported is to try it.
- **APA**
- **Aparat**
- **apple:​music:connect**: Apple Music Connect
- **ApplePodcasts**
- **apple:podcasts**: Apple Podcasts
- **archive.org**: archive.org video and audio
- **ArcPublishing**
- **ARD**
- **ARDAudiothek**
- **ARDAudiothekPlaylist**
- **ARDMediathek**
@@ -626,8 +625,10 @@ The only reliable way to check if a site is supported is to try it.
- **Kenh14Video**
- **khanacademy**
- **khanacademy:unit**
- **kick:clip**
- **kick:clips**
- **kick:live**
- **kick:videos**
- **kick:vod**
- **Kicker**
- **KickStarter**
@@ -884,6 +885,7 @@ The only reliable way to check if a site is supported is to try it.
- **nhl.com**
- **nick.com**
- **niconico**: [*niconico*](## "netrc machine") ニコニコ動画
- **niconico:channel**: [*niconico*](## "netrc machine")
- **niconico:history**: NicoNico user history or likes. Requires cookies.
- **niconico:live**: [*niconico*](## "netrc machine") ニコニコ生放送
- **niconico:playlist**
@@ -1237,7 +1239,8 @@ The only reliable way to check if a site is supported is to try it.
- **SharePoint**
- **ShemarooMe**
- **Shiey**
- **ShowRoomLive**: (**Currently broken**)
- **showroom:live**: SHOWROOM
- **showroom:vod**
- **ShugiinItvLive**: 衆議院インターネット審議中継
- **ShugiinItvLiveRoom**: 衆議院インターネット審議中継 (中継)
- **ShugiinItvVod**: 衆議院インターネット審議中継 (ビデオライブラリ)
@@ -1429,7 +1432,7 @@ The only reliable way to check if a site is supported is to try it.
- **Tube8**: (**Currently broken**)
- **TubeTuGraz**: [*tubetugraz*](## "netrc machine") tube.tugraz.at
- **TubeTuGrazSeries**: [*tubetugraz*](## "netrc machine")
- **tubitv**: [*tubitv*](## "netrc machine")
- **tubitv**
- **tubitv:series**
- **Tumblr**: [*tumblr*](## "netrc machine")
- **tunein:embed**
+1 -37
View File
@@ -3,7 +3,6 @@ import hashlib
import json
import os.path
import re
import ssl
import sys
import types
@@ -318,36 +317,6 @@ def expect_info_dict(self, got_dict, expected_dict):
'Missing keys in test definition: {}'.format(', '.join(sorted(missing_keys))))
def assertRegexpMatches(self, text, regexp, msg=None):
if hasattr(self, 'assertRegexp'):
return self.assertRegexp(text, regexp, msg)
else:
m = re.match(regexp, text)
if not m:
note = f'Regexp didn\'t match: {regexp!r} not found'
if len(text) < 1000:
note += f' in {text!r}'
if msg is None:
msg = note
else:
msg = note + ', ' + msg
self.assertTrue(m, msg)
def assertGreaterEqual(self, got, expected, msg=None):
if not (got >= expected):
if msg is None:
msg = f'{got!r} not greater than or equal to {expected!r}'
self.assertTrue(got >= expected, msg)
def assertLessEqual(self, got, expected, msg=None):
if not (got <= expected):
if msg is None:
msg = f'{got!r} not less than or equal to {expected!r}'
self.assertTrue(got <= expected, msg)
def assertEqual(self, got, expected, msg=None):
if got != expected:
if msg is None:
@@ -366,12 +335,7 @@ def expect_warnings(ydl, warnings_re):
def http_server_port(httpd):
if os.name == 'java' and isinstance(httpd.socket, ssl.SSLSocket):
# In Jython SSLSocket is not a subclass of socket.socket
sock = httpd.socket.sock
else:
sock = httpd.socket
return sock.getsockname()[1]
return httpd.server_address[1]
def verify_address_availability(address):
+3 -3
View File
@@ -15,7 +15,7 @@ import contextlib
import copy
import json
from test.helper import FakeYDL, assertRegexpMatches, try_rm
from test.helper import FakeYDL, try_rm
from yt_dlp import YoutubeDL
from yt_dlp.extractor.common import InfoExtractor
from yt_dlp.postprocessor.common import PostProcessor
@@ -860,10 +860,10 @@ class TestYoutubeDL(unittest.TestCase):
def test_format_note(self):
ydl = YoutubeDL()
self.assertEqual(ydl._format_note({}), '')
assertRegexpMatches(self, ydl._format_note({
self.assertRegex(ydl._format_note({
'vbr': 10,
}), r'^\s*10k$')
assertRegexpMatches(self, ydl._format_note({
self.assertRegex(ydl._format_note({
'fps': 30,
}), r'^30fps$')
+11 -15
View File
@@ -12,9 +12,7 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import struct
from yt_dlp import compat
from yt_dlp.compat import urllib # isort: split
from yt_dlp.compat import compat_etree_fromstring, compat_expanduser, compat_datetime_from_timestamp
from yt_dlp.compat.urllib.request import getproxies
class TestCompat(unittest.TestCase):
@@ -22,8 +20,6 @@ class TestCompat(unittest.TestCase):
with self.assertWarns(DeprecationWarning):
_ = compat.compat_basestring
self.assertEqual(urllib.request.getproxies, getproxies)
with self.assertWarns(DeprecationWarning):
_ = compat.compat_pycrypto_AES # Must not raise error
@@ -63,41 +59,41 @@ class TestCompat(unittest.TestCase):
def test_compat_datetime_from_timestamp(self):
self.assertEqual(
compat_datetime_from_timestamp(0),
dt.datetime(1970, 1, 1, 0, 0, 0, tzinfo=dt.timezone.utc))
dt.datetime(1970, 1, 1, 0, 0, 0, tzinfo=dt.UTC))
self.assertEqual(
compat_datetime_from_timestamp(1),
dt.datetime(1970, 1, 1, 0, 0, 1, tzinfo=dt.timezone.utc))
dt.datetime(1970, 1, 1, 0, 0, 1, tzinfo=dt.UTC))
self.assertEqual(
compat_datetime_from_timestamp(3600),
dt.datetime(1970, 1, 1, 1, 0, 0, tzinfo=dt.timezone.utc))
dt.datetime(1970, 1, 1, 1, 0, 0, tzinfo=dt.UTC))
self.assertEqual(
compat_datetime_from_timestamp(-1),
dt.datetime(1969, 12, 31, 23, 59, 59, tzinfo=dt.timezone.utc))
dt.datetime(1969, 12, 31, 23, 59, 59, tzinfo=dt.UTC))
self.assertEqual(
compat_datetime_from_timestamp(-86400),
dt.datetime(1969, 12, 31, 0, 0, 0, tzinfo=dt.timezone.utc))
dt.datetime(1969, 12, 31, 0, 0, 0, tzinfo=dt.UTC))
self.assertEqual(
compat_datetime_from_timestamp(0.5),
dt.datetime(1970, 1, 1, 0, 0, 0, 500000, tzinfo=dt.timezone.utc))
dt.datetime(1970, 1, 1, 0, 0, 0, 500000, tzinfo=dt.UTC))
self.assertEqual(
compat_datetime_from_timestamp(1.000001),
dt.datetime(1970, 1, 1, 0, 0, 1, 1, tzinfo=dt.timezone.utc))
dt.datetime(1970, 1, 1, 0, 0, 1, 1, tzinfo=dt.UTC))
self.assertEqual(
compat_datetime_from_timestamp(-1.25),
dt.datetime(1969, 12, 31, 23, 59, 58, 750000, tzinfo=dt.timezone.utc))
dt.datetime(1969, 12, 31, 23, 59, 58, 750000, tzinfo=dt.UTC))
self.assertEqual(
compat_datetime_from_timestamp(-1577923200),
dt.datetime(1920, 1, 1, 0, 0, 0, tzinfo=dt.timezone.utc))
dt.datetime(1920, 1, 1, 0, 0, 0, tzinfo=dt.UTC))
self.assertEqual(
compat_datetime_from_timestamp(4102444800),
dt.datetime(2100, 1, 1, 0, 0, 0, tzinfo=dt.timezone.utc))
dt.datetime(2100, 1, 1, 0, 0, 0, tzinfo=dt.UTC))
self.assertEqual(
compat_datetime_from_timestamp(173568960000),
dt.datetime(7470, 3, 8, 0, 0, 0, tzinfo=dt.timezone.utc))
dt.datetime(7470, 3, 8, 0, 0, 0, tzinfo=dt.UTC))
if __name__ == '__main__':
+1 -1
View File
@@ -163,7 +163,7 @@ class TestCookies(unittest.TestCase):
self.assertEqual(cookie.name, 'foo')
self.assertEqual(cookie.value, 'test%20%3Bcookie')
self.assertFalse(cookie.secure)
expected_expiration = dt.datetime(2021, 6, 18, 21, 39, 19, tzinfo=dt.timezone.utc)
expected_expiration = dt.datetime(2021, 6, 18, 21, 39, 19, tzinfo=dt.UTC)
self.assertEqual(cookie.expires, int(expected_expiration.timestamp()))
def test_pbkdf2_sha1(self):
+55 -2
View File
@@ -7,10 +7,12 @@ import sys
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import base64
import datetime as dt
import json
import math
import re
import struct
import unittest
from yt_dlp.utils.jslib import devalue
@@ -51,7 +53,7 @@ TEST_CASES_EQUALS = [{
}, {
'name': 'Date',
'unparsed': [['Date', '2001-09-09T01:46:40.000Z']],
'parsed': dt.datetime.fromtimestamp(1e9, tz=dt.timezone.utc),
'parsed': dt.datetime.fromtimestamp(1e9, tz=dt.UTC),
}, {
'name': 'Array',
'unparsed': [[1, 2, 3], 'a', 'b', 'c'],
@@ -84,10 +86,61 @@ TEST_CASES_EQUALS = [{
'name': 'Uint8Array',
'unparsed': [['Uint8Array', 'AQID']],
'parsed': [1, 2, 3],
}, {
'name': 'Uint8Array with ArrayBuffer reference',
'unparsed': [['Uint8Array', 1], ['ArrayBuffer', 'AQID']],
'parsed': [1, 2, 3],
}, {
'name': 'Uint8Array with byte offset and element length',
'unparsed': [['Uint8Array', 1, 1, 2], ['ArrayBuffer', 'AQIDBAU=']],
'parsed': [2, 3],
}, {
'name': 'Uint16Array with byte offset and element length',
'unparsed': [
['Uint16Array', 1, 2, 2],
['ArrayBuffer', base64.b64encode(struct.pack('=4H', 1, 2, 3, 4)).decode()],
],
'parsed': [2, 3],
}, {
'name': 'DataView with byte offset and byte length',
'unparsed': [['DataView', 1, 1, 2], ['ArrayBuffer', 'AQIDBAU=']],
'parsed': b'\x02\x03',
}, {
'name': 'DataView with byte offset',
'unparsed': [['DataView', 1, 2], ['ArrayBuffer', 'AQIDBAU=']],
'parsed': b'\x03\x04\x05',
}, {
'name': 'Float16Array',
'unparsed': [[
'Float16Array',
base64.b64encode(struct.pack('=2e', -2.0, 1.5)).decode(),
]],
'parsed': [-2.0, 1.5],
}, {
'name': 'Uint32Array',
'unparsed': [[
'Uint32Array',
base64.b64encode(struct.pack('=2I', 12345, 12345678)).decode(),
]],
'parsed': [12345, 12345678],
}, {
'name': 'BigInt64Array',
'unparsed': [[
'BigInt64Array',
base64.b64encode(struct.pack('=2q', -1, 2)).decode(),
]],
'parsed': [-1, 2],
}, {
'name': 'BigUint64Array',
'unparsed': [[
'BigUint64Array',
base64.b64encode(struct.pack('=2Q', 1, 2)).decode(),
]],
'parsed': [1, 2],
}, {
'name': 'ArrayBuffer',
'unparsed': [['ArrayBuffer', 'AQID']],
'parsed': [1, 2, 3],
'parsed': b'\x01\x02\x03',
}, {
'name': 'str (repetition)',
'unparsed': [[1, 1], 'a string'],
+11 -10
View File
@@ -13,8 +13,6 @@ import hashlib
import json
from test.helper import (
assertGreaterEqual,
assertLessEqual,
expect_info_dict,
expect_warnings,
get_params,
@@ -32,6 +30,7 @@ from yt_dlp.utils import (
ExtractorError,
UnavailableVideoError,
YoutubeDLError,
filter_dict,
format_bytes,
join_nonempty,
)
@@ -56,7 +55,7 @@ class YoutubeDL(yt_dlp.YoutubeDL):
def _file_md5(fn):
with open(fn, 'rb') as f:
return hashlib.md5(f.read()).hexdigest()
return hashlib.file_digest(f, hashlib.md5).hexdigest()
normal_test_cases = gettestcases()
@@ -137,7 +136,9 @@ def generator(test_case, tname):
expect_warnings(ydl, test_case.get('expected_warnings', []))
def get_tc_filename(tc):
return ydl.prepare_filename(dict(tc.get('info_dict', {})))
# Filename is generated from expected info dict, so filter out type wildcard values
return ydl.prepare_filename(
filter_dict(tc.get('info_dict', {}), cndn=lambda _, v: type(v) is not type))
res_dict = None
@@ -198,8 +199,8 @@ def generator(test_case, tname):
num_entries = len(res_dict.get('entries', []))
if 'playlist_mincount' in test_case:
mincount = test_case['playlist_mincount']
assertGreaterEqual(
self, num_entries, mincount,
self.assertGreaterEqual(
num_entries, mincount,
f'Expected at least {mincount} entries in playlist {test_url}, but got only {num_entries}')
if 'playlist_count' in test_case:
count = test_case['playlist_count']
@@ -209,8 +210,8 @@ def generator(test_case, tname):
f'Expected exactly {count} entries in playlist {test_url}, but got {got}')
if 'playlist_maxcount' in test_case:
maxcount = test_case['playlist_maxcount']
assertLessEqual(
self, num_entries, maxcount,
self.assertLessEqual(
num_entries, maxcount,
f'Expected at most {maxcount} entries in playlist {test_url}, but got more')
if 'playlist_duration_sum' in test_case:
got_duration = sum(e['duration'] for e in res_dict['entries'])
@@ -238,8 +239,8 @@ def generator(test_case, tname):
if params.get('test'):
expected_minsize = max(expected_minsize, 10000)
got_fsize = os.path.getsize(tc_filename)
assertGreaterEqual(
self, got_fsize, expected_minsize,
self.assertGreaterEqual(
got_fsize, expected_minsize,
f'Expected {tc_filename} to be at least {format_bytes(expected_minsize)}, '
f'but it\'s only {format_bytes(got_fsize)} ')
if 'md5' in tc:
+22 -2
View File
@@ -83,6 +83,12 @@ class HTTPProxyHandler(BaseHTTPRequestHandler, HTTPProxyAuthMixin):
self.server.close_request(self.request)
def finish(self):
try:
super().finish()
finally:
self.server.close_request(self.request)
if urllib3:
import urllib3.util.ssltransport
@@ -132,7 +138,11 @@ class HTTPSProxyHandler(HTTPProxyHandler):
request = SSLTransport(request, ssl_context=sslctx, server_side=True)
else:
request = sslctx.wrap_socket(request, server_side=True)
super().__init__(request, *args, **kwargs)
try:
super().__init__(request, *args, **kwargs)
except Exception:
request.close()
raise
class HTTPConnectProxyHandler(BaseHTTPRequestHandler, HTTPProxyAuthMixin):
@@ -163,6 +173,12 @@ class HTTPConnectProxyHandler(BaseHTTPRequestHandler, HTTPProxyAuthMixin):
self.request_handler(self.request, self.client_address, self.server, proxy_info=proxy_info)
self.server.close_request(self.request)
def finish(self):
try:
super().finish()
finally:
self.server.close_request(self.request)
class HTTPSConnectProxyHandler(HTTPConnectProxyHandler):
def __init__(self, request, *args, **kwargs):
@@ -171,7 +187,11 @@ class HTTPSConnectProxyHandler(HTTPConnectProxyHandler):
sslctx.load_cert_chain(certfn, None)
request = sslctx.wrap_socket(request, server_side=True)
self._original_request = request
super().__init__(request, *args, **kwargs)
try:
super().__init__(request, *args, **kwargs)
except Exception:
request.close()
raise
def do_CONNECT(self):
super().do_CONNECT()
+45 -34
View File
@@ -180,6 +180,11 @@ class HTTPTestRequestHandler(http.server.BaseHTTPRequestHandler):
self.send_header('Location', '/a/b/./../../headers')
self.send_header('Content-Length', '0')
self.end_headers()
elif self.path == '/a/b/redirect_relative_dotsegments':
self.send_response(301)
self.send_header('Location', '../../headers')
self.send_header('Content-Length', '0')
self.end_headers()
elif self.path == '/redirect_dotsegments_absolute':
self.send_response(301)
# redirect to /headers but with dot segments before - absolute url
@@ -338,7 +343,7 @@ class TestHTTPRequestHandler(TestRequestHandlerBase):
https_server_thread.start()
with handler(verify=False) as rh:
with pytest.raises(SSLError, match=r'(?i)ssl(?:v3|/tls).alert.handshake.failure') as exc_info:
with pytest.raises(SSLError, match=r'(?i)(?:sslv3|tls).alert.handshake.failure') as exc_info:
validate_and_send(rh, Request(f'https://127.0.0.1:{https_port}/headers'))
assert not issubclass(exc_info.type, CertificateVerifyError)
@@ -388,13 +393,23 @@ class TestHTTPRequestHandler(TestRequestHandlerBase):
assert res.status == 200
res.close()
def test_percent_encode(self, handler):
def test_percent_encode_unicode(self, handler):
# RFC 3986 §6.2.2.1 defines that percent-encoding SHOULD be normalized to uppercase.
with handler() as rh:
# Unicode characters should be encoded with uppercase percent-encoding
res = validate_and_send(rh, Request(f'http://127.0.0.1:{self.http_port}/中文.html'))
assert res.status == 200
res.close()
# don't normalize existing percent encodings
@pytest.mark.skip_handler('CurlCFFI', 'not supported by curl-cffi (non-standard)')
def test_percent_encode_keep_existing(self, handler):
# NOTE: RFC 3986 §6.2.2.1 defines that percent-encoding SHOULD be normalized to uppercase.
# For compatibility with legacy sites (e.g., redirects using lowercase encodings and only accept that),
# our default handlers (urllib/requests) preserve existing percent-encoding instead of normalizing it.
#
# CurlCFFI is excluded because it forces uppercase encodings and is hard to change. This is acceptable
# since CurlCFFI is used only for impersonation. https://github.com/curl/curl/pull/21592
with handler() as rh:
res = validate_and_send(rh, Request(f'http://127.0.0.1:{self.http_port}/%c7%9f'))
assert res.status == 200
res.close()
@@ -402,6 +417,7 @@ class TestHTTPRequestHandler(TestRequestHandlerBase):
@pytest.mark.parametrize('path', [
'/a/b/./../../headers',
'/redirect_dotsegments',
'/a/b/redirect_relative_dotsegments',
# https://github.com/yt-dlp/yt-dlp/issues/9020
'/redirect_dotsegments_absolute',
])
@@ -823,13 +839,24 @@ class TestClientCertificate:
@pytest.mark.parametrize('handler', ['CurlCFFI'], indirect=True)
class TestHTTPImpersonateRequestHandler(TestRequestHandlerBase):
def test_supported_impersonate_targets(self, handler):
CHROMIUMS = {
'chrome': 'Chrome',
'chromium': 'Chrome',
'edge': 'Edg',
}
with handler(headers=std_headers) as rh:
# note: this assumes the impersonate request handler supports the impersonate extension
for target in rh.supported_targets:
assert target.client and target.version
res = validate_and_send(rh, Request(
f'http://127.0.0.1:{self.http_port}/headers', extensions={'impersonate': target}))
assert res.status == 200
assert std_headers['user-agent'].lower() not in res.read().decode().lower()
res_text = res.read().decode()
# chromium-based targets' UAs can overlap with yt-dlp's built-in random UA
if target.client.lower() not in CHROMIUMS:
assert std_headers['user-agent'].lower() not in res_text.lower()
else:
assert f'{CHROMIUMS[target.client.lower()]}/{target.version}' in res_text
def test_response_extensions(self, handler):
with handler() as rh:
@@ -859,15 +886,15 @@ class TestRequestHandlerMisc:
('Websockets', 'websockets.server'),
], indirect=['handler'])
def test_remove_logging_handler(self, handler, logger_name):
# Ensure any logging handlers, which may contain a YoutubeDL instance,
# are removed when we close the request handler
# Ensure closing the request handler removes only its logging handlers,
# which may reference a YoutubeDL instance
# See: https://github.com/yt-dlp/yt-dlp/issues/8922
logging_handlers = logging.getLogger(logger_name).handlers
before_count = len(logging_handlers)
logger = logging.getLogger(logger_name)
original_handlers = logger.handlers.copy()
rh = handler()
assert len(logging_handlers) == before_count + 1
assert len(logger.handlers) == len(original_handlers) + 1
rh.close()
assert len(logging_handlers) == before_count
assert logger.handlers == original_handlers
def test_wrap_request_errors(self):
class TestRequestHandler(RequestHandler):
@@ -974,28 +1001,15 @@ class TestUrllibRequestHandler(TestRequestHandlerBase):
):
validate_and_send(rh, Request(f'https://127.0.0.1:{self.https_port}/headers'))
@pytest.mark.parametrize('req,match,version_check', [
@pytest.mark.parametrize('req,match', [
# https://github.com/python/cpython/blob/987b712b4aeeece336eed24fcc87a950a756c3e2/Lib/http/client.py#L1256
# bpo-39603: Check implemented in 3.7.9+, 3.8.5+
(
Request('http://127.0.0.1', method='GET\n'),
'method can\'t contain control characters',
lambda v: v < (3, 7, 9) or (3, 8, 0) <= v < (3, 8, 5),
),
(Request('http://127.0.0.1', method='GET\n'), 'method can\'t contain control characters'),
# https://github.com/python/cpython/blob/987b712b4aeeece336eed24fcc87a950a756c3e2/Lib/http/client.py#L1265
# bpo-38576: Check implemented in 3.7.8+, 3.8.3+
(
Request('http://127.0.0. 1', method='GET'),
'URL can\'t contain control characters',
lambda v: v < (3, 7, 8) or (3, 8, 0) <= v < (3, 8, 3),
),
(Request('http://127.0.0. 1', method='GET'), 'URL can\'t contain control characters'),
# https://github.com/python/cpython/blob/987b712b4aeeece336eed24fcc87a950a756c3e2/Lib/http/client.py#L1288C31-L1288C50
(Request('http://127.0.0.1', headers={'foo\n': 'bar'}), 'Invalid header name', None),
(Request('http://127.0.0.1', headers={'foo\n': 'bar'}), 'Invalid header name'),
])
def test_httplib_validation_errors(self, handler, req, match, version_check):
if version_check and version_check(sys.version_info):
pytest.skip(f'Python {sys.version} version does not have the required validation for this test.')
def test_httplib_validation_errors(self, handler, req, match):
with handler() as rh:
with pytest.raises(RequestError, match=match) as exc_info:
validate_and_send(rh, req)
@@ -1680,8 +1694,7 @@ class TestYoutubeDLNetworking:
def test_compat_opener(self):
with FakeYDL() as ydl:
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
with warnings.catch_warnings(action='ignore', category=DeprecationWarning):
assert isinstance(ydl._opener, urllib.request.OpenerDirector)
@pytest.mark.parametrize('proxy,expected', [
@@ -1700,8 +1713,7 @@ class TestYoutubeDLNetworking:
urllib_req = urllib.request.Request('http://foo.bar', data=b'test', method='PUT', headers={'X-Test': '1'})
urllib_req.add_unredirected_header('Cookie', 'bob=bob')
urllib_req.timeout = 2
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
with warnings.catch_warnings(action='ignore', category=DeprecationWarning):
req = ydl.urlopen(urllib_req).request
assert req.url == urllib_req.get_full_url()
assert req.data == urllib_req.data
@@ -2120,8 +2132,7 @@ class TestResponse:
def test_compat(self):
res = Response(io.BytesIO(b''), url='test://', status=404, headers={'test': 'test'})
with warnings.catch_warnings():
warnings.simplefilter('ignore', category=DeprecationWarning)
with warnings.catch_warnings(action='ignore', category=DeprecationWarning):
assert res.code == res.getcode() == res.status
assert res.geturl() == res.url
assert res.info() is res.headers
+3 -3
View File
@@ -63,13 +63,13 @@ class TestNetworkingUtils:
'username': 'user',
'password': '',
}),
('socks4://u%40ser:pa%20ss@127.0.0.1:1080', {
('socks4://u%40ser+name:pa%20ss+word@127.0.0.1:1080', {
'proxytype': ProxyType.SOCKS4,
'addr': '127.0.0.1',
'port': 1080,
'rdns': False,
'username': 'u@ser',
'password': 'pa ss',
'username': 'u@ser+name',
'password': 'pa ss+word',
}),
('socks4a://:pa%20ss@127.0.0.1', {
'proxytype': ProxyType.SOCKS4A,
+8 -1
View File
@@ -213,8 +213,13 @@ class SocksHTTPTestRequestHandler(http.server.BaseHTTPRequestHandler, SocksTestR
class SocksWebSocketTestRequestHandler(SocksTestRequestHandler):
def handle(self):
import websockets.sync.server
import websockets.version
protocol = websockets.ServerProtocol()
connection = websockets.sync.server.ServerConnection(socket=self.request, protocol=protocol, close_timeout=0)
connection_args = [self.request, protocol]
if int(websockets.version.version.partition('.')[0]) >= 17:
connection_args.append(self.server)
connection = websockets.sync.server.ServerConnection(*connection_args, close_timeout=0)
connection.handshake()
for message in connection:
if message == 'socks_info':
@@ -230,6 +235,7 @@ def socks_server(socks_server_class, request_handler, bind_ip=None, **socks_serv
server_type = ThreadingTCPServer if '.' in bind_address else IPv6ThreadingTCPServer
server = server_type(
(bind_address, 0), functools.partial(socks_server_class, request_handler, socks_server_kwargs))
server.socket_closed = threading.Event()
server_port = http_server_port(server)
server_thread = threading.Thread(target=server.serve_forever)
server_thread.daemon = True
@@ -240,6 +246,7 @@ def socks_server(socks_server_class, request_handler, bind_ip=None, **socks_serv
yield f'{bind_address}:{server_port}'
finally:
server.shutdown()
server.socket_closed.set()
server.server_close()
server_thread.join(2.0)
+12
View File
@@ -546,6 +546,18 @@ class TestTraversalHelpers:
{'url': 'https://example.com/subs/de4'},
],
}, 'non str types should be replaced by default id'
assert traverse_obj([
{'name': '', 'ext': '', 'url': 'https://example.com/subs/en'},
], [..., {
'id': 'name',
'ext': 'ext',
'url': 'url',
}, all, {subs_list_to_dict(lang='en', ext='vtt')}]) == {
'en': [{
'ext': 'vtt',
'url': 'https://example.com/subs/en',
}],
}, 'empty id and ext should be replaced by defaults'
def test_trim_str(self):
with pytest.raises(TypeError):
+47 -16
View File
@@ -9,6 +9,7 @@ sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
import contextlib
import datetime as dt
import email.message
import io
import itertools
import json
@@ -48,6 +49,7 @@ from yt_dlp.utils import (
determine_ext,
determine_file_encoding,
dfxp2srt,
disposition_filename,
encode_base_n,
encode_compat_str,
expand_path,
@@ -107,6 +109,7 @@ from yt_dlp.utils import (
sanitize_filename,
sanitize_path,
sanitize_url,
setproctitle,
shell_quote,
strftime_or_none,
smuggle_url,
@@ -125,6 +128,7 @@ from yt_dlp.utils import (
url_basename,
url_or_none,
urlencode_postdata,
urlhandle_detect_ext,
urljoin,
urshift,
variadic,
@@ -422,15 +426,15 @@ class TestUtil(unittest.TestCase):
def test_datetime_round(self):
self.assertEqual(datetime_round(dt.datetime.strptime('1820-05-12T01:23:45Z', '%Y-%m-%dT%H:%M:%SZ')),
dt.datetime(1820, 5, 12, tzinfo=dt.timezone.utc))
dt.datetime(1820, 5, 12, tzinfo=dt.UTC))
self.assertEqual(datetime_round(dt.datetime.strptime('1969-12-31T23:34:45Z', '%Y-%m-%dT%H:%M:%SZ'), 'hour'),
dt.datetime(1970, 1, 1, 0, tzinfo=dt.timezone.utc))
dt.datetime(1970, 1, 1, 0, tzinfo=dt.UTC))
self.assertEqual(datetime_round(dt.datetime.strptime('2024-12-25T01:23:45Z', '%Y-%m-%dT%H:%M:%SZ'), 'minute'),
dt.datetime(2024, 12, 25, 1, 24, tzinfo=dt.timezone.utc))
dt.datetime(2024, 12, 25, 1, 24, tzinfo=dt.UTC))
self.assertEqual(datetime_round(dt.datetime.strptime('2024-12-25T01:23:45.123Z', '%Y-%m-%dT%H:%M:%S.%fZ'), 'second'),
dt.datetime(2024, 12, 25, 1, 23, 45, tzinfo=dt.timezone.utc))
dt.datetime(2024, 12, 25, 1, 23, 45, tzinfo=dt.UTC))
self.assertEqual(datetime_round(dt.datetime.strptime('2024-12-25T01:23:45.678Z', '%Y-%m-%dT%H:%M:%S.%fZ'), 'second'),
dt.datetime(2024, 12, 25, 1, 23, 46, tzinfo=dt.timezone.utc))
dt.datetime(2024, 12, 25, 1, 23, 46, tzinfo=dt.UTC))
def test_strftime_or_none(self):
self.assertEqual(strftime_or_none(-4722192000), '18200512')
@@ -613,6 +617,14 @@ class TestUtil(unittest.TestCase):
self.assertEqual(res_url, url)
self.assertEqual(res_data, {'a': 'b', 'c': 'd'})
@unittest.mock.patch('ctypes.cdll.LoadLibrary')
def test_setproctitle(self, load_library):
for title in ('yt-dlp', 'café'):
with self.subTest(title=title):
setproctitle(title)
buf = load_library.return_value.prctl.call_args.args[1]
self.assertEqual(bytes(buf), title.encode() + b'\0')
def test_shell_quote(self):
args = ['ffmpeg', '-i', 'ñ€ß\'.mp4']
self.assertEqual(
@@ -626,6 +638,7 @@ class TestUtil(unittest.TestCase):
self.assertEqual(float_or_none(None), None)
self.assertEqual(float_or_none([]), None)
self.assertEqual(float_or_none(set()), None)
self.assertEqual(float_or_none(sys.float_info.radix ** sys.float_info.max_exp), None)
def test_int_or_none(self):
self.assertEqual(int_or_none('42'), 42)
@@ -1346,15 +1359,8 @@ class TestUtil(unittest.TestCase):
self.assertEqual(extract_attributes('<e _:funny-name1=1>'), {'_:funny-name1': '1'})
self.assertEqual(extract_attributes('<e x="Fáilte 世界 \U0001f600">'), {'x': 'Fáilte 世界 \U0001f600'})
self.assertEqual(extract_attributes('<e x="décompose&#769;">'), {'x': 'décompose\u0301'})
# "Narrow" Python builds don't support unicode code points outside BMP.
try:
chr(0x10000)
supports_outside_bmp = True
except ValueError:
supports_outside_bmp = False
if supports_outside_bmp:
self.assertEqual(extract_attributes('<e x="Smile &#128512;!">'), {'x': 'Smile \U0001f600!'})
# Malformed HTML should not break attributes extraction on older Python
self.assertEqual(extract_attributes('<e x="Smile &#128512;!">'), {'x': 'Smile \U0001f600!'})
# Malformed HTML should not break attribute extraction
self.assertEqual(extract_attributes('<mal"formed/>'), {})
def test_clean_html(self):
@@ -2120,6 +2126,32 @@ Line 1
self.assertEqual(get_compatible_ext(
vcodecs=['av1'], acodecs=['mp4a'], vexts=['webm'], aexts=['m4a'], preferences=('webm', 'mkv')), 'mkv')
def test_disposition_filename(self):
test_cases = (
(None, None),
('attachment', None),
('attachment; filename="video.mp4"', 'video.mp4'),
('attachment; FILENAME="video.mp4"', 'video.mp4'),
('inline; filename=video.mp4', 'video.mp4'),
('attachment; filename=" video.mp4 "', 'video.mp4'),
("attachment; filename*=UTF-8''r%C3%A9sum%C3%A9.mp4", 'résumé.mp4'),
("attachment; filename=fallback.mp4; filename*=UTF-8''actual.webm", 'actual.webm'),
("attachment; filename*=UTF-8''actual.webm; filename=fallback.mp4", 'actual.webm'),
)
for content_disposition, expected in test_cases:
headers = email.message.Message()
if content_disposition is not None:
headers['Content-Disposition'] = content_disposition
with self.subTest(content_disposition=content_disposition):
self.assertEqual(disposition_filename(headers), expected)
def test_urlhandle_detect_ext(self):
headers = email.message.Message()
headers['Content-Disposition'] = "attachment; filename=fallback.mp4; filename*=UTF-8''actual.webm"
headers['Content-Type'] = 'video/mp4'
self.assertEqual(urlhandle_detect_ext(unittest.mock.Mock(headers=headers)), 'webm')
def test_try_call(self):
def total(*x, **kwargs):
return sum(x) + sum(kwargs.values())
@@ -2145,8 +2177,7 @@ Line 1
self.assertEqual(variadic(None), (None, ))
self.assertEqual(variadic('spam'), ('spam', ))
self.assertEqual(variadic('spam', allowed_types=dict), 'spam')
with warnings.catch_warnings():
warnings.simplefilter('ignore')
with warnings.catch_warnings(action='ignore'):
self.assertEqual(variadic('spam', allowed_types=[dict]), 'spam')
def test_http_header_dict(self):
+6 -2
View File
@@ -130,7 +130,11 @@ def ws_validate_and_send(rh, req):
try:
return rh.send(req)
except TransportError as e:
if i < (max_tries - 1) and 'connection closed during handshake' in str(e):
if i < (max_tries - 1) and (
'connection closed during handshake' in str(e)
or (isinstance(e.cause, websockets.exceptions.InvalidMessage)
and isinstance(e.cause.__cause__, EOFError))
):
# websockets server sometimes hangs on new connections
continue
raise
@@ -186,7 +190,7 @@ class TestWebsSocketRequestHandlerConformance:
def test_ssl_error(self, handler):
with handler(verify=False) as rh:
with pytest.raises(SSLError, match=r'ssl(?:v3|/tls) alert handshake failure') as exc_info:
with pytest.raises(SSLError, match=r'(?:sslv3|tls) alert handshake failure') as exc_info:
ws_validate_and_send(rh, Request(self.bad_wss_host))
assert not issubclass(exc_info.type, CertificateVerifyError)
Generated
+786 -706
View File
File diff suppressed because it is too large Load Diff
+12 -17
View File
@@ -23,9 +23,10 @@ import time
import tokenize
import traceback
import unicodedata
import urllib.parse
import urllib.request
from .cache import Cache
from .compat import urllib # isort: split
from .compat import urllib_req_to_req
from .cookies import CookieLoadError, LenientSimpleCookie, load_cookies
from .downloader import FFmpegFD, get_suitable_downloader, shorten_protocol_name
@@ -140,7 +141,6 @@ from .utils import (
locked_file,
make_archive_id,
make_parent_dirs,
number_of_digits,
orderedSet,
orderedSet_from_options,
parse_filesize,
@@ -673,7 +673,6 @@ class YoutubeDL:
except Exception as e:
self.write_debug(f'Failed to enable VT mode: {e}')
# hehe "immutable" namespace
self._out_files.console = next(filter(supports_terminal_sequences, (sys.stderr, sys.stdout)), None)
if self.params.get('no_color'):
@@ -1082,13 +1081,13 @@ class YoutubeDL:
"""
if message is not None:
self.to_stderr(message)
error = sys.exception()
if self.params.get('verbose'):
if tb is None:
if sys.exc_info()[0]: # if .trouble has been called from an except block
tb = ''
if hasattr(sys.exc_info()[1], 'exc_info') and sys.exc_info()[1].exc_info[0]:
tb += ''.join(traceback.format_exception(*sys.exc_info()[1].exc_info))
tb += encode_compat_str(traceback.format_exc())
if error is not None: # if .trouble has been called from an except block
exc_info = getattr(error, 'exc_info', None)
tb = ''.join(traceback.format_exception(*exc_info)) if exc_info and exc_info[0] else ''
tb += ''.join(traceback.format_exception(error))
else:
tb_data = traceback.format_list(traceback.extract_stack())
tb = ''.join(tb_data)
@@ -1097,11 +1096,8 @@ class YoutubeDL:
if not is_error:
return
if not self.params.get('ignoreerrors'):
if sys.exc_info()[0] and hasattr(sys.exc_info()[1], 'exc_info') and sys.exc_info()[1].exc_info[0]:
exc_info = sys.exc_info()[1].exc_info
else:
exc_info = sys.exc_info()
raise DownloadError(message, exc_info)
exc_info = getattr(error, 'exc_info', None)
raise DownloadError(message, exc_info if exc_info and exc_info[0] else sys.exc_info())
self._download_retcode = 1
Styles = Namespace(
@@ -1286,8 +1282,8 @@ class YoutubeDL:
# For fields playlist_index, playlist_autonumber and autonumber convert all occurrences
# of %(field)s to %(field)0Nd for backward compatibility
field_size_compat_map = {
'playlist_index': number_of_digits(info_dict.get('__last_playlist_index') or 0),
'playlist_autonumber': number_of_digits(info_dict.get('n_entries') or 0),
'playlist_index': len(str(info_dict.get('__last_playlist_index') or 0)),
'playlist_autonumber': len(str(info_dict.get('n_entries') or 0)),
'autonumber': self.params.get('autonumber_size') or 5,
}
@@ -2399,8 +2395,7 @@ class YoutubeDL:
selectors = []
current_selector = None
for type_, string_, start, _, _ in tokens:
# ENCODING is only defined in Python 3.x
if type_ == getattr(tokenize, 'ENCODING', None):
if type_ == tokenize.ENCODING:
continue
elif type_ in [tokenize.NAME, tokenize.NUMBER]:
current_selector = FormatSelector(SINGLE, string_, [])
+2 -2
View File
@@ -1,8 +1,8 @@
import sys
if sys.version_info < (3, 10):
if sys.version_info < (3, 11):
raise ImportError(
f'You are using an unsupported version of Python. Only Python versions 3.10 and above are supported by yt-dlp') # noqa: F541
f'You are using an unsupported version of Python. Only Python versions 3.11 and above are supported by yt-dlp') # noqa: F541
__license__ = 'The Unlicense'
+5 -6
View File
@@ -203,7 +203,7 @@ def aes_cbc_encrypt(data, key, iv, *, padding_mode='pkcs7'):
def aes_gcm_decrypt_and_verify(data, key, tag, nonce):
"""
Decrypt with aes in GBM mode and checks authenticity using tag
Decrypt with AES in GCM mode and check authenticity using tag
@param {int[]} data cipher
@param {int[]} key 16-Byte cipher key
@@ -220,7 +220,7 @@ def aes_gcm_decrypt_and_verify(data, key, tag, nonce):
j0 = [*nonce, 0, 0, 0, 1]
else:
fill = (BLOCK_SIZE_BYTES - (len(nonce) % BLOCK_SIZE_BYTES)) % BLOCK_SIZE_BYTES + 8
ghash_in = nonce + [0] * fill + list((8 * len(nonce)).to_bytes(8, 'big'))
ghash_in = nonce + [0] * fill + list((8 * len(nonce)).to_bytes(8))
j0 = ghash(hash_subkey, ghash_in)
# TODO: add nonce support to aes_ctr_decrypt
@@ -233,9 +233,8 @@ def aes_gcm_decrypt_and_verify(data, key, tag, nonce):
s_tag = ghash(
hash_subkey,
data
+ [0] * pad_len # pad
+ list((0 * 8).to_bytes(8, 'big') # length of associated data
+ ((len(data) * 8).to_bytes(8, 'big'))), # length of data
+ [0] * (pad_len + 8) # padding and length of associated data
+ list((len(data) * 8).to_bytes(8)), # length of data
)
if tag != aes_ctr_encrypt(s_tag, key, j0):
@@ -293,7 +292,7 @@ def aes_decrypt_text(data, password, key_size_bytes):
- Mode of operation is 'counter'
@param {str} data Base64 encoded string
@param {str,unicode} password Password (will be encoded with utf-8)
@param {str} password Password (will be encoded with UTF-8)
@param {int} key_size_bytes Possible values: 16 for 128-Bit, 24 for 192-Bit or 32 for 256-Bit
@returns {str} Decrypted data
"""
+3 -4
View File
@@ -8,9 +8,8 @@ passthrough_module(__name__, '._deprecated')
del passthrough_module
# HTMLParseError has been deprecated in Python 3.3 and removed in
# Python 3.5. Introducing dummy exception for Python >3.5 for compatible
# and uniform cross-version exception handling
# HTMLParseError was deprecated in Python 3.3 and removed in Python 3.5.
# Keep a replacement for API compatibility and uniform exception handling.
class compat_HTMLParseError(ValueError):
pass
@@ -32,7 +31,7 @@ def compat_datetime_from_timestamp(timestamp):
# Calling dt.datetime.fromtimestamp with negative timestamps throws error in Windows
# Ref: https://github.com/yt-dlp/yt-dlp/issues/5185, https://github.com/python/cpython/issues/81708,
# https://github.com/yt-dlp/yt-dlp/issues/6706#issuecomment-1496842642
return (dt.datetime.fromtimestamp(0, dt.timezone.utc) + dt.timedelta(seconds=timestamp))
return (dt.datetime.fromtimestamp(0, dt.UTC) + dt.timedelta(seconds=timestamp))
# Python 3.8+ does not honor %HOME% on windows, but this breaks compatibility with youtube-dl
-10
View File
@@ -1,10 +0,0 @@
# flake8: noqa: F405
from urllib import * # noqa: F403
del request # noqa: F821
from . import request # noqa: F401
from ..compat_utils import passthrough_module
passthrough_module(__name__, 'urllib')
del passthrough_module
-36
View File
@@ -1,36 +0,0 @@
# flake8: noqa: F405
from urllib.request import * # noqa: F403
from ..compat_utils import passthrough_module
passthrough_module(__name__, 'urllib.request')
del passthrough_module
import os
if os.name == 'nt':
# On older Python versions, proxies are extracted from Windows registry erroneously. [1]
# If the https proxy in the registry does not have a scheme, urllib will incorrectly add https:// to it. [2]
# It is unlikely that the user has actually set it to be https, so we should be fine to safely downgrade
# it to http on these older Python versions to avoid issues
# This also applies for ftp proxy type, as ftp:// proxy scheme is not supported.
# 1: https://github.com/python/cpython/issues/86793
# 2: https://github.com/python/cpython/blob/51f1ae5ceb0673316c4e4b0175384e892e33cc6e/Lib/urllib/request.py#L2683-L2698
import sys
from urllib.request import getproxies_environment, getproxies_registry
def getproxies_registry_patched():
proxies = getproxies_registry()
if sys.version_info < (3, 10, 5): # https://docs.python.org/3.10/whatsnew/changelog.html#python-3-10-5-final
for scheme in ('https', 'ftp'):
if scheme in proxies and proxies[scheme].startswith(f'{scheme}://'):
proxies[scheme] = 'http' + proxies[scheme][len(scheme):]
return proxies
def getproxies():
return getproxies_environment() or getproxies_registry_patched()
del os
+1 -1
View File
@@ -647,7 +647,7 @@ class DataParser:
def _mac_absolute_time_to_posix(timestamp):
return int((dt.datetime(2001, 1, 1, 0, 0, tzinfo=dt.timezone.utc) + dt.timedelta(seconds=timestamp)).timestamp())
return int((dt.datetime(2001, 1, 1, 0, 0, tzinfo=dt.UTC) + dt.timedelta(seconds=timestamp)).timestamp())
def _parse_safari_cookies_header(data, logger):
+1 -1
View File
@@ -249,7 +249,7 @@ class CurlFD(ExternalFD):
return cmd
def _call_process(self, cmd, info_dict):
if self._curl_version > self._MIN_VERSION_FOR_STDIN_COOKIES or os.path.islink('/dev/fd/0'):
if self._curl_version >= self._MIN_VERSION_FOR_STDIN_COOKIES or os.path.islink('/dev/fd/0'):
# Supports `--cookies -` or reading from device file as `--cookies /dev/fd/0`
buffer = io.StringIO()
self.ydl.cookiejar._really_save(buffer, True, True)
+1 -1
View File
@@ -396,7 +396,7 @@ class FragmentFD(FileDownloader):
return future.result(0.1)
except KeyboardInterrupt:
raise
except concurrent.futures.TimeoutError:
except TimeoutError:
continue
else:
def future_result(future):
+1 -1
View File
@@ -300,7 +300,7 @@ class HlsFD(FragmentFD):
# We only download the first fragment during the test
if self.params.get('test', False):
fragments = [fragments[0] if fragments else None]
fragments = fragments[:1]
if real_downloader:
info_dict['fragments'] = fragments
+1 -1
View File
@@ -154,7 +154,7 @@ def write_piff_header(stream, params):
sample_entry_payload += u16.pack(0x18) # depth
sample_entry_payload += s16.pack(-1) # pre defined
codec_private_data = binascii.unhexlify(params['codec_private_data'].encode())
codec_private_data = binascii.unhexlify(params['codec_private_data'])
if fourcc in ('H264', 'AVC1'):
sps, pps = codec_private_data.split(u32.pack(1))[1:]
avcc_payload = u8.pack(1) # configuration version
+7 -2
View File
@@ -106,7 +106,6 @@ from .archiveorg import (
)
from .arcpublishing import ArcPublishingIE
from .ard import (
ARDIE,
ARDAudiothekIE,
ARDAudiothekPlaylistIE,
ARDBetaMediathekIE,
@@ -873,7 +872,9 @@ from .khanacademy import (
)
from .kick import (
KickClipIE,
KickClipsIE,
KickIE,
KickVideosIE,
KickVODIE,
)
from .kicker import KickerIE
@@ -1222,6 +1223,7 @@ from .nhk import (
from .nhl import NHLIE
from .nick import NickIE
from .niconico import (
NiconicoChannelIE,
NiconicoHistoryIE,
NiconicoIE,
NiconicoLiveIE,
@@ -1719,7 +1721,10 @@ from .shahid import (
from .sharepoint import SharePointIE
from .shemaroome import ShemarooMeIE
from .shiey import ShieyIE
from .showroomlive import ShowRoomLiveIE
from .showroomlive import (
ShowRoomLiveIE,
ShowRoomVodIE,
)
from .sibnet import SibnetEmbedIE
from .simplecast import (
SimplecastEpisodeIE,
+1 -1
View File
@@ -70,7 +70,7 @@ class AbemaLicenseRH(RequestHandler):
})
res = decode_base_n(license_response['k'], table=self._STRTABLE)
encvideokey = list(res.to_bytes(16, 'big'))
encvideokey = list(res.to_bytes(16))
h = hmac.new(
binascii.unhexlify(self._HKEY),
+4 -3
View File
@@ -50,14 +50,13 @@ class ADNIE(ADNBaseIE):
_VALID_URL = r'https?://(?:www\.)?animationdigitalnetwork\.com/(?:(?P<lang>de)/)?video/[^/?#]+/(?P<id>\d+)'
_TESTS = [{
'url': 'https://animationdigitalnetwork.com/video/558-fruits-basket/9841-episode-1-a-ce-soir',
'md5': '1c9ef066ceb302c86f80c2b371615261',
'md5': '3999b7b235ffb3591a385d1913cd3cd1',
'info_dict': {
'id': '9841',
'ext': 'mp4',
'title': 'Fruits Basket - Episode 1',
'description': 'md5:14be2f72c3c96809b0ca424b0097d336',
'series': 'Fruits Basket',
'duration': 1437,
'duration': 1436,
'release_date': '20190405',
'comment_count': int,
'average_rating': float,
@@ -174,6 +173,8 @@ Format: Marked,Start,End,Style,Name,MarginL,MarginR,MarginV,Effect,Text'''
def _real_extract(self, url):
lang, video_id = self._match_valid_url(url).group('lang', 'id')
self._HEADERS['X-Target-Distribution'] = lang or 'fr'
if 'Authorization' in self._HEADERS:
self._HEADERS['X-Profile-ID'] = self._configuration_arg('profile_id', ['1'])[0]
video_base_url = self._PLAYER_BASE_URL + f'video/{video_id}/'
player = self._download_json(
video_base_url + 'configuration', video_id,
+69 -57
View File
@@ -1,12 +1,16 @@
import json
import itertools
import re
from .common import InfoExtractor
from ..networking.exceptions import HTTPError
from ..utils import (
ExtractorError,
clean_html,
int_or_none,
try_get,
unified_strdate,
unified_timestamp,
urljoin,
)
@@ -17,7 +21,7 @@ class AmericasTestKitchenIE(InfoExtractor):
'md5': 'b861c3e365ac38ad319cfd509c30577f',
'info_dict': {
'id': '5b400b9ee338f922cb06450c',
'title': 'Japanese Suppers',
'title': 'Weeknight Japanese Suppers',
'ext': 'mp4',
'display_id': 'weeknight-japanese-suppers',
'description': 'md5:64e606bfee910627efc4b5f050de92b3',
@@ -106,23 +110,44 @@ class AmericasTestKitchenIE(InfoExtractor):
class AmericasTestKitchenSeasonIE(InfoExtractor):
_VALID_URL = r'https?://(?:www\.)?(?P<show>americastestkitchen|(?P<cooks>cooks(?:country|illustrated)))\.com(?:(?:/(?P<show2>cooks(?:country|illustrated)))?(?:/?$|(?<!ated)(?<!ated\.com)/episodes/browse/season_(?P<season>\d+)))'
_VALID_URL = r'''(?x)
https?://(?:www\.)?(?P<domain>americastestkitchen|cookscountry|cooksillustrated)\.com
(?:/(?P<path>cookscountry|cooksillustrated))?
(?:/episodes(?:/browse)?/season[-_](?P<season>\d+))?
/?(?:[?#]|$)'''
_SHOWS = {
'americastestkitchen': ('', 'America\'s Test Kitchen'),
'cookscountry': ('/cookscountry', 'Cook\'s Country'),
'cooksillustrated': ('/cooksillustrated', 'Cook\'s Illustrated'),
}
_TESTS = [{
# ATK Season
'url': 'https://www.americastestkitchen.com/episodes/browse/season_1',
'url': 'https://www.americastestkitchen.com/episodes/season-1',
'info_dict': {
'id': 'season_1',
'title': 'Season 1',
},
'playlist_count': 13,
'playlist_mincount': 13,
}, {
# Latest ATK Season (new URL scheme)
'url': 'https://www.americastestkitchen.com/episodes/season-26',
'info_dict': {
'id': 'season_26',
'title': 'Season 26',
},
'playlist_count': 26,
}, {
# Cooks Country Season
'url': 'https://www.americastestkitchen.com/cookscountry/episodes/browse/season_12',
'url': 'https://www.americastestkitchen.com/cookscountry/episodes/season-12',
'info_dict': {
'id': 'season_12',
'title': 'Season 12',
},
'playlist_count': 13,
'playlist_mincount': 13,
}, {
# Old-style URL (redirects to the new season page)
'url': 'https://www.americastestkitchen.com/episodes/browse/season_1',
'only_matching': True,
}, {
# America's Test Kitchen Series
'url': 'https://www.americastestkitchen.com/',
@@ -130,7 +155,7 @@ class AmericasTestKitchenSeasonIE(InfoExtractor):
'id': 'americastestkitchen',
'title': 'America\'s Test Kitchen',
},
'playlist_count': 558,
'playlist_mincount': 558,
}, {
# Cooks Country Series
'url': 'https://www.americastestkitchen.com/cookscountry',
@@ -138,7 +163,7 @@ class AmericasTestKitchenSeasonIE(InfoExtractor):
'id': 'cookscountry',
'title': 'Cook\'s Country',
},
'playlist_count': 199,
'playlist_mincount': 199,
}, {
'url': 'https://www.americastestkitchen.com/cookscountry/',
'only_matching': True,
@@ -157,59 +182,46 @@ class AmericasTestKitchenSeasonIE(InfoExtractor):
}]
def _real_extract(self, url):
season_number, show1, show = self._match_valid_url(url).group('season', 'show', 'show2')
show_path = ('/' + show) if show else ''
show = show or show1
season_number = int_or_none(season_number)
domain, url_path, season = self._match_valid_url(url).group('domain', 'path', 'season')
show_path, title = self._SHOWS[url_path or domain]
season = int_or_none(season)
slug, title = {
'americastestkitchen': ('atk', 'America\'s Test Kitchen'),
'cookscountry': ('cco', 'Cook\'s Country'),
'cooksillustrated': ('cio', 'Cook\'s Illustrated'),
}[show]
if season:
playlist_id = f'season_{season}'
playlist_title = f'Season {season}'
facet_filters = [
'search_document_klass:episode',
'search_show_slug:' + slug,
]
if season_number:
playlist_id = f'season_{season_number}'
playlist_title = f'Season {season_number}'
facet_filters.append('search_season_list:' + playlist_title)
def entries():
yield from self._season_entries(show_path, season)
else:
playlist_id = show
playlist_id = url_path or domain
playlist_title = title
season_search = self._download_json(
f'https://y1fnzxui30-dsn.algolia.net/1/indexes/everest_search_{slug}_season_desc_production',
playlist_id, headers={
'Origin': 'https://www.americastestkitchen.com',
'X-Algolia-API-Key': '8d504d0099ed27c1b73708d22871d805',
'X-Algolia-Application-Id': 'Y1FNZXUI30',
}, query={
'facetFilters': json.dumps(facet_filters),
'attributesToRetrieve': f'description,search_{slug}_episode_number,search_document_date,search_url,title,search_atk_episode_season',
'attributesToHighlight': '',
'hitsPerPage': 1000,
})
def entries():
for episode in (season_search.get('hits') or []):
search_url = episode.get('search_url') # always formatted like '/episode/123-title-of-episode'
if not search_url:
continue
yield {
'_type': 'url',
'url': f'https://www.americastestkitchen.com{show_path or ""}{search_url}',
'id': try_get(episode, lambda e: e['objectID'].split('_')[-1]),
'title': episode.get('title'),
'description': episode.get('description'),
'timestamp': unified_timestamp(episode.get('search_document_date')),
'season_number': season_number,
'episode_number': int_or_none(episode.get(f'search_{slug}_episode_number')),
'ie_key': AmericasTestKitchenIE.ie_key(),
}
def entries():
for season_number in itertools.count(1):
try:
yield from self._season_entries(show_path, season_number)
except ExtractorError as e:
if isinstance(e.cause, HTTPError) and e.cause.status == 404:
break
raise
return self.playlist_result(
entries(), playlist_id, playlist_title)
def _season_entries(self, show_path, season_number):
webpage = self._download_webpage(
f'https://www.americastestkitchen.com{show_path}/episodes/season-{season_number}',
f'season-{season_number}', f'Downloading season {season_number} webpage')
seen = set()
for episode in re.finditer(
r'<a [^>]*\bhref="(?P<path>/(?:cookscountry/|cooksillustrated/)?episode/(?P<id>\d+)-[^"]+)"[^>]*>\s*<h3[^>]*>(?P<title>[^<]+)</h3>',
webpage):
path = episode.group('path')
if path in seen:
continue
seen.add(path)
yield self.url_result(
urljoin('https://www.americastestkitchen.com', path),
AmericasTestKitchenIE, episode.group('id'),
clean_html(episode.group('title')),
season_number=season_number)
+12 -42
View File
@@ -1,39 +1,22 @@
import time
from .common import InfoExtractor
from .applepodcasts import AppleBaseIE
from ..utils import (
ExtractorError,
extract_attributes,
float_or_none,
jwt_decode_hs256,
jwt_encode,
parse_resolution,
qualities,
unified_strdate,
update_url,
url_or_none,
urljoin,
)
from ..utils.traversal import (
find_element,
require,
traverse_obj,
)
class AppleConnectIE(InfoExtractor):
class AppleConnectIE(AppleBaseIE):
IE_NAME = 'apple:music:connect'
IE_DESC = 'Apple Music Connect'
_BASE_URL = 'https://music.apple.com'
_QUALITIES = {
'provisionalUploadVideo': None,
'sdVideo': 480,
'sdVideoWithPlusAudio': 480,
'sd480pVideo': 480,
'720pHdVideo': 720,
'1080pHdVideo': 1080,
}
_VALID_URL = r'https?://music\.apple\.com/[\w-]+/post/(?P<id>\d+)'
_TESTS = [{
'url': 'https://music.apple.com/us/post/1018290019',
@@ -59,29 +42,16 @@ class AppleConnectIE(InfoExtractor):
},
}]
_jwt = None
@staticmethod
def _jwt_is_expired(token):
return jwt_decode_hs256(token)['exp'] - time.time() < 120
def _get_token(self, webpage, video_id):
if self._jwt and not self._jwt_is_expired(self._jwt):
return self._jwt
js_url = traverse_obj(webpage, (
{find_element(tag='script', attr='crossorigin', value='', html=True)},
{extract_attributes}, 'src', {urljoin(self._BASE_URL)}, {require('JS URL')}))
js = self._download_webpage(
js_url, video_id, 'Downloading token JS', 'Unable to download token JS')
header = jwt_encode({}, '', headers={'alg': 'ES256', 'kid': 'WebPlayKid'}).split('.')[0]
self._jwt = self._search_regex(
fr'(["\'])(?P<jwt>{header}(?:\.[\w-]+){{2}})\1', js, 'JSON Web Token', group='jwt')
if self._jwt_is_expired(self._jwt):
raise ExtractorError('The fetched token is already expired')
return self._jwt
_BASE_URL = 'https://music.apple.com'
_JWT_KEY_ID = 'WebPlayKid'
_QUALITIES = {
'provisionalUploadVideo': None,
'sdVideo': 480,
'sdVideoWithPlusAudio': 480,
'sd480pVideo': 480,
'720pHdVideo': 720,
'1080pHdVideo': 1080,
}
def _real_extract(self, url):
video_id = self._match_id(url)
+98 -9
View File
@@ -1,15 +1,55 @@
import time
from .common import InfoExtractor
from ..utils import (
ExtractorError,
clean_html,
clean_podcast_url,
int_or_none,
jwt_decode_hs256,
jwt_encode,
parse_iso8601,
try_call,
update_url,
url_or_none,
urljoin,
)
from ..utils.traversal import traverse_obj
class ApplePodcastsIE(InfoExtractor):
_VALID_URL = r'https?://podcasts\.apple\.com/(?:[^/]+/)?podcast(?:/[^/]+){1,2}.*?\bi=(?P<id>\d+)'
class AppleBaseIE(InfoExtractor):
"""Subclasses must set _BASE_URL and _JWT_KEY_ID"""
_jwt_cache = {}
@staticmethod
def _jwt_is_expired(token):
return jwt_decode_hs256(token)['exp'] - time.time() < 120
def _get_token(self, webpage, episode_id):
if self._jwt_cache.get(self._BASE_URL) and not self._jwt_is_expired(self._jwt_cache[self._BASE_URL]):
return self._jwt_cache[self._BASE_URL]
js_path = self._search_regex(
r'<script [^>]*\bsrc="(/assets/index~[0-9a-f]+\.js)">', webpage, 'JS asset path')
js_code = self._download_webpage(
urljoin(self._BASE_URL, js_path), episode_id,
'Downloading JS asset', 'Unable to download JS asset')
header = jwt_encode({}, '', headers={'typ': 'JWT', 'alg': 'ES256', 'kid': self._JWT_KEY_ID}).split('.')[0]
self._jwt_cache[self._BASE_URL] = self._search_regex(
fr'(["\'])(?P<jwt>{header}(?:\.[\w-]+){{2}})\1', js_code, 'JSON Web Token', group='jwt')
if self._jwt_is_expired(self._jwt_cache[self._BASE_URL]):
raise ExtractorError('The fetched token is already expired')
return self._jwt_cache[self._BASE_URL]
class ApplePodcastsIE(AppleBaseIE):
IE_NAME = 'apple:podcasts'
IE_DESC = 'Apple Podcasts'
_VALID_URL = r'https?://podcasts\.apple\.com/(?P<country>[^/?#]+/)?podcast(?:/[^/?#]+){1,2}/?\?(?:[^#]+&)?i=(?P<id>\d+)'
_TESTS = [{
'url': 'https://podcasts.apple.com/us/podcast/urbana-podcast-724-by-david-penn/id1531349107?i=1000748574256',
'md5': 'f8a6f92735d0cfbd5e6a7294151e28d8',
@@ -23,7 +63,7 @@ class ApplePodcastsIE(InfoExtractor):
'timestamp': 1770400801,
'duration': 3602,
'series': 'Urbana Radio Show',
'thumbnail': 're:.+[.](png|jpe?g|webp)',
'thumbnail': r're:https://.+/.+\.jpg',
},
}, {
'url': 'https://podcasts.apple.com/us/podcast/207-whitney-webb-returns/id1135137367?i=1000482637777',
@@ -39,7 +79,7 @@ class ApplePodcastsIE(InfoExtractor):
'timestamp': 1593932400,
'duration': 5369,
'series': 'The Tim Dillon Show',
'thumbnail': 're:.+[.](png|jpe?g|webp)',
'thumbnail': r're:https://.+/.+\.jpg',
},
}, {
'url': 'https://podcasts.apple.com/podcast/207-whitney-webb-returns/id1135137367?i=1000482637777',
@@ -52,15 +92,55 @@ class ApplePodcastsIE(InfoExtractor):
'only_matching': True,
}]
def _real_extract(self, url):
episode_id = self._match_id(url)
webpage = self._download_webpage(url, episode_id)
_BASE_URL = 'https://podcasts.apple.com'
_JWT_KEY_ID = 'C4J7GBP74H'
def _extract_podcast_from_api(self, webpage, episode_id, country_code):
data = self._download_json(
f'https://amp-api.podcasts.apple.com/v1/catalog/{country_code or "us"}/podcast-episodes/{episode_id}',
episode_id, headers={
'Authorization': f'Bearer {self._get_token(webpage, episode_id)}',
'Origin': self._BASE_URL,
},
query={
# XXX: if video is available, try adding the params 'with=entitlements,hlsVideo'
'extend': 'fullDescription',
'include': 'podcast',
'l': 'en-US',
})['data'][0]
thumb_info = traverse_obj(data, ('attributes', 'artwork', {
'url': ('url', {url_or_none}),
'h': ('height', {int_or_none}),
'w': ('width', {int_or_none}),
}))
return {
'id': episode_id,
**traverse_obj(data, {
'title': ('attributes', 'name', {str}),
'description': ('attributes', 'fullDescription', {clean_html}),
'url': ('attributes', 'assetUrl', {clean_podcast_url}, {update_url(scheme='https')}),
'timestamp': ('attributes', 'releaseDateTime', {parse_iso8601}),
'duration': ('attributes', 'durationInMilliseconds', {int_or_none(scale=1000)}),
'episode': ('attributes', 'name', {str}),
'episode_number': ('attributes', 'episodeNumber', {int_or_none}),
'series': ('relationships', 'podcast', 'data', 0, 'attributes', 'name', {str}),
}),
'thumbnail': try_call(lambda: thumb_info.pop('url').format(f='jpg', **thumb_info)),
'vcodec': 'none',
}
def _extract_podcast_from_webpage(self, webpage, episode_id):
server_data = self._search_json(
r'<script [^>]*\bid=["\']serialized-server-data["\'][^>]*>', webpage,
'server data', episode_id)['data'][0]['data']
'server data', episode_id, default=None)
model_data = traverse_obj(server_data, (
'headerButtonItems', lambda _, v: v['$kind'] == 'share' and v['modelType'] == 'EpisodeLockup',
'data', 0, 'data', 'headerButtonItems',
lambda _, v: v['$kind'] == 'share' and v['modelType'] == 'EpisodeLockup',
'model', {dict}, any))
if not model_data:
return None
return {
'id': episode_id,
@@ -77,3 +157,12 @@ class ApplePodcastsIE(InfoExtractor):
'thumbnail': self._og_search_thumbnail(webpage),
'vcodec': 'none',
}
def _real_extract(self, url):
episode_id, country_code = self._match_valid_url(url).group('id', 'country')
# Webpage may be unavailable, see https://github.com/yt-dlp/yt-dlp/issues/17266
webpage = self._download_webpage(url, episode_id, expected_status=500)
return (
self._extract_podcast_from_webpage(webpage, episode_id)
or self._extract_podcast_from_api(webpage, episode_id, country_code))
-115
View File
@@ -11,15 +11,12 @@ from ..utils import (
join_nonempty,
jwt_decode_hs256,
make_archive_id,
parse_duration,
parse_iso8601,
remove_start,
str_or_none,
unified_strdate,
update_url,
update_url_query,
url_or_none,
xpath_text,
)
from ..utils.traversal import traverse_obj, value
@@ -119,118 +116,6 @@ class ARDMediathekBaseIE(InfoExtractor):
return formats
class ARDIE(InfoExtractor):
_VALID_URL = r'(?P<mainurl>https?://(?:www\.)?daserste\.de/(?:[^/?#&]+/)+(?P<id>[^/?#&]+))\.html'
_TESTS = [{
# available till 7.12.2023
'url': 'https://www.daserste.de/information/talk/maischberger/videos/maischberger-video-424.html',
'md5': '94812e6438488fb923c361a44469614b',
'info_dict': {
'id': 'maischberger-video-424',
'display_id': 'maischberger-video-424',
'ext': 'mp4',
'duration': 4452.0,
'title': 'maischberger am 07.12.2022',
'upload_date': '20221207',
'thumbnail': r're:^https?://.*\.jpg$',
},
}, {
'url': 'https://www.daserste.de/information/politik-weltgeschehen/morgenmagazin/videosextern/dominik-kahun-aus-der-nhl-direkt-zur-weltmeisterschaft-100.html',
'only_matching': True,
}, {
'url': 'https://www.daserste.de/information/nachrichten-wetter/tagesthemen/videosextern/tagesthemen-17736.html',
'only_matching': True,
}, {
'url': 'https://www.daserste.de/unterhaltung/serie/in-aller-freundschaft-die-jungen-aerzte/videos/diversity-tag-sanam-afrashteh100.html',
'only_matching': True,
}, {
'url': 'http://www.daserste.de/information/reportage-dokumentation/dokus/videos/die-story-im-ersten-mission-unter-falscher-flagge-100.html',
'only_matching': True,
}, {
'url': 'https://www.daserste.de/unterhaltung/serie/in-aller-freundschaft-die-jungen-aerzte/Drehpause-100.html',
'only_matching': True,
}, {
'url': 'https://www.daserste.de/unterhaltung/film/filmmittwoch-im-ersten/videos/making-ofwendezeit-video-100.html',
'only_matching': True,
}]
def _real_extract(self, url):
mobj = self._match_valid_url(url)
display_id = mobj.group('id')
player_url = mobj.group('mainurl') + '~playerXml.xml'
doc = self._download_xml(player_url, display_id)
video_node = doc.find('./video')
upload_date = unified_strdate(xpath_text(
video_node, './broadcastDate'))
thumbnail = xpath_text(video_node, './/teaserImage//variant/url')
formats = []
for a in video_node.findall('.//asset'):
file_name = xpath_text(a, './fileName', default=None)
if not file_name:
continue
format_type = a.attrib.get('type')
format_url = url_or_none(file_name)
if format_url:
ext = determine_ext(file_name)
if ext == 'm3u8':
formats.extend(self._extract_m3u8_formats(
format_url, display_id, 'mp4', entry_protocol='m3u8_native',
m3u8_id=format_type or 'hls', fatal=False))
continue
elif ext == 'f4m':
formats.extend(self._extract_f4m_formats(
update_url_query(format_url, {'hdcore': '3.7.0'}),
display_id, f4m_id=format_type or 'hds', fatal=False))
continue
f = {
'format_id': format_type,
'width': int_or_none(xpath_text(a, './frameWidth')),
'height': int_or_none(xpath_text(a, './frameHeight')),
'vbr': int_or_none(xpath_text(a, './bitrateVideo')),
'abr': int_or_none(xpath_text(a, './bitrateAudio')),
'vcodec': xpath_text(a, './codecVideo'),
'tbr': int_or_none(xpath_text(a, './totalBitrate')),
}
server_prefix = xpath_text(a, './serverPrefix', default=None)
if server_prefix:
f.update({
'url': server_prefix,
'playpath': file_name,
})
else:
if not format_url:
continue
f['url'] = format_url
formats.append(f)
_SUB_FORMATS = (
('./dataTimedText', 'ttml'),
('./dataTimedTextNoOffset', 'ttml'),
('./dataTimedTextVtt', 'vtt'),
)
subtitles = {}
for subsel, subext in _SUB_FORMATS:
for node in video_node.findall(subsel):
subtitles.setdefault('de', []).append({
'url': node.attrib['url'],
'ext': subext,
})
return {
'id': xpath_text(video_node, './videoId', default=display_id),
'formats': formats,
'subtitles': subtitles,
'display_id': display_id,
'title': video_node.find('./title').text,
'duration': parse_duration(video_node.find('./duration').text),
'upload_date': upload_date,
'thumbnail': thumbnail,
}
class ARDBetaMediathekIE(InfoExtractor):
IE_NAME = 'ARDMediathek'
_VALID_URL = r'''(?x)https?://
+1 -1
View File
@@ -12,7 +12,7 @@ class AWSIE(InfoExtractor): # XXX: Conventionally, base classes should end with
def _aws_execute_api(self, aws_dict, video_id, query=None):
query = query or {}
amz_date = dt.datetime.now(dt.timezone.utc).strftime('%Y%m%dT%H%M%SZ')
amz_date = dt.datetime.now(dt.UTC).strftime('%Y%m%dT%H%M%SZ')
date = amz_date[:8]
headers = {
'Accept': 'application/json',
+60 -34
View File
@@ -25,7 +25,35 @@ from ..utils import (
from ..utils.traversal import find_element, find_elements, traverse_obj
class BandcampIE(InfoExtractor):
class BandcampBaseIE(InfoExtractor):
# Initially try without impersonation, retry with impersonation
def _download_webpage(self, *args, **kwargs):
impersonate = kwargs.pop('impersonate', None) or True
kwargs.pop('require_impersonation', None)
webpage = super()._download_webpage(*args, **kwargs)
if webpage:
if self._html_extract_title(webpage) == 'Client Challenge':
self.write_debug('Got client challenge webpage response')
else:
return webpage
res = self._download_webpage_handle(*args, impersonate=impersonate, require_impersonation=True, **kwargs)
if res is False:
return False
webpage, urlh = res
if self._html_extract_title(webpage) == 'Client Challenge':
raise ExtractorError(f'Got client challenge webpage response with {urlh.extensions.get("impersonate")}')
return webpage
def _extract_data_attr(self, webpage, video_id, attr='tralbum', fatal=True):
return self._parse_json(self._html_search_regex(
rf'data-{attr}=(["\'])({{.+?}})\1', webpage,
attr + ' data', group=2), video_id, fatal=fatal)
class BandcampIE(BandcampBaseIE):
_VALID_URL = r'https?://(?P<uploader>[^/]+)\.bandcamp\.com/track/(?P<id>[^/?#&]+)'
_EMBED_REGEX = [r'<meta property="og:url"[^>]*?content="(?P<url>.*?bandcamp\.com.*?)"']
_TESTS = [{
@@ -68,7 +96,7 @@ class BandcampIE(InfoExtractor):
'album': 'FTL: Advanced Edition Soundtrack',
'uploader_url': 'https://benprunty.bandcamp.com',
'uploader_id': 'benprunty',
'tags': ['soundtrack', 'chiptunes', 'cinematic', 'electronic', 'video game music', 'California'],
'tags': ['soundtrack', 'chiptunes', 'cinematic', 'electronic', 'video game music', 'North Carolina'],
'artists': ['Ben Prunty'],
'album_artists': ['Ben Prunty'],
},
@@ -146,13 +174,9 @@ class BandcampIE(InfoExtractor):
'uploader_id': 'stayinside',
'uploader_url': 'https://stayinside.bandcamp.com',
},
'skip': 'embed detection is broken',
}]
def _extract_data_attr(self, webpage, video_id, attr='tralbum', fatal=True):
return self._parse_json(self._html_search_regex(
rf'data-{attr}=(["\'])({{.+?}})\1', webpage,
attr + ' data', group=2), video_id, fatal=fatal)
def _real_extract(self, url):
title, uploader = self._match_valid_url(url).group('id', 'uploader')
webpage = self._download_webpage(url, title)
@@ -283,7 +307,7 @@ class BandcampIE(InfoExtractor):
}
class BandcampAlbumIE(BandcampIE): # XXX: Do not subclass from concrete IE
class BandcampAlbumIE(BandcampBaseIE):
IE_NAME = 'Bandcamp:album'
_VALID_URL = r'https?://(?:(?P<subdomain>[^.]+)\.)?bandcamp\.com/album/(?P<id>[^/?#&]+)'
@@ -296,21 +320,22 @@ class BandcampAlbumIE(BandcampIE): # XXX: Do not subclass from concrete IE
'id': '1353101989',
'ext': 'mp3',
'title': 'Blazo - Intro',
'thumbnail': r're:https?://f4\.bcbits\.com/img/.+\.jpg',
'uploader': 'Blazo',
'uploader_id': 'blazo',
'uploader_url': 'https://blazo.bandcamp.com',
'duration': 19.335,
'thumbnail': 'https://f4.bcbits.com/img/a1721150828_5.jpg',
'tags': ['hip-hop/rap', 'hip-hop', 'Poland'],
'artists': ['Blazo'],
'album_artists': ['Blazo'],
'track': 'Intro',
'track_number': 1,
'track_id': '1353101989',
'album': 'Jazz Format Mixtape vol.1',
'timestamp': 1311756226,
'upload_date': '20110727',
'uploader': 'Blazo',
'album_artists': ['Blazo'],
'uploader_url': 'https://blazo.bandcamp.com',
'release_timestamp': 1311724800,
'release_date': '20110727',
'release_timestamp': 1311724800.0,
'track': 'Intro',
'uploader_id': 'blazo',
'track_number': 1,
'album': 'Jazz Format Mixtape vol.1',
'artists': ['Blazo'],
'duration': 19.335,
'track_id': '1353101989',
},
},
{
@@ -319,21 +344,22 @@ class BandcampAlbumIE(BandcampIE): # XXX: Do not subclass from concrete IE
'id': '38097443',
'ext': 'mp3',
'title': 'Blazo - Kero One - Keep It Alive (Blazo remix)',
'thumbnail': r're:https?://f4\.bcbits\.com/img/.+\.jpg',
'uploader': 'Blazo',
'uploader_id': 'blazo',
'uploader_url': 'https://blazo.bandcamp.com',
'duration': 181.467,
'thumbnail': 'https://f4.bcbits.com/img/a1721150828_5.jpg',
'tags': ['hip-hop/rap', 'hip-hop', 'Poland'],
'artists': ['Blazo'],
'album_artists': ['Blazo'],
'track': 'Kero One - Keep It Alive (Blazo remix)',
'track_number': 2,
'track_id': '38097443',
'album': 'Jazz Format Mixtape vol.1',
'timestamp': 1311757238,
'upload_date': '20110727',
'uploader': 'Blazo',
'track': 'Kero One - Keep It Alive (Blazo remix)',
'release_timestamp': 1311724800,
'release_date': '20110727',
'track_id': '38097443',
'track_number': 2,
'duration': 181.467,
'uploader_url': 'https://blazo.bandcamp.com',
'album': 'Jazz Format Mixtape vol.1',
'uploader_id': 'blazo',
'album_artists': ['Blazo'],
'artists': ['Blazo'],
'release_timestamp': 1311724800.0,
},
},
],
@@ -411,7 +437,7 @@ class BandcampAlbumIE(BandcampIE): # XXX: Do not subclass from concrete IE
}
class BandcampWeeklyIE(BandcampIE): # XXX: Do not subclass from concrete IE
class BandcampWeeklyIE(BandcampBaseIE):
IE_NAME = 'Bandcamp:weekly'
_VALID_URL = r'https?://(?:www\.)?bandcamp\.com/radio/?\?(?:[^#]+&)?show=(?P<id>\d+)'
_TESTS = [{
@@ -475,7 +501,7 @@ class BandcampWeeklyIE(BandcampIE): # XXX: Do not subclass from concrete IE
}
class BandcampUserIE(InfoExtractor):
class BandcampUserIE(BandcampBaseIE):
IE_NAME = 'Bandcamp:user'
_VALID_URL = r'https?://(?!www\.)(?P<id>[^.]+)\.bandcamp\.com(?:/music)?/?(?:[#?]|$)'
+18 -32
View File
@@ -7,30 +7,23 @@ from ..utils import ExtractorError, extract_attributes
class BFMTVBaseIE(InfoExtractor):
_VALID_URL_BASE = r'https?://(?:www\.|rmc\.)?bfmtv\.com/'
_VALID_URL_TMPL = _VALID_URL_BASE + r'(?:[^/]+/)*[^/?&#]+_%s[A-Z]-(?P<id>\d{12})\.html'
_VIDEO_BLOCK_REGEX = r'(<div[^>]+class="video_block[^"]*"[^>]*>.*?</div>)'
_VIDEO_ELEMENT_REGEX = r'(<video-js[^>]+>)'
_VIDEO_BLOCK_REGEX = r'(<div[^>]+\bdata-video-id=[^>]+>.*?</div>)'
BRIGHTCOVE_URL_TEMPLATE = 'http://players.brightcove.net/%s/%s_default/index.html?videoId=%s'
def _extract_video(self, video_block):
video_element = self._search_regex(
self._VIDEO_ELEMENT_REGEX, video_block, 'video element', default=None)
if video_element:
video_element_attrs = extract_attributes(video_element)
video_id = video_element_attrs.get('data-video-id')
if not video_id:
return
account_id = video_element_attrs.get('data-account') or '876450610001'
player_id = video_element_attrs.get('adjustplayer') or '19dszYXgm'
else:
video_block_attrs = extract_attributes(video_block)
video_id = video_block_attrs.get('videoid')
if not video_id:
return
account_id = video_block_attrs.get('accountid') or '876630703001'
player_id = video_block_attrs.get('playerid') or 'KbPwEbuHx'
return self.url_result(
self.BRIGHTCOVE_URL_TEMPLATE % (account_id, player_id, video_id),
'BrightcoveNew', video_id)
def _extract_video(self, video_block, fatal=True):
video_block_attrs = extract_attributes(video_block)
video_id = video_block_attrs.get('data-video-id')
if not video_id:
msg = 'Unable to extract Brightcove video id'
if not fatal:
self.report_warning(msg)
return {}
raise ExtractorError(msg)
account_id = video_block_attrs.get('data-account-id') or '876450612001'
player_id = video_block_attrs.get('playerid') or 'default'
return self.url_result(self.BRIGHTCOVE_URL_TEMPLATE % (account_id, player_id, video_id), 'BrightcoveNew', video_id)
class BFMTVIE(BFMTVBaseIE):
@@ -55,11 +48,8 @@ class BFMTVIE(BFMTVBaseIE):
def _real_extract(self, url):
bfmtv_id = self._match_id(url)
webpage = self._download_webpage(url, bfmtv_id)
video = self._extract_video(self._search_regex(
return self._extract_video(self._search_regex(
self._VIDEO_BLOCK_REGEX, webpage, 'video block'))
if not video:
raise ExtractorError('Failed to extract video')
return video
class BFMTVLiveIE(BFMTVBaseIE):
@@ -76,7 +66,6 @@ class BFMTVLiveIE(BFMTVBaseIE):
'timestamp': 1706887572,
'live_status': 'is_live',
'thumbnail': r're:https://.+/image\.jpg',
'tags': [],
},
'params': {
'skip_download': True,
@@ -89,11 +78,8 @@ class BFMTVLiveIE(BFMTVBaseIE):
def _real_extract(self, url):
bfmtv_id = self._match_id(url)
webpage = self._download_webpage(url, bfmtv_id)
video = self._extract_video(self._search_regex(
return self._extract_video(self._search_regex(
self._VIDEO_BLOCK_REGEX, webpage, 'video block'))
if not video:
raise ExtractorError('Failed to extract video')
return video
class BFMTVArticleIE(BFMTVBaseIE):
@@ -130,7 +116,7 @@ class BFMTVArticleIE(BFMTVBaseIE):
def _entries(self, webpage):
for video_block_el in re.findall(self._VIDEO_BLOCK_REGEX, webpage):
video = self._extract_video(video_block_el)
video = self._extract_video(video_block_el, fatal=False)
if video:
yield video
+24 -15
View File
@@ -432,29 +432,28 @@ class InfoExtractor:
chapter: Name or title of the chapter the video belongs to.
chapter_number: Number of the chapter the video belongs to, as an integer.
chapter_id: Id of the chapter the video belongs to, as a unicode string.
chapter_id: Id of the chapter the video belongs to.
The following fields should only be used when the video is an episode of some
series, programme or podcast:
series: Title of the series or programme the video episode belongs to.
series_id: Id of the series or programme the video episode belongs to, as a unicode string.
series_id: Id of the series or programme the video episode belongs to.
season: Title of the season the video episode belongs to.
season_number: Number of the season the video episode belongs to, as an integer.
season_id: Id of the season the video episode belongs to, as a unicode string.
season_id: Id of the season the video episode belongs to.
episode: Title of the video episode. Unlike mandatory video title field,
this field should denote the exact title of the video episode
without any kind of decoration.
episode_number: Number of the video episode within a season, as an integer.
episode_id: Id of the video episode, as a unicode string.
episode_id: Id of the video episode.
The following fields should only be used when the media is a track or a part of
a music album:
track: Title of the track.
track_number: Number of the track within an album or a disc, as an integer.
track_id: Id of the track (useful in case of custom indexing, e.g. 6.iii),
as a unicode string.
track_id: Id of the track (useful for custom indexing, e.g. 6.iii).
artists: List of artists of the track.
composers: List of composers of the piece.
genres: List of genres of the track.
@@ -487,7 +486,7 @@ class InfoExtractor:
creator: Use "creators" instead.
The creator of the video.
Unless mentioned otherwise, the fields should be Unicode strings.
Unless mentioned otherwise, the fields should be strings.
Unless mentioned otherwise, None is equivalent to absence of information.
@@ -1277,6 +1276,9 @@ class InfoExtractor:
"""Returns a URL that points to a page that should be processed"""
if ie is not None:
kwargs['ie_key'] = ie if isinstance(ie, str) else ie.ie_key()
# Silence fallback warning if this is an intentional generic result
if kwargs.get('ie_key') == 'Generic':
url = smuggle_url(url, {'to_generic': True})
if video_id is not None:
kwargs['id'] = video_id
if video_title is not None:
@@ -1309,7 +1311,7 @@ class InfoExtractor:
'entries': entries,
}
def _search_regex(self, pattern, string, name, default=NO_DEFAULT, fatal=True, flags=0, group=None):
def _search_regex(self, pattern, string, name, default=NO_DEFAULT, fatal=True, flags=re.NOFLAG, group=None):
"""
Perform a regex search on the given string, using a single or a list of
patterns returning the first matching group.
@@ -1371,7 +1373,7 @@ class InfoExtractor:
f'Unable to extract {_name} - Failed to parse JSON: {e}', video_id=video_id)
return default
def _html_search_regex(self, pattern, string, name, default=NO_DEFAULT, fatal=True, flags=0, group=None):
def _html_search_regex(self, pattern, string, name, default=NO_DEFAULT, fatal=True, flags=re.NOFLAG, group=None):
"""
Like _search_regex, but strips HTML tags and unescapes entities.
"""
@@ -1411,12 +1413,6 @@ class InfoExtractor:
self.write_debug(f'Using netrc for {netrc_machine} authentication')
# compat: <=py3.10: netrc cannot parse tokens as empty strings, will return `""` instead
# Ref: https://github.com/yt-dlp/yt-dlp/issues/11413
# https://github.com/python/cpython/commit/15409c720be0503131713e3d3abc1acd0da07378
if sys.version_info < (3, 11):
return tuple(x if x != '""' else '' for x in info[::2])
return info[0], info[2]
def _get_login_info(self, username_option='username', password_option='password', netrc_machine=None):
@@ -3960,6 +3956,19 @@ class InfoExtractor:
headers['Ytdl-request-proxy'] = geo_verification_proxy
return headers
@staticmethod
def _generate_blockbuster_headers(*, min_headers=2, max_headers=8):
"""Randomize our HTTP header fingerprint in an attempt to bust HTTP Error 403 blockage"""
def random_letters(minimum, maximum):
# Omit vowels so we don't generate valid header names like 'authorization', etc
return ''.join(random.choices('bcdfghjklmnpqrstvwxz', k=random.randint(minimum, maximum)))
return {
random_letters(8, 24): random_letters(16, 32)
for _ in range(random.randint(min_headers, max_headers))
}
@staticmethod
def _generic_id(url):
return urllib.parse.unquote(os.path.splitext(url.rstrip('/').split('/')[-1])[0])
-14
View File
@@ -1,6 +1,5 @@
import functools
import json
import random
import re
import urllib.parse
@@ -364,19 +363,6 @@ class DailymotionIE(DailymotionBaseInfoExtractor):
continue
yield update_url(player_url, query=query_string)
@staticmethod
def _generate_blockbuster_headers():
"""Randomize our HTTP header fingerprint to bust the HTTP Error 403 block"""
def random_letters(minimum, maximum):
# Omit vowels so we don't generate valid header names like 'authorization', etc
return ''.join(random.choices('bcdfghjklmnpqrstvwxz', k=random.randint(minimum, maximum)))
return {
random_letters(8, 24): random_letters(16, 32)
for _ in range(random.randint(2, 8))
}
def _extract_dailymotion_m3u8_formats_and_subtitles(self, media_url, video_id, live=False):
"""See https://github.com/yt-dlp/yt-dlp/issues/15526"""
+105 -116
View File
@@ -1,14 +1,6 @@
from .common import InfoExtractor
from ..utils import (
clean_html,
join_nonempty,
parse_duration,
str_or_none,
traverse_obj,
unified_strdate,
unified_timestamp,
urlhandle_detect_ext,
)
from ..utils import url_or_none
from ..utils.traversal import require, traverse_obj
class GlobalPlayerBaseIE(InfoExtractor):
@@ -16,29 +8,11 @@ class GlobalPlayerBaseIE(InfoExtractor):
webpage = self._download_webpage(url, video_id)
return self._search_nextjs_data(webpage, video_id)['props']['pageProps']
def _request_ext(self, url, video_id):
return urlhandle_detect_ext(self._request_webpage( # Server rejects HEAD requests
url, video_id, note='Determining source extension'))
def _extract_audio(self, episode, series):
return {
'vcodec': 'none',
**traverse_obj(series, {
'series': 'title',
'series_id': 'id',
'thumbnail': 'imageUrl',
'uploader': 'itunesAuthor', # podcasts only
}),
**traverse_obj(episode, {
'id': 'id',
'description': ('description', {clean_html}),
'duration': ('duration', {parse_duration}),
'thumbnail': 'imageUrl',
'url': 'streamUrl',
'timestamp': (('pubDate', 'startDate'), {unified_timestamp}),
'title': 'title',
}, get_all=False),
}
@staticmethod
def _get_playback_url(data):
return traverse_obj(data, (
'playback', lambda _, v: v['canUse'] == 'true',
'url', {url_or_none}, any, {require('playback URL')}))
class GlobalPlayerLiveIE(GlobalPlayerBaseIE):
@@ -48,11 +22,10 @@ class GlobalPlayerLiveIE(GlobalPlayerBaseIE):
'info_dict': {
'id': '2mx1E',
'ext': 'aac',
'display_id': 'smoothchill-uk',
'title': 're:^Smooth Chill.+$',
'thumbnail': 'https://herald.musicradio.com/media/f296ade8-50c9-4f60-911f-924e96873620.png',
'description': 'Music To Chill To',
'live_status': 'is_live',
'thumbnail': 'md5:d5040f26c7c4061014a44866129b900e',
'description': 'md5:6e183929da9001778895f32ae85124bc',
'title': 're:^Smooth Chill.+$',
},
}, {
# national station
@@ -60,11 +33,10 @@ class GlobalPlayerLiveIE(GlobalPlayerBaseIE):
'info_dict': {
'id': '2mwx4',
'ext': 'aac',
'description': 'turn up the feel good!',
'thumbnail': 'https://herald.musicradio.com/media/49b9e8cb-15bf-4bf2-8c28-a4850cc6b0f3.png',
'live_status': 'is_live',
'description': 'md5:492d07dfea8addadd15650ef40c10d02',
'thumbnail': 'md5:6f13378a53ce55bcf57365a654e1b490',
'title': 're:^Heart UK.+$',
'display_id': 'heart-uk',
},
}, {
# regional variation
@@ -72,110 +44,131 @@ class GlobalPlayerLiveIE(GlobalPlayerBaseIE):
'info_dict': {
'id': 'AMqg',
'ext': 'aac',
'thumbnail': 'https://herald.musicradio.com/media/49b9e8cb-15bf-4bf2-8c28-a4850cc6b0f3.png',
'title': 're:^Heart London.+$',
'live_status': 'is_live',
'display_id': 'heart-london',
'description': 'turn up the feel good!',
'description': 'md5:492d07dfea8addadd15650ef40c10d02',
'thumbnail': 'md5:6f13378a53ce55bcf57365a654e1b490',
'title': 're:^Heart London.+$',
},
}]
def _real_extract(self, url):
video_id = self._match_id(url)
station = self._get_page_props(url, video_id)['station']
stream_url = station['streamUrl']
meta = self._get_page_props(url, video_id)['station']
station_id = meta['id']
data = self._download_json(f'https://bff-web-guacamole.musicradio.com/playables/{station_id}', video_id)
return {
'id': station['id'],
'display_id': join_nonempty('brandSlug', 'slug', from_dict=station) or station.get('legacyStationPrefix'),
'url': stream_url,
'ext': self._request_ext(stream_url, video_id),
'id': station_id,
'url': self._get_playback_url(data),
'ext': 'aac',
'vcodec': 'none',
'is_live': True,
**traverse_obj(station, {
'title': (('name', 'brandName'), {str_or_none}),
'description': 'tagline',
'thumbnail': 'brandLogo',
}, get_all=False),
**traverse_obj(meta, {
'thumbnail': ('brandLogo', {url_or_none}),
'description': ('tagline', {str}),
'title': ('name', {str}),
}),
}
class GlobalPlayerLivePlaylistIE(GlobalPlayerBaseIE):
_VALID_URL = r'https?://www\.globalplayer\.com/playlists/(?P<id>\w+)'
_TESTS = [{
# "live playlist"
# live playlist
'url': 'https://www.globalplayer.com/playlists/8bLk/',
'info_dict': {
'id': '8bLk',
'ext': 'aac',
'live_status': 'is_live',
'description': 'md5:e10f5e10b01a7f2c14ba815509fbb38d',
'thumbnail': 'https://images.globalplayer.com/images/551379?width=450&signature=oMLPZIoi5_dBSHnTMREW0Xg76mA=',
'thumbnail': 'md5:391a13cc087b42f626e9e65bbeaf0a11',
'description': 'md5:f015f2f6c6f6a807669ebcc9a0ca147c',
'title': 're:^Classic FM Hall of Fame.+$',
},
}]
def _real_extract(self, url):
video_id = self._match_id(url)
station = self._get_page_props(url, video_id)['playlistData']
stream_url = station['streamUrl']
meta = self._get_page_props(url, video_id)['playlistData']
return {
'id': video_id,
'url': stream_url,
'ext': self._request_ext(stream_url, video_id),
'url': meta['streamUrl'],
'ext': 'aac',
'vcodec': 'none',
'id': video_id,
'is_live': True,
**traverse_obj(station, {
'title': 'title',
'description': 'description',
'thumbnail': 'image',
**traverse_obj(meta, {
'thumbnail': ('image', {url_or_none}),
'description': ('description', {str}),
'title': ('title', {str}),
}),
}
class GlobalPlayerAudioIE(GlobalPlayerBaseIE):
_VALID_URL = r'https?://www\.globalplayer\.com/(?:(?P<podcast>podcasts)/|catchup/\w+/\w+/)(?P<id>\w+)/?(?:$|[?#])'
_VALID_URL = r'https?://www\.globalplayer\.com/(?P<path>(?P<podcast>podcasts)/|catchup/\w+/\w+/)(?P<id>\w+)/?(?:$|[?#])'
_TESTS = [{
# podcast
'url': 'https://www.globalplayer.com/podcasts/42KuaM/',
'playlist_mincount': 5,
'playlist_mincount': 2,
'info_dict': {
'id': '42KuaM',
'title': 'Filthy Ritual',
'thumbnail': 'md5:60286e7d12d795bd1bbc9efc6cee643e',
'categories': ['Society & Culture', 'True Crime'],
'uploader': 'Global',
'description': 'md5:da5b918eac9ae319454a10a563afacf9',
'description': 'md5:17b7b9e3c76b2f4d9e31ccc4f0b66e32',
'title': 'Filthy Ritual',
},
}, {
# radio catchup
'url': 'https://www.globalplayer.com/catchup/lbc/uk/46vyD7z/',
'playlist_mincount': 3,
'playlist_mincount': 2,
'info_dict': {
'id': '46vyD7z',
'description': 'Nick Ferrari At Breakfast is Leading Britain\'s Conversation.',
'thumbnail': 'md5:664ad62a8fb920a2b8e264ed780eee3d',
'description': 'md5:53b6fa5ef71a3cff6628551bcc416384',
'title': 'Nick Ferrari',
'thumbnail': 'md5:4df24d8a226f5b2508efbcc6ae874ebf',
},
}]
def _real_extract(self, url):
video_id, podcast = self._match_valid_url(url).group('id', 'podcast')
video_id, path, podcast = self._match_valid_url(url).group('id', 'path', 'podcast')
props = self._get_page_props(url, video_id)
series = props['podcastInfo'] if podcast else props['catchupInfo']
if podcast:
meta = props['podcastInfo']['metadata']
blocks = props['podcastInfo']['blocks'][1]['items']
else:
catchup = props['catchupShow'] if 'catchupShow' in props else props['catchupInfo']
meta = catchup['metadata']
blocks = catchup['blocks'][1]['items']
def _entries():
for block in blocks:
entry_id = block['id']
data = self._download_json(
f'https://bff-web-guacamole.musicradio.com/playables/{entry_id}',
video_id, f'Downloading metadata JSON for {entry_id}')
yield {
'id': entry_id,
'url': self._get_playback_url(data),
'vcodec': 'none',
'extractor': GlobalPlayerAudioEpisodeIE.IE_NAME,
'extractor_key': GlobalPlayerAudioEpisodeIE.ie_key(),
'webpage_url': f'https://www.globalplayer.com/{path}episodes/{entry_id}',
**traverse_obj(block, {
'thumbnail': ('image', 'url', {url_or_none}),
'description': ('description', {str}),
'title': ('title', {str}),
}),
}
return {
'_type': 'playlist',
'id': video_id,
'entries': [self._extract_audio(ep, series) for ep in traverse_obj(
series, ('episodes', lambda _, v: v['id'] and v['streamUrl']))],
'categories': traverse_obj(series, ('categories', ..., 'name')) or None,
**traverse_obj(series, {
'description': 'description',
'thumbnail': 'imageUrl',
'title': 'title',
'uploader': 'itunesAuthor', # podcasts only
'entries': _entries(),
**traverse_obj(meta, {
'thumbnail': ('image', 'url', {url_or_none}),
'description': ('description', {str}),
'title': ('title', {str}),
}),
}
@@ -184,44 +177,42 @@ class GlobalPlayerAudioEpisodeIE(GlobalPlayerBaseIE):
_VALID_URL = r'https?://www\.globalplayer\.com/(?:(?P<podcast>podcasts)|catchup/\w+/\w+)/episodes/(?P<id>\w+)/?(?:$|[?#])'
_TESTS = [{
# podcast
'url': 'https://www.globalplayer.com/podcasts/episodes/7DrfNnE/',
'url': 'https://www.globalplayer.com/podcasts/episodes/7DrorSc/',
'info_dict': {
'id': '7DrfNnE',
'id': '7DrorSc',
'ext': 'mp3',
'title': 'Filthy Ritual - Trailer',
'description': 'md5:1f1562fd0f01b4773b590984f94223e0',
'thumbnail': 'md5:60286e7d12d795bd1bbc9efc6cee643e',
'duration': 225.0,
'timestamp': 1681254900,
'series': 'Filthy Ritual',
'series_id': '42KuaM',
'upload_date': '20230411',
'uploader': 'Global',
'description': 'md5:372e5aa2b531f9eba863dfc67d007c1c',
'title': 'Filthy Ritual - Trailer',
},
}, {
# radio catchup
'url': 'https://www.globalplayer.com/catchup/lbc/uk/episodes/2zGq26Vcv1fCWhddC4JAwETXWe/',
# radio catchup - test urls are removed after 7 days
'url': 'https://www.globalplayer.com/catchup/lbc/uk/episodes/2zGmrV6DnvogKkNCXkwkQ8HQTA/',
'info_dict': {
'id': '2zGq26Vcv1fCWhddC4JAwETXWe',
'id': '2zGmrV6DnvogKkNCXkwkQ8HQTA',
'ext': 'm4a',
'timestamp': 1682056800,
'series': 'Nick Ferrari',
'thumbnail': 'md5:4df24d8a226f5b2508efbcc6ae874ebf',
'upload_date': '20230421',
'series_id': '46vyD7z',
'description': 'Nick Ferrari At Breakfast is Leading Britain\'s Conversation.',
'thumbnail': 'md5:664ad62a8fb920a2b8e264ed780eee3d',
'description': 'md5:53b6fa5ef71a3cff6628551bcc416384',
'title': 'Nick Ferrari',
'duration': 10800.0,
},
}]
def _real_extract(self, url):
video_id, podcast = self._match_valid_url(url).group('id', 'podcast')
props = self._get_page_props(url, video_id)
episode = props['podcastEpisode'] if podcast else props['catchupEpisode']
meta = props['podcastEpisode']['metadata'] if podcast else props['catchupEpisode']['metadata']
data = self._download_json(f'https://bff-web-guacamole.musicradio.com/playables/{video_id}', video_id)
return self._extract_audio(
episode, traverse_obj(episode, 'podcast', 'show', expected_type=dict) or {})
return {
'id': video_id,
'url': self._get_playback_url(data),
'vcodec': 'none',
**traverse_obj(meta, {
'thumbnail': ('image', 'url', {url_or_none}),
'description': ('description', {str}),
'title': ('title', {str}),
}),
}
class GlobalPlayerVideoIE(GlobalPlayerBaseIE):
@@ -231,9 +222,8 @@ class GlobalPlayerVideoIE(GlobalPlayerBaseIE):
'info_dict': {
'id': '2JsSZ7Gm2uP',
'ext': 'mp4',
'description': 'md5:6a9f063c67c42f218e42eee7d0298bfd',
'thumbnail': 'md5:d4498af48e15aae4839ce77b97d39550',
'upload_date': '20230420',
'description': 'md5:6a9f063c67c42f218e42eee7d0298bfd',
'title': 'Treble Malakai Bayoh sings a sublime Handel aria at Classic FM Live',
},
}]
@@ -245,10 +235,9 @@ class GlobalPlayerVideoIE(GlobalPlayerBaseIE):
return {
'id': video_id,
**traverse_obj(meta, {
'url': 'url',
'thumbnail': ('image', 'url'),
'title': 'title',
'upload_date': ('publish_date', {unified_strdate}),
'description': 'description',
'url': ('url', {url_or_none}),
'thumbnail': ('image', 'url', {url_or_none}),
'description': ('description', {str}),
'title': ('title', {str}),
}),
}
+26 -23
View File
@@ -116,41 +116,41 @@ class GoIE(AdobePassIE):
'params': {'skip_download': 'm3u8'},
'skip': 'This video requires AdobePass MSO credentials',
}, {
'url': 'https://www.freeform.com/episode/bda0eaf7-761a-4838-aa44-96f794000844/playlist/PL553044961',
'url': 'https://www.freeform.com/episode/235128d8-2609-4df4-9874-0b0b687fe9f9/playlist/PL5539647334',
'info_dict': {
'id': 'VDKA39007340',
'id': 'VDKA39623200',
'ext': 'mp4',
'title': 'Angel\'s Landing',
'description': 'md5:91bf084e785c968fab16734df7313446',
'title': 'New House / New Rules',
'description': 'md5:6f38b4b1649dc9f3a9e7acf911a70056',
'age_limit': 14,
'duration': 2523,
'duration': 2733,
'thumbnail': r're:https?://.+/.+\.jpg',
'series': 'How I Escaped My Cult',
'season': 'Season 1',
'season_number': 1,
'episode': 'Episode 2',
'episode_number': 2,
'timestamp': 1740038400.0,
'upload_date': '20250220',
'series': 'Project Runway',
'season': 'Season 21',
'season_number': 21,
'episode': 'Episode 1',
'episode_number': 1,
'timestamp': 1754020800,
'upload_date': '20250801',
},
'params': {'skip_download': 'm3u8'},
}, {
'url': 'https://www.nationalgeographic.com/tv/episode/ca694661-1186-41ae-8089-82f64d69b16d/playlist/PL554408064',
'url': 'https://www.nationalgeographic.com/tv/episode/df0e5bd8-f9bb-4c92-9f94-74dec4dad8a7/playlist/PL553044961',
'info_dict': {
'id': 'VDKA39492078',
'id': 'VDKA35475602',
'ext': 'mp4',
'title': 'Heart of the Emperors',
'description': 'md5:4fc50a2878f030bb3a7eac9124dca677',
'title': 'The Pol Shebang',
'description': 'md5:ccea1210c5ebcdc5c1a435f01bdb8b82',
'age_limit': 0,
'duration': 2775,
'duration': 1323,
'thumbnail': r're:https?://.+/.+\.jpg',
'series': 'Secrets of the Penguins',
'series': 'The Incredible Pol Farm',
'season': 'Season 1',
'season_number': 1,
'episode': 'Episode 1',
'episode_number': 1,
'timestamp': 1745204400.0,
'upload_date': '20250421',
'episode': 'Episode 14',
'episode_number': 14,
'timestamp': 1704614400,
'upload_date': '20240107',
},
'params': {'skip_download': 'm3u8'},
}, {
@@ -190,7 +190,10 @@ class GoIE(AdobePassIE):
site_info = self._SITE_INFO[site]
brand = site_info['brand']
video_data = self._extract_videos(brand, video_id)[0]
videos = self._extract_videos(brand, video_id)
if not videos:
self.report_drm(video_id)
video_data = videos[0]
video_id = video_data['id']
title = video_data['title']
+4 -5
View File
@@ -3,6 +3,7 @@ import re
from .common import InfoExtractor
from ..utils import (
determine_ext,
disposition_filename,
extract_attributes,
filter_dict,
get_element_by_class,
@@ -184,9 +185,7 @@ class GoogleDriveIE(InfoExtractor):
def add_source_format(urlh):
nonlocal title
if not title:
title = self._search_regex(
r'\bfilename="([^"]+)"', urlh.headers.get('Content-Disposition'),
'title', default=None)
title = disposition_filename(urlh.headers) or None
formats.append({
# Use redirect URLs as download URLs in order to calculate
# correct cookies in _calc_cookies.
@@ -198,7 +197,7 @@ class GoogleDriveIE(InfoExtractor):
'format_id': 'source',
'quality': 1,
})
if urlh.headers.get('Content-Disposition'):
if urlh.headers.get_content_disposition():
add_source_format(urlh)
else:
confirmation_webpage = self._webpage_read_content(
@@ -209,7 +208,7 @@ class GoogleDriveIE(InfoExtractor):
get_element_html_by_id('download-form', confirmation_webpage) or '').get('action')
if confirmed_source_url:
urlh = request_source_file(confirmed_source_url, 'confirmed source', data=b'')
if urlh and urlh.headers.get('Content-Disposition'):
if urlh and urlh.headers.get_content_disposition():
add_source_format(urlh)
else:
self.report_warning(
+1 -1
View File
@@ -431,7 +431,7 @@ class AwsIdp:
months = [None, 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
time_now = dt.datetime.now(dt.timezone.utc)
time_now = dt.datetime.now(dt.UTC)
format_string = f'{days[time_now.weekday()]} {months[time_now.month]} {time_now.day} %H:%M:%S UTC %Y'
return time_now.strftime(format_string)
+8 -2
View File
@@ -42,7 +42,6 @@ def _id_to_pk(shortcode):
class InstagramBaseIE(InfoExtractor):
_API_BASE_URL = 'https://i.instagram.com/api/v1'
_BASE_URL = 'https://www.instagram.com/'
_APP_IDS = {
'ios': '124024574287414',
@@ -75,6 +74,12 @@ class InstagramBaseIE(InfoExtractor):
def _is_web_app(self):
return self._app_id == self._APP_IDS['web']
@property
def _API_BASE_URL(self):
if not self._is_web_app:
return 'https://i.instagram.com/api/v1'
return 'https://www.instagram.com/api/v1'
@property
def _api_headers(self):
return {
@@ -87,7 +92,8 @@ class InstagramBaseIE(InfoExtractor):
@staticmethod
def _is_login_redirect(url):
return urllib.parse.urlparse(url).path.startswith('/accounts/login')
path = urllib.parse.urlparse(url).path
return path.startswith('/accounts/login') or path == '/'
def _get_count(self, media, kind, *keys):
return traverse_obj(
+2 -2
View File
@@ -114,7 +114,7 @@ class ITVIE(InfoExtractor):
# See: https://github.com/yt-dlp/yt-dlp/issues/986
platform_tag_subs, featureset_subs = next(
((platform_tag, featureset)
for platform_tag, featuresets in reversed(list(variants.items())) for featureset in featuresets
for platform_tag, featuresets in reversed(variants.items()) for featureset in featuresets
if try_get(featureset, lambda x: x[2]) == 'outband-webvtt'),
(None, None))
@@ -143,7 +143,7 @@ class ITVIE(InfoExtractor):
# See: https://github.com/yt-dlp/yt-dlp/issues/986
platform_tag_video, featureset_video = next(
((platform_tag, featureset)
for platform_tag, featuresets in reversed(list(variants.items())) for featureset in featuresets
for platform_tag, featuresets in reversed(variants.items()) for featureset in featuresets
if set(try_get(featureset, lambda x: x[:2]) or []) == {'aes', 'hls'}),
(None, None))
if not platform_tag_video or not featureset_video:
+375 -137
View File
@@ -1,209 +1,337 @@
import functools
import itertools
import json
import urllib.parse
from .common import InfoExtractor
from ..utils import (
ExtractorError,
UserNotLive,
clean_html,
determine_ext,
float_or_none,
int_or_none,
join_nonempty,
parse_iso8601,
parse_qs,
parse_resolution,
smuggle_url,
str_or_none,
traverse_obj,
unified_timestamp,
unsmuggle_url,
url_basename,
url_or_none,
)
from ..utils.traversal import require, traverse_obj
class KickBaseIE(InfoExtractor):
_BASE_URL = 'https://kick.com'
@functools.cached_property
def _api_headers(self):
token = traverse_obj(
self._get_cookies('https://kick.com/'),
self._get_cookies(self._BASE_URL),
('session_token', 'value', {urllib.parse.unquote}))
return {'Authorization': f'Bearer {token}'} if token else {}
def _call_api(self, path, display_id, note='Downloading API JSON', headers={}, **kwargs):
api_domain = {
'v1': 'web.kick.com',
'v2': 'kick.com',
}[path.partition('/')[0]]
return self._download_json(
f'https://kick.com/api/{path}', display_id, note=note,
f'https://{api_domain}/api/{path}', display_id, note=note,
headers={**self._api_headers, **headers}, impersonate=True, **kwargs)
def _get_creator_info(self, channel_slug):
channel_data = self._call_api(
f'v2/channels/{channel_slug}',
channel_slug, note='Downloading creator info')
creator_id = traverse_obj(channel_data, (
'id', {int}, {str_or_none}, {require('creator ID')}))
username = traverse_obj(channel_data, ('user', 'username', {str}, filter))
return creator_id, username
@staticmethod
def _extract_vod_metadata(video_data):
return {
'availability': {
'sub_only': 'subscriber_only',
'private': 'private',
'public': 'public',
}.get(traverse_obj(video_data, ('status', {str}))),
**traverse_obj(video_data, {
'title': ('title', {clean_html}, filter),
'age_limit': ('is_mature', {bool}, {lambda x: 18 if x else None}),
'categories': ('category', 'name', {clean_html}, filter, all, filter),
'duration': ('duration', {int_or_none}),
'is_live': ('is_live', {bool}),
'tags': ('tags', ..., {clean_html}, filter, all, filter),
'thumbnails': (
'thumbnail', 'srcSet', {lambda x: x.split(',')}, ..., {str.strip},
{lambda x: x.rsplit(maxsplit=1)}, {
'url': (0, {url_or_none}),
'width': (1, {parse_resolution(lenient=True)}, 'width'),
'height': (0, {url_basename}, {lambda x: int_or_none(x.partition('.')[0])}),
},
),
'timestamp': ('start_time', {parse_iso8601}),
'view_count': ('viewer_count', {int_or_none}),
}),
**traverse_obj(video_data, ('channel', {
'channel': ('username', {str}, filter),
'uploader': ('username', {str}, filter),
'uploader_id': ('slug', {str}, filter),
})),
}
@staticmethod
def _extract_clip_metadata(clip_data):
return {
**traverse_obj(clip_data, {
'title': ('title', {clean_html}, filter),
'age_limit': ('is_mature', {bool}, {lambda x: 18 if x else None}),
'categories': ('category', 'name', {clean_html}, filter, all, filter),
'duration': ('duration', {int_or_none}),
'like_count': (('likes_count', 'likes'), {int_or_none}, any),
'thumbnail': ('thumbnail_url', {url_or_none}),
'timestamp': ('created_at', {parse_iso8601}),
'view_count': (('views_count', 'view_count', 'views'), {int_or_none}, any),
}),
**traverse_obj(clip_data, ('channel', {
'channel': ('username', {str}, filter),
'channel_id': ('id', {int}, {str_or_none}),
'uploader': ('username', {str}, filter),
'uploader_id': ('slug', {str}, filter),
})),
}
class KickIE(KickBaseIE):
IE_NAME = 'kick:live'
_VALID_URL = r'https?://(?:www\.)?kick\.com/(?!(?:video|categories|search|auth)(?:[/?#]|$))(?P<id>[\w-]+)'
_TESTS = [{
'url': 'https://kick.com/buddha',
'url': 'https://kick.com/coringa',
'info_dict': {
'id': '92722911-nopixel-40',
'id': '123735729',
'ext': 'mp4',
'title': str,
'description': str,
'timestamp': int,
'thumbnail': r're:https?://.+\.jpg',
'categories': list,
'upload_date': str,
'channel': 'buddha',
'channel_id': '32807',
'uploader': 'Buddha',
'uploader_id': '33057',
'live_status': 'is_live',
'categories': 'count:1',
'channel': 'Coringa',
'channel_follower_count': int,
'channel_id': '4124791',
'channel_is_verified': True,
'concurrent_view_count': int,
'description': str,
'live_status': 'is_live',
'release_date': r're:\d{8}',
'release_timestamp': int,
'age_limit': 18,
'release_date': str,
'thumbnail': r're:https?://.+',
'timestamp': int,
'upload_date': r're:\d{8}',
'uploader': 'Coringa',
'uploader_id': 'coringa',
},
'params': {'skip_download': 'livestream'},
# 'skip': 'livestream',
}, {
'url': 'https://kick.com/xqc',
'only_matching': True,
'skip': 'Livestream',
}]
@classmethod
def suitable(cls, url):
return False if (KickVODIE.suitable(url) or KickClipIE.suitable(url)) else super().suitable(url)
return False if (
KickVODIE.suitable(url)
or KickClipIE.suitable(url)
or KickVideosIE.suitable(url)
or KickClipsIE.suitable(url)
) else super().suitable(url)
def _real_extract(self, url):
channel = self._match_id(url)
response = self._call_api(f'v2/channels/{channel}', channel)
if not traverse_obj(response, 'livestream', expected_type=dict):
raise UserNotLive(video_id=channel)
channel_slug = self._match_id(url).lower()
channel_data = self._call_api(f'v2/channels/{channel_slug}', channel_slug)
if not traverse_obj(channel_data, ('livestream', {dict})):
raise UserNotLive(video_id=channel_slug)
m3u8_url = traverse_obj(channel_data, (
'playback_url', {url_or_none}, {require('m3u8 URL')}))
return {
'channel': channel,
'formats': self._extract_m3u8_formats(m3u8_url, channel_slug, 'mp4'),
'is_live': True,
'formats': self._extract_m3u8_formats(response['playback_url'], channel, 'mp4', live=True),
**traverse_obj(response, {
'id': ('livestream', 'slug', {str}),
'title': ('livestream', 'session_title', {str}),
'description': ('user', 'bio', {str}),
'channel_id': (('id', ('livestream', 'channel_id')), {int}, {str_or_none}, any),
'uploader': (('name', ('user', 'username')), {str}, any),
'uploader_id': (('user_id', ('user', 'id')), {int}, {str_or_none}, any),
'timestamp': ('livestream', 'created_at', {unified_timestamp}),
'release_timestamp': ('livestream', 'start_time', {unified_timestamp}),
'thumbnail': ('livestream', 'thumbnail', 'url', {url_or_none}),
'categories': ('recent_categories', ..., 'name', {str}),
'concurrent_view_count': ('livestream', 'viewer_count', {int_or_none}),
'age_limit': ('livestream', 'is_mature', {bool}, {lambda x: 18 if x else 0}),
'uploader_id': channel_slug,
**traverse_obj(channel_data, {
'channel_follower_count': ('followers_count', {int_or_none}),
'channel_id': ('id', {int}, {str_or_none}),
'channel_is_verified': ('verified', {bool}),
}),
**traverse_obj(channel_data, ('livestream', {
'id': ('id', {str_or_none}),
'title': ('session_title', {clean_html}, filter),
'age_limit': ('is_mature', {bool}, {lambda x: 18 if x else None}),
'categories': ('categories', ..., 'name', {clean_html}, filter, all, filter),
'concurrent_view_count': ('viewer_count', {int_or_none}),
'release_timestamp': ('start_time', {unified_timestamp}),
'tags': ('tags', ..., {clean_html}, filter, all, filter),
'thumbnail': ('thumbnail', 'url', {url_or_none}),
'timestamp': ('created_at', {unified_timestamp}),
})),
**traverse_obj(channel_data, ('user', {
'channel': ('username', {str}, filter),
'description': ('bio', {clean_html}, filter),
'uploader': ('username', {str}, filter),
})),
}
class KickVODIE(KickBaseIE):
IE_NAME = 'kick:vod'
_VALID_URL = r'https?://(?:www\.)?kick\.com/[\w-]+/videos/(?P<id>[\da-f]{8}-(?:[\da-f]{4}-){3}[\da-f]{12})'
_TESTS = [{
# Regular VOD
'url': 'https://kick.com/xqc/videos/5c697a87-afce-4256-b01f-3c8fe71ef5cb',
'url': 'https://kick.com/xqc/videos/01a0251f-ef48-702d-9289-d66922da0e84',
'info_dict': {
'id': '5c697a87-afce-4256-b01f-3c8fe71ef5cb',
'id': '01a0251f-ef48-702d-9289-d66922da0e84',
'ext': 'mp4',
'title': '🐗LIVE🐗CLICK🐗HERE🐗DRAMA🐗ALL DAY🐗NEWS🐗VIDEOS🐗CLIPS🐗GAMES🐗STUFF🐗WOW🐗IM HERE🐗LETS GO🐗COOL🐗VERY NICE🐗',
'description': 'THE BEST AT ABSOLUTELY EVERYTHING. THE JUICER. LEADER OF THE JUICERS.',
'uploader': 'xQc',
'uploader_id': '676',
'channel': 'xqc',
'channel_id': '668',
'view_count': int,
'title': 'md5:03d5dbce5b2379d9c5e1229a8fb05e17',
'age_limit': 18,
'duration': 22278.0,
'thumbnail': r're:^https?://.*\.jpg',
'categories': ['Deadlock'],
'timestamp': 1756082443,
'upload_date': '20250825',
'availability': 'public',
'categories': ['Just Chatting'],
'channel': 'xQc',
'channel_id': '668',
'duration': 42250,
'thumbnail': r're:https?://.+',
'timestamp': 1787329245,
'upload_date': '20260821',
'uploader': 'xQc',
'uploader_id': 'xqc',
'view_count': int,
},
'params': {'skip_download': 'm3u8'},
}, {
# VOD of ongoing livestream (at the time of writing the test, ID rotates every two days)
'url': 'https://kick.com/a-log-burner/videos/5230df84-ea38-46e1-be4f-f5949ae55641',
# Ongoing livestream VOD
'url': 'https://kick.com/a-log-burner/videos/01a02882-5428-7ea1-9237-97f070aab4cc',
'info_dict': {
'id': '5230df84-ea38-46e1-be4f-f5949ae55641',
'id': '01a02882-5428-7ea1-9237-97f070aab4cc',
'ext': 'mp4',
'title': r're:😴 Cozy Fireplace ASMR 🔥 | Relax, Focus, Sleep 💤',
'description': 'md5:080bc713eac0321a7b376a1b53816d1b',
'uploader': 'A_Log_Burner',
'uploader_id': '65114691',
'channel': 'a-log-burner',
'title': str,
'availability': 'public',
'categories': ['Meditation & Mindfulness'],
'channel': 'A_Log_Burner',
'channel_id': '63967687',
'view_count': int,
'age_limit': 18,
'thumbnail': r're:^https?://.*\.jpg',
'categories': ['Other, Watch Party'],
'timestamp': int,
'upload_date': str,
'live_status': 'is_live',
'tags': 'count:9',
'thumbnail': r're:https?://.+',
'timestamp': 1787386025,
'upload_date': '20260822',
'uploader': 'A_Log_Burner',
'uploader_id': 'a-log-burner',
'view_count': int,
},
'skip': 'live',
'skip': 'Livestream',
}]
_subscription_cache = None
def _is_subscribed(self, creator_id):
if self._subscription_cache is None:
self._subscription_cache = {}
if creator_id not in self._subscription_cache:
me = self._call_api(
f'v1/channels/{creator_id}/me',
creator_id, note='Checking subscription status')
self._subscription_cache[creator_id] = bool(
traverse_obj(me, ('data', 'subscription', {dict})))
return self._subscription_cache[creator_id]
def _real_extract(self, url):
url, smuggled_data = unsmuggle_url(url, {})
video_id = self._match_id(url)
response = self._call_api(f'v1/video/{video_id}', video_id)
playback = self._call_api(
f'v1/stream/{video_id}/playback', video_id, headers={
'Content-Type': 'application/json',
}, data=json.dumps({
'video_player': {'player': {}},
'video_session': {},
'user_session': {
'non_personalised_ads': True,
},
}).encode(), expected_status=404)
if data := traverse_obj(playback, ('data', {dict})):
err_msg = join_nonempty('type', 'details', delim=': ', from_dict=data)
raise ExtractorError(
err_msg or 'API returned an error response', expected=True)
creator_id = traverse_obj(playback, (
'video_session', 'creator_id', {str}, {require('creator ID')}))
metadata = {}
if 'availability' in smuggled_data:
availability = smuggled_data['availability']
else:
videos = self._call_api(f'v1/channels/{creator_id}/videos', creator_id)
video_data = traverse_obj(videos, (
'data', lambda _, v: v['id'] == video_id, {dict}, any))
metadata = self._extract_vod_metadata(video_data)
availability = metadata['availability']
m3u8_url = traverse_obj(playback, ('playback_url', 'vod', {url_or_none}))
if not m3u8_url:
if availability == 'subscriber_only' and not self._is_subscribed(creator_id):
self.raise_login_required(
'This video requires a channel subscription', metadata_available=True)
return {
'id': video_id,
'formats': self._extract_m3u8_formats(response['source'], video_id, 'mp4'),
**traverse_obj(response, {
'title': ('livestream', ('session_title', 'slug'), {str}, any),
'description': ('livestream', 'channel', 'user', 'bio', {str}),
'channel': ('livestream', 'channel', 'slug', {str}),
'channel_id': ('livestream', 'channel', 'id', {int}, {str_or_none}),
'uploader': ('livestream', 'channel', 'user', 'username', {str}),
'uploader_id': ('livestream', 'channel', 'user_id', {int}, {str_or_none}),
'timestamp': ('created_at', {parse_iso8601}),
'duration': ('livestream', 'duration', {float_or_none(scale=1000)}),
'thumbnail': ('livestream', 'thumbnail', {url_or_none}),
'categories': ('livestream', 'categories', ..., 'name', {str}),
'view_count': ('views', {int_or_none}),
'age_limit': ('livestream', 'is_mature', {bool}, {lambda x: 18 if x else 0}),
'is_live': ('livestream', 'is_live', {bool}),
}),
'channel_id': creator_id,
'formats': self._extract_m3u8_formats(m3u8_url, video_id, 'mp4'),
**metadata,
}
class KickClipIE(KickBaseIE):
IE_NAME = 'kick:clips'
IE_NAME = 'kick:clip'
_VALID_URL = r'https?://(?:www\.)?kick\.com/[\w-]+(?:/clips/|/?\?(?:[^#]+&)?clip=)(?P<id>clip_[\w-]+)'
_TESTS = [{
'url': 'https://kick.com/mxddy?clip=clip_01GYXVB5Y8PWAPWCWMSBCFB05X',
'md5': 'a1014e8a26b6f45bc64bcef679dd19a7',
'info_dict': {
'id': 'clip_01GYXVB5Y8PWAPWCWMSBCFB05X',
'ext': 'mp4',
'title': 'Maddy detains Abd D:',
'channel': 'mxddy',
'age_limit': 18,
'categories': ['VALORANT'],
'channel': 'Mxddy',
'channel_id': '133789',
'uploader': 'AbdCreates',
'uploader_id': '3309077',
'thumbnail': r're:^https?://.*\.jpeg',
'duration': 35,
'like_count': int,
'thumbnail': r're:https?://.+',
'timestamp': 1682481453,
'upload_date': '20230426',
'uploader': 'Mxddy',
'uploader_id': 'mxddy',
'view_count': int,
'like_count': int,
'categories': ['VALORANT'],
'age_limit': 18,
},
'params': {'skip_download': 'm3u8'},
}, {
'url': 'https://kick.com/destiny?clip=clip_01H9SKET879NE7N9RJRRDS98J3',
'info_dict': {
'id': 'clip_01H9SKET879NE7N9RJRRDS98J3',
'title': 'W jews',
'ext': 'mp4',
'channel': 'destiny',
'channel_id': '1772249',
'uploader': 'punished_furry',
'uploader_id': '2027722',
'duration': 49.0,
'upload_date': '20230908',
'timestamp': 1694150180,
'thumbnail': 'https://clips.kick.com/clips/j3/clip_01H9SKET879NE7N9RJRRDS98J3/thumbnail.png',
'view_count': int,
'like_count': int,
'title': 'W jews',
'categories': ['Just Chatting'],
'age_limit': 0,
'channel': 'Destiny',
'channel_id': '1772249',
'duration': 49,
'like_count': int,
'thumbnail': r're:https?://.+',
'timestamp': 1694150180,
'upload_date': '20230908',
'uploader': 'Destiny',
'uploader_id': 'destiny',
'view_count': int,
},
'params': {'skip_download': 'm3u8'},
}, {
@@ -212,27 +340,34 @@ class KickClipIE(KickBaseIE):
'id': 'clip_01J8RGZRKHXHXXKJEHGRM932A5',
'ext': 'mp4',
'title': 'KLJASLDJKLJKASDLJKDAS',
'channel': 'spreen',
'categories': ['Just Chatting'],
'channel': 'Spreen',
'channel_id': '5312671',
'uploader': 'AnormalBarraBaja',
'uploader_id': '26518262',
'duration': 43.0,
'upload_date': '20240927',
'timestamp': 1727399987,
'thumbnail': 'https://clips.kick.com/clips/f2/clip_01J8RGZRKHXHXXKJEHGRM932A5/thumbnail.webp',
'view_count': int,
'duration': 43,
'like_count': int,
'categories': ['Minecraft'],
'age_limit': 0,
'thumbnail': r're:https?://.+',
'timestamp': 1727399987,
'upload_date': '20240927',
'uploader': 'Spreen',
'uploader_id': 'spreen',
'view_count': int,
},
'params': {'skip_download': 'm3u8'},
}]
def _real_extract(self, url):
clip_id = self._match_id(url)
clip = self._call_api(f'v2/clips/{clip_id}/play', clip_id)['clip']
clip_url = clip['clip_url']
clip = self._call_api(
f'v2/clips/{clip_id}', clip_id, expected_status=404)
if err_msg := traverse_obj(clip, (
'message', {clean_html}, filter,
)):
raise ExtractorError(err_msg, expected=True)
clip_data = traverse_obj(clip, ('clip', {dict}))
clip_url = traverse_obj(clip_data, (
('playback_url', 'clip_url', 'video_url'),
{url_or_none}, any, {require('clip source URL')}))
if determine_ext(clip_url) == 'm3u8':
formats = self._extract_m3u8_formats(clip_url, clip_id, 'mp4')
else:
@@ -241,18 +376,121 @@ class KickClipIE(KickBaseIE):
return {
'id': clip_id,
'formats': formats,
**traverse_obj(clip, {
'title': ('title', {str}),
'channel': ('channel', 'slug', {str}),
'channel_id': ('channel', 'id', {int}, {str_or_none}),
'uploader': ('creator', 'username', {str}),
'uploader_id': ('creator', 'id', {int}, {str_or_none}),
'thumbnail': ('thumbnail_url', {url_or_none}),
'duration': ('duration', {float_or_none}),
'categories': ('category', 'name', {str}, all),
'timestamp': ('created_at', {parse_iso8601}),
'view_count': ('views', {int_or_none}),
'like_count': ('likes', {int_or_none}),
'age_limit': ('is_mature', {bool}, {lambda x: 18 if x else 0}),
}),
**self._extract_clip_metadata(clip_data),
}
class KickVideosIE(KickBaseIE):
IE_NAME = 'kick:videos'
_VALID_URL = r'https?://(?:www\.)?kick\.com/(?P<id>[\w-]+)/videos/?(?:[?#]|$)'
_TESTS = [{
'url': 'https://kick.com/xqc/videos',
'info_dict': {
'id': 'xqc',
'title': 'xQc - Videos sorted by Date',
},
'playlist_mincount': 10,
}, {
'url': 'https://kick.com/xqc/videos?sort=views',
'info_dict': {
'id': 'xqc',
'title': 'xQc - Videos sorted by Views',
},
'playlist_mincount': 10,
}]
def _entries(self, creator_id, channel_slug, sort_param):
videos = self._call_api(f'v1/channels/{creator_id}/videos', channel_slug)
if sort_param == 'views':
videos['data'].sort(key=lambda v: v['viewer_count'], reverse=True)
for video_data in traverse_obj(videos, (
'data', lambda _, v: str_or_none(v['id']),
)):
video_id = video_data['id']
metadata = self._extract_vod_metadata(video_data)
yield self.url_result(smuggle_url(
f'{self._BASE_URL}/{channel_slug}/videos/{video_id}',
{'availability': metadata['availability']},
), KickVODIE, video_id, url_transparent=True, **metadata)
def _real_extract(self, url):
channel_slug = self._match_id(url).lower()
creator_id, username = self._get_creator_info(channel_slug)
sort_param = traverse_obj(parse_qs(url), ('sort', -1, {str}, filter))
sort_label = 'Views' if sort_param == 'views' else 'Date'
return self.playlist_result(
self._entries(creator_id, channel_slug, sort_param), channel_slug,
f'{username or channel_slug} - Videos sorted by {sort_label}')
class KickClipsIE(KickBaseIE):
IE_NAME = 'kick:clips'
_VALID_URL = r'https?://(?:www\.)?kick\.com/(?P<id>[\w-]+)/clips/?(?:[?#]|$)'
_TESTS = [{
'url': 'https://kick.com/xqc/clips',
'info_dict': {
'id': 'xqc',
'title': 'xQc - Clips sorted by Views (Last Week)',
},
'playlist_mincount': 100,
}, {
'url': 'https://kick.com/xqc/clips?sort=date&range=day',
'info_dict': {
'id': 'xqc',
'title': 'xQc - Clips sorted by Date (Last Day)',
},
'playlist_mincount': 10,
}]
def _entries(self, creator_id, channel_slug, sort_param, range_param):
query = {
'sort': 'views' if sort_param == 'view' else 'date',
'time': range_param,
}
for page in itertools.count(1):
clips = self._call_api(
f'v1/channels/{creator_id}/clips', channel_slug,
note=f'Downloading page {page}', query=query)
for clip_data in traverse_obj(clips, (
'data', 'clips', lambda _, v: str_or_none(v['id']),
)):
clip_id = clip_data['id']
yield self.url_result(
f'{self._BASE_URL}/{channel_slug}/clips/{clip_id}',
KickClipIE, clip_id, **self._extract_clip_metadata(clip_data))
cursor = traverse_obj(clips, ('data', 'cursor', {str}, filter))
if not cursor:
break
query['cursor'] = cursor
def _real_extract(self, url):
channel_slug = self._match_id(url).lower()
creator_id, username = self._get_creator_info(channel_slug)
query = parse_qs(url)
sort_param = traverse_obj(query, ('sort', -1, {str}, filter))
if sort_param not in ('view', 'date'):
sort_param = 'view'
range_param = traverse_obj(query, ('range', -1, {str}, filter))
if range_param not in ('day', 'week', 'month', 'all'):
range_param = 'week'
sort_label = 'Views' if sort_param == 'view' else 'Date'
range_label = {
'day': 'Last Day',
'month': 'Last Month',
'all': 'All Time',
}.get(range_param, 'Last Week')
return self.playlist_result(
self._entries(creator_id, channel_slug, sort_param, range_param), channel_slug,
f'{username or channel_slug} - Clips sorted by {sort_label} ({range_label})')

Some files were not shown because too many files have changed in this diff Show More