diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index b5d0b2d9a8..d2ec61a421 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -23,8 +23,6 @@ repos: - id: mdformat additional_dependencies: - mdformat-mkdocs - - mdformat-black - - black==23.1.0 # Must be the latest version of Black - repo: https://github.com/igorshubovych/markdownlint-cli rev: v0.33.0 diff --git a/crates/ruff_cli/src/args.rs b/crates/ruff_cli/src/args.rs index dd039f7403..a3c8c927ea 100644 --- a/crates/ruff_cli/src/args.rs +++ b/crates/ruff_cli/src/args.rs @@ -388,7 +388,7 @@ pub struct LogLevelArgs { help_heading = "Log levels" )] pub verbose: bool, - /// Print lint violations, but nothing else. + /// Print diagnostics, but nothing else. #[arg( short, long, @@ -397,7 +397,7 @@ pub struct LogLevelArgs { help_heading = "Log levels" )] pub quiet: bool, - /// Disable all logging (but still exit with status code "1" upon detecting lint violations). + /// Disable all logging (but still exit with status code "1" upon detecting diagnostics). #[arg( short, long, diff --git a/crates/ruff_python_formatter/README.md b/crates/ruff_python_formatter/README.md new file mode 100644 index 0000000000..f505f42778 --- /dev/null +++ b/crates/ruff_python_formatter/README.md @@ -0,0 +1,304 @@ +# Ruff Formatter + +The Ruff formatter is an extremely fast Python code formatter that ships as part of the `ruff` +CLI (as of Ruff v0.0.287). + +The formatter is currently in an **alpha** state. As such, it's not yet recommended for production +use, but it _is_ ready for experimentation and testing. _We'd love to have your feedback._ + +## Goals + +The formatter is designed to be a drop-in replacement for [Black](https://github.com/psf/black), +but with an excessive focus on performance and direct integration with Ruff. + +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. + +If you identify deviations in your project, spot-check them against the [intentional deviations](#intentional-deviations) +enumerated below, 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). + +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. +For details, see [Black compatibility](#black-compatibility). + +## Getting started + +The Ruff formatter shipped in an alpha state as part of Ruff v0.0.287. + +### CLI + +The Ruff formatter is available as a standalone subcommand on the `ruff` CLI: + +```console +❯ ruff format --help +Run the Ruff formatter on the given files or directories + +Usage: ruff format [OPTIONS] [FILES]... + +Arguments: + [FILES]... List of files or directories to format + +Options: + --check Avoid writing any formatted files back; instead, exit with a non-zero status code if any files would have been modified, and zero otherwise + --config Path to the `pyproject.toml` or `ruff.toml` file to use for configuration + -h, --help Print help + +File selection: + --respect-gitignore Respect file exclusions via `.gitignore` and other standard ignore files + --force-exclude Enforce exclusions, even for paths passed to Ruff directly on the command-line + +Miscellaneous: + --isolated Ignore all configuration files + --stdin-filename The name of the file when passing it through stdin + +Log levels: + -v, --verbose Enable verbose logging + -q, --quiet Print diagnostics, but nothing else + -s, --silent Disable all logging (but still exit with status code "1" upon detecting diagnostics) +``` + +Note: `ruff format` is currently hidden by default and will not be visible when running +`ruff --help`. + +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, +instead exiting with a non-zero status code if any files are not already formatted. + +### VS Code + +As of `v2023.34.0`, +the [Ruff VS Code extension](https://marketplace.visualstudio.com/items?itemName=charliermarsh.ruff) +ships with support for the Ruff formatter. To enable formatting capabilities, set the +`ruff.enableExperimentalFormatter` setting to `true` in your `settings.json`, and mark the Ruff +extension as your default Python formatter: + +```json +{ + "ruff.enableExperimentalFormatter": true, + "[python]": { + "editor.defaultFormatter": "charliermarsh.ruff" + } +} +``` + +From there, you can format a file by running the `Format Document` command, or enable formatting +on-save by adding `"editor.formatOnSave": true` to your `settings.json`: + +```json +{ + "ruff.enableExperimentalFormatter": true, + "[python]": { + "editor.defaultFormatter": "charliermarsh.ruff", + "editor.formatOnSave": true + } +} +``` + +### Configuration + +The Ruff formatter respects Ruff's [`line-length`](https://beta.ruff.rs/docs/settings/#line-length) +setting, which can be provided via a `pyproject.toml` or `ruff.toml` file, or on the CLI, as in: + +```console +ruff format --line-length 100 /path/to/file.py +``` + +In future releases, the Ruff formatter will likely support configuration of: + +- Quote style (single vs. double). +- Line endings (LF vs. CRLF). +- Indentation (tabs vs. spaces). +- Tab width. + +### Excluding code from formatting + +Ruff supports Black's `# fmt: off`, `# fmt: on`, and `# fmt: skip` pragmas, with a few caveats. + +See Ruff's [suppression comment proposal](https://github.com/astral-sh/ruff/discussions/6338) for +details. + +## 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 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 formatted identically. +Note, however, that the formatter does not yet implement or support Black's preview style. + +When run over _non_-Black-formatted code, the formatter makes some different decisions than Black, +and so more deviations should be expected. + +### Intentional deviations + +This section enumerates the known, intentional deviations between the Ruff formatter and Black's +stable style. (Unintentional deviations are tracked in the [issue tracker](https://github.com/astral-sh/ruff/issues?q=is%3Aopen+is%3Aissue+label%3Aformatter).) + +#### Trailing end-of-line comments + +Black's priority is to fit an entire statement on a line, even if it contains end-of-line comments. +In such cases, Black collapses the statement, and moves the comment to the end of the collapsed +statement: + +```python +# Input +while ( + cond1 # almost always true + and cond2 # almost never true +): + print("Do something") + +# Black +while cond1 and cond2: # almost always true # almost never true + print("Do something") +``` + +Ruff, like [Prettier](https://prettier.io/), expands any statement that contains trailing +end-of-line comments. For example, Ruff would avoid collapsing the `while` test in the snippet +above. This ensures that the comments remain close to their original position and retain their +original intent, at the cost of retaining additional vertical space. + +This deviation only impacts unformatted code, in that Ruff's output should not deviate for code that +has already been formatted by Black. + +### Pragma comments are ignored when computing line width + +Pragma comments (`# type`, `# noqa`, `# pyright`, `# pylint`, etc.) are ignored when computing the width of a line. +This prevents Ruff from moving pragma comments around, thereby modifying their meaning and behavior: + +See Ruff's [pragma comment handling proposal](https://github.com/astral-sh/ruff/discussions/6670) +for details. + +This is similar to [Pyink](https://github.com/google/pyink) but a deviation from Black. Black avoids +splitting any lines that contain a `# type` comment ([#997](https://github.com/psf/black/issues/997)), +but otherwise avoids special-casing pragma comments. + +As Ruff expands trailing end-of-line comments, Ruff will also avoid moving pragma comments in cases +like the following, where moving the `# noqa` to the end of the line causes it to suppress errors +on both `first()` and `second()`: + +```python +# Input +[ + first(), # noqa + second() +] + +# Black +[first(), second()] # noqa + +# Ruff +[ + first(), # noqa + second(), +] +``` + +### Line width vs. line length + +Ruff uses the Unicode width of a line to determine if a line fits. Black's stable style uses +character width, while Black's preview style uses Unicode width for strings ([#3445](https://github.com/psf/black/pull/3445)), +and character width for all other tokens. Ruff's behavior is closer to Black's preview style than +Black's stable style, although Ruff _also_ uses Unicode width for identifiers and comments. + +### Walruses in slice expressions + +Black avoids inserting space around `:=` operators within slices. For example, the following adheres +to Black stable style: + +```python +# Input +x[y:=1] + +# Black +x[y:=1] +``` + +Ruff will instead add space around the `:=` operator: + +```python +# Input +x[y:=1] + +# Ruff +x[y := 1] +``` + +This will likely be incorporated into Black's preview style ([#3823](https://github.com/psf/black/pull/3823)). + +### `global` and `nonlocal` names are broken across multiple lines by continuations + +If a `global` or `nonlocal` statement includes multiple names, and exceeds the configured line +width, Ruff will break them across multiple lines using continuations: + +```python +# Input +global analyze_featuremap_layer, analyze_featuremapcompression_layer, analyze_latencies_post, analyze_motions_layer, analyze_size_model + +# Ruff +global \ + analyze_featuremap_layer, \ + analyze_featuremapcompression_layer, \ + analyze_latencies_post, \ + analyze_motions_layer, \ + analyze_size_model +``` + +### Newlines are inserted after all class docstrings + +Black typically enforces a single newline after a class docstring. However, it does not apply such +formatting if the docstring is single-quoted rather than triple-quoted, while Ruff enforces a +single newline in both cases: + +```python +# Input +class IntFromGeom(GEOSFuncFactory): + "Argument is a geometry, return type is an integer." + argtypes = [GEOM_PTR] + restype = c_int + errcheck = staticmethod(check_minus_one) + +# Black +class IntFromGeom(GEOSFuncFactory): + "Argument is a geometry, return type is an integer." + argtypes = [GEOM_PTR] + restype = c_int + errcheck = staticmethod(check_minus_one) + +# Ruff +class IntFromGeom(GEOSFuncFactory): + "Argument is a geometry, return type is an integer." + + argtypes = [GEOM_PTR] + restype = c_int + errcheck = staticmethod(check_minus_one) +``` + +### Trailing own-line comments on imports are not moved to the next line + +Black enforces a single empty line between an import and a trailing own-line comment. Ruff leaves +such comments in-place: + +```python +# Input +import os +# comment + +import sys + +# Black +import os + +# comment + +import sys + +# Ruff +import os +# comment + +import sys +``` diff --git a/docs/configuration.md b/docs/configuration.md index a6743731da..438b1f922d 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -171,8 +171,8 @@ Options: Log levels: -v, --verbose Enable verbose logging - -q, --quiet Print lint violations, but nothing else - -s, --silent Disable all logging (but still exit with status code "1" upon detecting lint violations) + -q, --quiet Print diagnostics, but nothing else + -s, --silent Disable all logging (but still exit with status code "1" upon detecting diagnostics) For help with a specific command, see: `ruff help `. ``` @@ -265,8 +265,8 @@ Miscellaneous: Log levels: -v, --verbose Enable verbose logging - -q, --quiet Print lint violations, but nothing else - -s, --silent Disable all logging (but still exit with status code "1" upon detecting lint violations) + -q, --quiet Print diagnostics, but nothing else + -s, --silent Disable all logging (but still exit with status code "1" upon detecting diagnostics) ```