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