Hey! These docs are for version 2.10, which is no longer officially supported. Click here for the latest version, 2.18!

Benefit of Pants: consistent interface

`./pants lint` and `./pants fmt` will consistently and correctly run all your linters and formatters. No need to remember how to invoke each tool, and no need to write custom scripts.

This consistent interface even works with multiple languages, like running Python linters at the same time as Go, Shell, Java, and Scala.

Benefit of Pants: concurrency

Pants does several things to speed up running formatters and linters:

  • Automatically configures tools that support concurrency (e.g. a `--jobs` option) based on your number of cores and what else is already running.

  • Runs everything in parallel with the `lint` goal (although not the `fmt` goal, which pipes the results of one formatter to the next for correctness).

  • Runs in batches of 256 files by default, which gives parallelism even for tools that don't have a `--jobs` option. This also increases cache reuse.

## Activating linters and formatters

Linter/formatter support is implemented in separate [backends](🔗) so that they are easy to opt in to individually:

`pants.backend.python.lint.bandit`[Bandit](🔗): security linter
`pants.backend.python.lint.black`[Black](🔗): code formatter
`pants.backend.python.lint.docformatter`[Docformatter](🔗): docstring formatter
`pants.backend.python.lint.flake8`[Flake8](🔗): style and bug linter
`pants.backend.python.lint.isort`[isort](🔗): import statement formatter
`pants.backend.python.lint.pylint`[Pylint](🔗): style and bug linter
`pants.backend.python.lint.yapf`[Yapf](🔗): code formatter
`pants.backend.experimental.python.lint.autoflake`[Autoflake](🔗): remove unused imports
`pants.backend.experimental.python.lint.pyupgrade`[Pyupgrade](🔗): automatically update code to use modern Python idioms like `f-strings`

To enable, add the appropriate backends in `pants.toml`:

You should now be able to run `./pants lint`, and possibly `./pants fmt`:

How to activate MyPy

MyPy is run with the [check goal](🔗), rather than `lint`.

## Configuring the tools, e.g. adding plugins

You can configure each formatter and linter using these options:

OptionWhat it does
`version`E.g. `flake8==3.8.0`.
`extra_requirements`Any additional dependencies to install, such as any plugins.
`interpreter_constraints`What interpreter to run the tool with. (`bandit`, `flake8`, and `pylint` instead determine this based on your [code's interpreter constraints](🔗).)
`args`Any command-line arguments you want to pass to the tool.
`config`Path to a config file. Useful if the file is in a non-standard location such that it cannot be auto-discovered.
`lockfile`Path to a custom lockfile if the default does not work, or `"<none>"` to opt out. See [Third-party dependencies](🔗).

For example:

Run `./pants help-advanced black`, `./pants help-advanced flake8`, and so on for more information.

Config files are normally auto-discovered

For tools that autodiscover config files—such as Black, isort, Flake8, and Pylint—Pants will include any relevant config files in the process's sandbox when running the tool.

If your config file is in a non-standard location, you must instead set the `--config` option, e.g. `[isort].config`. This will ensure that the config file is included in the process's sandbox and Pants will instruct the tool to load the config.

## Running only certain formatters or linters

To temporarily skip a tool, use the `--skip` option for that tool. For example, run:

You can also use the `--lint-only` and `--fmt-only` options with the names of the tools:

You can also skip for certain targets with the `skip_<tool>` fields, which can be useful for [incrementally adopting new tools](🔗). For example:

When you run `./pants fmt` and `./pants lint`, Pants will ignore any files belonging to skipped targets.

## Tip: only run over changed files

With formatters and linters, there is usually no need to rerun on files that have not changed.

Use the option `--changed-since` to get much better performance, like this:


Pants will find which files have changed and only run over those files. See [Advanced target selection](🔗) for more information.

## Tips for specific tools

### Order of `backend_packages` matters for `fmt`

Pants will run formatters in the order in which they appear in the `backend_packages` option.

For example, you likely want to put Autoflake (which removes unused imports) before Black and Isort, which will format your import statements.

### Bandit and Flake8: report files

Flake8 and Bandit can both generate report files saved to disk.

For Pants to properly preserve the reports, instruct both tools to write to the `reports/` folder by updating their config files or `--flake8-args` and `--bandit-args`. For example, in your `pants.toml`:

Pants will copy all reports into the folder `dist/lint/<linter_name>`.

### Pylint and Flake8: how to add first-party plugins

See [`[pylint].source_plugins`](🔗) and [`[flake8].source_plugins`](🔗) for instructions to add plugins written by you.

### Bandit: less verbose logging

Bandit output can be extremely verbose, including on successful runs. You may want to use its `--quiet` option, which will turn off output for successful runs but keep it for failures.

For example, you can set this in your `pants.toml`:

### Black and isort can work together

If you use both `black` and `isort`, you most likely will need to tell `isort` to work in a mode compatible with `black`. It is also a good idea to ensure they use the same line length. This requires tool specific configuration, which could go into `pyproject.toml` for example:

### Pyupgrade: specify which Python version to target

You must tell Pyupgrade which version of Python to target, like this:

### Autoflake and Pyupgrade are experimental

These tools are marked experimental because we are debating adding a new goal called `fix` and running them with `fix` rather than `fmt`. The tools are safe to use, other than possibly changing how you invoke them in the future.

We invite you to [weigh in with what you think](🔗)!

### isort: possible issues with its import classifier algorithm

Some Pants users had to explicitly set `default_section = "THIRDPARTY"` to get iSort 5 to correctly classify their first-party imports, even though this is the default value.

They report that this config works for them:

You may also want to try downgrading to iSort 4.x by setting `version = "isort>=4.6,<5"` in the `[isort]` options scope.