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