[pyupgrade] Prevent infinite loop with I002 and UP026 (#20327)

## Summary

Fixes #19842

Prevent infinite loop with I002 and UP026

- Implement isort-aware handling for UP026 (deprecated mock import):
- Add CLI integration tests in crates/ruff/tests/lint.rs:

## Test Plan

I have added two integration tests
`pyupgrade_up026_respects_isort_required_import_fix` and
`pyupgrade_up026_respects_isort_required_import_from_fix` in
`crates/ruff/tests/lint.rs`.
This commit is contained in:
Takayuki Maeda 2025-09-13 05:45:26 +09:00 committed by GitHub
parent 82796df9b5
commit 151ba49b36
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 73 additions and 1 deletions

View file

@ -17,6 +17,7 @@ use crate::Locator;
use crate::checkers::ast::Checker;
use crate::cst::matchers::{match_import, match_import_from, match_statement};
use crate::fix::codemods::CodegenStylist;
use crate::rules::pyupgrade::rules::is_import_required_by_isort;
use crate::{AlwaysFixableViolation, Edit, Fix};
#[derive(Debug, PartialEq, Eq, Copy, Clone)]
@ -299,7 +300,13 @@ pub(crate) fn deprecated_mock_import(checker: &Checker, stmt: &Stmt) {
// Add a `Diagnostic` for each `mock` import.
for name in names {
if &name.name == "mock" || &name.name == "mock.mock" {
if (&name.name == "mock" || &name.name == "mock.mock")
&& !is_import_required_by_isort(
&checker.settings().isort.required_imports,
stmt.into(),
name,
)
{
let mut diagnostic = checker.report_diagnostic(
DeprecatedMockImport {
reference_type: MockReference::Import,
@ -319,6 +326,7 @@ pub(crate) fn deprecated_mock_import(checker: &Checker, stmt: &Stmt) {
Stmt::ImportFrom(ast::StmtImportFrom {
module: Some(module),
level,
names,
..
}) => {
if *level > 0 {
@ -326,6 +334,17 @@ pub(crate) fn deprecated_mock_import(checker: &Checker, stmt: &Stmt) {
}
if module == "mock" {
if names.iter().any(|alias| {
alias.name.as_str() == "mock"
&& is_import_required_by_isort(
&checker.settings().isort.required_imports,
stmt.into(),
alias,
)
}) {
return;
}
let mut diagnostic = checker.report_diagnostic(
DeprecatedMockImport {
reference_type: MockReference::Import,