Contributing Basics

An overview on contributing to the Black project.

If you are making a large change, please open an issue first to discuss it beforehand.

Overview

Development on the latest version of Python is preferred. You can use any operating system.

First clone the Black repository:

$ git clone https://github.com/psf/black.git
$ cd black

Then install development dependencies inside a virtual environment of your choice, for example:

$ python3 -m venv .venv
$ source .venv/bin/activate # activation for linux and mac
$ .venv\Scripts\activate # activation for windows

(.venv)$ pip install --group dev
(.venv)$ pip install -e ".[d]"
(.venv)$ pre-commit install

Before submitting pull requests, run lints and tests with the following commands from the root of the black repo:

(.venv)$ tox -e run_self # Format Black itself (required!)
(.venv)$ pre-commit run -a # Linting
(.venv)$ tox -e py # Unit tests (also run by CI)
(.venv)$ tox -e fuzz # Fuzz testing (optional)

(.venv)$ tox --parallel=auto # Run format, tests, and fuzz in parallel

News / Changelog Requirement

Black has CI that will check for an entry corresponding to your PR in CHANGES.md. If you feel your PR does not require a changelog entry, please state that and a maintainer can add the ci: skip news label to bypass the check. Otherwise, please ensure you have a line in the following format added below the appropriate header:

- `Black` is now more awesome (#X)

Note that X should be your PR number, not issue number! To workout X, you may use Next PR Number.

The description should be no more than two sentences and should accurately describe the user-facing change. Avoid referencing Black internals or the implementation details of the change.

This saves a lot of release overhead as the releaser does not need to work out what to add to the CHANGES.md for each commit.

Style Changes

If a change would affect the advertised code style, please modify the documentation to reflect that change. Patches that fix unintended bugs in formatting don’t need to be mentioned separately.

Please familiarize yourself with our stability policy. Most style changes must be added to the --preview style. Exceptions are fixing crashes or changes that would not affect an already-formatted file.

New formatting styles are implemented by adding a new item to the Preview enum in mode.py. The name of this style should accurately summarize the user-facing change in about 3-6 words and under 40 characters. All new formatting logic should be gated under a Preview.FEATURE in mode check. The diff-shades check ensures this is implemented correctly.

If the change is implemented under the --preview or --unstable style, please include the change in the Future Style document instead. Additionally, please ensure you include the changelog entry under the dedicated “Preview style” heading.

Testing

All aspects of the Black style should be tested. PRs are welcome to add tests for parts of Black that aren’t covered by existing tests. Additionally, if you come across a resolved but unclosed issue, please PR test cases for it before we close it, if they don’t exist already.

It’s a good practice to follow Test-Driven Development: If you’re fixing a bug, first add a test. Run it to confirm it fails, then fix the bug, and run the test again to confirm it’s really fixed. Please add tests for any and all changes you make.

Whenever possible, tests should be created as files in the tests/data/cases directory. These files consist of up to three parts:

  • A line that starts with # flags: followed by a set of command-line options. For example, if the line is # flags: --preview --skip-magic-trailing-comma, the test case will be run with preview mode on and the magic trailing comma off. The options accepted are mostly a subset of those of Black itself, except for the --minimum-version= flag, which should be used when testing a grammar feature that works only in newer versions of Python. This flag ensures that we don’t try to validate the AST on older versions and tests that we autodetect the Python version correctly when the feature is used. For the exact flags accepted, see the function get_flags_parser in tests/util.py. If this line is omitted, the default options are used.

  • A block of Python code used as input for the formatter.

  • The line # output, followed by the output of Black when run on the previous block. If this is omitted, the test asserts that Black will leave the input code unchanged.

Test Arguments

Run tests on a specific python version:

(.venv)$ tox -e py314

Run an individual test:

(.venv)$ pytest -k <test name>

Pass arguments to pytest:

(.venv)$ tox -e py -- --no-cov

Black also has two unique CLI options that serve to help depug failing test files in tests/data/. These can be passed to pytest through tox as shown above, or directly into pytest if not using tox.

--print-full-tree prints the full concrete syntax tree (CST) upon a failing test. Both the CST after parsing the input (“actual”) and the CST after parsing the output (“expected”) are printed. Note that a test can fail with different formatting outputs but the same CST.

(.venv)$ tox -e py -- --print-full-tree

--print-tree-diff prints the diff of the two CSTs described above upon a failing test. This is the default. To turn it off pass --print-tree-diff=False.

(.venv)$ tox -e py -- --print-tree-diff=False

Docs Testing

If you make changes to docs, you can test they still build locally:

(.venv)$ pip install --group docs
(.venv)$ pip install -e ".[d]"
(.venv)$ sphinx-build -a -b html -W docs/ docs/_build/

Thank You!

Thanks again for your interest in improving the project! You’re taking action when most people decide to sit and watch.