mirror of
https://github.com/astral-sh/ruff
synced 2026-01-07 14:44:17 -05:00
Rework the documentation to incorporate the Ruff formatter (#7732)
## Summary
This PR updates our documentation for the upcoming formatter release.
Broadly, the documentation is now structured as follows:
- Overview
- Tutorial
- Installing Ruff
- The Ruff Linter
- Overview
- `ruff check`
- Rule selection
- Error suppression
- Exit codes
- The Ruff Formatter
- Overview
- `ruff format`
- Philosophy
- Configuration
- Format suppression
- Exit codes
- Black compatibility
- Known deviations
- Configuring Ruff
- pyproject.toml
- File discovery
- Configuration discovery
- CLI
- Shell autocompletion
- Preview
- Rules
- Settings
- Integrations
- `pre-commit`
- VS Code
- LSP
- PyCharm
- GitHub Actions
- FAQ
- Contributing
The major changes include:
- Removing the "Usage" section from the docs, and instead folding that
information into "Integrations" and the new Linter and Formatter
sections.
- Breaking up "Configuration" into "Configuring Ruff" (for generic
configuration), and new Linter- and Formatter-specific sections.
- Updating all example configurations to use `[tool.ruff.lint]` and
`[tool.ruff.format]`.
My suggestion is to pull and build the docs locally, and review by
reading them in the browser rather than trying to parse all the code
changes.
Closes https://github.com/astral-sh/ruff/issues/7235.
Closes https://github.com/astral-sh/ruff/issues/7647.
This commit is contained in:
263
docs/formatter.md
Normal file
263
docs/formatter.md
Normal file
@@ -0,0 +1,263 @@
|
||||
# The Ruff Formatter
|
||||
|
||||
The Ruff formatter is an extremely fast Python code formatter designed as a drop-in replacement for
|
||||
[Black](https://pypi.org/project/black/), available as part of the `ruff` CLI (as of Ruff v0.0.289).
|
||||
|
||||
## `ruff format`
|
||||
|
||||
`ruff format` is the primary entrypoint to the formatter. It accepts a list of files or
|
||||
directories, and formats all discovered Python files:
|
||||
|
||||
```shell
|
||||
ruff format . # Format all files in the current directory.
|
||||
ruff format /path/to/file.py # Format a single file.
|
||||
```
|
||||
|
||||
Similar to Black, running `ruff format /path/to/file.py` will format the given file or directory
|
||||
in-place, while `ruff format --check /path/to/file.py` will avoid writing any formatted files back,
|
||||
and instead exit with a non-zero status code upon detecting any unformatted files.
|
||||
|
||||
For the full list of supported options, run `ruff format --help`.
|
||||
|
||||
## Philosophy
|
||||
|
||||
The initial goal of the Ruff formatter is _not_ to innovate on code style, but rather, to innovate
|
||||
on performance, and provide a unified toolchain across Ruff's linter, formatter, and any and all
|
||||
future tools.
|
||||
|
||||
As such, the formatter is designed as a drop-in replacement for [Black](https://github.com/psf/black),
|
||||
but with an excessive focus on performance and direct integration with Ruff. Given Black's
|
||||
popularity within the Python ecosystem, targeting Black compatibility ensures that formatter
|
||||
adoption is minimally disruptive for the vast majority of projects.
|
||||
|
||||
Specifically, the formatter is intended to emit near-identical output when run over existing
|
||||
Black-formatted code. When run over extensive Black-formatted projects like Django and Zulip, > 99.9%
|
||||
of lines are formatted identically. (See: [_Black compatibility_](#black-compatibility).)
|
||||
|
||||
Given this focus on Black compatibility, the formatter thus adheres to [Black's (stable) code style](https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html),
|
||||
which aims for "consistency, generality, readability and reducing git diffs". To give you a sense
|
||||
for the enforced code style, here's an example:
|
||||
|
||||
```python
|
||||
# Input
|
||||
def _make_ssl_transport(
|
||||
rawsock, protocol, sslcontext, waiter=None,
|
||||
*, server_side=False, server_hostname=None,
|
||||
extra=None, server=None,
|
||||
ssl_handshake_timeout=None,
|
||||
call_connection_made=True):
|
||||
'''Make an SSL transport.'''
|
||||
if waiter is None:
|
||||
waiter = Future(loop=loop)
|
||||
|
||||
if extra is None:
|
||||
extra = {}
|
||||
|
||||
...
|
||||
|
||||
# Ruff
|
||||
def _make_ssl_transport(
|
||||
rawsock,
|
||||
protocol,
|
||||
sslcontext,
|
||||
waiter=None,
|
||||
*,
|
||||
server_side=False,
|
||||
server_hostname=None,
|
||||
extra=None,
|
||||
server=None,
|
||||
ssl_handshake_timeout=None,
|
||||
call_connection_made=True,
|
||||
):
|
||||
"""Make an SSL transport."""
|
||||
if waiter is None:
|
||||
waiter = Future(loop=loop)
|
||||
|
||||
if extra is None:
|
||||
extra = {}
|
||||
|
||||
...
|
||||
```
|
||||
|
||||
Like Black, the Ruff formatter does _not_ support extensive code style configuration; however,
|
||||
unlike Black, it _does_ support configuring the desired quote style, indent style, line endings,
|
||||
and more. (See: [_Configuration_](#configuration).)
|
||||
|
||||
While the formatter is designed to be a drop-in replacement for Black, it is not intended to be
|
||||
used interchangeably with Black on an ongoing basis, as the formatter _does_ differ from
|
||||
Black in a few conscious ways (see: [_Known deviations_](formatter/black.md)). In general,
|
||||
deviations are limited to cases in which Ruff's behavior was deemed more consistent, or
|
||||
significantly simpler to support (with negligible end-user impact) given the differences in the
|
||||
underlying implementations between Black and Ruff.
|
||||
|
||||
Going forward, the Ruff Formatter will support Black's preview style under Ruff's own
|
||||
[preview](preview.md) mode.
|
||||
|
||||
## Configuration
|
||||
|
||||
The Ruff Formatter exposes a small set of configuration options, some of which are also supported
|
||||
by Black (like line width), some of which are unique to Ruff (like quote and indentation style).
|
||||
|
||||
For example, to configure the formatter to use single quotes, a line width of 100, and
|
||||
tab indentation, add the following to your `pyproject.toml`:
|
||||
|
||||
```toml
|
||||
[tool.ruff]
|
||||
line-length = 100
|
||||
|
||||
[tool.ruff.format]
|
||||
quote-style = "single"
|
||||
indent-style = "tab"
|
||||
```
|
||||
|
||||
For the full list of supported settings, see [_Settings_](settings.md#format). For more on
|
||||
configuring Ruff via `pyproject.toml`, see [_Configuring Ruff_](configuration.md).
|
||||
|
||||
Given the focus on Black compatibility (and unlike formatters like [YAPF](https://github.com/google/yapf)),
|
||||
Ruff does not currently expose any configuration options to modify core formatting behavior outside
|
||||
of these trivia-related settings.
|
||||
|
||||
## Format suppression
|
||||
|
||||
Like Black, Ruff supports `# fmt: on`, `# fmt: off`, and `# fmt: skip` pragma comments, which can
|
||||
be used to temporarily disable formatting for a given code block.
|
||||
|
||||
`# fmt: on` and `# fmt: off` comments are enforced at the statement level:
|
||||
|
||||
```python
|
||||
# fmt: off
|
||||
not_formatted=3
|
||||
also_not_formatted=4
|
||||
# fmt: on
|
||||
```
|
||||
|
||||
As such, adding `# fmt: on` and `# fmt: off` comments within expressions will have no effect. In
|
||||
the following example, both list entries will be formatted, despite the `# fmt: off`:
|
||||
|
||||
```python
|
||||
[
|
||||
# fmt: off
|
||||
'1',
|
||||
# fmt: on
|
||||
'2',
|
||||
]
|
||||
```
|
||||
|
||||
Instead, apply the `# fmt: off` comment to the entire statement:
|
||||
|
||||
```python
|
||||
# fmt: off
|
||||
[
|
||||
'1',
|
||||
'2',
|
||||
]
|
||||
# fmt: on
|
||||
```
|
||||
|
||||
`# fmt: skip` comments suppress formatting for a preceding statement, case header, decorator,
|
||||
function definition, or class definition:
|
||||
|
||||
```python
|
||||
if True:
|
||||
pass
|
||||
elif False: # fmt: skip
|
||||
pass
|
||||
|
||||
@Test
|
||||
@Test2 # fmt: off
|
||||
def test(): ...
|
||||
|
||||
a = [1, 2, 3, 4, 5] # fmt: off
|
||||
|
||||
def test(a, b, c, d, e, f) -> int: # fmt: skip
|
||||
pass
|
||||
```
|
||||
|
||||
Like Black, Ruff will _also_ recognize [YAPF](https://github.com/google/yapf)'s `# yapf: disable` and `# yapf: enable` pragma
|
||||
comments, which are treated equivalently to `# fmt: off` and `# fmt: on`, respectively.
|
||||
|
||||
## Conflicting lint rules
|
||||
|
||||
Ruff's formatter is designed to be used alongside the linter. However, the linter includes
|
||||
some rules that, when enabled, can cause conflicts with the formatter, leading to unexpected
|
||||
behavior.
|
||||
|
||||
When using Ruff as a formatter, we recommend disabling the following rules:
|
||||
|
||||
- [`tab-indentation`](rules/tab-indentation.md) (`W191`)
|
||||
- [`indentation-with-invalid-multiple`](rules/indentation-with-invalid-multiple.md) (`E111`)
|
||||
- [`indentation-with-invalid-multiple-comment`](rules/indentation-with-invalid-multiple-comment.md) (`E114`)
|
||||
- [`over-indented`](rules/over-indented.md) (`E117`)
|
||||
- [`indent-with-spaces`](rules/indent-with-spaces.md) (`D206`)
|
||||
- [`triple-single-quotes`](rules/triple-single-quotes.md) (`D300`)
|
||||
- [`bad-quotes-inline-string`](rules/bad-quotes-inline-string.md) (`Q000`)
|
||||
- [`bad-quotes-multiline-string`](rules/bad-quotes-multiline-string.md) (`Q001`)
|
||||
- [`bad-quotes-docstring`](rules/bad-quotes-docstring.md) (`Q002`)
|
||||
- [`avoidable-escaped-quote`](rules/avoidable-escaped-quote.md) (`Q003`)
|
||||
- [`missing-trailing-comma`](rules/missing-trailing-comma.md) (`COM812`)
|
||||
- [`prohibited-trailing-comma`](rules/prohibited-trailing-comma.md) (`COM819`)
|
||||
- [`single-line-implicit-string-concatenation`](rules/single-line-implicit-string-concatenation.md) (`ISC001`)
|
||||
- [`multi-line-implicit-string-concatenation`](rules/multi-line-implicit-string-concatenation.md) (`ISC002`)
|
||||
|
||||
Similarly, we recommend disabling the following isort settings, which are incompatible with the
|
||||
formatter's treatment of import statements when set to non-default values:
|
||||
|
||||
- [`force-single-line`](settings.md#isort-force-single-line)
|
||||
- [`force-wrap-aliases`](settings.md#isort-force-wrap-aliases)
|
||||
- [`lines-after-imports`](settings.md#isort-lines-after-imports)
|
||||
- [`lines-between-types`](settings.md#isort-lines-between-types)
|
||||
- [`split-on-trailing-comma`](settings.md#isort-split-on-trailing-comma)
|
||||
|
||||
## Exit codes
|
||||
|
||||
`ruff format` exits with the following status codes:
|
||||
|
||||
- `0` if Ruff terminates successfully, regardless of whether any files were formatted.
|
||||
- `2` if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an
|
||||
internal error.
|
||||
|
||||
Meanwhile, `ruff format --check` exits with the following status codes:
|
||||
|
||||
- `0` if Ruff terminates successfully, and no files would be formatted if `--check` were not
|
||||
specified.
|
||||
- `1` if Ruff terminates successfully, and one or more files would be formatted if `--check` were
|
||||
not specified.
|
||||
- `2` if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an
|
||||
internal error.
|
||||
|
||||
## Black compatibility
|
||||
|
||||
The formatter is designed to be a drop-in replacement for [Black](https://github.com/psf/black).
|
||||
|
||||
Specifically, the formatter is intended to emit near-identical output when run over Black-formatted
|
||||
code. When run over extensive Black-formatted projects like Django and Zulip, > 99.9% of lines
|
||||
are formatted identically. When migrating an existing project from Black to Ruff, you should expect
|
||||
to see a few differences on the margins, but the vast majority of your code should be unchanged.
|
||||
|
||||
When run over _non_-Black-formatted code, the formatter makes some different decisions than Black,
|
||||
and so more deviations should be expected, especially around the treatment of end-of-line comments.
|
||||
|
||||
If you identify deviations in your project, spot-check them against the [known deviations](formatter/black.md),
|
||||
as well as the [unintentional deviations](https://github.com/astral-sh/ruff/issues?q=is%3Aopen+is%3Aissue+label%3Aformatter)
|
||||
filed in the issue tracker. If you've identified a new deviation, please [file an issue](https://github.com/astral-sh/ruff/issues/new).
|
||||
|
||||
### Intentional deviations
|
||||
|
||||
While the Ruff formatter aims to be a drop-in replacement for Black, it does differ from Black
|
||||
in a few known ways. Some of these differences emerge from conscious attempts to improve upon
|
||||
Black's code style, while others fall out of differences in the underlying implementations.
|
||||
|
||||
For a complete enumeration of these intentional deviations, see [_Known deviations_](formatter/black.md).
|
||||
|
||||
Unintentional deviations from Black are tracked in the [issue tracker](https://github.com/astral-sh/ruff/issues?q=is%3Aopen+is%3Aissue+label%3Aformatter).
|
||||
|
||||
### Preview style
|
||||
|
||||
Black gates formatting changes behind a [`preview`](https://black.readthedocs.io/en/stable/the_black_code_style/future_style.html#preview-style)
|
||||
flag. The formatter does not yet support Black's preview style, though the intention is to support
|
||||
it within the coming months behind Ruff's own [`preview`](https://docs.astral.sh/ruff/settings/#preview)
|
||||
flag.
|
||||
|
||||
Black promotes some of its preview styling to stable at the end of each year. Ruff will similarly
|
||||
implement formatting changes under the [`preview`](https://docs.astral.sh/ruff/settings/#preview)
|
||||
flag, promoting them to stable through minor releases, in accordance with our [versioning policy](https://github.com/astral-sh/ruff/discussions/6998#discussioncomment-7016766).
|
||||
Reference in New Issue
Block a user