Skip to content

Implement #ruff:file-ignore file-level suppressions#23599

Merged
amyreese merged 7 commits intomainfrom
amy/ruff-ignore-all
Apr 24, 2026
Merged

Implement #ruff:file-ignore file-level suppressions#23599
amyreese merged 7 commits intomainfrom
amy/ruff-ignore-all

Conversation

@amyreese
Copy link
Copy Markdown
Contributor

@amyreese amyreese commented Feb 27, 2026

Follow-up to #23404

Add support for #ruff:file-ignore[code] style file-level suppressions
as own-line comments at global module scope. The range covered by these
suppressions is always the entirety of the file:

# ruff:file-ignore[ARG001]

def foo(
	arg1,
	arg2,
):
	pass

def bar(
	arg1,
	arg2,
):
	pass

This currently requires having preview mode enabled. Without preview mode,
the comments are parsed and processed, but not materialized into active
suppressions at runtime.

@amyreese amyreese changed the base branch from main to amy/ruff-ignore-end-of-line February 27, 2026 02:21
@amyreese amyreese changed the title Implement #ruff:ignore-all range suppressions Implement #ruff:ignore-all file-level suppressions Feb 27, 2026
@amyreese amyreese added suppression Related to supression of violations e.g. noqa preview Related to preview mode features labels Feb 27, 2026
@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot Bot commented Feb 27, 2026

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Copy link
Copy Markdown
Contributor

@ntBre ntBre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks reasonable to me! I'll just be curious to get Micha's thoughts on this and #23404 next week.

