diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 653ddd885..e48e62510 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -136,13 +136,34 @@ # DEVELOPER INSTRUCTIONS Most users do not need to build yt-dlp and can [download the builds](https://github.com/yt-dlp/yt-dlp/releases) or get them via [the other installation methods](README.md#installation). -To run yt-dlp as a developer, you don't need to build anything either. Simply execute +To quickly run yt-dlp as a developer, you don't need to build anything either. Simply execute - python -m yt_dlp +```shell +$ python -m yt_dlp +``` + +To properly interact with `yt-dlp` as a developer, you should use [`hatch`]() (easily installed using [`pipx`]()). +After installing, you can use `hatch shell` to create a shell with all dependencies as well as `yt-dlp` installed. + +If you plan on contributing to `yt-dlp`, run + +```shell +$ hatch run install +``` + +to prepare a full development environment and install `pre-commit`. To run all the available core tests, use: - python devscripts/run_tests.py +```shell +$ hatch run tests core +``` + +You can also run tests for all installed python versions sequentially by setting the `TEST_ALL` variable, like so: + +```shell +$ TEST_ALL=1 hatch run tests core +``` See item 6 of [new extractor tutorial](#adding-support-for-a-new-site) for how to run extractor specific test cases. @@ -165,12 +186,16 @@ ## Adding support for a new site 1. [Fork this repository](https://github.com/yt-dlp/yt-dlp/fork) 1. Check out the source code with: - git clone git@github.com:YOUR_GITHUB_USERNAME/yt-dlp.git + ```shell + $ git clone git@github.com:YOUR_GITHUB_USERNAME/yt-dlp.git + ``` 1. Start a new git branch with - cd yt-dlp - git checkout -b yourextractor + ```shell + $ cd yt-dlp + $ git checkout -b yourextractor + ``` 1. Start with this simple template and save it to `yt_dlp/extractor/yourextractor.py`: @@ -218,20 +243,27 @@ ## Adding support for a new site } ``` 1. Add an import in [`yt_dlp/extractor/_extractors.py`](yt_dlp/extractor/_extractors.py). Note that the class name must end with `IE`. -1. Run `python devscripts/run_tests.py YourExtractor`. This *may fail* at first, but you can continually re-run it until you're done. Upon failure, it will output the missing fields and/or correct values which you can copy. If you decide to add more than one test, the tests will then be named `YourExtractor`, `YourExtractor_1`, `YourExtractor_2`, etc. Note that tests with an `only_matching` key in the test's dict are not included in the count. You can also run all the tests in one go with `YourExtractor_all` +1. Run `hatch run tests YourExtractor`. This *may fail* at first, but you can continually re-run it until you're done. Upon failure, it will output the missing fields and/or correct values which you can copy. If you decide to add more than one test, the tests will then be named `YourExtractor`, `YourExtractor_1`, `YourExtractor_2`, etc. Note that tests with an `only_matching` key in the test's dict are not included in the count. You can also run all the tests in one go with `YourExtractor_all` 1. Make sure you have at least one test for your extractor. Even if all videos covered by the extractor are expected to be inaccessible for automated testing, tests should still be added with a `skip` parameter indicating why the particular test is disabled from running. 1. Have a look at [`yt_dlp/extractor/common.py`](yt_dlp/extractor/common.py) for possible helper methods and a [detailed description of what your extractor should and may return](yt_dlp/extractor/common.py#L119-L440). Add tests and code for as many as you want. -1. Make sure your code follows [yt-dlp coding conventions](#yt-dlp-coding-conventions) and check the code with [ruff](https://docs.astral.sh/ruff/tutorial/#getting-started): +1. Make sure your code follows [yt-dlp coding conventions](#yt-dlp-coding-conventions), passes [ruff](https://docs.astral.sh/ruff/tutorial/#getting-started) code checks and is properly formatted: - $ ruff check yt_dlp/extractor/yourextractor.py + ```shell + $ hatch run lint + $ hatch run format + ``` + + You can use `hatch run lint --fix` to automatically fix problems. 1. Make sure your code works under all [Python](https://www.python.org/) versions supported by yt-dlp, namely CPython and PyPy for Python 3.8 and above. 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: - $ git add yt_dlp/extractor/_extractors.py - $ git add yt_dlp/extractor/yourextractor.py - $ git commit -m '[yourextractor] Add extractor' - $ git push origin yourextractor + ```shell + $ git add yt_dlp/extractor/_extractors.py + $ git add yt_dlp/extractor/yourextractor.py + $ git commit -m '[yourextractor] Add extractor' + $ git push origin yourextractor + ``` 1. Finally, [create a pull request](https://help.github.com/articles/creating-a-pull-request). We'll then review and merge it. diff --git a/devscripts/run_tests.py b/devscripts/run_tests.py index 6d638a974..5a8b2c67d 100755 --- a/devscripts/run_tests.py +++ b/devscripts/run_tests.py @@ -29,12 +29,12 @@ def run_tests(*tests, pattern=None, ci=False): arguments = ['pytest', '-Werror', '--tb=short'] if ci: arguments.append('--color=yes') - if run_core: - arguments.extend(['-m', 'not download']) - elif run_download: - arguments.extend(['-m', 'download']) - elif pattern: + if pattern: arguments.extend(['-k', pattern]) + if run_core: + arguments.extend(['--ignore', 'test/test_download.py']) + elif run_download: + arguments.extend(['test/test_download.py']) else: arguments.extend( f'test/test_download.py::TestDownload::test_{test}' for test in tests) @@ -46,13 +46,13 @@ def run_tests(*tests, pattern=None, ci=False): pass arguments = [sys.executable, '-Werror', '-m', 'unittest'] + if pattern: + arguments.extend(['-k', pattern]) if run_core: print('"pytest" needs to be installed to run core tests', file=sys.stderr, flush=True) return 1 elif run_download: arguments.append('test.test_download') - elif pattern: - arguments.extend(['-k', pattern]) else: arguments.extend( f'test.test_download.TestDownload.test_{test}' for test in tests) diff --git a/pyproject.toml b/pyproject.toml index 3bda1a9bf..003c13d2f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -90,7 +90,6 @@ install = "pre-commit install" lint = "ruff check {args:.}" format = "autopep8 {args:.}" tests = "python -m devscripts.run_tests {args}" -tests-core = "pytest -We --tb=short --ignore=test/test_download.py {args}" [[tool.hatch.envs.default.overrides.env.TEST_ALL.matrix.value]] python = [