mirror of https://github.com/astral-sh/ruff
Move configuration out of README and into permanent docs (#3150)
This commit is contained in:
parent
2d4fae45d9
commit
b9bfb81e36
491
README.md
491
README.md
|
|
@ -97,21 +97,19 @@ developer of [Zulip](https://github.com/zulip/zulip):
|
||||||
|
|
||||||
For more, see the [documentation](https://beta.ruff.rs/docs/).
|
For more, see the [documentation](https://beta.ruff.rs/docs/).
|
||||||
|
|
||||||
1. [Installation and Usage](#installation-and-usage)
|
1. [Getting Started](#getting-started)
|
||||||
2. [Configuration](#configuration)
|
2. [Configuration](#configuration)
|
||||||
3. [Supported Rules](#supported-rules)
|
3. [Rules](#rules)
|
||||||
4. [Contributing](#contributing)
|
4. [Contributing](#contributing)
|
||||||
5. [Support](#support)
|
5. [Support](#support)
|
||||||
6. [Acknowledgements](#acknowledgements)
|
6. [Acknowledgements](#acknowledgements)
|
||||||
7. [Who's Using Ruff?](#whos-using-ruff)
|
7. [Who's Using Ruff?](#whos-using-ruff)
|
||||||
8. [License](#license)
|
8. [License](#license)
|
||||||
|
|
||||||
## Installation and Usage
|
## Getting Started
|
||||||
|
|
||||||
For more, see the [documentation](https://beta.ruff.rs/docs/).
|
For more, see the [documentation](https://beta.ruff.rs/docs/).
|
||||||
|
|
||||||
<!-- Begin section: Installation and Usage -->
|
|
||||||
|
|
||||||
### Installation
|
### Installation
|
||||||
|
|
||||||
Ruff is available as [`ruff`](https://pypi.org/project/ruff/) on PyPI:
|
Ruff is available as [`ruff`](https://pypi.org/project/ruff/) on PyPI:
|
||||||
|
|
@ -120,31 +118,8 @@ Ruff is available as [`ruff`](https://pypi.org/project/ruff/) on PyPI:
|
||||||
pip install ruff
|
pip install ruff
|
||||||
```
|
```
|
||||||
|
|
||||||
For **macOS Homebrew** and **Linuxbrew** users, Ruff is also available as [`ruff`](https://formulae.brew.sh/formula/ruff) on Homebrew:
|
You can also install Ruff via [Homebrew](https://formulae.brew.sh/formula/ruff), [Conda](https://anaconda.org/conda-forge/ruff),
|
||||||
|
and with [a variety of other package managers](https://beta.ruff.rs/docs/installation-and-usage/).
|
||||||
```shell
|
|
||||||
brew install ruff
|
|
||||||
```
|
|
||||||
|
|
||||||
For **Conda** users, Ruff is also available as [`ruff`](https://anaconda.org/conda-forge/ruff) on `conda-forge`:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
conda install -c conda-forge ruff
|
|
||||||
```
|
|
||||||
|
|
||||||
For **Arch Linux** users, Ruff is also available as [`ruff`](https://archlinux.org/packages/community/x86_64/ruff/) on the official repositories:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
pacman -S ruff
|
|
||||||
```
|
|
||||||
|
|
||||||
For **Alpine** users, Ruff is also available as [`ruff`](https://pkgs.alpinelinux.org/package/edge/testing/x86_64/ruff) on the testing repositories:
|
|
||||||
|
|
||||||
```shell
|
|
||||||
apk add ruff
|
|
||||||
```
|
|
||||||
|
|
||||||
[](https://repology.org/project/ruff-python-linter/versions)
|
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
|
|
@ -157,13 +132,7 @@ ruff check path/to/code/*.py # Lint all `.py` files in `/path/to/code`
|
||||||
ruff check path/to/code/to/file.py # Lint `file.py`
|
ruff check path/to/code/to/file.py # Lint `file.py`
|
||||||
```
|
```
|
||||||
|
|
||||||
You can run Ruff in `--watch` mode to automatically re-run on-change:
|
Ruff can also be used as a [pre-commit](https://pre-commit.com) hook:
|
||||||
|
|
||||||
```shell
|
|
||||||
ruff check path/to/code/ --watch
|
|
||||||
```
|
|
||||||
|
|
||||||
Ruff also works with [pre-commit](https://pre-commit.com):
|
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||||
|
|
@ -173,37 +142,20 @@ Ruff also works with [pre-commit](https://pre-commit.com):
|
||||||
- id: ruff
|
- id: ruff
|
||||||
```
|
```
|
||||||
|
|
||||||
Or, to enable autofix:
|
Ruff can also be used as a [VS Code extension](https://github.com/charliermarsh/ruff-vscode) or
|
||||||
|
with other editors through the [Ruff LSP](https://github.com/charliermarsh/ruff-lsp).
|
||||||
|
|
||||||
```yaml
|
### Configuration
|
||||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
|
||||||
# Ruff version.
|
|
||||||
rev: 'v0.0.252'
|
|
||||||
hooks:
|
|
||||||
- id: ruff
|
|
||||||
args: [--fix, --exit-non-zero-on-fix]
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that Ruff's pre-commit hook should run before Black, isort, and other formatting tools.
|
Ruff can be configured via a `pyproject.toml` file, a `ruff.toml` file, or through the command line
|
||||||
|
(see: [_Configuration_](https://beta.ruff.rs/docs/configuration/), or
|
||||||
<!-- End section: Installation and Usage -->
|
[_Settings_](https://beta.ruff.rs/docs/settings/) for a complete list of all configuration options).
|
||||||
|
|
||||||
## Configuration
|
|
||||||
|
|
||||||
<!-- Begin section: Configuration -->
|
|
||||||
|
|
||||||
Ruff can be configured via a `pyproject.toml` file, a `ruff.toml` file, or through the command line.
|
|
||||||
|
|
||||||
For a complete enumeration of the available configuration options, see the
|
|
||||||
[documentation](https://beta.ruff.rs/docs/settings/).
|
|
||||||
|
|
||||||
### Configure via `pyproject.toml`
|
|
||||||
|
|
||||||
If left unspecified, the default configuration is equivalent to:
|
If left unspecified, the default configuration is equivalent to:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[tool.ruff]
|
[tool.ruff]
|
||||||
# Enable Pyflakes `E` and `F` codes by default.
|
# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
|
||||||
select = ["E", "F"]
|
select = ["E", "F"]
|
||||||
ignore = []
|
ignore = []
|
||||||
|
|
||||||
|
|
@ -250,428 +202,39 @@ target-version = "py310"
|
||||||
max-complexity = 10
|
max-complexity = 10
|
||||||
```
|
```
|
||||||
|
|
||||||
As an example, the following would configure Ruff to: (1) enforce flake8-bugbear rules, in addition
|
Some configuration options can be provided via the command-line, such as those related to
|
||||||
to the defaults; (2) avoid enforcing line-length violations (`E501`); (3) avoid attempting to fix
|
|
||||||
flake8-bugbear (`B`) violations; and (3) ignore import-at-top-of-file violations (`E402`) in
|
|
||||||
`__init__.py` files:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[tool.ruff]
|
|
||||||
# Enable flake8-bugbear (`B`) rules.
|
|
||||||
select = ["E", "F", "B"]
|
|
||||||
|
|
||||||
# Never enforce `E501` (line length violations).
|
|
||||||
ignore = ["E501"]
|
|
||||||
|
|
||||||
# Avoid trying to fix flake8-bugbear (`B`) violations.
|
|
||||||
unfixable = ["B"]
|
|
||||||
|
|
||||||
# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
|
|
||||||
[tool.ruff.per-file-ignores]
|
|
||||||
"__init__.py" = ["E402"]
|
|
||||||
"path/to/file.py" = ["E402"]
|
|
||||||
```
|
|
||||||
|
|
||||||
Plugin configurations should be expressed as subsections, e.g.:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[tool.ruff]
|
|
||||||
# Add "Q" to the list of enabled codes.
|
|
||||||
select = ["E", "F", "Q"]
|
|
||||||
|
|
||||||
[tool.ruff.flake8-quotes]
|
|
||||||
docstring-quotes = "double"
|
|
||||||
```
|
|
||||||
|
|
||||||
Ruff mirrors Flake8's rule code system, in which each rule code consists of a one-to-three letter
|
|
||||||
prefix, followed by three digits (e.g., `F401`). The prefix indicates that "source" of the rule
|
|
||||||
(e.g., `F` for Pyflakes, `E` for pycodestyle, `ANN` for flake8-annotations). The set of enabled
|
|
||||||
rules is determined by the `select` and `ignore` options, which support both the full code (e.g.,
|
|
||||||
`F401`) and the prefix (e.g., `F`).
|
|
||||||
|
|
||||||
As a special-case, Ruff also supports the `ALL` code, which enables all rules. Note that some of the
|
|
||||||
pydocstyle rules conflict (e.g., `D203` and `D211`) as they represent alternative docstring
|
|
||||||
formats. Enabling `ALL` without further configuration may result in suboptimal behavior, especially
|
|
||||||
for the pydocstyle plugin.
|
|
||||||
|
|
||||||
If you're wondering how to configure Ruff, here are some **recommended guidelines**:
|
|
||||||
|
|
||||||
* Prefer `select` and `ignore` over `extend-select` and `extend-ignore`, to make your rule set
|
|
||||||
explicit.
|
|
||||||
* Use `ALL` with discretion. Enabling `ALL` will implicitly enable new rules whenever you upgrade.
|
|
||||||
* Start with a small set of rules (`select = ["E", "F"]`) and add a category at-a-time. For example,
|
|
||||||
you might consider expanding to `select = ["E", "F", "B"]` to enable the popular flake8-bugbear
|
|
||||||
extension.
|
|
||||||
* By default, Ruff's autofix is aggressive. If you find that it's too aggressive for your liking,
|
|
||||||
consider turning off autofix for specific rules or categories (see: [FAQ](https://beta.ruff.rs/docs/faq/#ruff-tried-to-fix-something-but-it-broke-my-code-what-should-i-do)).
|
|
||||||
|
|
||||||
### Configure via `ruff.toml`
|
|
||||||
|
|
||||||
As an alternative to `pyproject.toml`, Ruff will also respect a `ruff.toml` file, which implements
|
|
||||||
an equivalent schema (though the `[tool.ruff]` hierarchy can be omitted). For example, the
|
|
||||||
`pyproject.toml` described above would be represented via the following `ruff.toml`:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
# Enable flake8-bugbear (`B`) rules.
|
|
||||||
select = ["E", "F", "B"]
|
|
||||||
|
|
||||||
# Never enforce `E501` (line length violations).
|
|
||||||
ignore = ["E501"]
|
|
||||||
|
|
||||||
# Avoid trying to fix flake8-bugbear (`B`) violations.
|
|
||||||
unfixable = ["B"]
|
|
||||||
|
|
||||||
# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
|
|
||||||
[per-file-ignores]
|
|
||||||
"__init__.py" = ["E402"]
|
|
||||||
"path/to/file.py" = ["E402"]
|
|
||||||
```
|
|
||||||
|
|
||||||
For a full list of configurable options, see the [list of all options](https://beta.ruff.rs/docs/settings/).
|
|
||||||
|
|
||||||
### Command-line interface
|
|
||||||
|
|
||||||
Some configuration settings can be provided via the command-line, such as those related to
|
|
||||||
rule enablement and disablement, file discovery, logging level, and more:
|
rule enablement and disablement, file discovery, logging level, and more:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
ruff check path/to/code/ --select F401 --select F403 --quiet
|
ruff check path/to/code/ --select F401 --select F403 --quiet
|
||||||
```
|
```
|
||||||
|
|
||||||
See `ruff help` for more on Ruff's top-level commands:
|
See `ruff help` for more on Ruff's top-level commands, or `ruff help check` for more on the
|
||||||
|
linting command.
|
||||||
|
|
||||||
<!-- Begin auto-generated command help. -->
|
## Rules
|
||||||
|
|
||||||
```text
|
|
||||||
Ruff: An extremely fast Python linter.
|
|
||||||
|
|
||||||
Usage: ruff [OPTIONS] <COMMAND>
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
check Run Ruff on the given files or directories (default)
|
|
||||||
rule Explain a rule
|
|
||||||
config List or describe the available configuration options
|
|
||||||
linter List all supported upstream linters
|
|
||||||
clean Clear any caches in the current directory and any subdirectories
|
|
||||||
help Print this message or the help of the given subcommand(s)
|
|
||||||
|
|
||||||
Options:
|
|
||||||
-h, --help Print help
|
|
||||||
-V, --version Print version
|
|
||||||
|
|
||||||
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)
|
|
||||||
|
|
||||||
For help with a specific command, see: `ruff help <command>`.
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- End auto-generated command help. -->
|
|
||||||
|
|
||||||
Or `ruff help check` for more on the linting command:
|
|
||||||
|
|
||||||
<!-- Begin auto-generated subcommand help. -->
|
|
||||||
|
|
||||||
```text
|
|
||||||
Run Ruff on the given files or directories (default)
|
|
||||||
|
|
||||||
Usage: ruff check [OPTIONS] [FILES]...
|
|
||||||
|
|
||||||
Arguments:
|
|
||||||
[FILES]... List of files or directories to check
|
|
||||||
|
|
||||||
Options:
|
|
||||||
--fix
|
|
||||||
Attempt to automatically fix lint violations
|
|
||||||
--show-source
|
|
||||||
Show violations with source code
|
|
||||||
--show-fixes
|
|
||||||
Show an enumeration of all autofixed lint violations
|
|
||||||
--diff
|
|
||||||
Avoid writing any fixed files back; instead, output a diff for each changed file to stdout
|
|
||||||
-w, --watch
|
|
||||||
Run in watch mode by re-running whenever files change
|
|
||||||
--fix-only
|
|
||||||
Fix any fixable lint violations, but don't report on leftover violations. Implies `--fix`
|
|
||||||
--format <FORMAT>
|
|
||||||
Output serialization format for violations [env: RUFF_FORMAT=] [possible values: text, json, junit, grouped, github, gitlab, pylint]
|
|
||||||
--target-version <TARGET_VERSION>
|
|
||||||
The minimum Python version that should be supported
|
|
||||||
--config <CONFIG>
|
|
||||||
Path to the `pyproject.toml` or `ruff.toml` file to use for configuration
|
|
||||||
--statistics
|
|
||||||
Show counts for every rule with at least one violation
|
|
||||||
--add-noqa
|
|
||||||
Enable automatic additions of `noqa` directives to failing lines
|
|
||||||
--show-files
|
|
||||||
See the files Ruff will be run against with the current settings
|
|
||||||
--show-settings
|
|
||||||
See the settings Ruff will use to lint a given Python file
|
|
||||||
-h, --help
|
|
||||||
Print help
|
|
||||||
|
|
||||||
Rule selection:
|
|
||||||
--select <RULE_CODE>
|
|
||||||
Comma-separated list of rule codes to enable (or ALL, to enable all rules)
|
|
||||||
--ignore <RULE_CODE>
|
|
||||||
Comma-separated list of rule codes to disable
|
|
||||||
--extend-select <RULE_CODE>
|
|
||||||
Like --select, but adds additional rule codes on top of the selected ones
|
|
||||||
--per-file-ignores <PER_FILE_IGNORES>
|
|
||||||
List of mappings from file pattern to code to exclude
|
|
||||||
--fixable <RULE_CODE>
|
|
||||||
List of rule codes to treat as eligible for autofix. Only applicable when autofix itself is enabled (e.g., via `--fix`)
|
|
||||||
--unfixable <RULE_CODE>
|
|
||||||
List of rule codes to treat as ineligible for autofix. Only applicable when autofix itself is enabled (e.g., via `--fix`)
|
|
||||||
|
|
||||||
File selection:
|
|
||||||
--exclude <FILE_PATTERN> List of paths, used to omit files and/or directories from analysis
|
|
||||||
--extend-exclude <FILE_PATTERN> Like --exclude, but adds additional files and directories on top of those already excluded
|
|
||||||
--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:
|
|
||||||
-n, --no-cache
|
|
||||||
Disable cache reads
|
|
||||||
--isolated
|
|
||||||
Ignore all configuration files
|
|
||||||
--cache-dir <CACHE_DIR>
|
|
||||||
Path to the cache directory [env: RUFF_CACHE_DIR=]
|
|
||||||
--stdin-filename <STDIN_FILENAME>
|
|
||||||
The name of the file when passing it through stdin
|
|
||||||
-e, --exit-zero
|
|
||||||
Exit with status code "0", even upon detecting lint violations
|
|
||||||
--exit-non-zero-on-fix
|
|
||||||
Exit with a non-zero status code if any files were modified via autofix, even if no lint violations remain
|
|
||||||
|
|
||||||
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)
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- End auto-generated subcommand help. -->
|
|
||||||
|
|
||||||
### `pyproject.toml` discovery
|
|
||||||
|
|
||||||
Similar to [ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#cascading-and-hierarchy),
|
|
||||||
Ruff supports hierarchical configuration, such that the "closest" `pyproject.toml` file in the
|
|
||||||
directory hierarchy is used for every individual file, with all paths in the `pyproject.toml` file
|
|
||||||
(e.g., `exclude` globs, `src` paths) being resolved relative to the directory containing the
|
|
||||||
`pyproject.toml` file.
|
|
||||||
|
|
||||||
There are a few exceptions to these rules:
|
|
||||||
|
|
||||||
1. In locating the "closest" `pyproject.toml` file for a given path, Ruff ignores any
|
|
||||||
`pyproject.toml` files that lack a `[tool.ruff]` section.
|
|
||||||
2. If a configuration file is passed directly via `--config`, those settings are used for across
|
|
||||||
files. Any relative paths in that configuration file (like `exclude` globs or `src` paths) are
|
|
||||||
resolved relative to the _current working directory_.
|
|
||||||
3. If no `pyproject.toml` file is found in the filesystem hierarchy, Ruff will fall back to using
|
|
||||||
a default configuration. If a user-specific configuration file exists
|
|
||||||
at `${config_dir}/ruff/pyproject.toml`, that file will be used instead of the default
|
|
||||||
configuration, with `${config_dir}` being determined via the [`dirs`](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html)
|
|
||||||
crate, and all relative paths being again resolved relative to the _current working directory_.
|
|
||||||
4. Any `pyproject.toml`-supported settings that are provided on the command-line (e.g., via
|
|
||||||
`--select`) will override the settings in _every_ resolved configuration file.
|
|
||||||
|
|
||||||
Unlike [ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#cascading-and-hierarchy),
|
|
||||||
Ruff does not merge settings across configuration files; instead, the "closest" configuration file
|
|
||||||
is used, and any parent configuration files are ignored. In lieu of this implicit cascade, Ruff
|
|
||||||
supports an [`extend`](https://beta.ruff.rs/docs/settings#extend) field, which allows you to inherit the settings from another
|
|
||||||
`pyproject.toml` file, like so:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
# Extend the `pyproject.toml` file in the parent directory.
|
|
||||||
extend = "../pyproject.toml"
|
|
||||||
# But use a different line length.
|
|
||||||
line-length = 100
|
|
||||||
```
|
|
||||||
|
|
||||||
All of the above rules apply equivalently to `ruff.toml` files. If Ruff detects both a `ruff.toml`
|
|
||||||
and `pyproject.toml` file, it will defer to the `ruff.toml`.
|
|
||||||
|
|
||||||
### Python file discovery
|
|
||||||
|
|
||||||
When passed a path on the command-line, Ruff will automatically discover all Python files in that
|
|
||||||
path, taking into account the [`exclude`](https://beta.ruff.rs/docs/settings#exclude) and
|
|
||||||
[`extend-exclude`](https://beta.ruff.rs/docs/settings#extend-exclude) settings in each directory's
|
|
||||||
`pyproject.toml` file.
|
|
||||||
|
|
||||||
By default, Ruff will also skip any files that are omitted via `.ignore`, `.gitignore`,
|
|
||||||
`.git/info/exclude`, and global `gitignore` files (see: [`respect-gitignore`](https://beta.ruff.rs/docs/settings#respect-gitignore)).
|
|
||||||
|
|
||||||
Files that are passed to `ruff` directly are always linted, regardless of the above criteria.
|
|
||||||
For example, `ruff check /path/to/excluded/file.py` will always lint `file.py`.
|
|
||||||
|
|
||||||
### Rule resolution
|
|
||||||
|
|
||||||
The set of enabled rules is controlled via the [`select`](https://beta.ruff.rs/docs/settings#select)
|
|
||||||
and [`ignore`](https://beta.ruff.rs/docs/settings#ignore) settings, along with the
|
|
||||||
[`extend-select`](https://beta.ruff.rs/docs/settings#extend-select) and
|
|
||||||
[`extend-ignore`](https://beta.ruff.rs/docs/settings#extend-ignore) modifiers.
|
|
||||||
|
|
||||||
To resolve the enabled rule set, Ruff may need to reconcile `select` and `ignore` from a variety
|
|
||||||
of sources, including the current `pyproject.toml`, any inherited `pyproject.toml` files, and the
|
|
||||||
CLI (e.g., `--select`).
|
|
||||||
|
|
||||||
In those scenarios, Ruff uses the "highest-priority" `select` as the basis for the rule set, and
|
|
||||||
then applies any `extend-select`, `ignore`, and `extend-ignore` adjustments. CLI options are given
|
|
||||||
higher priority than `pyproject.toml` options, and the current `pyproject.toml` file is given higher
|
|
||||||
priority than any inherited `pyproject.toml` files.
|
|
||||||
|
|
||||||
For example, given the following `pyproject.toml` file:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[tool.ruff]
|
|
||||||
select = ["E", "F"]
|
|
||||||
ignore = ["F401"]
|
|
||||||
```
|
|
||||||
|
|
||||||
Running `ruff check --select F401` would result in Ruff enforcing `F401`, and no other rules.
|
|
||||||
|
|
||||||
Running `ruff check --extend-select B` would result in Ruff enforcing the `E`, `F`, and `B` rules, with
|
|
||||||
the exception of `F401`.
|
|
||||||
|
|
||||||
### Suppressing errors
|
|
||||||
|
|
||||||
To omit a lint rule entirely, add it to the "ignore" list via [`ignore`](https://beta.ruff.rs/docs/settings#ignore)
|
|
||||||
or [`extend-ignore`](https://beta.ruff.rs/docs/settings#extend-ignore), either on the command-line
|
|
||||||
or in your `pyproject.toml` file.
|
|
||||||
|
|
||||||
To ignore a violation inline, Ruff uses a `noqa` system similar to [Flake8](https://flake8.pycqa.org/en/3.1.1/user/ignoring-errors.html).
|
|
||||||
To ignore an individual violation, add `# noqa: {code}` to the end of the line, like so:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# Ignore F841.
|
|
||||||
x = 1 # noqa: F841
|
|
||||||
|
|
||||||
# Ignore E741 and F841.
|
|
||||||
i = 1 # noqa: E741, F841
|
|
||||||
|
|
||||||
# Ignore _all_ violations.
|
|
||||||
x = 1 # noqa
|
|
||||||
```
|
|
||||||
|
|
||||||
Note that, for multi-line strings, the `noqa` directive should come at the end of the string, and
|
|
||||||
will apply to the entire string, like so:
|
|
||||||
|
|
||||||
```python
|
|
||||||
"""Lorem ipsum dolor sit amet.
|
|
||||||
|
|
||||||
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.
|
|
||||||
""" # noqa: E501
|
|
||||||
```
|
|
||||||
|
|
||||||
To ignore all violations across an entire file, add `# ruff: noqa` to any line in the file, like so:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# ruff: noqa
|
|
||||||
```
|
|
||||||
|
|
||||||
To ignore a specific rule across an entire file, add `# ruff: noqa: {code}` to any line in the file,
|
|
||||||
like so:
|
|
||||||
|
|
||||||
```python
|
|
||||||
# ruff: noqa: F841
|
|
||||||
```
|
|
||||||
|
|
||||||
Or see the [`per-file-ignores`](https://beta.ruff.rs/docs/settings#per-file-ignores) configuration
|
|
||||||
setting, which enables the same functionality via a `pyproject.toml` file.
|
|
||||||
|
|
||||||
Note that Ruff will also respect Flake8's `# flake8: noqa` directive, and will treat it as
|
|
||||||
equivalent to `# ruff: noqa`.
|
|
||||||
|
|
||||||
#### Automatic error suppression
|
|
||||||
|
|
||||||
Ruff supports several workflows to aid in `noqa` management.
|
|
||||||
|
|
||||||
First, Ruff provides a special rule code, `RUF100`, to enforce that your `noqa` directives are
|
|
||||||
"valid", in that the violations they _say_ they ignore are actually being triggered on that line (and
|
|
||||||
thus suppressed). You can run `ruff check /path/to/file.py --extend-select RUF100` to flag unused `noqa`
|
|
||||||
directives.
|
|
||||||
|
|
||||||
Second, Ruff can _automatically remove_ unused `noqa` directives via its autofix functionality.
|
|
||||||
You can run `ruff check /path/to/file.py --extend-select RUF100 --fix` to automatically remove unused
|
|
||||||
`noqa` directives.
|
|
||||||
|
|
||||||
Third, Ruff can _automatically add_ `noqa` directives to all failing lines. This is useful when
|
|
||||||
migrating a new codebase to Ruff. You can run `ruff check /path/to/file.py --add-noqa` to automatically
|
|
||||||
add `noqa` directives to all failing lines, with the appropriate rule codes.
|
|
||||||
|
|
||||||
#### Action comments
|
|
||||||
|
|
||||||
Ruff respects `isort`'s [action comments](https://pycqa.github.io/isort/docs/configuration/action_comments.html)
|
|
||||||
(`# isort: skip_file`, `# isort: on`, `# isort: off`, `# isort: skip`, and `# isort: split`), which
|
|
||||||
enable selectively enabling and disabling import sorting for blocks of code and other inline
|
|
||||||
configuration.
|
|
||||||
|
|
||||||
See the [`isort` documentation](https://pycqa.github.io/isort/docs/configuration/action_comments.html)
|
|
||||||
for more.
|
|
||||||
|
|
||||||
### Exit codes
|
|
||||||
|
|
||||||
By default, Ruff exits with the following status codes:
|
|
||||||
|
|
||||||
* `0` if no violations were found, or if all present violations were fixed automatically.
|
|
||||||
* `1` if violations were found.
|
|
||||||
* `2` if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an internal error.
|
|
||||||
|
|
||||||
This convention mirrors that of tools like ESLint, Prettier, and RuboCop.
|
|
||||||
|
|
||||||
Ruff supports two command-line flags that alter its exit code behavior:
|
|
||||||
|
|
||||||
* `--exit-zero` will cause Ruff to exit with a status code of `0` even if violations were found.
|
|
||||||
Note that Ruff will still exit with a status code of `2` if it terminates abnormally.
|
|
||||||
* `--exit-non-zero-on-fix` will cause Ruff to exit with a status code of `1` if violations were
|
|
||||||
found, _even if_ all such violations were fixed automatically. Note that the use of
|
|
||||||
`--exit-non-zero-on-fix` can result in a non-zero exit code even if no violations remain after
|
|
||||||
autofixing.
|
|
||||||
|
|
||||||
### Autocompletion
|
|
||||||
|
|
||||||
Ruff supports autocompletion for most shells. A shell-specific completion script can be generated
|
|
||||||
by `ruff generate-shell-completion <SHELL>`, where `<SHELL>` is one of `bash`, `elvish`, `fig`, `fish`,
|
|
||||||
`powershell`, or `zsh`.
|
|
||||||
|
|
||||||
The exact steps required to enable autocompletion will vary by shell. For example instructions,
|
|
||||||
see the [Poetry](https://python-poetry.org/docs/#enable-tab-completion-for-bash-fish-or-zsh) or
|
|
||||||
[ripgrep](https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#complete) documentation.
|
|
||||||
|
|
||||||
As an example: to enable autocompletion for Zsh, run
|
|
||||||
`ruff generate-shell-completion zsh > ~/.zfunc/_ruff`. Then add the following line to your
|
|
||||||
`~/.zshrc` file, if they're not already present:
|
|
||||||
|
|
||||||
```zsh
|
|
||||||
fpath+=~/.zfunc
|
|
||||||
autoload -Uz compinit && compinit
|
|
||||||
```
|
|
||||||
|
|
||||||
<!-- End section: Configuration -->
|
|
||||||
|
|
||||||
## Supported Rules
|
|
||||||
|
|
||||||
<!-- Begin section: Rules -->
|
<!-- Begin section: Rules -->
|
||||||
|
|
||||||
Ruff supports over 400 lint rules, many of which are inspired by popular tools like Flake8, isort,
|
**Ruff supports over 400 lint rules**, many of which are inspired by popular tools like Flake8,
|
||||||
pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in
|
isort, pyupgrade, and others. Regardless of the rule's origin, Ruff re-implements every rule in
|
||||||
Rust as a first-party feature.
|
Rust as a first-party feature.
|
||||||
|
|
||||||
By default, Ruff enables Flake8's `E` and `F` rules. Ruff supports all rules from the `F` category,
|
By default, Ruff enables Flake8's `E` and `F` rules. Ruff supports all rules from the `F` category,
|
||||||
and a [subset](https://beta.ruff.rs/docs/rules/#error-e) of the `E` category, omitting those
|
and a [subset](https://beta.ruff.rs/docs/rules/#error-e) of the `E` category, omitting those
|
||||||
stylistic rules made obsolete by the use of an autoformatter, like [Black](https://github.com/psf/black).
|
stylistic rules made obsolete by the use of an autoformatter, like
|
||||||
|
[Black](https://github.com/psf/black).
|
||||||
|
|
||||||
<!-- End section: Rules -->
|
<!-- End section: Rules -->
|
||||||
|
|
||||||
For a complete enumeration, see the [list of rules](https://beta.ruff.rs/docs/rules/) in the
|
For a complete enumeration of the supported rules, see [_Rules_](https://beta.ruff.rs/docs/rules/).
|
||||||
Ruff documentation.
|
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
|
|
||||||
Contributions are welcome and highly appreciated. To get started, check out the
|
Contributions are welcome and highly appreciated. To get started, check out the
|
||||||
[**contributing guidelines**](https://github.com/charliermarsh/ruff/blob/main/CONTRIBUTING.md). You
|
[**contributing guidelines**](https://beta.ruff.rs/docs/contributing/).
|
||||||
can also join us on [**Discord**](https://discord.gg/c9MhzV8aU5).
|
|
||||||
|
You can also join us on [**Discord**](https://discord.gg/c9MhzV8aU5).
|
||||||
|
|
||||||
## Support
|
## Support
|
||||||
|
|
||||||
|
|
@ -680,8 +243,6 @@ or feel free to [**open a new one**](https://github.com/charliermarsh/ruff/issue
|
||||||
|
|
||||||
You can also ask for help on [**Discord**](https://discord.gg/c9MhzV8aU5).
|
You can also ask for help on [**Discord**](https://discord.gg/c9MhzV8aU5).
|
||||||
|
|
||||||
<!-- Begin section: Acknowledgements -->
|
|
||||||
|
|
||||||
## Acknowledgements
|
## Acknowledgements
|
||||||
|
|
||||||
Ruff's linter draws on both the APIs and implementation details of many other
|
Ruff's linter draws on both the APIs and implementation details of many other
|
||||||
|
|
@ -704,8 +265,6 @@ Ruff is the beneficiary of a large number of [contributors](https://github.com/c
|
||||||
|
|
||||||
Ruff is released under the MIT license.
|
Ruff is released under the MIT license.
|
||||||
|
|
||||||
<!-- End section: Acknowledgements -->
|
|
||||||
|
|
||||||
## Who's Using Ruff?
|
## Who's Using Ruff?
|
||||||
|
|
||||||
Ruff is used in a number of major open-source projects, including:
|
Ruff is used in a number of major open-source projects, including:
|
||||||
|
|
|
||||||
|
|
@ -1,11 +1,14 @@
|
||||||
//! Generate CLI help.
|
//! Generate CLI help.
|
||||||
#![allow(clippy::print_stdout, clippy::print_stderr)]
|
#![allow(clippy::print_stdout, clippy::print_stderr)]
|
||||||
|
|
||||||
use std::str;
|
use std::fs::OpenOptions;
|
||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use std::{fs, str};
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
|
|
||||||
use crate::utils::replace_readme_section;
|
use crate::ROOT_DIR;
|
||||||
|
|
||||||
const COMMAND_HELP_BEGIN_PRAGMA: &str = "<!-- Begin auto-generated command help. -->\n";
|
const COMMAND_HELP_BEGIN_PRAGMA: &str = "<!-- Begin auto-generated command help. -->\n";
|
||||||
const COMMAND_HELP_END_PRAGMA: &str = "<!-- End auto-generated command help. -->";
|
const COMMAND_HELP_END_PRAGMA: &str = "<!-- End auto-generated command help. -->";
|
||||||
|
|
@ -15,7 +18,7 @@ const SUBCOMMAND_HELP_END_PRAGMA: &str = "<!-- End auto-generated subcommand hel
|
||||||
|
|
||||||
#[derive(clap::Args)]
|
#[derive(clap::Args)]
|
||||||
pub struct Args {
|
pub struct Args {
|
||||||
/// Write the generated help to stdout (rather than to `README.md`).
|
/// Write the generated help to stdout (rather than to `docs/configuration.md`).
|
||||||
#[arg(long)]
|
#[arg(long)]
|
||||||
pub(crate) dry_run: bool,
|
pub(crate) dry_run: bool,
|
||||||
}
|
}
|
||||||
|
|
@ -24,6 +27,32 @@ fn trim_lines(s: &str) -> String {
|
||||||
s.lines().map(str::trim_end).collect::<Vec<_>>().join("\n")
|
s.lines().map(str::trim_end).collect::<Vec<_>>().join("\n")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn replace_docs_section(content: &str, begin_pragma: &str, end_pragma: &str) -> Result<()> {
|
||||||
|
// Read the existing file.
|
||||||
|
let file = PathBuf::from(ROOT_DIR).join("docs/configuration.md");
|
||||||
|
let existing = fs::read_to_string(&file)?;
|
||||||
|
|
||||||
|
// Extract the prefix.
|
||||||
|
let index = existing
|
||||||
|
.find(begin_pragma)
|
||||||
|
.expect("Unable to find begin pragma");
|
||||||
|
let prefix = &existing[..index + begin_pragma.len()];
|
||||||
|
|
||||||
|
// Extract the suffix.
|
||||||
|
let index = existing
|
||||||
|
.find(end_pragma)
|
||||||
|
.expect("Unable to find end pragma");
|
||||||
|
let suffix = &existing[index..];
|
||||||
|
|
||||||
|
// Write the prefix, new contents, and suffix.
|
||||||
|
let mut f = OpenOptions::new().write(true).truncate(true).open(&file)?;
|
||||||
|
writeln!(f, "{prefix}")?;
|
||||||
|
write!(f, "{content}")?;
|
||||||
|
write!(f, "{suffix}")?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn main(args: &Args) -> Result<()> {
|
pub fn main(args: &Args) -> Result<()> {
|
||||||
// Generate `ruff help`.
|
// Generate `ruff help`.
|
||||||
let command_help = trim_lines(ruff_cli::command_help().trim());
|
let command_help = trim_lines(ruff_cli::command_help().trim());
|
||||||
|
|
@ -35,12 +64,12 @@ pub fn main(args: &Args) -> Result<()> {
|
||||||
print!("{command_help}");
|
print!("{command_help}");
|
||||||
print!("{subcommand_help}");
|
print!("{subcommand_help}");
|
||||||
} else {
|
} else {
|
||||||
replace_readme_section(
|
replace_docs_section(
|
||||||
&format!("```text\n{command_help}\n```\n\n"),
|
&format!("```text\n{command_help}\n```\n\n"),
|
||||||
COMMAND_HELP_BEGIN_PRAGMA,
|
COMMAND_HELP_BEGIN_PRAGMA,
|
||||||
COMMAND_HELP_END_PRAGMA,
|
COMMAND_HELP_END_PRAGMA,
|
||||||
)?;
|
)?;
|
||||||
replace_readme_section(
|
replace_docs_section(
|
||||||
&format!("```text\n{subcommand_help}\n```\n\n"),
|
&format!("```text\n{subcommand_help}\n```\n\n"),
|
||||||
SUBCOMMAND_HELP_BEGIN_PRAGMA,
|
SUBCOMMAND_HELP_BEGIN_PRAGMA,
|
||||||
SUBCOMMAND_HELP_END_PRAGMA,
|
SUBCOMMAND_HELP_END_PRAGMA,
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,6 @@ mod print_ast;
|
||||||
mod print_cst;
|
mod print_cst;
|
||||||
mod print_tokens;
|
mod print_tokens;
|
||||||
mod round_trip;
|
mod round_trip;
|
||||||
mod utils;
|
|
||||||
|
|
||||||
const ROOT_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../");
|
const ROOT_DIR: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../../");
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,34 +0,0 @@
|
||||||
use std::fs;
|
|
||||||
use std::fs::OpenOptions;
|
|
||||||
use std::io::Write;
|
|
||||||
use std::path::PathBuf;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
use crate::ROOT_DIR;
|
|
||||||
|
|
||||||
pub fn replace_readme_section(content: &str, begin_pragma: &str, end_pragma: &str) -> Result<()> {
|
|
||||||
// Read the existing file.
|
|
||||||
let file = PathBuf::from(ROOT_DIR).join("README.md");
|
|
||||||
let existing = fs::read_to_string(&file)?;
|
|
||||||
|
|
||||||
// Extract the prefix.
|
|
||||||
let index = existing
|
|
||||||
.find(begin_pragma)
|
|
||||||
.expect("Unable to find begin pragma");
|
|
||||||
let prefix = &existing[..index + begin_pragma.len()];
|
|
||||||
|
|
||||||
// Extract the suffix.
|
|
||||||
let index = existing
|
|
||||||
.find(end_pragma)
|
|
||||||
.expect("Unable to find end pragma");
|
|
||||||
let suffix = &existing[index..];
|
|
||||||
|
|
||||||
// Write the prefix, new contents, and suffix.
|
|
||||||
let mut f = OpenOptions::new().write(true).truncate(true).open(&file)?;
|
|
||||||
writeln!(f, "{prefix}")?;
|
|
||||||
write!(f, "{content}")?;
|
|
||||||
write!(f, "{suffix}")?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
@ -3,3 +3,5 @@
|
||||||
!requirements.txt
|
!requirements.txt
|
||||||
!editor-integrations.md
|
!editor-integrations.md
|
||||||
!faq.md
|
!faq.md
|
||||||
|
!configuration.md
|
||||||
|
!installation-and-usage.md
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,456 @@
|
||||||
|
Ruff can be configured via a `pyproject.toml` file, a `ruff.toml` file, or through the command line.
|
||||||
|
|
||||||
|
For a complete enumeration of the available configuration options, see the
|
||||||
|
[documentation](/docs/settings/).
|
||||||
|
|
||||||
|
### Configure via `pyproject.toml`
|
||||||
|
|
||||||
|
If left unspecified, the default configuration is equivalent to:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ruff]
|
||||||
|
# Enable pycodestyle (`E`) and Pyflakes (`F`) codes by default.
|
||||||
|
select = ["E", "F"]
|
||||||
|
ignore = []
|
||||||
|
|
||||||
|
# Allow autofix for all enabled rules (when `--fix`) is provided.
|
||||||
|
fixable = ["A", "B", "C", "D", "E", "F", "..."]
|
||||||
|
unfixable = []
|
||||||
|
|
||||||
|
# Exclude a variety of commonly ignored directories.
|
||||||
|
exclude = [
|
||||||
|
".bzr",
|
||||||
|
".direnv",
|
||||||
|
".eggs",
|
||||||
|
".git",
|
||||||
|
".hg",
|
||||||
|
".mypy_cache",
|
||||||
|
".nox",
|
||||||
|
".pants.d",
|
||||||
|
".pytype",
|
||||||
|
".ruff_cache",
|
||||||
|
".svn",
|
||||||
|
".tox",
|
||||||
|
".venv",
|
||||||
|
"__pypackages__",
|
||||||
|
"_build",
|
||||||
|
"buck-out",
|
||||||
|
"build",
|
||||||
|
"dist",
|
||||||
|
"node_modules",
|
||||||
|
"venv",
|
||||||
|
]
|
||||||
|
per-file-ignores = {}
|
||||||
|
|
||||||
|
# Same as Black.
|
||||||
|
line-length = 88
|
||||||
|
|
||||||
|
# Allow unused variables when underscore-prefixed.
|
||||||
|
dummy-variable-rgx = "^(_+|(_+[a-zA-Z0-9_]*[a-zA-Z0-9]+?))$"
|
||||||
|
|
||||||
|
# Assume Python 3.10.
|
||||||
|
target-version = "py310"
|
||||||
|
|
||||||
|
[tool.ruff.mccabe]
|
||||||
|
# Unlike Flake8, default to a complexity level of 10.
|
||||||
|
max-complexity = 10
|
||||||
|
```
|
||||||
|
|
||||||
|
As an example, the following would configure Ruff to: (1) enforce flake8-bugbear rules, in addition
|
||||||
|
to the defaults; (2) avoid enforcing line-length violations (`E501`); (3) avoid attempting to fix
|
||||||
|
flake8-bugbear (`B`) violations; and (3) ignore import-at-top-of-file violations (`E402`) in
|
||||||
|
`__init__.py` files:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ruff]
|
||||||
|
# Enable flake8-bugbear (`B`) rules.
|
||||||
|
select = ["E", "F", "B"]
|
||||||
|
|
||||||
|
# Never enforce `E501` (line length violations).
|
||||||
|
ignore = ["E501"]
|
||||||
|
|
||||||
|
# Avoid trying to fix flake8-bugbear (`B`) violations.
|
||||||
|
unfixable = ["B"]
|
||||||
|
|
||||||
|
# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
|
||||||
|
[tool.ruff.per-file-ignores]
|
||||||
|
"__init__.py" = ["E402"]
|
||||||
|
"path/to/file.py" = ["E402"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Plugin configurations should be expressed as subsections, e.g.:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ruff]
|
||||||
|
# Add "Q" to the list of enabled codes.
|
||||||
|
select = ["E", "F", "Q"]
|
||||||
|
|
||||||
|
[tool.ruff.flake8-quotes]
|
||||||
|
docstring-quotes = "double"
|
||||||
|
```
|
||||||
|
|
||||||
|
Ruff mirrors Flake8's rule code system, in which each rule code consists of a one-to-three letter
|
||||||
|
prefix, followed by three digits (e.g., `F401`). The prefix indicates that "source" of the rule
|
||||||
|
(e.g., `F` for Pyflakes, `E` for pycodestyle, `ANN` for flake8-annotations). The set of enabled
|
||||||
|
rules is determined by the `select` and `ignore` options, which support both the full code (e.g.,
|
||||||
|
`F401`) and the prefix (e.g., `F`).
|
||||||
|
|
||||||
|
As a special-case, Ruff also supports the `ALL` code, which enables all rules. Note that some of the
|
||||||
|
pydocstyle rules conflict (e.g., `D203` and `D211`) as they represent alternative docstring
|
||||||
|
formats. Enabling `ALL` without further configuration may result in suboptimal behavior, especially
|
||||||
|
for the pydocstyle plugin.
|
||||||
|
|
||||||
|
If you're wondering how to configure Ruff, here are some **recommended guidelines**:
|
||||||
|
|
||||||
|
* Prefer `select` and `ignore` over `extend-select` and `extend-ignore`, to make your rule set
|
||||||
|
explicit.
|
||||||
|
* Use `ALL` with discretion. Enabling `ALL` will implicitly enable new rules whenever you upgrade.
|
||||||
|
* Start with a small set of rules (`select = ["E", "F"]`) and add a category at-a-time. For example,
|
||||||
|
you might consider expanding to `select = ["E", "F", "B"]` to enable the popular flake8-bugbear
|
||||||
|
extension.
|
||||||
|
* By default, Ruff's autofix is aggressive. If you find that it's too aggressive for your liking,
|
||||||
|
consider turning off autofix for specific rules or categories (see: [FAQ](/docs/faq/#ruff-tried-to-fix-something-but-it-broke-my-code-what-should-i-do)).
|
||||||
|
|
||||||
|
### Configure via `ruff.toml`
|
||||||
|
|
||||||
|
As an alternative to `pyproject.toml`, Ruff will also respect a `ruff.toml` file, which implements
|
||||||
|
an equivalent schema (though the `[tool.ruff]` hierarchy can be omitted). For example, the
|
||||||
|
`pyproject.toml` described above would be represented via the following `ruff.toml`:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# Enable flake8-bugbear (`B`) rules.
|
||||||
|
select = ["E", "F", "B"]
|
||||||
|
|
||||||
|
# Never enforce `E501` (line length violations).
|
||||||
|
ignore = ["E501"]
|
||||||
|
|
||||||
|
# Avoid trying to fix flake8-bugbear (`B`) violations.
|
||||||
|
unfixable = ["B"]
|
||||||
|
|
||||||
|
# Ignore `E402` (import violations) in all `__init__.py` files, and in `path/to/file.py`.
|
||||||
|
[per-file-ignores]
|
||||||
|
"__init__.py" = ["E402"]
|
||||||
|
"path/to/file.py" = ["E402"]
|
||||||
|
```
|
||||||
|
|
||||||
|
For a full list of configurable options, see the [list of all options](/docs/settings/).
|
||||||
|
|
||||||
|
### Command-line interface
|
||||||
|
|
||||||
|
Some configuration settings can be provided via the command-line, such as those related to
|
||||||
|
rule enablement and disablement, file discovery, logging level, and more:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ruff check path/to/code/ --select F401 --select F403 --quiet
|
||||||
|
```
|
||||||
|
|
||||||
|
See `ruff help` for more on Ruff's top-level commands:
|
||||||
|
|
||||||
|
<!-- Begin auto-generated command help. -->
|
||||||
|
|
||||||
|
```text
|
||||||
|
Ruff: An extremely fast Python linter.
|
||||||
|
|
||||||
|
Usage: ruff [OPTIONS] <COMMAND>
|
||||||
|
|
||||||
|
Commands:
|
||||||
|
check Run Ruff on the given files or directories (default)
|
||||||
|
rule Explain a rule
|
||||||
|
config List or describe the available configuration options
|
||||||
|
linter List all supported upstream linters
|
||||||
|
clean Clear any caches in the current directory and any subdirectories
|
||||||
|
help Print this message or the help of the given subcommand(s)
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-h, --help Print help
|
||||||
|
-V, --version Print version
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
For help with a specific command, see: `ruff help <command>`.
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- End auto-generated command help. -->
|
||||||
|
|
||||||
|
Or `ruff help check` for more on the linting command:
|
||||||
|
|
||||||
|
<!-- Begin auto-generated subcommand help. -->
|
||||||
|
|
||||||
|
```text
|
||||||
|
Run Ruff on the given files or directories (default)
|
||||||
|
|
||||||
|
Usage: ruff check [OPTIONS] [FILES]...
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
[FILES]... List of files or directories to check
|
||||||
|
|
||||||
|
Options:
|
||||||
|
--fix
|
||||||
|
Attempt to automatically fix lint violations
|
||||||
|
--show-source
|
||||||
|
Show violations with source code
|
||||||
|
--show-fixes
|
||||||
|
Show an enumeration of all autofixed lint violations
|
||||||
|
--diff
|
||||||
|
Avoid writing any fixed files back; instead, output a diff for each changed file to stdout
|
||||||
|
-w, --watch
|
||||||
|
Run in watch mode by re-running whenever files change
|
||||||
|
--fix-only
|
||||||
|
Fix any fixable lint violations, but don't report on leftover violations. Implies `--fix`
|
||||||
|
--format <FORMAT>
|
||||||
|
Output serialization format for violations [env: RUFF_FORMAT=] [possible values: text, json, junit, grouped, github, gitlab, pylint]
|
||||||
|
--target-version <TARGET_VERSION>
|
||||||
|
The minimum Python version that should be supported
|
||||||
|
--config <CONFIG>
|
||||||
|
Path to the `pyproject.toml` or `ruff.toml` file to use for configuration
|
||||||
|
--statistics
|
||||||
|
Show counts for every rule with at least one violation
|
||||||
|
--add-noqa
|
||||||
|
Enable automatic additions of `noqa` directives to failing lines
|
||||||
|
--show-files
|
||||||
|
See the files Ruff will be run against with the current settings
|
||||||
|
--show-settings
|
||||||
|
See the settings Ruff will use to lint a given Python file
|
||||||
|
-h, --help
|
||||||
|
Print help
|
||||||
|
|
||||||
|
Rule selection:
|
||||||
|
--select <RULE_CODE>
|
||||||
|
Comma-separated list of rule codes to enable (or ALL, to enable all rules)
|
||||||
|
--ignore <RULE_CODE>
|
||||||
|
Comma-separated list of rule codes to disable
|
||||||
|
--extend-select <RULE_CODE>
|
||||||
|
Like --select, but adds additional rule codes on top of the selected ones
|
||||||
|
--per-file-ignores <PER_FILE_IGNORES>
|
||||||
|
List of mappings from file pattern to code to exclude
|
||||||
|
--fixable <RULE_CODE>
|
||||||
|
List of rule codes to treat as eligible for autofix. Only applicable when autofix itself is enabled (e.g., via `--fix`)
|
||||||
|
--unfixable <RULE_CODE>
|
||||||
|
List of rule codes to treat as ineligible for autofix. Only applicable when autofix itself is enabled (e.g., via `--fix`)
|
||||||
|
|
||||||
|
File selection:
|
||||||
|
--exclude <FILE_PATTERN> List of paths, used to omit files and/or directories from analysis
|
||||||
|
--extend-exclude <FILE_PATTERN> Like --exclude, but adds additional files and directories on top of those already excluded
|
||||||
|
--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:
|
||||||
|
-n, --no-cache
|
||||||
|
Disable cache reads
|
||||||
|
--isolated
|
||||||
|
Ignore all configuration files
|
||||||
|
--cache-dir <CACHE_DIR>
|
||||||
|
Path to the cache directory [env: RUFF_CACHE_DIR=]
|
||||||
|
--stdin-filename <STDIN_FILENAME>
|
||||||
|
The name of the file when passing it through stdin
|
||||||
|
-e, --exit-zero
|
||||||
|
Exit with status code "0", even upon detecting lint violations
|
||||||
|
--exit-non-zero-on-fix
|
||||||
|
Exit with a non-zero status code if any files were modified via autofix, even if no lint violations remain
|
||||||
|
|
||||||
|
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)
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- End auto-generated subcommand help. -->
|
||||||
|
|
||||||
|
### `pyproject.toml` discovery
|
||||||
|
|
||||||
|
Similar to [ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#cascading-and-hierarchy),
|
||||||
|
Ruff supports hierarchical configuration, such that the "closest" `pyproject.toml` file in the
|
||||||
|
directory hierarchy is used for every individual file, with all paths in the `pyproject.toml` file
|
||||||
|
(e.g., `exclude` globs, `src` paths) being resolved relative to the directory containing the
|
||||||
|
`pyproject.toml` file.
|
||||||
|
|
||||||
|
There are a few exceptions to these rules:
|
||||||
|
|
||||||
|
1. In locating the "closest" `pyproject.toml` file for a given path, Ruff ignores any
|
||||||
|
`pyproject.toml` files that lack a `[tool.ruff]` section.
|
||||||
|
2. If a configuration file is passed directly via `--config`, those settings are used for across
|
||||||
|
files. Any relative paths in that configuration file (like `exclude` globs or `src` paths) are
|
||||||
|
resolved relative to the _current working directory_.
|
||||||
|
3. If no `pyproject.toml` file is found in the filesystem hierarchy, Ruff will fall back to using
|
||||||
|
a default configuration. If a user-specific configuration file exists
|
||||||
|
at `${config_dir}/ruff/pyproject.toml`, that file will be used instead of the default
|
||||||
|
configuration, with `${config_dir}` being determined via the [`dirs`](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html)
|
||||||
|
crate, and all relative paths being again resolved relative to the _current working directory_.
|
||||||
|
4. Any `pyproject.toml`-supported settings that are provided on the command-line (e.g., via
|
||||||
|
`--select`) will override the settings in _every_ resolved configuration file.
|
||||||
|
|
||||||
|
Unlike [ESLint](https://eslint.org/docs/latest/user-guide/configuring/configuration-files#cascading-and-hierarchy),
|
||||||
|
Ruff does not merge settings across configuration files; instead, the "closest" configuration file
|
||||||
|
is used, and any parent configuration files are ignored. In lieu of this implicit cascade, Ruff
|
||||||
|
supports an [`extend`](/docs/settings#extend) field, which allows you to inherit the settings from another
|
||||||
|
`pyproject.toml` file, like so:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
# Extend the `pyproject.toml` file in the parent directory.
|
||||||
|
extend = "../pyproject.toml"
|
||||||
|
# But use a different line length.
|
||||||
|
line-length = 100
|
||||||
|
```
|
||||||
|
|
||||||
|
All of the above rules apply equivalently to `ruff.toml` files. If Ruff detects both a `ruff.toml`
|
||||||
|
and `pyproject.toml` file, it will defer to the `ruff.toml`.
|
||||||
|
|
||||||
|
### Python file discovery
|
||||||
|
|
||||||
|
When passed a path on the command-line, Ruff will automatically discover all Python files in that
|
||||||
|
path, taking into account the [`exclude`](/docs/settings#exclude) and
|
||||||
|
[`extend-exclude`](/docs/settings#extend-exclude) settings in each directory's
|
||||||
|
`pyproject.toml` file.
|
||||||
|
|
||||||
|
By default, Ruff will also skip any files that are omitted via `.ignore`, `.gitignore`,
|
||||||
|
`.git/info/exclude`, and global `gitignore` files (see: [`respect-gitignore`](/docs/settings#respect-gitignore)).
|
||||||
|
|
||||||
|
Files that are passed to `ruff` directly are always linted, regardless of the above criteria.
|
||||||
|
For example, `ruff check /path/to/excluded/file.py` will always lint `file.py`.
|
||||||
|
|
||||||
|
### Rule resolution
|
||||||
|
|
||||||
|
The set of enabled rules is controlled via the [`select`](/docs/settings#select)
|
||||||
|
and [`ignore`](/docs/settings#ignore) settings, along with the
|
||||||
|
[`extend-select`](/docs/settings#extend-select) and
|
||||||
|
[`extend-ignore`](/docs/settings#extend-ignore) modifiers.
|
||||||
|
|
||||||
|
To resolve the enabled rule set, Ruff may need to reconcile `select` and `ignore` from a variety
|
||||||
|
of sources, including the current `pyproject.toml`, any inherited `pyproject.toml` files, and the
|
||||||
|
CLI (e.g., `--select`).
|
||||||
|
|
||||||
|
In those scenarios, Ruff uses the "highest-priority" `select` as the basis for the rule set, and
|
||||||
|
then applies any `extend-select`, `ignore`, and `extend-ignore` adjustments. CLI options are given
|
||||||
|
higher priority than `pyproject.toml` options, and the current `pyproject.toml` file is given higher
|
||||||
|
priority than any inherited `pyproject.toml` files.
|
||||||
|
|
||||||
|
For example, given the following `pyproject.toml` file:
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[tool.ruff]
|
||||||
|
select = ["E", "F"]
|
||||||
|
ignore = ["F401"]
|
||||||
|
```
|
||||||
|
|
||||||
|
Running `ruff check --select F401` would result in Ruff enforcing `F401`, and no other rules.
|
||||||
|
|
||||||
|
Running `ruff check --extend-select B` would result in Ruff enforcing the `E`, `F`, and `B` rules, with
|
||||||
|
the exception of `F401`.
|
||||||
|
|
||||||
|
### Suppressing errors
|
||||||
|
|
||||||
|
To omit a lint rule entirely, add it to the "ignore" list via [`ignore`](/docs/settings#ignore)
|
||||||
|
or [`extend-ignore`](/docs/settings#extend-ignore), either on the command-line
|
||||||
|
or in your `pyproject.toml` file.
|
||||||
|
|
||||||
|
To ignore a violation inline, Ruff uses a `noqa` system similar to [Flake8](https://flake8.pycqa.org/en/3.1.1/user/ignoring-errors.html).
|
||||||
|
To ignore an individual violation, add `# noqa: {code}` to the end of the line, like so:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Ignore F841.
|
||||||
|
x = 1 # noqa: F841
|
||||||
|
|
||||||
|
# Ignore E741 and F841.
|
||||||
|
i = 1 # noqa: E741, F841
|
||||||
|
|
||||||
|
# Ignore _all_ violations.
|
||||||
|
x = 1 # noqa
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that, for multi-line strings, the `noqa` directive should come at the end of the string, and
|
||||||
|
will apply to the entire string, like so:
|
||||||
|
|
||||||
|
```python
|
||||||
|
"""Lorem ipsum dolor sit amet.
|
||||||
|
|
||||||
|
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.
|
||||||
|
""" # noqa: E501
|
||||||
|
```
|
||||||
|
|
||||||
|
To ignore all violations across an entire file, add `# ruff: noqa` to any line in the file, like so:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# ruff: noqa
|
||||||
|
```
|
||||||
|
|
||||||
|
To ignore a specific rule across an entire file, add `# ruff: noqa: {code}` to any line in the file,
|
||||||
|
like so:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# ruff: noqa: F841
|
||||||
|
```
|
||||||
|
|
||||||
|
Or see the [`per-file-ignores`](/docs/settings#per-file-ignores) configuration
|
||||||
|
setting, which enables the same functionality via a `pyproject.toml` file.
|
||||||
|
|
||||||
|
Note that Ruff will also respect Flake8's `# flake8: noqa` directive, and will treat it as
|
||||||
|
equivalent to `# ruff: noqa`.
|
||||||
|
|
||||||
|
#### Automatic error suppression
|
||||||
|
|
||||||
|
Ruff supports several workflows to aid in `noqa` management.
|
||||||
|
|
||||||
|
First, Ruff provides a special rule code, `RUF100`, to enforce that your `noqa` directives are
|
||||||
|
"valid", in that the violations they _say_ they ignore are actually being triggered on that line (and
|
||||||
|
thus suppressed). You can run `ruff check /path/to/file.py --extend-select RUF100` to flag unused `noqa`
|
||||||
|
directives.
|
||||||
|
|
||||||
|
Second, Ruff can _automatically remove_ unused `noqa` directives via its autofix functionality.
|
||||||
|
You can run `ruff check /path/to/file.py --extend-select RUF100 --fix` to automatically remove unused
|
||||||
|
`noqa` directives.
|
||||||
|
|
||||||
|
Third, Ruff can _automatically add_ `noqa` directives to all failing lines. This is useful when
|
||||||
|
migrating a new codebase to Ruff. You can run `ruff check /path/to/file.py --add-noqa` to automatically
|
||||||
|
add `noqa` directives to all failing lines, with the appropriate rule codes.
|
||||||
|
|
||||||
|
#### Action comments
|
||||||
|
|
||||||
|
Ruff respects `isort`'s [action comments](https://pycqa.github.io/isort/docs/configuration/action_comments.html)
|
||||||
|
(`# isort: skip_file`, `# isort: on`, `# isort: off`, `# isort: skip`, and `# isort: split`), which
|
||||||
|
enable selectively enabling and disabling import sorting for blocks of code and other inline
|
||||||
|
configuration.
|
||||||
|
|
||||||
|
See the [`isort` documentation](https://pycqa.github.io/isort/docs/configuration/action_comments.html)
|
||||||
|
for more.
|
||||||
|
|
||||||
|
### Exit codes
|
||||||
|
|
||||||
|
By default, Ruff exits with the following status codes:
|
||||||
|
|
||||||
|
* `0` if no violations were found, or if all present violations were fixed automatically.
|
||||||
|
* `1` if violations were found.
|
||||||
|
* `2` if Ruff terminates abnormally due to invalid configuration, invalid CLI options, or an internal error.
|
||||||
|
|
||||||
|
This convention mirrors that of tools like ESLint, Prettier, and RuboCop.
|
||||||
|
|
||||||
|
Ruff supports two command-line flags that alter its exit code behavior:
|
||||||
|
|
||||||
|
* `--exit-zero` will cause Ruff to exit with a status code of `0` even if violations were found.
|
||||||
|
Note that Ruff will still exit with a status code of `2` if it terminates abnormally.
|
||||||
|
* `--exit-non-zero-on-fix` will cause Ruff to exit with a status code of `1` if violations were
|
||||||
|
found, _even if_ all such violations were fixed automatically. Note that the use of
|
||||||
|
`--exit-non-zero-on-fix` can result in a non-zero exit code even if no violations remain after
|
||||||
|
autofixing.
|
||||||
|
|
||||||
|
### Autocompletion
|
||||||
|
|
||||||
|
Ruff supports autocompletion for most shells. A shell-specific completion script can be generated
|
||||||
|
by `ruff generate-shell-completion <SHELL>`, where `<SHELL>` is one of `bash`, `elvish`, `fig`, `fish`,
|
||||||
|
`powershell`, or `zsh`.
|
||||||
|
|
||||||
|
The exact steps required to enable autocompletion will vary by shell. For example instructions,
|
||||||
|
see the [Poetry](https://python-poetry.org/docs/#enable-tab-completion-for-bash-fish-or-zsh) or
|
||||||
|
[ripgrep](https://github.com/BurntSushi/ripgrep/blob/master/FAQ.md#complete) documentation.
|
||||||
|
|
||||||
|
As an example: to enable autocompletion for Zsh, run
|
||||||
|
`ruff generate-shell-completion zsh > ~/.zfunc/_ruff`. Then add the following line to your
|
||||||
|
`~/.zshrc` file, if they're not already present:
|
||||||
|
|
||||||
|
```zsh
|
||||||
|
fpath+=~/.zfunc
|
||||||
|
autoload -Uz compinit && compinit
|
||||||
|
```
|
||||||
|
|
||||||
18
docs/faq.md
18
docs/faq.md
|
|
@ -21,7 +21,7 @@ implements all of the `F` rules (which originate from Pyflakes), along with a su
|
||||||
Ruff also re-implements some of the most popular Flake8 plugins and related code quality tools
|
Ruff also re-implements some of the most popular Flake8 plugins and related code quality tools
|
||||||
natively, including:
|
natively, including:
|
||||||
|
|
||||||
* [autoflake](https://pypi.org/project/autoflake/) ([#1647](https://github.com/charliermarsh/ruff/issues/1647))
|
* [autoflake](https://pypi.org/project/autoflake/)
|
||||||
* [eradicate](https://pypi.org/project/eradicate/)
|
* [eradicate](https://pypi.org/project/eradicate/)
|
||||||
* [flake8-2020](https://pypi.org/project/flake8-2020/)
|
* [flake8-2020](https://pypi.org/project/flake8-2020/)
|
||||||
* [flake8-annotations](https://pypi.org/project/flake8-annotations/)
|
* [flake8-annotations](https://pypi.org/project/flake8-annotations/)
|
||||||
|
|
@ -51,7 +51,7 @@ natively, including:
|
||||||
* [flake8-raise](https://pypi.org/project/flake8-raise/)
|
* [flake8-raise](https://pypi.org/project/flake8-raise/)
|
||||||
* [flake8-return](https://pypi.org/project/flake8-return/)
|
* [flake8-return](https://pypi.org/project/flake8-return/)
|
||||||
* [flake8-self](https://pypi.org/project/flake8-self/)
|
* [flake8-self](https://pypi.org/project/flake8-self/)
|
||||||
* [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
|
* [flake8-simplify](https://pypi.org/project/flake8-simplify/)
|
||||||
* [flake8-super](https://pypi.org/project/flake8-super/)
|
* [flake8-super](https://pypi.org/project/flake8-super/)
|
||||||
* [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
|
* [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
|
||||||
* [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
|
* [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
|
||||||
|
|
@ -62,7 +62,7 @@ natively, including:
|
||||||
* [pep8-naming](https://pypi.org/project/pep8-naming/)
|
* [pep8-naming](https://pypi.org/project/pep8-naming/)
|
||||||
* [pydocstyle](https://pypi.org/project/pydocstyle/)
|
* [pydocstyle](https://pypi.org/project/pydocstyle/)
|
||||||
* [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) ([#980](https://github.com/charliermarsh/ruff/issues/980))
|
* [pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) ([#980](https://github.com/charliermarsh/ruff/issues/980))
|
||||||
* [pyupgrade](https://pypi.org/project/pyupgrade/) ([#827](https://github.com/charliermarsh/ruff/issues/827))
|
* [pyupgrade](https://pypi.org/project/pyupgrade/)
|
||||||
* [yesqa](https://github.com/asottile/yesqa)
|
* [yesqa](https://github.com/asottile/yesqa)
|
||||||
|
|
||||||
Note that, in some cases, Ruff uses different rule codes and prefixes than would be found in the
|
Note that, in some cases, Ruff uses different rule codes and prefixes than would be found in the
|
||||||
|
|
@ -149,7 +149,7 @@ Today, Ruff can be used to replace Flake8 when used with any of the following pl
|
||||||
* [flake8-raise](https://pypi.org/project/flake8-raise/)
|
* [flake8-raise](https://pypi.org/project/flake8-raise/)
|
||||||
* [flake8-return](https://pypi.org/project/flake8-return/)
|
* [flake8-return](https://pypi.org/project/flake8-return/)
|
||||||
* [flake8-self](https://pypi.org/project/flake8-self/)
|
* [flake8-self](https://pypi.org/project/flake8-self/)
|
||||||
* [flake8-simplify](https://pypi.org/project/flake8-simplify/) ([#998](https://github.com/charliermarsh/ruff/issues/998))
|
* [flake8-simplify](https://pypi.org/project/flake8-simplify/)
|
||||||
* [flake8-super](https://pypi.org/project/flake8-super/)
|
* [flake8-super](https://pypi.org/project/flake8-super/)
|
||||||
* [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
|
* [flake8-tidy-imports](https://pypi.org/project/flake8-tidy-imports/)
|
||||||
* [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
|
* [flake8-type-checking](https://pypi.org/project/flake8-type-checking/)
|
||||||
|
|
@ -160,11 +160,11 @@ Today, Ruff can be used to replace Flake8 when used with any of the following pl
|
||||||
* [pydocstyle](https://pypi.org/project/pydocstyle/)
|
* [pydocstyle](https://pypi.org/project/pydocstyle/)
|
||||||
|
|
||||||
Ruff can also replace [isort](https://pypi.org/project/isort/),
|
Ruff can also replace [isort](https://pypi.org/project/isort/),
|
||||||
[yesqa](https://github.com/asottile/yesqa), [eradicate](https://pypi.org/project/eradicate/),
|
[yesqa](https://github.com/asottile/yesqa), [eradicate](https://pypi.org/project/eradicate/), and
|
||||||
[pygrep-hooks](https://github.com/pre-commit/pygrep-hooks) ([#980](https://github.com/charliermarsh/ruff/issues/980)), and a subset of the rules
|
most of the rules implemented in [pyupgrade](https://pypi.org/project/pyupgrade/).
|
||||||
implemented in [pyupgrade](https://pypi.org/project/pyupgrade/) ([#827](https://github.com/charliermarsh/ruff/issues/827)).
|
|
||||||
|
|
||||||
If you're looking to use Ruff, but rely on an unsupported Flake8 plugin, feel free to file an Issue.
|
If you're looking to use Ruff, but rely on an unsupported Flake8 plugin, feel free to file an
|
||||||
|
[issue](https://github.com/charliermarsh/ruff/issues/new).
|
||||||
|
|
||||||
## What versions of Python does Ruff support?
|
## What versions of Python does Ruff support?
|
||||||
|
|
||||||
|
|
@ -309,7 +309,7 @@ On Windows, Ruff expects that file to be located at `C:\Users\Alice\AppData\Roam
|
||||||
|
|
||||||
For more, see the [`dirs`](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html) crate.
|
For more, see the [`dirs`](https://docs.rs/dirs/4.0.0/dirs/fn.config_dir.html) crate.
|
||||||
|
|
||||||
## Ruff tried to fix something, but it broke my code. What should I do?
|
## Ruff tried to fix something — but it broke my code?
|
||||||
|
|
||||||
Ruff's autofix is a best-effort mechanism. Given the dynamic nature of Python, it's difficult to
|
Ruff's autofix is a best-effort mechanism. Given the dynamic nature of Python, it's difficult to
|
||||||
have _complete_ certainty when making changes to code, even for the seemingly trivial fixes.
|
have _complete_ certainty when making changes to code, even for the seemingly trivial fixes.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,73 @@
|
||||||
|
### Installation
|
||||||
|
|
||||||
|
Ruff is available as [`ruff`](https://pypi.org/project/ruff/) on PyPI:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pip install ruff
|
||||||
|
```
|
||||||
|
|
||||||
|
For **macOS Homebrew** and **Linuxbrew** users, Ruff is also available as [`ruff`](https://formulae.brew.sh/formula/ruff) on Homebrew:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
brew install ruff
|
||||||
|
```
|
||||||
|
|
||||||
|
For **Conda** users, Ruff is also available as [`ruff`](https://anaconda.org/conda-forge/ruff) on `conda-forge`:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
conda install -c conda-forge ruff
|
||||||
|
```
|
||||||
|
|
||||||
|
For **Arch Linux** users, Ruff is also available as [`ruff`](https://archlinux.org/packages/community/x86_64/ruff/) on the official repositories:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
pacman -S ruff
|
||||||
|
```
|
||||||
|
|
||||||
|
For **Alpine** users, Ruff is also available as [`ruff`](https://pkgs.alpinelinux.org/package/edge/testing/x86_64/ruff) on the testing repositories:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
apk add ruff
|
||||||
|
```
|
||||||
|
|
||||||
|
[](https://repology.org/project/ruff-python-linter/versions)
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
To run Ruff, try any of the following:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ruff check . # Lint all files in the current directory (and any subdirectories)
|
||||||
|
ruff check path/to/code/ # Lint all files in `/path/to/code` (and any subdirectories)
|
||||||
|
ruff check path/to/code/*.py # Lint all `.py` files in `/path/to/code`
|
||||||
|
ruff check path/to/code/to/file.py # Lint `file.py`
|
||||||
|
```
|
||||||
|
|
||||||
|
You can run Ruff in `--watch` mode to automatically re-run on-change:
|
||||||
|
|
||||||
|
```shell
|
||||||
|
ruff check path/to/code/ --watch
|
||||||
|
```
|
||||||
|
|
||||||
|
Ruff also works with [pre-commit](https://pre-commit.com):
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||||
|
# Ruff version.
|
||||||
|
rev: 'v0.0.252'
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
```
|
||||||
|
|
||||||
|
Or, to enable autofix:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||||
|
# Ruff version.
|
||||||
|
rev: 'v0.0.252'
|
||||||
|
hooks:
|
||||||
|
- id: ruff
|
||||||
|
args: [--fix, --exit-non-zero-on-fix]
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that Ruff's pre-commit hook should run before Black, isort, and other formatting tools.
|
||||||
|
|
@ -11,7 +11,6 @@ theme:
|
||||||
- toc.follow
|
- toc.follow
|
||||||
- navigation.path
|
- navigation.path
|
||||||
- navigation.top
|
- navigation.top
|
||||||
- navigation.footer
|
|
||||||
- content.code.copy
|
- content.code.copy
|
||||||
palette:
|
palette:
|
||||||
- media: "(prefers-color-scheme: light)"
|
- media: "(prefers-color-scheme: light)"
|
||||||
|
|
|
||||||
|
|
@ -3,16 +3,28 @@ import argparse
|
||||||
import shutil
|
import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import NamedTuple
|
||||||
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
SECTIONS: list[tuple[str, str]] = [
|
|
||||||
("Overview", "index.md"),
|
class Section(NamedTuple):
|
||||||
("Installation and Usage", "installation-and-usage.md"),
|
"""A section to include in the MkDocs documentation."""
|
||||||
("Configuration", "configuration.md"),
|
|
||||||
("Rules", "rules.md"),
|
title: str
|
||||||
("Settings", "settings.md"),
|
filename: str
|
||||||
("Acknowledgements", "acknowledgements.md"),
|
generated: bool
|
||||||
|
|
||||||
|
|
||||||
|
SECTIONS: list[Section] = [
|
||||||
|
Section("Overview", "index.md", generated=True),
|
||||||
|
Section("Installation and Usage", "installation-and-usage.md", generated=False),
|
||||||
|
Section("Configuration", "configuration.md", generated=False),
|
||||||
|
Section("Rules", "rules.md", generated=True),
|
||||||
|
Section("Settings", "settings.md", generated=True),
|
||||||
|
Section("Editor Integrations", "editor-integrations.md", generated=False),
|
||||||
|
Section("FAQ", "faq.md", generated=False),
|
||||||
|
Section("Contributing", "contributing.md", generated=True),
|
||||||
]
|
]
|
||||||
|
|
||||||
DOCUMENTATION_LINK: str = (
|
DOCUMENTATION_LINK: str = (
|
||||||
|
|
@ -39,16 +51,29 @@ def main() -> None:
|
||||||
raise ValueError(msg)
|
raise ValueError(msg)
|
||||||
content = content.replace(DOCUMENTATION_LINK, "")
|
content = content.replace(DOCUMENTATION_LINK, "")
|
||||||
|
|
||||||
# Make the documentation links in the README more relative.
|
# Convert any inter-documentation links to relative links.
|
||||||
content = content.replace("https://beta.ruff.rs", "")
|
content = content.replace("https://beta.ruff.rs", "")
|
||||||
|
|
||||||
Path("docs").mkdir(parents=True, exist_ok=True)
|
Path("docs").mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
# Split the README.md into sections.
|
# Split the README.md into sections.
|
||||||
for title, filename in SECTIONS:
|
for title, filename, generated in SECTIONS:
|
||||||
|
if not generated:
|
||||||
|
continue
|
||||||
|
|
||||||
with Path(f"docs/{filename}").open("w+") as f:
|
with Path(f"docs/{filename}").open("w+") as f:
|
||||||
|
if filename == "contributing.md":
|
||||||
|
# Copy the CONTRIBUTING.md.
|
||||||
|
shutil.copy("CONTRIBUTING.md", "docs/contributing.md")
|
||||||
|
continue
|
||||||
|
|
||||||
if filename == "settings.md":
|
if filename == "settings.md":
|
||||||
f.write(subprocess.check_output(["cargo", "dev", "generate-options"], encoding="utf-8"))
|
f.write(
|
||||||
|
subprocess.check_output(
|
||||||
|
["cargo", "dev", "generate-options"],
|
||||||
|
encoding="utf-8",
|
||||||
|
),
|
||||||
|
)
|
||||||
continue
|
continue
|
||||||
|
|
||||||
block = content.split(f"<!-- Begin section: {title} -->")
|
block = content.split(f"<!-- Begin section: {title} -->")
|
||||||
|
|
@ -64,24 +89,17 @@ def main() -> None:
|
||||||
f.write(block[0])
|
f.write(block[0])
|
||||||
|
|
||||||
if filename == "rules.md":
|
if filename == "rules.md":
|
||||||
f.write(subprocess.check_output(["cargo", "dev", "generate-rules-table"], encoding="utf-8"))
|
f.write(
|
||||||
|
subprocess.check_output(
|
||||||
# Copy the CONTRIBUTING.md.
|
["cargo", "dev", "generate-rules-table"],
|
||||||
shutil.copy("CONTRIBUTING.md", "docs/contributing.md")
|
encoding="utf-8",
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
# Add the nav section to mkdocs.yml.
|
# Add the nav section to mkdocs.yml.
|
||||||
with Path("mkdocs.template.yml").open(encoding="utf8") as fp:
|
with Path("mkdocs.template.yml").open(encoding="utf8") as fp:
|
||||||
config = yaml.safe_load(fp)
|
config = yaml.safe_load(fp)
|
||||||
config["nav"] = [
|
config["nav"] = [{section.title: section.filename} for section in SECTIONS]
|
||||||
{"Overview": "index.md"},
|
|
||||||
{"Installation and Usage": "installation-and-usage.md"},
|
|
||||||
{"Configuration": "configuration.md"},
|
|
||||||
{"Rules": "rules.md"},
|
|
||||||
{"Settings": "settings.md"},
|
|
||||||
{"Editor Integrations": "editor-integrations.md"},
|
|
||||||
{"FAQ": "faq.md"},
|
|
||||||
{"Contributing": "contributing.md"},
|
|
||||||
]
|
|
||||||
config["extra"] = {"analytics": {"provider": "fathom"}}
|
config["extra"] = {"analytics": {"provider": "fathom"}}
|
||||||
|
|
||||||
Path(".overrides/partials/integrations/analytics").mkdir(
|
Path(".overrides/partials/integrations/analytics").mkdir(
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue