yt-dlp-utils 0.0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of yt-dlp-utils might be problematic. Click here for more details.

@@ -0,0 +1,18 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2025 yt-dlp-utils authors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy of this software and
6
+ associated documentation files (the "Software"), to deal in the Software without restriction,
7
+ including without limitation the rights to use, copy, modify, merge, publish, distribute,
8
+ sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
9
+ furnished to do so, subject to the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be included in all copies or
12
+ substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15
+ NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17
+ DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT
18
+ OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,64 @@
1
+ Metadata-Version: 2.3
2
+ Name: yt-dlp-utils
3
+ Version: 0.0.1
4
+ Summary: Utilities for programmatic use of yt-dlp.
5
+ License: MIT
6
+ Keywords: command line,yt-dlp
7
+ Author: Andrew Udvare
8
+ Author-email: audvare@gmail.com
9
+ Requires-Python: >=3.10,<3.14
10
+ Classifier: Development Status :: 2 - Pre-Alpha
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3.10
15
+ Classifier: Programming Language :: Python :: 3.11
16
+ Classifier: Programming Language :: Python :: 3.12
17
+ Classifier: Programming Language :: Python :: 3.13
18
+ Classifier: Typing :: Typed
19
+ Requires-Dist: requests (>=2.32.3,<3.0.0)
20
+ Requires-Dist: typing-extensions (>=4.13.1,<5.0.0)
21
+ Requires-Dist: yt-dlp[default] (>=2025.3.31,<2026.0.0)
22
+ Project-URL: Documentation, https://yt-dlp-utils.readthedocs.org
23
+ Project-URL: Homepage, https://tatsh.github.io/yt-dlp-utils/
24
+ Project-URL: Issues, https://github.com/Tatsh/yt-dlp-utils/issues
25
+ Project-URL: Repository, https://github.com/Tatsh/yt-dlp-utils
26
+ Description-Content-Type: text/markdown
27
+
28
+ # yt-dlp-utils
29
+
30
+ [![QA](https://github.com/Tatsh/yt-dlp-utils/actions/workflows/qa.yml/badge.svg)](https://github.com/Tatsh/yt-dlp-utils/actions/workflows/qa.yml)
31
+ [![Tests](https://github.com/Tatsh/yt-dlp-utils/actions/workflows/tests.yml/badge.svg)](https://github.com/Tatsh/yt-dlp-utils/actions/workflows/tests.yml)
32
+ [![Coverage Status](https://coveralls.io/repos/github/Tatsh/yt-dlp-utils/badge.svg?branch=master)](https://coveralls.io/github/Tatsh/yt-dlp-utils?branch=master)
33
+ [![Documentation Status](https://readthedocs.org/projects/yt-dlp-utils/badge/?version=latest)](https://yt-dlp-utils.readthedocs.org/?badge=latest)
34
+ [![PyPI - Version](https://img.shields.io/pypi/v/yt-dlp-utils)](https://pypi.org/project/yt-dlp-utils/)
35
+ [![GitHub tag (with filter)](https://img.shields.io/github/v/tag/Tatsh/yt-dlp-utils)](https://github.com/Tatsh/yt-dlp-utils/tags)
36
+ [![License](https://img.shields.io/github/license/Tatsh/yt-dlp-utils)](https://github.com/Tatsh/yt-dlp-utils/blob/master/LICENSE.txt)
37
+ [![GitHub commits since latest release (by SemVer including pre-releases)](https://img.shields.io/github/commits-since/Tatsh/yt-dlp-utils/v0.0.1/master)](https://github.com/Tatsh/yt-dlp-utils/compare/v0.0.1...master)
38
+ ![License](https://img.shields.io/badge/License-MIT-success.svg)
39
+ [![mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)
40
+ [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
41
+ [![pydocstyle](https://img.shields.io/badge/pydocstyle-enabled-AD4CD3)](http://www.pydocstyle.org/en/stable/)
42
+ [![pytest](https://img.shields.io/badge/pytest-zz?logo=Pytest&labelColor=black&color=black)](https://docs.pytest.org/en/stable/)
43
+ [![Python](https://img.shields.io/badge/Python-3.12-3776AB.svg?style=flat&logo=python&logoColor=white)](https://www.python.org)
44
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
45
+
46
+ [![@Tatsh](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fpublic.api.bsky.app%2Fxrpc%2Fapp.bsky.actor.getProfile%2F%3Factor%3Ddid%3Aplc%3Auq42idtvuccnmtl57nsucz72%26query%3D%24.followersCount%26style%3Dsocial%26logo%3Dbluesky%26label%3DFollow%2520%40Tatsh&query=%24.followersCount&style=social&logo=bluesky&label=Follow%20%40Tatsh)](https://bsky.app/profile/tatsh.bsky.social)
47
+ [![Mastodon Follow](https://img.shields.io/mastodon/follow/109370961877277568?domain=hostux.social&style=social)](https://hostux.social/@tatsh)
48
+
49
+ Utilities for programmatic use of yt-dlp.
50
+
51
+ ## Installation
52
+
53
+ ### Poetry
54
+
55
+ ```shell
56
+ poetry add yt-dlp-utils
57
+ ```
58
+
59
+ ### Pip
60
+
61
+ ```shell
62
+ pip install yt-dlp-utils
63
+ ```
64
+
@@ -0,0 +1,36 @@
1
+ # yt-dlp-utils
2
+
3
+ [![QA](https://github.com/Tatsh/yt-dlp-utils/actions/workflows/qa.yml/badge.svg)](https://github.com/Tatsh/yt-dlp-utils/actions/workflows/qa.yml)
4
+ [![Tests](https://github.com/Tatsh/yt-dlp-utils/actions/workflows/tests.yml/badge.svg)](https://github.com/Tatsh/yt-dlp-utils/actions/workflows/tests.yml)
5
+ [![Coverage Status](https://coveralls.io/repos/github/Tatsh/yt-dlp-utils/badge.svg?branch=master)](https://coveralls.io/github/Tatsh/yt-dlp-utils?branch=master)
6
+ [![Documentation Status](https://readthedocs.org/projects/yt-dlp-utils/badge/?version=latest)](https://yt-dlp-utils.readthedocs.org/?badge=latest)
7
+ [![PyPI - Version](https://img.shields.io/pypi/v/yt-dlp-utils)](https://pypi.org/project/yt-dlp-utils/)
8
+ [![GitHub tag (with filter)](https://img.shields.io/github/v/tag/Tatsh/yt-dlp-utils)](https://github.com/Tatsh/yt-dlp-utils/tags)
9
+ [![License](https://img.shields.io/github/license/Tatsh/yt-dlp-utils)](https://github.com/Tatsh/yt-dlp-utils/blob/master/LICENSE.txt)
10
+ [![GitHub commits since latest release (by SemVer including pre-releases)](https://img.shields.io/github/commits-since/Tatsh/yt-dlp-utils/v0.0.1/master)](https://github.com/Tatsh/yt-dlp-utils/compare/v0.0.1...master)
11
+ ![License](https://img.shields.io/badge/License-MIT-success.svg)
12
+ [![mypy](https://www.mypy-lang.org/static/mypy_badge.svg)](http://mypy-lang.org/)
13
+ [![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
14
+ [![pydocstyle](https://img.shields.io/badge/pydocstyle-enabled-AD4CD3)](http://www.pydocstyle.org/en/stable/)
15
+ [![pytest](https://img.shields.io/badge/pytest-zz?logo=Pytest&labelColor=black&color=black)](https://docs.pytest.org/en/stable/)
16
+ [![Python](https://img.shields.io/badge/Python-3.12-3776AB.svg?style=flat&logo=python&logoColor=white)](https://www.python.org)
17
+ [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff)
18
+
19
+ [![@Tatsh](https://img.shields.io/badge/dynamic/json?url=https%3A%2F%2Fpublic.api.bsky.app%2Fxrpc%2Fapp.bsky.actor.getProfile%2F%3Factor%3Ddid%3Aplc%3Auq42idtvuccnmtl57nsucz72%26query%3D%24.followersCount%26style%3Dsocial%26logo%3Dbluesky%26label%3DFollow%2520%40Tatsh&query=%24.followersCount&style=social&logo=bluesky&label=Follow%20%40Tatsh)](https://bsky.app/profile/tatsh.bsky.social)
20
+ [![Mastodon Follow](https://img.shields.io/mastodon/follow/109370961877277568?domain=hostux.social&style=social)](https://hostux.social/@tatsh)
21
+
22
+ Utilities for programmatic use of yt-dlp.
23
+
24
+ ## Installation
25
+
26
+ ### Poetry
27
+
28
+ ```shell
29
+ poetry add yt-dlp-utils
30
+ ```
31
+
32
+ ### Pip
33
+
34
+ ```shell
35
+ pip install yt-dlp-utils
36
+ ```
@@ -0,0 +1,343 @@
1
+ [build-system]
2
+ build-backend = "poetry.core.masonry.api"
3
+ requires = ["poetry-core"]
4
+
5
+ [project]
6
+ classifiers = [
7
+ "Development Status :: 2 - Pre-Alpha",
8
+ "Intended Audience :: Developers",
9
+ "License :: OSI Approved :: MIT License",
10
+ "Programming Language :: Python",
11
+ "Programming Language :: Python :: 3.10",
12
+ "Programming Language :: Python :: 3.11",
13
+ "Programming Language :: Python :: 3.12",
14
+ "Programming Language :: Python :: 3.13",
15
+ "Typing :: Typed",
16
+ ]
17
+ description = "Utilities for programmatic use of yt-dlp."
18
+ dynamic = ["dependencies", "requires-python"]
19
+ keywords = ["command line", "yt-dlp"]
20
+ license = "MIT"
21
+ name = "yt-dlp-utils"
22
+ readme = "README.md"
23
+ version = "0.0.1"
24
+
25
+ [[project.authors]]
26
+ email = "audvare@gmail.com"
27
+ name = "Andrew Udvare"
28
+
29
+ [project.scripts]
30
+
31
+ [project.urls]
32
+ Issues = "https://github.com/Tatsh/yt-dlp-utils/issues"
33
+ documentation = "https://yt-dlp-utils.readthedocs.org"
34
+ homepage = "https://tatsh.github.io/yt-dlp-utils/"
35
+ repository = "https://github.com/Tatsh/yt-dlp-utils"
36
+
37
+ [tool]
38
+
39
+ [tool.commitizen]
40
+ tag_format = "v$version"
41
+ version_files = [
42
+ ".wiswa.jsonnet",
43
+ "CITATION.cff",
44
+ "README.md",
45
+ "package.json",
46
+ "yt_dlp_utils/__init__.py",
47
+ ]
48
+ version_provider = "pep621"
49
+
50
+ [tool.coverage]
51
+
52
+ [tool.coverage.report]
53
+ exclude_also = ["if TYPE_CHECKING:"]
54
+ omit = ["conftest.py", "tests.py", "tests/test_*.py"]
55
+ show_missing = true
56
+
57
+ [tool.coverage.run]
58
+ branch = true
59
+ omit = ["conftest.py", "tests.py", "tests/test_*.py"]
60
+
61
+ [tool.djlint]
62
+ max_line_length = 100
63
+ no_line_after_yaml = true
64
+ preserve_blank_lines = true
65
+ preserve_leading_space = true
66
+ profile = "jinja"
67
+ use_gitignore = true
68
+
69
+ [tool.doc8]
70
+ max-line-length = 100
71
+
72
+ [tool.mypy]
73
+ cache_dir = "~/.cache/mypy"
74
+ explicit_package_bases = true
75
+ platform = "linux"
76
+ python_version = "3.10"
77
+ show_column_numbers = true
78
+ strict = true
79
+ strict_optional = true
80
+ warn_unreachable = true
81
+
82
+ [tool.poetry]
83
+
84
+ [tool.poetry.dependencies]
85
+ python = ">=3.10,<3.14"
86
+ requests = "^2.32.3"
87
+ typing-extensions = "^4.13.1"
88
+
89
+ [tool.poetry.dependencies.yt-dlp]
90
+ extras = ["default"]
91
+ version = "^2025.3.31"
92
+
93
+ [tool.poetry.group]
94
+
95
+ [tool.poetry.group.dev]
96
+ optional = true
97
+
98
+ [tool.poetry.group.dev.dependencies]
99
+ commitizen = "^4.5.0"
100
+ djlint = "^1.36.4"
101
+ mypy = ">=1.12,<1.16"
102
+ ruff = "^0.11.7"
103
+ types-requests = "^2.32.0.20250328"
104
+ yapf = "^0.43.0"
105
+ yt-dlp-types = "^0"
106
+
107
+ [tool.poetry.group.docs]
108
+ optional = true
109
+
110
+ [tool.poetry.group.docs.dependencies]
111
+ autodoc-pydantic = "^2.2.0"
112
+ doc8 = "^1.1.2"
113
+ docutils = "^0.21.2"
114
+ esbonio = "^0.16.5"
115
+ numpydoc = "^1.8.0"
116
+ restructuredtext-lint = "^1.4.0"
117
+ sphinx = "<8.2.0"
118
+ sphinx-click = "^6.0.0"
119
+ sphinx-datatables = "^0.2.1"
120
+ sphinx-hoverxref = "^1.4.2"
121
+ sphinx-immaterial = "^0.13.4"
122
+
123
+ [tool.poetry.group.docs.dependencies.enum-tools]
124
+ extras = ["sphinx"]
125
+ version = "^0.12.0"
126
+
127
+ [tool.poetry.group.docs.dependencies.erdantic]
128
+ optional = true
129
+ version = "<2.0"
130
+
131
+ [tool.poetry.group.tests]
132
+ optional = true
133
+
134
+ [tool.poetry.group.tests.dependencies]
135
+ mock = "^5.2.0"
136
+ pytest = "^8.3.5"
137
+ pytest-cov = "^6.1.1"
138
+ pytest-mock = "^3.14.0"
139
+
140
+ [tool.poetry.group.tests.dependencies.coveralls]
141
+ python = "<3.13"
142
+ version = "^4.0.1"
143
+
144
+ [[tool.poetry.packages]]
145
+ include = "yt_dlp_utils"
146
+
147
+ [tool.pyright]
148
+ deprecateTypingAliases = true
149
+ enableExperimentalFeatures = true
150
+ include = ["./yt_dlp_utils", "./tests"]
151
+ pythonPlatform = "Linux"
152
+ pythonVersion = "3.10"
153
+ reportCallInDefaultInitializer = "warning"
154
+ reportImplicitOverride = "warning"
155
+ reportImportCycles = "error"
156
+ reportMissingModuleSource = "error"
157
+ reportPropertyTypeMismatch = "error"
158
+ reportShadowedImports = "error"
159
+ reportUnnecessaryTypeIgnoreComment = "none"
160
+ typeCheckingMode = "off"
161
+ useLibraryCodeForTypes = false
162
+
163
+ [tool.pytest]
164
+
165
+ [tool.pytest.ini_options]
166
+ mock_use_standalone_module = true
167
+ norecursedirs = ["node_modules"]
168
+ python_files = ["tests.py", "test_*.py", "*_tests.py"]
169
+ testpaths = ["tests"]
170
+
171
+ [tool.ruff]
172
+ cache-dir = "~/.cache/ruff"
173
+ force-exclude = true
174
+ line-length = 100
175
+ namespace-packages = ["docs", "tests"]
176
+ target-version = "py310"
177
+ unsafe-fixes = true
178
+
179
+ [tool.ruff.lint]
180
+ extend-select = [
181
+ "A",
182
+ "AIR",
183
+ "ANN",
184
+ "ARG",
185
+ "ASYNC",
186
+ "B",
187
+ "BLE",
188
+ "C4",
189
+ "C90",
190
+ "COM",
191
+ "CPY",
192
+ "D",
193
+ "DJ",
194
+ "DTZ",
195
+ "E",
196
+ "EM",
197
+ "ERA",
198
+ "EXE",
199
+ "F",
200
+ "FA",
201
+ "FBT",
202
+ "FIX",
203
+ "FLY",
204
+ "FURB",
205
+ "G",
206
+ "I",
207
+ "ICN",
208
+ "INP",
209
+ "INT",
210
+ "ISC",
211
+ "LOG",
212
+ "N",
213
+ "NPY",
214
+ "PD",
215
+ "PERF",
216
+ "PGH",
217
+ "PIE",
218
+ "PL",
219
+ "PT",
220
+ "PTH",
221
+ "PYI",
222
+ "Q",
223
+ "RET",
224
+ "RSE",
225
+ "RUF",
226
+ "S",
227
+ "SIM",
228
+ "SLF",
229
+ "SLOT",
230
+ "T10",
231
+ "T20",
232
+ "TCH",
233
+ "TD",
234
+ "TID",
235
+ "TRY",
236
+ "UP",
237
+ "YTT",
238
+ ]
239
+ ignore = [
240
+ "A005",
241
+ "ANN401",
242
+ "ARG001",
243
+ "ARG002",
244
+ "ARG004",
245
+ "C901",
246
+ "COM812",
247
+ "CPY001",
248
+ "D100",
249
+ "D101",
250
+ "D102",
251
+ "D103",
252
+ "D104",
253
+ "D105",
254
+ "D106",
255
+ "D107",
256
+ "D203",
257
+ "D204",
258
+ "D212",
259
+ "EM101",
260
+ "N818",
261
+ "PLR0912",
262
+ "PLR0913",
263
+ "PLR0914",
264
+ "PLR0915",
265
+ "PLR0917",
266
+ "PLR1702",
267
+ "PLR6301",
268
+ "S101",
269
+ "S404",
270
+ "S603",
271
+ "TD002",
272
+ "TD003",
273
+ "TD004",
274
+ "UP046",
275
+ "UP047",
276
+ ]
277
+ preview = true
278
+
279
+ [tool.ruff.lint.flake8-quotes]
280
+ inline-quotes = "single"
281
+ multiline-quotes = "double"
282
+
283
+ [tool.ruff.lint.isort]
284
+ case-sensitive = true
285
+ combine-as-imports = true
286
+ from-first = true
287
+ required-imports = ["from __future__ import annotations"]
288
+ section-order = ["future", "standard-library", "third-party", "local-folder"]
289
+
290
+ [tool.ruff.lint.pep8-naming]
291
+ extend-ignore-names = ["test_*"]
292
+
293
+ [tool.ruff.lint.pydocstyle]
294
+ convention = "numpy"
295
+
296
+ [tool.yapf]
297
+ align_closing_bracket_with_visual_indent = true
298
+ allow_multiline_dictionary_keys = false
299
+ allow_multiline_lambdas = false
300
+ allow_split_before_dict_value = true
301
+ blank_line_before_class_docstring = false
302
+ blank_line_before_module_docstring = false
303
+ blank_line_before_nested_class_or_def = false
304
+ blank_lines_around_top_level_definition = 2
305
+ coalesce_brackets = true
306
+ column_limit = 100
307
+ continuation_align_style = "SPACE"
308
+ continuation_indent_width = 4
309
+ dedent_closing_brackets = false
310
+ disable_ending_comma_heuristic = false
311
+ each_dict_entry_on_separate_line = true
312
+ indent_dictionary_value = true
313
+ indent_width = 4
314
+ join_multiple_lines = true
315
+ no_spaces_around_selected_binary_operators = false
316
+ space_between_ending_comma_and_closing_bracket = false
317
+ spaces_around_default_or_named_assign = false
318
+ spaces_around_power_operator = true
319
+ spaces_before_comment = 2
320
+ split_all_comma_separated_values = false
321
+ split_arguments_when_comma_terminated = false
322
+ split_before_bitwise_operator = true
323
+ split_before_closing_bracket = true
324
+ split_before_dict_set_generator = true
325
+ split_before_dot = false
326
+ split_before_expression_after_opening_paren = false
327
+ split_before_first_argument = false
328
+ split_before_logical_operator = true
329
+ split_before_named_assigns = true
330
+ split_complex_comprehension = false
331
+ split_penalty_after_opening_bracket = 30
332
+ split_penalty_after_unary_operator = 10000
333
+ split_penalty_before_if_expr = 0
334
+ split_penalty_bitwise_operator = 300
335
+ split_penalty_comprehension = 80
336
+ split_penalty_excess_character = 7000
337
+ split_penalty_for_added_line_split = 30
338
+ split_penalty_import_names = 0
339
+ split_penalty_logical_operator = 300
340
+ use_tabs = false
341
+
342
+ [tool.yapfignore]
343
+ ignore_patterns = ["node_modules/**"]
@@ -0,0 +1,7 @@
1
+ """Utilities for programmatic use of yt-dlp."""
2
+ from __future__ import annotations
3
+
4
+ from .lib import YoutubeDLLogger, get_configured_yt_dlp, setup_session
5
+
6
+ __all__ = ('YoutubeDLLogger', 'get_configured_yt_dlp', 'setup_session')
7
+ __version__ = '0.0.1'
@@ -0,0 +1,22 @@
1
+ from __future__ import annotations
2
+
3
+ __all__ = ('DEFAULT_RETRY_BACKOFF_FACTOR', 'DEFAULT_RETRY_STATUS_FORCELIST', 'SHARED_HEADERS',
4
+ 'USER_AGENT')
5
+
6
+ DEFAULT_RETRY_STATUS_FORCELIST = (429, 500, 502, 503, 504)
7
+ """Default status codes to retry on."""
8
+ DEFAULT_RETRY_BACKOFF_FACTOR = 2.5
9
+ """Default backoff factor for retrying requests."""
10
+
11
+ USER_AGENT = ('Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) '
12
+ 'Chrome/136.0.0.0 Safari/537.36')
13
+ """User agent."""
14
+ SHARED_HEADERS = {
15
+ 'accept': '*/*',
16
+ 'cache-control': 'no-cache',
17
+ 'content-type': 'application/vnd.api+json',
18
+ 'dnt': '1',
19
+ 'pragma': 'no-cache',
20
+ 'user-agent': USER_AGENT,
21
+ }
22
+ """Default headers for requests."""
@@ -0,0 +1,133 @@
1
+ """Utilities."""
2
+ from __future__ import annotations
3
+
4
+ from typing import TYPE_CHECKING, Any
5
+ import logging
6
+ import re
7
+ import sys
8
+
9
+ from requests.adapters import HTTPAdapter
10
+ from urllib3 import Retry
11
+ from yt_dlp.cookies import extract_cookies_from_browser
12
+ import requests
13
+ import yt_dlp
14
+
15
+ from .constants import DEFAULT_RETRY_BACKOFF_FACTOR, DEFAULT_RETRY_STATUS_FORCELIST, SHARED_HEADERS
16
+
17
+ if TYPE_CHECKING:
18
+ from collections.abc import Collection, Iterable, Mapping
19
+
20
+ __all__ = ('YoutubeDLLogger', 'get_configured_yt_dlp', 'setup_session')
21
+
22
+ log = logging.getLogger(__name__)
23
+
24
+
25
+ class YoutubeDLLogger:
26
+ """Logger for yt-dlp."""
27
+ def debug(self, message: str) -> None:
28
+ """Log a debug message."""
29
+ if re.match(r'^\[download\]\s+[0-9\.]+%', message):
30
+ return
31
+ log.info('%s', re.sub(r'^\[(?:info|debug)\]\s+', '', message))
32
+
33
+ def info(self, message: str) -> None:
34
+ """Log an info message."""
35
+ log.info('%s', re.sub(r'^\[info\]\s+', '', message))
36
+
37
+ def warning(self, message: str) -> None:
38
+ """Log a warning message."""
39
+ log.warning('%s', re.sub(r'^\[warn(?:ing)?\]\s+', '', message))
40
+
41
+ def error(self, message: str) -> None:
42
+ """Log an error message."""
43
+ log.error('%s', re.sub(r'^\[err(?:or)?\]\s+', '', message))
44
+
45
+
46
+ def get_configured_yt_dlp(sleep_time: int = 3,
47
+ logger: Any = None,
48
+ *,
49
+ debug: bool = False) -> yt_dlp.YoutubeDL:
50
+ """
51
+ Get a configured ``YoutubeDL`` instance.
52
+
53
+ This function sets up a ``yt_dlp.YoutubeDL`` instance with the user's configuration (e.g.
54
+ located at ``~/.config/yt-dlp/config``). It overrides the default logger, disables colours, and
55
+ sets the sleep time between requests. It also sets the verbose flag based on the ``debug``
56
+ parameter.
57
+
58
+ Parameters
59
+ ----------
60
+ sleep_time : int
61
+ The time to sleep between requests, in seconds. Default is 3 seconds.
62
+ logger : Any
63
+ The logger to use. See :py:class:`YoutubeDLLogger` for details.
64
+ debug : bool
65
+ Whether to enable debug mode. Default is False.
66
+
67
+ Returns
68
+ -------
69
+ yt_dlp.YoutubeDL
70
+ A configured instance of `yt_dlp.YoutubeDL`_.
71
+ """
72
+ old_sys_argv = sys.argv
73
+ sys.argv = [sys.argv[0]]
74
+ ydl_opts = yt_dlp.parse_options()[-1]
75
+ ydl_opts['color'] = {'stdout': 'never', 'stderr': 'never'}
76
+ ydl_opts['logger'] = logger or YoutubeDLLogger()
77
+ ydl_opts['sleep_interval_requests'] = sleep_time
78
+ ydl_opts['verbose'] = debug
79
+ sys.argv = old_sys_argv
80
+ return yt_dlp.YoutubeDL(ydl_opts)
81
+
82
+
83
+ def setup_session(browser: str,
84
+ profile: str,
85
+ domains: Iterable[str],
86
+ headers: Mapping[str, str] | None = None,
87
+ add_headers: Mapping[str, str] | None = None,
88
+ backoff_factor: float = DEFAULT_RETRY_BACKOFF_FACTOR,
89
+ status_forcelist: Collection[int] = DEFAULT_RETRY_STATUS_FORCELIST,
90
+ session: requests.Session | None = None,
91
+ *,
92
+ setup_retry: bool = False) -> requests.Session:
93
+ """
94
+ Create or modify a Requests :py:class:`requests.Session` instance with cookies from the browser.
95
+
96
+ Parameters
97
+ ----------
98
+ browser : str
99
+ The browser to extract cookies from.
100
+ profile : str
101
+ The profile to extract cookies from.
102
+ domains : Iterable[str]
103
+ The domains of which to extract cookies.
104
+ headers : Mapping[str, str]
105
+ The headers to use for the requests session. If not specified, a default set will be used.
106
+ add_headers : Mapping[str, str]
107
+ Additional headers to add to the requests session.
108
+ backoff_factor : float
109
+ The backoff factor to use for the retry mechanism.
110
+ status_forcelist : Collection[int]
111
+ The status codes to retry on.
112
+ setup_retry : bool
113
+ Whether to set up a retry mechanism for the Requests session.
114
+
115
+ Returns
116
+ -------
117
+ requests.Session
118
+ A Requests session.
119
+ """
120
+ headers = headers or SHARED_HEADERS
121
+ add_headers = add_headers or {}
122
+ session = session or requests.Session()
123
+ if setup_retry:
124
+ session.mount(
125
+ 'https://',
126
+ HTTPAdapter(max_retries=Retry(backoff_factor=backoff_factor,
127
+ status_forcelist=status_forcelist)))
128
+ extracted = extract_cookies_from_browser(browser, profile)
129
+ cookies = '; '.join('; '.join(f'{cookie.name}={cookie.value}' for cookie in extracted
130
+ if domain in cookie.domain) for domain in domains)
131
+ # | does not work for Mapping
132
+ session.headers.update({**headers, **add_headers, 'cookie': cookies})
133
+ return session
File without changes