Skip to content

[flake8-tidy-imports] Skip fixes for multi-member imports (TID254) - #26584

Merged
ntBre merged 7 commits into
astral-sh:mainfrom
nightt5879:nightt5879/fix-tid254-conflicting-lazy-imports
Sep 8, 2026
Merged

ntBre merged 7 commits into
astral-sh:mainfrom
nightt5879:nightt5879/fix-tid254-conflicting-lazy-imports

Conversation

@nightt5879

@nightt5879 nightt5879 commented Jul 7, 2026 •

Copy link
Copy Markdown
Contributor

This fixes #26450.

TID254 now reports policy violations without offering a fix when an import statement contains multiple names. Single-name imports remain fixable. This prevents conflicting lazy-import requirements from repeatedly adding and removing lazy, and uses the same single-member check as TID255.

The tests cover both import and from ... import ..., including conflicting policies and fixes in both directions.

btw: cuz i not the natvie English speaker, i will use ai to imporve my txt, which may let it look like a AI generate....

@nightt5879
nightt5879 marked this pull request as ready for review July 7, 2026 08:00
@astral-sh-bot
astral-sh-bot Bot requested a review from ntBre July 7, 2026 08:00

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 2b9e1c75ab

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_mismatch.rs Outdated
Comment thread crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_mismatch.rs Outdated
Comment thread crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_mismatch.rs Outdated
@MichaReiser

Copy link
Copy Markdown
Member

Thank you. Please take a look at our AI Policy (https://github.com/astral-sh/ruff/blob/main/CONTRIBUTING.md#use-of-ai). Your summary gives me a strong impression that it was written by AI

@nightt5879

nightt5879 commented Jul 7, 2026 •

Copy link
Copy Markdown
Contributor Author

Thank you. Please take a look at our AI Policy (https://github.com/astral-sh/ruff/blob/main/CONTRIBUTING.md#use-of-ai). Your summary gives me a strong impression that it was written by AI

thanks for pointing this out. i read the AI policy.

i used AI tooling to help open the PR and draft the first description, but i reviewed the diff and tested it locally on Windows.

and i want to know weather the review comment by the [chatgpt-codex-connector] that i should handle it?

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: dda755d551

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_mismatch.rs Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: b75a2639e0

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_mismatch.rs Outdated
@ntBre ntBre added the bug An issue describing something that isn't working, or a PR that fixes a bug label Sep 2, 2026
@ntBre

ntBre commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Thanks for looking into this and coming up with a fix! However, the new code looks quite complicated, and I didn't realize that TID255 already bails out without a fix if multiple imports are affected:

};
let binding = semantic.binding(binding_id);
let Some(import) = lazy_import_statement(binding, semantic) else {
return;

What do you think about doing the same here? I think a minimal patch like this would share the same helper here and take care of the issue:

diff --git a/crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_immediately_resolved.rs b/crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_immediately_resolved.rs
index 2cb5fee1e4..9eab43f6b3 100644
--- a/crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_immediately_resolved.rs
+++ b/crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_immediately_resolved.rs
@@ -126,8 +126,8 @@ fn lazy_import_statement<'a>(binding: &Binding, semantic: &SemanticModel<'a>) ->
     .then_some(stmt)
 }
 
-/// Return `true` if removing `lazy` only makes the resolved import eager.
-fn is_single_member_import(stmt: &Stmt) -> bool {
+/// Return `true` if changing `lazy` affects only one imported name.
+pub(super) fn is_single_member_import(stmt: &Stmt) -> bool {
     match stmt {
         Stmt::Import(StmtImport { names, .. }) | Stmt::ImportFrom(StmtImportFrom { names, .. }) => {
             names.len() == 1
diff --git a/crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_mismatch.rs b/crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_mismatch.rs
index 1aae71b8de..09b49a8c8c 100644
--- a/crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_mismatch.rs
+++ b/crates/ruff_linter/src/rules/flake8_tidy_imports/rules/lazy_import_mismatch.rs
@@ -2,6 +2,7 @@ use ruff_macros::{ViolationMetadata, derive_message_formats};
 use ruff_python_ast::{PythonVersion, Stmt, StmtImport, StmtImportFrom};
 use ruff_text_size::{Ranged, TextRange, TextSize};
 
+use super::lazy_import_immediately_resolved::is_single_member_import;
 use crate::checkers::ast::Checker;
 use crate::codes::Category;
 use crate::rules::flake8_tidy_imports::rules::BannedModuleImportPolicies;
@@ -50,7 +51,7 @@ enum LazyImportPolicy {
 }
 
 impl Violation for LazyImportMismatch {
-    const FIX_AVAILABILITY: FixAvailability = FixAvailability::Always;
+    const FIX_AVAILABILITY: FixAvailability = FixAvailability::Sometimes;
 
     #[derive_message_formats]
     fn message(&self) -> String {
@@ -168,6 +169,10 @@ fn report_lazy_import_policy(
     policy: LazyImportPolicy,
 ) {
     let mut diagnostic = checker.report_diagnostic(LazyImportMismatch { policy, name }, range);
+    // Changing the entire statement could violate another imported name's policy.
+    if !is_single_member_import(stmt) {
+        return;
+    }
     match policy {
         LazyImportPolicy::RequireLazy => {
             diagnostic.set_fix(Fix::unsafe_edit(Edit::insertion(

@ntBre ntBre mentioned this pull request Sep 4, 2026
27 of 32 tasks
Share TID255's single-member guard so conflicting import policies still
produce diagnostics without oscillating fixes. Cover both import forms,
both fix directions, and the single-member fixes in regression tests.

Merge upstream main to resolve the PR conflict.
@nightt5879 nightt5879 changed the title Fix TID254 mixed lazy import fixes Skip TID254 fixes for multi-member imports Sep 7, 2026
@nightt5879

Copy link
Copy Markdown
Contributor Author

@ntBre

好,我看了一下这个 PR,我之前弄的确实有点复杂了。我觉得你提出的方向是可以的,我按照这个方向修改了一个版本,提交了 commit 修改。(因为我不是英语母语使用者,这个用了 AI 进行翻译我的中文。)

English translation (AI-assisted):

I took another look at this PR, and my previous implementation was indeed a bit too complicated. I think your suggested approach makes sense, so I've updated the code in that direction and pushed a new commit. I'm not a native English speaker, so I used AI to translate my Chinese reply.

@ntBre ntBre left a comment

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.

Thank you! I made a small tweak to the docs and then switched the tests over to our new mdtest framework, but this looks great.

@ntBre ntBre changed the title Skip TID254 fixes for multi-member imports [flake8-tidy-imports] Skip fixes for multi-member imports (TID254) Sep 8, 2026
@ntBre
ntBre enabled auto-merge (squash) September 8, 2026 21:38
@ntBre
ntBre disabled auto-merge September 8, 2026 21:48
@astral-sh-bot

astral-sh-bot Bot commented Sep 8, 2026

Copy link
Copy Markdown

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug An issue describing something that isn't working, or a PR that fixes a bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Infinite loop] TID254 when an import statement has conflicting laziness requirements

3 participants