Comment thread docs/linter.md
# ruff: ignore-all[F401, ARG001]
```

The full-level suppression comment specification is as follows:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
The full-level suppression comment specification is as follows:
The full file-level suppression comment specification is as follows:

I think

Copy link
Copy Markdown
Collaborator

@dylwil3 dylwil3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this is a great idea! Especially because users have reported accidentally doing ruff: noqa: code when they meant to just do noqa: code. So I think eventually we should deprecate the ruff: noqa: code option in favor of this one.

One question I have is whether we want to take this opportunity to be more stringent about the requirement that the file-level suppression be "towards the top". Maybe before any code? (possibly excluding module-level docstrings)?

It always seemed strange to me that someone could stick # ruff: noqa: code randomly in the middle of the file and it would affect the whole file.

Comment thread docs/linter.md Outdated
@ntBre
Copy link
Copy Markdown
Contributor

ntBre commented Feb 27, 2026

One question I have is whether we want to take this opportunity to be more stringent about the requirement that the file-level suppression be "towards the top". Maybe before any code? (possibly excluding module-level docstrings)?

I thought about this as well, but I guess it could be a separate lint rule or something as an alternative.

@amyreese amyreese force-pushed the amy/ruff-ignore-end-of-line branch 2 times, most recently from c9df742 to aef5860 Compare March 4, 2026 23:04
@amyreese amyreese force-pushed the amy/ruff-ignore-all branch from 7bce278 to dfb0d89 Compare March 4, 2026 23:10
Copy link
Copy Markdown
Member

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We'll need to update is_pragma_comment to recognize the new pragma comments that this PR and the ruff: ignore PR add.

Comment thread crates/ruff_linter/src/suppression.rs
Comment thread crates/ruff_linter/src/suppression.rs
Comment thread crates/ruff_linter/src/suppression.rs Outdated
@amyreese
Copy link
Copy Markdown
Contributor Author

amyreese commented Mar 6, 2026

We'll need to update is_pragma_comment to recognize the new pragma comments that this PR and the ruff: ignore PR add.

That function already recognizes all comments starting with ruff: as pragma comments. :)

@amyreese amyreese force-pushed the amy/ruff-ignore-end-of-line branch from aef5860 to d03c94e Compare March 12, 2026 21:23
@amyreese amyreese force-pushed the amy/ruff-ignore-all branch from dfb0d89 to 64ca042 Compare March 12, 2026 21:24
@amyreese amyreese force-pushed the amy/ruff-ignore-end-of-line branch from d03c94e to fdfae04 Compare March 17, 2026 20:18
@amyreese amyreese force-pushed the amy/ruff-ignore-end-of-line branch from 20cf527 to 3cb3a2f Compare April 8, 2026 22:46
@amyreese amyreese force-pushed the amy/ruff-ignore-end-of-line branch from 7089290 to 029f481 Compare April 20, 2026 14:59
Base automatically changed from amy/ruff-ignore-end-of-line to main April 20, 2026 18:38
@amyreese amyreese force-pushed the amy/ruff-ignore-all branch from 64ca042 to f87a79a Compare April 20, 2026 19:17
@amyreese amyreese force-pushed the amy/ruff-ignore-all branch from 8298523 to 87d0adf Compare April 21, 2026 15:03
@amyreese
Copy link
Copy Markdown
Contributor Author

Rebased, ensured suppressions are sorted by (action, textrange, rule) for consistent behavior/precedence, and added integration tests.

@MichaReiser
Copy link
Copy Markdown
Member

Coming back to this and not remembering what this PR was about, I misinterpreted the PR title as meaning this PR introduces ruff: ignore-all as an equivalent to ruff: ignore[all] (assuming we supported categories within ignore comments). This triggered me to think a bit more about the naming and overall design. I'll lay out my thoughts because I haven't reached a conclusion on which I prefer, and I'm interested in your opinion.

  • The term all is overloaded because of rule selection, and I made the mistake of assuming that ruff: ignore-all is the same as ruff: ignore[all]. That's why I think we should avoid all. We could consider using ruff: ignore-file[code] or ruff: file-ignore[code].
  • Semantically, ruff: ignore-all feels closer to a ruff: disable comment because it suppresses a block of code and not just the next statement. That's why I think I'd prefer ruff: disable-all (or ruff: disable-file) over ruff: ignore-all.
  • When using ESLint, I always struggled to remember all the suppression styles. Which is why I think fewer suppression styles are generally preferred. One way to accomplish this is to special-case ruff: disable[...] at the start of a file. However, this would require adding an exception to unmatched-suppression-comment to not warn about ruff: disable comments at the start of a file, and open the door for accidental file-level suppressions. This is the part I have the least clarity on what I prefer. Do I prefer fewer suppression styles or avoiding accidental suppressions at all costs? Note mostly for myself: ESLint has a single eslint: disable comment, and so does ESLint-inspired Oxc; Rust has #![allow] for module-level suppression and #[allow] for block/next-definition suppression; Pyright uses pyright: E501=ignore.

@amyreese
Copy link
Copy Markdown
Contributor Author

amyreese commented Apr 22, 2026

For reference, Biome uses ignore, ignore-all, ignore-start, and ignore-end — the last two being analogs of disable and enable. We also don't allow # ruff:ignore[all], (or ignoring by prefix for that matter) so I think the chance of confusion is low.

@MichaReiser
Copy link
Copy Markdown
Member

We also don't allow # ruff:ignore[all],

I could see us allowing this in the future (using categories in suppressions). It's something I find useful in clippy, specifically at the file level.

@amyreese amyreese force-pushed the amy/ruff-ignore-all branch from f1d6b14 to 0ba1467 Compare April 23, 2026 20:57
@amyreese amyreese changed the title Implement #ruff:ignore-all file-level suppressions Implement #ruff:file-ignore file-level suppressions Apr 23, 2026
@amyreese
Copy link
Copy Markdown
Contributor Author

Updated to use # ruff: file-ignore terminology.

Copy link
Copy Markdown
Collaborator

@dylwil3 dylwil3 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, thank you!

Comment thread crates/ruff_linter/src/rules/ruff/rules/invalid_suppression_comment.rs Outdated
}
} else {
warn_user_once!(
"#ruff:file-ignore comment found but not active, enable preview mode"
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
"#ruff:file-ignore comment found but not active, enable preview mode"
"#ruff:file-ignore comment found but has no effect, enable preview mode"

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not fond of "has no effect" because it seems to imply that it's "unused", ie, doesn't suppress anything, rather than it being ignored by Ruff because it's not running in preview mode... 🤔

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also this matches what we already used for #ruff:ignore

Comment on lines -1220 to +1279
covered_source: "# ruff: disable[bar]\n print('hello')\n\n",
code: "bar",
covered_source: "# ruff: disable[foo]\nprint('hello')\n\ndef foo():\n # ruff: disable[bar]\n print('hello')\n\n",
code: "foo",
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

did these snapshots change just because of the ordering change? (I think so but just making sure I'm not missing something)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, this is because the sorting changed the order of the suppressions in the snapshots, and so the diff is a bit weird.

Comment thread crates/ruff_linter/src/rules/ruff/rules/invalid_suppression_comment.rs Outdated
def bar(self, arg1, arg2):
print("hello")

# ruff: file-ignore[ARG002] should cover the class method above!
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit tricky, and I can see an argument in both directions:

  • Marking the inline comment as unused has the advantage that it reduces the total number of suppressions.
  • Marking the file-level suppression as unused has the advantage that it keeps suppressions as local as possible (unless the file-level suppression is used in at least one other place).

I wanted to argue that ty implements the second behavior, but it doesn't (https://play.ty.dev/47a21efb-d9e7-46f4-964e-69ff82bb5467). So I think this is fine.

Comment thread crates/ruff_linter/src/suppression.rs Outdated
Comment thread crates/ruff_linter/src/suppression.rs Outdated
@amyreese amyreese enabled auto-merge (squash) April 24, 2026 15:58
@amyreese amyreese merged commit ed669ea into main Apr 24, 2026
43 checks passed
@amyreese amyreese deleted the amy/ruff-ignore-all branch April 24, 2026 16:02
carljm added a commit to tamird/ruff that referenced this pull request Apr 27, 2026
* main: (248 commits)
  [ty] bump conformance suite commit (astral-sh#24848)
  [ty] Pass unmapped type variables to `SpecializationBuilder::build_with` (astral-sh#24809)
  [ty] Avoid bookkeeping for unannotated functions (astral-sh#24842)
  [ty] Optimize signature checking based on number of arguments (astral-sh#24674)
  [ty] Avoid eagerly inferring legacy generic context (astral-sh#24841)
  [ty] Skip decorator inference for undecorated functions (astral-sh#24839)
  [ty] solve unions against generic protocols (astral-sh#24837)
  [ty] Lazily allocate parameter type builders (astral-sh#24838)
  [ty] Lazily compute call argument fallbacks (astral-sh#24836)
  [ty] Avoid collecting type context callables (astral-sh#24835)
  Bump ecosystem-analyzer to e7576e6 (astral-sh#24834)
  [ty] Support basic narrowing with aliased conditional expressions (astral-sh#24302)
  [ty] Fix project and workspace selection (astral-sh#24824)
  [ty] Fix missing memory usage attributes (astral-sh#24823)
  Fix setting selection for multi folder workspace (astral-sh#24819)
  Improve diagnostics for implicit calls to a possibly unbound unary operator. (astral-sh#24816)
  [ty] Update review pool (astral-sh#24818)
  Bump 0.15.12 (astral-sh#24815)
  [ty] Complete support for more detailed diagnostics on possibly unbound errors from implicit dunder calls against unions. (astral-sh#24676)
  Implement `#ruff:file-ignore` file-level suppressions (astral-sh#23599)
  ...
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

preview Related to preview mode features suppression Related to supression of violations e.g. noqa

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants