crates/ruff_linter/resources/mdtest/suppression/ignore.md
ruff:ignore commentsruff:ignore rangeThese are regression tests for https://github.com/astral-sh/ruff/issues/25644, where ruff:ignore
comments behaved differently from noqa and ty:ignore comments when placed on the first line of a
diagnostic range.
[lint]
preview = true
select = ["RUF015"]
suppressed = [ # noqa: RUF015
*range(10)
][0]
not_suppressed = [ # ruff:ignore[RUF015]
*range(10)
][0]
ruff:ignore rangeThis case also was previously not suppressed but will be now. The B903 diagnostic covers the
entire class definition.
[lint]
preview = true
select = ["B903"]
# ruff:ignore[B903]
class Point:
def __init__(self, x: int):
self.x = x
Diagnostics with empty ranges should also be suppressible, as with noqa.
[lint]
preview = true
select = ["W292"]
suppressed = 1 # ruff:ignore[W292]
A block suppression should not apply to a diagnostic that starts inside the disabled range but ends
after the matching ruff:enable comment:
[lint]
preview = true
select = ["RUF015"]
# ruff:disable[RUF015]
# error: [unnecessary-iterable-allocation-for-first-element]
not_suppressed = [
# ruff:enable[RUF015]
*range(10)
][0]
This isn't strictly a problem because the formatter will indent and invalidate the ruff:enable
comment here, raising RUF103, but it seems better for this not to work regardless of formatting.
This is how the comments should look instead:
# ruff:disable[RUF015]
not_suppressed = [
*range(10)
][0]
# ruff:enable[RUF015]
[lint]
preview = true
select = ["RUF015"]
This case tests that both the range and suppression code are checked.
# error: [unnecessary-iterable-allocation-for-first-element]
not_suppressed = [ # ruff:ignore[F401]
*range(10)
][0]
[lint]
preview = true
select = [ "E" ]
This should be suppressed:
# ruff:ignore[E262]
x = 1 #bad
An ignore comment inside a multi-line statement only covers the next physical line, including its trailing comment:
values = [
# ruff:ignore[E262]
1, #bad
# error: [no-space-after-inline-comment]
2, #bad
]
An own-line ignore does not extend to a comment on the following line:
# ruff:ignore[E265]
x = 1
# error: [no-space-after-block-comment]
#bad
An own-line ignore above a multi-line statement covers a trailing comment on its final line:
# ruff:ignore[E262]
x = (
1
) #bad
[lint]
preview = true
select = [ "F" ]
Some diagnostics have a "parent" range, which should also be accounted for when suppressing them
with both noqa and ruff:ignore.
from foo import ( # noqa: F401
bar
)
from foo import ( # ruff:ignore[F401]
baz
)
[lint]
preview = true
select = [ "F401", "RUF100" ]
For cases with both a parent and non-parent noqa comment, the parent is marked as used, while the
non-parent, which falls later textually, is marked as unused.
from math import ( # noqa: F401
# error: [unused-noqa]
cos # noqa: F401
)
ruff:ignore should behave in the same way:
from sys import ( # ruff:ignore[F401]
# error: [unused-noqa]
argv # ruff:ignore[F401]
)
[lint]
preview = true
select = [ "W291" ]
For both logical and non-logical newlines:
<!-- fmt:off --># ruff:ignore[W291]
foo
values = [
# ruff:ignore[W291]
bar
]
ruff:ignore comments within a disable/enable pair[lint]
preview = true
select = ["E501", "F401", "RUF10"]
An intervening ruff:ignore directive shouldn't cause a disable/enable pair to be reported as
unmatched. Instead, the range suppression should take precedence, and the inner ruff:ignore should
be unused, just like a noqa comment:
# ruff:disable[F401]
# error: [unused-noqa]
import os # ruff:ignore[F401]
# ruff:enable[F401]
# ruff:disable[F401]
# error: [unused-noqa]
import sys # noqa: F401
# ruff:enable[F401]
This applies to own-line comments too:
# ruff:disable[F401]
# error: [unused-noqa]
# ruff:ignore[F401]
import os
# ruff:enable[F401]
and cases where the disable and ignore suppress different codes:
# ruff:disable[E501]
import os # ruff:ignore[F401]
message = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
# ruff:enable[E501]
file-ignore comments within a disable/enable pair[lint]
preview = true
select = ["F401", "RUF10"]
A file-ignore within a range suppression takes precedence and marks the disable as unused:
# error: [unused-noqa]
# ruff:disable[F401]
# ruff:file-ignore[F401]
import os
message = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
# ruff:enable[F401]
[lint]
preview = false
select = ["F401", "RUF102"]
With preview disabled, this should continue to emit F401, as well as RUF102:
# snapshot: invalid-rule-code
# ruff:disable[unused-import]
# error: [unused-import]
import math
# ruff:enable[unused-import]
error[RUF102]: Invalid rule code in suppression: unused-import
--> src/mdtest_snippet.py:2:16
|
2 | # ruff:disable[unused-import]
| ^^^^^^^^^^^^^
3 | # error: [unused-import]
4 | import math
5 | # ruff:enable[unused-import]
| -------------
|
help: Enable `lint.preview` to use rule names
help: Remove the suppression comment
1 | # snapshot: invalid-rule-code
- # ruff:disable[unused-import]
2 | # error: [unused-import]
3 | import math
- # ruff:enable[unused-import]
4 | # snapshot: invalid-rule-code
5 | # ruff:disable[unused-import, unknown-rule]
6 | # error: [unused-import]
Emit both (non-fix-title) help messages when rule names and unknown codes are present:
# snapshot: invalid-rule-code
# ruff:disable[unused-import, unknown-rule]
# error: [unused-import]
import sys
# ruff:enable[unused-import, unknown-rule]
error[RUF102]: Invalid rule code in suppression: unknown-rule, unused-import
--> src/mdtest_snippet.py:7:1
|
7 | # ruff:disable[unused-import, unknown-rule]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
8 | # error: [unused-import]
9 | import sys
10 | # ruff:enable[unused-import, unknown-rule]
| ------------------------------------------
|
help: Add non-Ruff rule codes to the `lint.external` configuration option
help: Enable `lint.preview` to use rule names
help: Remove the suppression comment
4 | import math
5 | # ruff:enable[unused-import]
6 | # snapshot: invalid-rule-code
- # ruff:disable[unused-import, unknown-rule]
7 | # error: [unused-import]
8 | import sys
- # ruff:enable[unused-import, unknown-rule]
Enable preview, unused-import and several RUF rules to check for valid suppression comments:
[lint]
preview = true
select = ["F401", "RUF100", "RUF102", "RUF103", "RUF104"]
ruff:ignoreThis comment should suppress the F401 diagnostic and not emit any other errors:
# ruff:ignore[unused-import]
import math
ruff:file-ignoreFile-level ignores should also work:
# ruff:file-ignore[unused-import]
import math
import sys
import traceback
ruff:disableAs should block-level ignores:
import math # error: [unused-import]
# ruff:disable[unused-import]
import sys
# ruff:enable[unused-import]
import traceback # error: [unused-import]
The disable and enable comments must match textually, even when a rule code and name identify
the same rule:
# error: [unmatched-suppression-comment]
# ruff:disable[unused-import]
import math
# snapshot: invalid-suppression-comment
# ruff:enable[F401]
error[RUF103]: Invalid suppression comment: no matching 'disable' comment
--> src/mdtest_snippet.py:12:1
|
12 | # ruff:enable[F401]
| ^^^^^^^^^^^^^^^^^^^
|
help: Remove suppression comment
9 | # ruff:disable[unused-import]
10 | import math
11 | # snapshot: invalid-suppression-comment
- # ruff:enable[F401]
note: This is an unsafe fix and may change runtime behavior
noqaOld-style noqa comments should continue to reject rule names:
# error: [unused-import]
import math # noqa: unused-import
but obviously continue working with rule codes:
import math # noqa: F401
invalid-rule-codeUnknown rule names should emit RUF102, while preserving valid names in the same suppression:
# snapshot: invalid-rule-code
# ruff:ignore[unused-import, not-a-rule]
import pathlib
error[RUF102]: Invalid rule code in suppression: not-a-rule
--> src/mdtest_snippet.py:2:30
|
2 | # ruff:ignore[unused-import, not-a-rule]
| ^^^^^^^^^^
|
help: Add non-Ruff rule codes to the `lint.external` configuration option
help: Remove the rule code `not-a-rule`
1 | # snapshot: invalid-rule-code
- # ruff:ignore[unused-import, not-a-rule]
2 + # ruff:ignore[unused-import]
3 | import pathlib
unused-noqaUnused suppressions with rule codes should still emit RUF100 with an appropriate error message:
# error: [unused-noqa]
import math # noqa: F401
# error: [unused-noqa]
import math # ruff:ignore[F401]
# snapshot: unused-noqa
import math # ruff:ignore[unused-import]
math.cos(1)
error[RUF100]: Unused suppression (unused: `unused-import`)
--> src/mdtest_snippet.py:8:14
|
8 | import math # ruff:ignore[unused-import]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: Remove unused suppression
5 | import math # ruff:ignore[F401]
6 |
7 | # snapshot: unused-noqa
- import math # ruff:ignore[unused-import]
8 + import math
9 |
10 | math.cos(1)
11 | # snapshot: unused-noqa
A rule code and human-readable name for the same rule are treated as separate suppressions. The second suppression is therefore unused rather than duplicated:
# snapshot: unused-noqa
# ruff:ignore[F401, unused-import]
import pathlib
error[RUF100]: Unused suppression (unused: `unused-import`)
--> src/mdtest_snippet.py:12:1
|
12 | # ruff:ignore[F401, unused-import]
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
help: Remove unused suppression
9 |
10 | math.cos(1)
11 | # snapshot: unused-noqa
- # ruff:ignore[F401, unused-import]
12 + # ruff:ignore[F401]
13 | import pathlib