| # The Ruff Linter | |
| The Ruff Linter is an extremely fast Python linter designed as a drop-in replacement for [Flake8](https://pypi.org/project/flake8/) | |
| (plus dozens of plugins), [isort](https://pypi.org/project/isort/), [pydocstyle](https://pypi.org/project/pydocstyle/), | |
| [pyupgrade](https://pypi.org/project/pyupgrade/), [autoflake](https://pypi.org/project/autoflake/), | |
| and more. | |
| ## `ruff check` | |
| `ruff check` is the primary entrypoint to the Ruff linter. It accepts a list of files or | |
| directories, and lints all discovered Python files, optionally fixing any fixable errors. | |
| When linting a directory, Ruff searches for Python files recursively in that directory | |
| and all its subdirectories: | |
| ```console | |
| $ ruff check # Lint files in the current directory. | |
| $ ruff check --fix # Lint files in the current directory and fix any fixable errors. | |
| $ ruff check --watch # Lint files in the current directory and re-lint on change. | |
| $ ruff check path/to/code/ # Lint files in `path/to/code`. | |
| ``` | |
| For the full list of supported options, run `ruff check --help`. | |
| ## Rule selection | |
| The set of enabled rules is controlled via the [`lint.select`](settings.md#lint_select), | |
| [`lint.extend-select`](settings.md#lint_extend-select), and [`lint.ignore`](settings.md#lint_ignore) settings. | |
| Ruff's linter uses Flake8-style rule codes: an alphabetic prefix followed by digits (e.g., `F401`). | |
| The prefix indicates the source of the rule | |
| (e.g., `F` for Pyflakes, `E` for pycodestyle, `ANN` for flake8-annotations). | |
| Rule selectors like [`lint.select`](settings.md#lint_select) and [`lint.ignore`](settings.md#lint_ignore) accept either | |
| a full rule code (e.g., `F401`) or any valid prefix (e.g., `F`). For example, given the following | |
| configuration file: | |
| === "pyproject.toml" | |
| ```toml | |
| [tool.ruff.lint] | |
| select = ["E", "F"] | |
| ignore = ["F401"] | |
| ``` | |
| === "ruff.toml" | |
| ```toml | |
| [lint] | |
| select = ["E", "F"] | |
| ignore = ["F401"] | |
| ``` | |
| Ruff would enable all rules with the `E` (pycodestyle) or `F` (Pyflakes) prefix, with the exception | |
| of `F401`. For more on configuring Ruff via `pyproject.toml`, see [_Configuring Ruff_](configuration.md). | |
| As a special-case, Ruff also supports the `ALL` code, which enables all rules. Note that some | |
| pydocstyle rules conflict (e.g., `D203` and `D211`) as they represent alternative docstring | |
| formats. Ruff will automatically disable any conflicting rules when `ALL` is enabled. | |
| If you're wondering how to configure Ruff, here are some **recommended guidelines**: | |
| - Prefer [`lint.select`](settings.md#lint_select) over [`lint.extend-select`](settings.md#lint_extend-select) 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 group at-a-time. For example, | |
| you might consider expanding to `select = ["E", "F", "B"]` to enable the popular flake8-bugbear | |
| extension. | |
| For example, a configuration that enables some of the most popular rules (without being too | |
| pedantic) might look like the following: | |
| === "pyproject.toml" | |
| ```toml | |
| [tool.ruff.lint] | |
| select = [ | |
| # pycodestyle | |
| "E", | |
| # Pyflakes | |
| "F", | |
| # pyupgrade | |
| "UP", | |
| # flake8-bugbear | |
| "B", | |
| # flake8-simplify | |
| "SIM", | |
| # isort | |
| "I", | |
| ] | |
| ``` | |
| === "ruff.toml" | |
| ```toml | |
| [lint] | |
| select = [ | |
| # pycodestyle | |
| "E", | |
| # Pyflakes | |
| "F", | |
| # pyupgrade | |
| "UP", | |
| # flake8-bugbear | |
| "B", | |
| # flake8-simplify | |
| "SIM", | |
| # isort | |
| "I", | |
| ] | |
| ``` | |
| To resolve the enabled rule set, Ruff may need to reconcile [`lint.select`](settings.md#lint_select) and | |
| [`lint.ignore`](settings.md#lint_ignore) from a variety of sources, including the current `pyproject.toml`, | |
| any inherited `pyproject.toml` files, and the CLI (e.g., [`--select`](settings.md#lint_select)). | |
| In those scenarios, Ruff uses the "highest-priority" [`select`](settings.md#lint_select) as the basis for | |
| the rule set, and then applies [`extend-select`](settings.md#lint_extend-select) and | |
| [`ignore`](settings.md#lint_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 configuration file: | |
| === "pyproject.toml" | |
| ```toml | |
| [tool.ruff.lint] | |
| select = ["E", "F"] | |
| ignore = ["F401"] | |
| ``` | |
| === "ruff.toml" | |
| ```toml | |
| [lint] | |
| 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`. | |
| When [preview mode](preview.md) is enabled, rule selectors also accept the human-readable name of a | |
| rule (e.g., `unused-import`). | |
| ## Rule categories | |
| In [preview](preview.md), Ruff supports rule categories in addition to the Flake8-style linter | |
| groups described above. These categories organize rules by the types of issues they detect and | |
| determine whether rules are enabled by default. These categories and their descriptions, in | |
| order of decreasing severity, are: | |
| - **Correctness**: These rules flag code that is outright wrong as written. If you encounter a | |
| correctness issue, you should try to fix it rather than suppressing the error with `noqa` or | |
| `ruff: ignore`. | |
| - **Suspicious**: These rules are similar to `correctness` lints in that the code is likely wrong, | |
| but `suspicious` lints acknowledge that there are valid reasons for the code to be written in this | |
| way. You will still typically want to fix these issues, but using a suppression comment may | |
| occasionally be necessary. Deprecations generally also fit into this category. | |
| - **Complexity**: These rules detect code that can be written in a simpler or more readable way | |
| without changing its semantics. | |
| - **Performance**: These rules detect code that can be written in a more efficient way, without changing its semantics or significantly degrading readability. | |
| - **Style**: These rules flag code that could be written more idiomatically and where the relevant | |
| idiom has broad community acceptance. | |
| - **Security**: These rules flag issues that could lead to security vulnerabilities, and as such, | |
| bias heavily toward false positives to avoid false negatives. | |
| - **Formatting**: These rules flag formatting issues and are generally redundant with a code | |
| formatter. | |
| - **Pedantic**: These rules are generally stylistic, like those in the `style` or similar | |
| categories, but enforce styles that are too opinionated or are too prone to false positives to fit | |
| into another category. | |
| - **Restriction**: These rules restrict the usage of certain features in arbitrary ways. | |
| The first five categories compose the default rule set: | |
| === "pyproject.toml" | |
| ```toml | |
| [tool.ruff.lint] | |
| preview = true | |
| select = [ | |
| "correctness", | |
| "suspicious", | |
| "complexity", | |
| "performance", | |
| "style", | |
| ] | |
| ``` | |
| === "ruff.toml" | |
| ```toml | |
| [lint] | |
| preview = true | |
| select = [ | |
| "correctness", | |
| "suspicious", | |
| "complexity", | |
| "performance", | |
| "style", | |
| ] | |
| ``` | |
| while the remaining four (`security`, `formatting`, `pedantic`, and `restriction`) are off by | |
| default. For certain projects, you may want to enable `security` as an entire category, but | |
| `formatting`, `pedantic`, and `restriction` contain a wider variety of opinionated lints, and you | |
| will typically only want to select individual rules from these categories directly. | |
| See [Trying out categories](#trying-out-categories) for more detailed steps on getting started. | |
| ### Interaction with other selectors | |
| Categories can be freely mixed with linter groups, linter prefixes, rule codes, and rule names. In | |
| addition to the priority relationships described above for settings like `lint.select`, | |
| `lint.extend-select`, and `lint.ignore`, and those for various configuration sources like | |
| `pyproject.toml` files and the CLI, the various selectors also have precedence relationships with | |
| each other. In general, you can think of this precedence as increasing from the broadest selector | |
| (`ALL`) to the narrowest single-rule selectors (e.g. `F401` or `unused-import`): | |
| ```text | |
| ALL < category < linter group < linter prefix < rule | |
| ``` | |
| As shown above, this means that configuration like: | |
| === "pyproject.toml" | |
| ```toml | |
| [tool.ruff.lint] | |
| preview = true | |
| select = ["E", "F"] | |
| ignore = ["F401"] | |
| ``` | |
| === "ruff.toml" | |
| ```toml | |
| [lint] | |
| preview = true | |
| select = ["E", "F"] | |
| ignore = ["F401"] | |
| ``` | |
| will select all `E` and `F` rules, with the exception of `F401`. Analogously, a selection with the | |
| `suspicious` category like: | |
| === "pyproject.toml" | |
| ```toml | |
| [tool.ruff.lint] | |
| preview = true | |
| select = ["suspicious"] | |
| ignore = ["UP"] | |
| ``` | |
| === "ruff.toml" | |
| ```toml | |
| [lint] | |
| preview = true | |
| select = ["suspicious"] | |
| ignore = ["UP"] | |
| ``` | |
| would select all `suspicious` rules, except for the `UP` rules in that category. | |
| ### Trying out categories | |
| This section is intended to help you choose which categories you want to enable, based on the rules | |
| and linter groups you have selected and on the types of issues you want to catch. | |
| We expect virtually all projects to want the `correctness` rules enabled. The lints in this category | |
| include syntax errors that are not yet mapped to `invalid-syntax` diagnostics and other problems | |
| that cause immediate runtime errors. From there, `suspicious` is likely to be the next most helpful | |
| category. It includes rules that flag deprecated code, as well as classic footguns like | |
| `mutable-argument-default` (`B006`) that are almost always wrong but may be intentional in some | |
| cases. We tried to be conservative with the rules in `correctness`, so many rules like this that are | |
| only _usually_ accurate are found in `suspicious` instead. In general, you should feel comfortable | |
| using a `ruff: ignore` comment on diagnostics from the `suspicious` or lower categories but think | |
| twice (or share feedback!) about suppressing a `correctness` lint. | |
| The rules in the `complexity`, `performance`, and `style` categories are all stylistic, but we feel | |
| that these rules represent widely-accepted styles in the Python community. As demonstrated by their | |
| inclusion in the defaults, we expect most projects to want these rules enabled. Again, even if you | |
| enable these categories, you should feel comfortable ignoring certain rules project-wide or inline | |
| with suppression comments. | |
| The `security` rules are focused on issues that may cause security vulnerabilities and overlap | |
| closely with the `flake8-bandit` (`S`) linter group. They are in their own category because these | |
| rules are intentionally biased toward false positives over false negatives and can be quite noisy. | |
| However, if your project is security-critical or just security-conscious, you will likely want to | |
| enable this entire category. | |
| The `formatting` category contains rules that overlap with code formatters like the Ruff formatter | |
| or Black. If you use a code formatter, you will likely want to leave this category off. On the other | |
| hand, if you don't use a code formatter and rely on lint rules to enforce a consistent code format, you can select | |
| those rules from this category. Note that it contains rules beyond those related to PEP 8, however, | |
| so you may still want to select a subset of the `formatting` rules rather than the whole category. | |
| `pedantic` rules, as you may guess, are pedantic, which can mean either "noisy," leading to many | |
| diagnostics, or overly opinionated, suggesting changes that many Python users disagree with. Unlike | |
| the `security` category, you probably will not want to enable this category as a whole. Instead, we | |
| intend for rules from the `pedantic` category to be selected individually. | |
| The `restriction` category goes beyond being pedantic to arbitrarily restrict even common code | |
| patterns, such as `print` (`T201`) or `assert` (`S101`). Like the `pedantic` category, we do not | |
| recommend enabling `restriction` as a whole. If you enable any `restriction` lints, they should be | |
| chosen narrowly for your project's needs. | |
| If you're already using `extend-select` to extend the default rule set, you'll inherit the | |
| category-based defaults automatically and won't need to modify your configuration. Similarly, if | |
| you'd like to try out the new categories without replacing your current configuration wholesale, the | |
| defaults, or a smaller subset like `correctness` and `suspicious`, are a great place to start. You | |
| can append them to an existing `select` configuration, or add them with `extend-select`. In either | |
| case, you shouldn't feel obligated to enable all of the new categories and can freely `ignore` the | |
| ones that don't suit your needs. | |
| If you run into any issues or have any suggestions about the new categories, please share any | |
| feedback in the [tracking issue](https://github.com/astral-sh/ruff/issues/27959)! | |
| ## Fixes | |
| Ruff supports automatic fixes for a variety of lint errors. For example, Ruff can remove unused | |
| imports, reformat docstrings, rewrite type annotations to use newer Python syntax, and more. | |
| To enable fixes, pass the `--fix` flag to `ruff check`: | |
| ```console | |
| $ ruff check --fix | |
| ``` | |
| By default, Ruff will fix all violations for which safe fixes are available; to determine | |
| whether a rule supports fixing, see [_Rules_](rules.md). | |
| ### Fix safety | |
| Ruff labels fixes as "safe" and "unsafe". The meaning and intent of your code will be retained when | |
| applying safe fixes, but the meaning could change when applying unsafe fixes. | |
| Specifically, an unsafe fix could lead to a change in runtime behavior, the removal of comments, or both, | |
| while safe fixes are intended to preserve runtime behavior and will only remove comments when deleting | |
| entire statements or expressions (e.g., removing unused imports). | |
| For example, [`unnecessary-iterable-allocation-for-first-element`](rules/unnecessary-iterable-allocation-for-first-element.md) | |
| (`RUF015`) is a rule which checks for potentially unperformant use of `list(...)[0]`. The fix | |
| replaces this pattern with `next(iter(...))` which can result in a drastic speedup: | |
| ```console | |
| $ python -m timeit "head = list(range(99999999))[0]" | |
| 1 loop, best of 5: 1.69 sec per loop | |
| ``` | |
| ```console | |
| $ python -m timeit "head = next(iter(range(99999999)))" | |
| 5000000 loops, best of 5: 70.8 nsec per loop | |
| ``` | |
| However, when the collection is empty, the raised exception changes from an `IndexError` to `StopIteration`: | |
| ```console | |
| $ python -c 'list(range(0))[0]' | |
| Traceback (most recent call last): | |
| File "<string>", line 1, in <module> | |
| IndexError: list index out of range | |
| ``` | |
| ```console | |
| $ python -c 'next(iter(range(0)))' | |
| Traceback (most recent call last): | |
| File "<string>", line 1, in <module> | |
| StopIteration | |
| ``` | |
| Since the change in exception type could break error handling upstream, this fix is categorized as unsafe. | |
| Ruff only applies safe fixes by default. To apply unsafe fixes as well, enable [`unsafe-fixes`](settings.md#unsafe-fixes) in your configuration file or pass the `--unsafe-fixes` flag alongside `--fix`: | |
| ```console | |
| # Apply unsafe fixes | |
| ruff check --fix --unsafe-fixes | |
| ``` | |
| The default `full` output format shows all suggested fixes, regardless of the `unsafe-fixes` setting. | |
| This includes fixes that require manual review and cannot be applied automatically, even with | |
| `--unsafe-fixes`. | |
| By default, Ruff will display a hint to use `--unsafe-fixes` when unsafe fixes are available but not | |
| applied. The suggestion can be silenced by setting the [`unsafe-fixes`](settings.md#unsafe-fixes) | |
| setting to `false` or using the `--no-unsafe-fixes` flag. | |
| The safety of fixes can be adjusted per rule using the [`lint.extend-safe-fixes`](settings.md#lint_extend-safe-fixes) and [`lint.extend-unsafe-fixes`](settings.md#lint_extend-unsafe-fixes) settings. | |
| For example, the following configuration would promote unsafe fixes for `F601` to safe fixes and demote safe fixes for `UP034` to unsafe fixes: | |
| === "pyproject.toml" | |
| ```toml | |
| [tool.ruff.lint] | |
| extend-safe-fixes = ["F601"] | |
| extend-unsafe-fixes = ["UP034"] | |
| ``` | |
| === "ruff.toml" | |
| ```toml | |
| [lint] | |
| extend-safe-fixes = ["F601"] | |
| extend-unsafe-fixes = ["UP034"] | |
| ``` | |
| You may use prefixes to select rules as well, e.g., `F` can be used to promote fixes for all rules in Pyflakes to safe. | |
| !!! note | |
| All fixes will always be displayed by Ruff when using the `json` output format. The safety of each fix is available under the `applicability` field. | |
| ### Disabling fixes | |
| To limit the set of rules that Ruff should fix, use the [`lint.fixable`](settings.md#lint_fixable) | |
| or [`lint.extend-fixable`](settings.md#lint_extend-fixable), and [`lint.unfixable`](settings.md#lint_unfixable) settings. | |
| For example, the following configuration would enable fixes for all rules except | |
| [`unused-imports`](rules/unused-import.md) (`F401`): | |
| === "pyproject.toml" | |
| ```toml | |
| [tool.ruff.lint] | |
| fixable = ["ALL"] | |
| unfixable = ["F401"] | |
| ``` | |
| === "ruff.toml" | |
| ```toml | |
| [lint] | |
| fixable = ["ALL"] | |
| unfixable = ["F401"] | |
| ``` | |
| Conversely, the following configuration would only enable fixes for `F401`: | |
| === "pyproject.toml" | |
| ```toml | |
| [tool.ruff.lint] | |
| fixable = ["F401"] | |
| ``` | |
| === "ruff.toml" | |
| ```toml | |
| [lint] | |
| fixable = ["F401"] | |
| ``` | |
| ## Error suppression | |
| Ruff supports several mechanisms for suppressing lint errors, be they false positives or | |
| permissible violations. | |
| ### Configuration | |
| To omit a lint rule everywhere, add it to the "ignore" list via the [`lint.ignore`](settings.md#lint_ignore) | |
| setting, either on the command-line or in your `pyproject.toml` or `ruff.toml` file. | |
| To omit a lint rule within specific files based on file path prefixes or patterns, | |
| see the [`lint.per-file-ignores`](settings.md#lint_per-file-ignores) setting. | |
| ### Comments | |
| Ruff supports multiple forms of suppression comments, including inline and file-level `noqa` and | |
| `ruff: ignore` comments, and range suppressions. | |
| In [`preview`](preview.md) mode, rule names (e.g. `unused-import`) can be used in `ruff: ignore`, | |
| `ruff: file-ignore`, `ruff: disable`, and `ruff: enable` comments instead of rule codes (e.g. | |
| `F401`). | |
| #### Line-level | |
| Ruff supports 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 | |
| ``` | |
| For multi-line strings (like docstrings), the `noqa` directive should come at the end of the string | |
| (after the closing triple quote), 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 | |
| ``` | |
| For import sorting, the `noqa` should come at the end of the first line in the import block, and | |
| will apply to all imports in the block, like so: | |
| ```python | |
| import os # noqa: I001 | |
| import abc | |
| ``` | |
| The full inline comment specification is as follows: | |
| - An inline blanket `noqa` comment is given by a case-insensitive match for | |
| `#noqa` with optional whitespace after the `#` symbol, followed by either: the | |
| end of the comment, the beginning of a new comment (`#`), or whitespace | |
| followed by any character other than `:`. | |
| - An inline `noqa` suppression is given by first finding a case-insensitive match | |
| for `#noqa` with optional whitespace after the `#` symbol, optional whitespace | |
| after `noqa`, and followed by the symbol `:`. After this we are expected to | |
| have a list of rule codes which is given by sequences of uppercase ASCII | |
| characters followed by ASCII digits, separated by whitespace or commas. The | |
| list ends at the last valid code. We will attempt to interpret rules with a | |
| missing delimiter (e.g. `F401F841`), though a warning will be emitted in this | |
| case. | |
| To cover an entire "logical" line (a multi-line statement or suite header), | |
| an "ignore" comment may be placed above the first line: | |
| ```python | |
| # ruff: ignore[ARG001] # Covers the entire function signature | |
| def foo( | |
| arg1, | |
| arg2, | |
| ): | |
| pass | |
| # ruff: ignore[E501] # Covers the entire list literal | |
| things = [ | |
| "really long string literal ...", | |
| "really long string literal ...", | |
| ] | |
| ``` | |
| Alternately, placing the "ignore" comment inside of a multi-line statement, or | |
| at the end of a line, will cover only a single "physical" line, leaving the rest | |
| of the multi-line statement or header uncovered: | |
| ```python | |
| def foo( | |
| arg1, | |
| # ruff: ignore[ARG001] # Only covers `arg2` | |
| arg2, | |
| ): | |
| pass | |
| things = [ | |
| "really long string literal ...", # ruff: ignore[E501] # Only covers this line | |
| "really long string literal ...", | |
| ] | |
| ``` | |
| Ignore comments can also be "stacked" with other comments or pragmas, and will | |
| still cover the next logical line: | |
| ```python | |
| # ruff: ignore[E741] | |
| # ruff: ignore[F841] | |
| # I definitely know what I'm doing. | |
| i = 1 | |
| ``` | |
| The full line-level suppression comment specification is as follows: | |
| - An own-line or trailing comment starting with case sensitive `#ruff:`, with | |
| optional whitespace after the `#` symbol and `:` symbol, followed by `ignore[`, | |
| any rules to be suppressed, and ending with `]`. | |
| - Rules to be suppressed must be separated by commas, with optional whitespace | |
| before or after each rule name, and may be followed by an optional trailing comma | |
| after the last rule name. | |
| #### Block-level | |
| To ignore one or more violations within a range or block of code, a "disable" comment | |
| followed by a matching "enable" comment can be used, like so: | |
| ```python | |
| # ruff: disable[E501] | |
| VALUE_1 = "Lorem ipsum dolor sit amet ..." | |
| VALUE_2 = "Lorem ipsum dolor sit amet ..." | |
| VALUE_3 = "Lorem ipsum dolor sit amet ..." | |
| # ruff: enable[E501] | |
| ``` | |
| To define a range, both the "disable" and "enable" comments must have matching codes, | |
| in the same order, as well as matching indentation levels within a logical block of code: | |
| ```python | |
| def foo(): | |
| # ruff: disable[E741, F841] | |
| i = 1 | |
| # ruff: enable[E741, F841] | |
| ``` | |
| If no matching "enable" comment is found, Ruff will also treat this as an "implicit" range. | |
| The implicit range is defined from the starting "disable" comment, until reaching | |
| a logical scope indented less than the starting comment: | |
| ```python | |
| def foo(): | |
| # ruff: disable[E741, F841] | |
| i = 1 | |
| if True: | |
| O = 1 | |
| l = 1 | |
| # implicit end of range | |
| foo() | |
| ``` | |
| We strongly suggest using explicit range suppressions to prevent | |
| accidental suppressions of violations, especially at global module scope. | |
| For this reason, a `RUF104` diagnostic will also be produced for any implicit range. | |
| If implicit range suppressions are desired, the `RUF104` rule can be disabled, | |
| or an inline `noqa` suppression can be added to the end of the "disable" comment. | |
| Range suppressions cannot be used to enable or select rules that aren't already | |
| selected by the project configuration or runtime flags. An "enable" comment can only | |
| be used to terminate a preceding "disable" comment with identical codes. | |
| Unlike `noqa` suppressions, range suppressions do not support "blanket" suppression | |
| of all violations. At least one violation code must be listed. | |
| The full range suppression comment specification is as follows: | |
| - An own-line comment starting with case sensitive `#ruff:`, with optional whitespace | |
| after the `#` symbol and `:` symbol, followed by either `disable` or `enable` | |
| to start or end a range respectively, immediately followed by `[`, any codes to | |
| be suppressed, and ending with `]`. | |
| - Codes to be suppressed must be separated by commas, with optional whitespace | |
| before or after each code, and may be followed by an optional trailing comma | |
| after the last code. | |
| #### File-level | |
| To ignore all violations across an entire file, add the line `# ruff: noqa` anywhere in the file, | |
| preferably towards the top, like so: | |
| ```python | |
| # ruff: noqa | |
| ``` | |
| To ignore a specific rule across an entire file, add the line `# ruff: noqa: {code}` anywhere in the | |
| file, preferably towards the top, like so: | |
| ```python | |
| # ruff: noqa: F841 | |
| ``` | |
| Global `noqa` comments must be on their own line to disambiguate from comments which ignore | |
| violations on a single line. | |
| Note that Ruff will also respect Flake8's `# flake8: noqa` directive, and will treat it as | |
| equivalent to `# ruff: noqa`. | |
| The file-level suppression comment specification is as follows: | |
| - A file-level exemption comment is given by a case-sensitive match for `#ruff:` | |
| or `#flake8:`, with optional whitespace after `#` and before `:`, followed by | |
| optional whitespace and a case-insensitive match for `noqa`. After this, the | |
| specification is as in the inline `noqa` suppressions above. | |
| One or more rules can also be ignored across an entire file with a `file-ignore` comment on its own | |
| line, at global module scope, and preferably near the top of the file: | |
| ```python | |
| # ruff: file-ignore[F401, ARG001] | |
| ``` | |
| The file-level suppression comment specification is as follows: | |
| - An own-line comment starting with case sensitive `#ruff:`, with optional whitespace | |
| after the `#` symbol and `:` symbol, followed by `file-ignore[`, any rules to | |
| be suppressed, and ending with `]`. | |
| - Rules to be suppressed must be separated by commas, with optional whitespace | |
| before or after each rule name, and may be followed by an optional trailing comma | |
| after the last rule name. | |
| ### Detecting unused suppressions | |
| Ruff implements a special rule, [`unused-noqa`](https://docs.astral.sh/ruff/rules/unused-noqa/), | |
| under the `RUF100` code, to enforce that your suppressions are "valid", in that the violations | |
| they _say_ they ignore are actually being triggered and suppressed. To flag | |
| unused suppression comments, run Ruff with `--extend-select RUF100`, like so: | |
| ```shell-session | |
| $ ruff check /path/to/file.py --extend-select RUF100 | |
| ``` | |
| Ruff can also _remove_ any unused suppression comments via its fix functionality. | |
| To remove any unused suppressions, run Ruff with `--fix`, like so: | |
| ```shell-session | |
| $ ruff check /path/to/file.py --extend-select RUF100 --fix | |
| ``` | |
| ### Inserting necessary suppression comments | |
| Ruff can _automatically add_ suppression comments to all lines that contain violations, which is | |
| useful when migrating a new codebase to Ruff. To add the appropriate comments to all relevant lines, | |
| run Ruff with `--add-noqa` to add `noqa` comments or with `--add-ignore` to add `ruff: ignore` | |
| comments: | |
| ```shell-session | |
| $ ruff check /path/to/file.py --add-noqa | |
| $ ruff check /path/to/file.py --add-ignore | |
| ``` | |
| Both of these flags use rule codes on stable. To add `ruff: ignore` comments with human-readable | |
| rule names instead, use `--add-ignore` with preview mode enabled. | |
| ### isort 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. | |
| Ruff will also respect variants of these action comments with a `# ruff:` prefix | |
| (e.g., `# ruff: isort: skip_file`, `# ruff: isort: on`, and so on). These variants more clearly | |
| convey that the action comment is intended for Ruff, but are functionally equivalent to the | |
| isort variants. | |
| Unlike isort, Ruff does not respect action comments within docstrings. | |
| See the [isort documentation](https://pycqa.github.io/isort/docs/configuration/action_comments.html) | |
| for more. | |
| ## Exit codes | |
| By default, `ruff check` 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 check` 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 | |
| fixing. |