]> jfr.im git - yt-dlp.git/blob - pyproject.toml
[test:download] Raise on network errors (#10283)
[yt-dlp.git] / pyproject.toml
1 [build-system]
2 requires = ["hatchling"]
3 build-backend = "hatchling.build"
4
5 [project]
6 name = "yt-dlp"
7 maintainers = [
8 {name = "pukkandan", email = "pukkandan.ytdlp@gmail.com"},
9 {name = "Grub4K", email = "contact@grub4k.xyz"},
10 {name = "bashonly", email = "bashonly@protonmail.com"},
11 {name = "coletdjnz", email = "coletdjnz@protonmail.com"},
12 ]
13 description = "A feature-rich command-line audio/video downloader"
14 readme = "README.md"
15 requires-python = ">=3.8"
16 keywords = [
17 "youtube-dl",
18 "video-downloader",
19 "youtube-downloader",
20 "sponsorblock",
21 "youtube-dlc",
22 "yt-dlp",
23 ]
24 license = {file = "LICENSE"}
25 classifiers = [
26 "Topic :: Multimedia :: Video",
27 "Development Status :: 5 - Production/Stable",
28 "Environment :: Console",
29 "Programming Language :: Python",
30 "Programming Language :: Python :: 3 :: Only",
31 "Programming Language :: Python :: 3.8",
32 "Programming Language :: Python :: 3.9",
33 "Programming Language :: Python :: 3.10",
34 "Programming Language :: Python :: 3.11",
35 "Programming Language :: Python :: 3.12",
36 "Programming Language :: Python :: Implementation",
37 "Programming Language :: Python :: Implementation :: CPython",
38 "Programming Language :: Python :: Implementation :: PyPy",
39 "License :: OSI Approved :: The Unlicense (Unlicense)",
40 "Operating System :: OS Independent",
41 ]
42 dynamic = ["version"]
43 dependencies = [
44 "brotli; implementation_name=='cpython'",
45 "brotlicffi; implementation_name!='cpython'",
46 "certifi",
47 "mutagen",
48 "pycryptodomex",
49 "requests>=2.32.2,<3",
50 "urllib3>=1.26.17,<3",
51 "websockets>=12.0",
52 ]
53
54 [project.optional-dependencies]
55 default = []
56 curl-cffi = ["curl-cffi==0.5.10; implementation_name=='cpython'"]
57 secretstorage = [
58 "cffi",
59 "secretstorage",
60 ]
61 build = [
62 "build",
63 "hatchling",
64 "pip",
65 "setuptools",
66 "wheel",
67 ]
68 dev = [
69 "pre-commit",
70 "yt-dlp[static-analysis]",
71 "yt-dlp[test]",
72 ]
73 static-analysis = [
74 "autopep8~=2.0",
75 "ruff~=0.4.4",
76 ]
77 test = [
78 "pytest~=8.1",
79 ]
80 pyinstaller = [
81 "pyinstaller>=6.7.0", # for compat with setuptools>=70
82 ]
83 py2exe = [
84 "py2exe>=0.12",
85 ]
86
87 [project.urls]
88 Documentation = "https://github.com/yt-dlp/yt-dlp#readme"
89 Repository = "https://github.com/yt-dlp/yt-dlp"
90 Tracker = "https://github.com/yt-dlp/yt-dlp/issues"
91 Funding = "https://github.com/yt-dlp/yt-dlp/blob/master/Collaborators.md#collaborators"
92
93 [project.scripts]
94 yt-dlp = "yt_dlp:main"
95
96 [project.entry-points.pyinstaller40]
97 hook-dirs = "yt_dlp.__pyinstaller:get_hook_dirs"
98
99 [tool.hatch.build.targets.sdist]
100 include = [
101 "/yt_dlp",
102 "/devscripts",
103 "/test",
104 "/.gitignore", # included by default, needed for auto-excludes
105 "/Changelog.md",
106 "/LICENSE", # included as license
107 "/pyproject.toml", # included by default
108 "/README.md", # included as readme
109 "/setup.cfg",
110 "/supportedsites.md",
111 ]
112 artifacts = [
113 "/yt_dlp/extractor/lazy_extractors.py",
114 "/completions",
115 "/AUTHORS", # included by default
116 "/README.txt",
117 "/yt-dlp.1",
118 ]
119
120 [tool.hatch.build.targets.wheel]
121 packages = ["yt_dlp"]
122 artifacts = ["/yt_dlp/extractor/lazy_extractors.py"]
123
124 [tool.hatch.build.targets.wheel.shared-data]
125 "completions/bash/yt-dlp" = "share/bash-completion/completions/yt-dlp"
126 "completions/zsh/_yt-dlp" = "share/zsh/site-functions/_yt-dlp"
127 "completions/fish/yt-dlp.fish" = "share/fish/vendor_completions.d/yt-dlp.fish"
128 "README.txt" = "share/doc/yt_dlp/README.txt"
129 "yt-dlp.1" = "share/man/man1/yt-dlp.1"
130
131 [tool.hatch.version]
132 path = "yt_dlp/version.py"
133 pattern = "_pkg_version = '(?P<version>[^']+)'"
134
135 [tool.hatch.envs.default]
136 features = ["curl-cffi", "default"]
137 dependencies = ["pre-commit"]
138 path = ".venv"
139 installer = "uv"
140
141 [tool.hatch.envs.default.scripts]
142 setup = "pre-commit install --config .pre-commit-hatch.yaml"
143 yt-dlp = "python -Werror -Xdev -m yt_dlp {args}"
144
145 [tool.hatch.envs.hatch-static-analysis]
146 detached = true
147 features = ["static-analysis"]
148 dependencies = [] # override hatch ruff version
149 config-path = "pyproject.toml"
150
151 [tool.hatch.envs.hatch-static-analysis.scripts]
152 format-check = "autopep8 --diff {args:.}"
153 format-fix = "autopep8 --in-place {args:.}"
154 lint-check = "ruff check {args:.}"
155 lint-fix = "ruff check --fix {args:.}"
156
157 [tool.hatch.envs.hatch-test]
158 features = ["test"]
159 dependencies = [
160 "pytest-randomly~=3.15",
161 "pytest-rerunfailures~=14.0",
162 "pytest-xdist[psutil]~=3.5",
163 ]
164
165 [tool.hatch.envs.hatch-test.scripts]
166 run = "python -m devscripts.run_tests {args}"
167 run-cov = "echo Code coverage not implemented && exit 1"
168
169 [[tool.hatch.envs.hatch-test.matrix]]
170 python = [
171 "3.8",
172 "3.9",
173 "3.10",
174 "3.11",
175 "3.12",
176 "pypy3.8",
177 "pypy3.9",
178 "pypy3.10",
179 ]
180
181 [tool.ruff]
182 line-length = 120
183
184 [tool.ruff.lint]
185 ignore = [
186 "E402", # module-import-not-at-top-of-file
187 "E501", # line-too-long
188 "E731", # lambda-assignment
189 "E741", # ambiguous-variable-name
190 "UP036", # outdated-version-block
191 "B006", # mutable-argument-default
192 "B008", # function-call-in-default-argument
193 "B011", # assert-false
194 "B017", # assert-raises-exception
195 "B023", # function-uses-loop-variable (false positives)
196 "B028", # no-explicit-stacklevel
197 "B904", # raise-without-from-inside-except
198 "C401", # unnecessary-generator-set
199 "C402", # unnecessary-generator-dict
200 "PIE790", # unnecessary-placeholder
201 "SIM102", # collapsible-if
202 "SIM108", # if-else-block-instead-of-if-exp
203 "SIM112", # uncapitalized-environment-variables
204 "SIM113", # enumerate-for-loop
205 "SIM114", # if-with-same-arms
206 "SIM115", # open-file-with-context-handler
207 "SIM117", # multiple-with-statements
208 "SIM223", # expr-and-false
209 "SIM300", # yoda-conditions
210 "TD001", # invalid-todo-tag
211 "TD002", # missing-todo-author
212 "TD003", # missing-todo-link
213 "PLE0604", # invalid-all-object (false positives)
214 "PLW0603", # global-statement
215 "PLW1510", # subprocess-run-without-check
216 "PLW2901", # redefined-loop-name
217 "RUF001", # ambiguous-unicode-character-string
218 "RUF012", # mutable-class-default
219 "RUF100", # unused-noqa (flake8 has slightly different behavior)
220 ]
221 select = [
222 "E", # pycodestyle Error
223 "W", # pycodestyle Warning
224 "F", # Pyflakes
225 "I", # isort
226 "Q", # flake8-quotes
227 "N803", # invalid-argument-name
228 "N804", # invalid-first-argument-name-for-class-method
229 "UP", # pyupgrade
230 "B", # flake8-bugbear
231 "A", # flake8-builtins
232 "COM", # flake8-commas
233 "C4", # flake8-comprehensions
234 "FA", # flake8-future-annotations
235 "ISC", # flake8-implicit-str-concat
236 "ICN003", # banned-import-from
237 "PIE", # flake8-pie
238 "T20", # flake8-print
239 "RSE", # flake8-raise
240 "RET504", # unnecessary-assign
241 "SIM", # flake8-simplify
242 "TID251", # banned-api
243 "TD", # flake8-todos
244 "PLC", # Pylint Convention
245 "PLE", # Pylint Error
246 "PLW", # Pylint Warning
247 "RUF", # Ruff-specific rules
248 ]
249
250 [tool.ruff.lint.per-file-ignores]
251 "devscripts/lazy_load_template.py" = [
252 "F401", # unused-import
253 ]
254 "!yt_dlp/extractor/**.py" = [
255 "I", # isort
256 "ICN003", # banned-import-from
257 "T20", # flake8-print
258 "A002", # builtin-argument-shadowing
259 "C408", # unnecessary-collection-call
260 ]
261 "yt_dlp/jsinterp.py" = [
262 "UP031", # printf-string-formatting
263 ]
264
265 [tool.ruff.lint.isort]
266 known-first-party = [
267 "bundle",
268 "devscripts",
269 "test",
270 ]
271 relative-imports-order = "closest-to-furthest"
272
273 [tool.ruff.lint.flake8-quotes]
274 docstring-quotes = "double"
275 multiline-quotes = "single"
276 inline-quotes = "single"
277 avoid-escape = false
278
279 [tool.ruff.lint.pep8-naming]
280 classmethod-decorators = [
281 "yt_dlp.utils.classproperty",
282 ]
283
284 [tool.ruff.lint.flake8-import-conventions]
285 banned-from = [
286 "base64",
287 "datetime",
288 "functools",
289 "glob",
290 "hashlib",
291 "itertools",
292 "json",
293 "math",
294 "os",
295 "pathlib",
296 "random",
297 "re",
298 "string",
299 "sys",
300 "time",
301 "urllib",
302 "uuid",
303 "xml",
304 ]
305
306 [tool.ruff.lint.flake8-tidy-imports.banned-api]
307 "yt_dlp.compat.compat_str".msg = "Use `str` instead."
308 "yt_dlp.compat.compat_b64decode".msg = "Use `base64.b64decode` instead."
309 "yt_dlp.compat.compat_urlparse".msg = "Use `urllib.parse` instead."
310 "yt_dlp.compat.compat_parse_qs".msg = "Use `urllib.parse.parse_qs` instead."
311 "yt_dlp.compat.compat_urllib_parse_unquote".msg = "Use `urllib.parse.unquote` instead."
312 "yt_dlp.compat.compat_urllib_parse_urlencode".msg = "Use `urllib.parse.urlencode` instead."
313 "yt_dlp.compat.compat_urllib_parse_urlparse".msg = "Use `urllib.parse.urlparse` instead."
314 "yt_dlp.compat.compat_shlex_quote".msg = "Use `yt_dlp.utils.shell_quote` instead."
315 "yt_dlp.utils.error_to_compat_str".msg = "Use `str` instead."
316
317 [tool.autopep8]
318 max_line_length = 120
319 recursive = true
320 exit-code = true
321 jobs = 0
322 select = [
323 "E101",
324 "E112",
325 "E113",
326 "E115",
327 "E116",
328 "E117",
329 "E121",
330 "E122",
331 "E123",
332 "E124",
333 "E125",
334 "E126",
335 "E127",
336 "E128",
337 "E129",
338 "E131",
339 "E201",
340 "E202",
341 "E203",
342 "E211",
343 "E221",
344 "E222",
345 "E223",
346 "E224",
347 "E225",
348 "E226",
349 "E227",
350 "E228",
351 "E231",
352 "E241",
353 "E242",
354 "E251",
355 "E252",
356 "E261",
357 "E262",
358 "E265",
359 "E266",
360 "E271",
361 "E272",
362 "E273",
363 "E274",
364 "E275",
365 "E301",
366 "E302",
367 "E303",
368 "E304",
369 "E305",
370 "E306",
371 "E502",
372 "E701",
373 "E702",
374 "E704",
375 "W391",
376 "W504",
377 ]
378
379 [tool.pytest.ini_options]
380 addopts = "-ra -v --strict-markers"
381 markers = [
382 "download",
383 ]