Mark UP043 fix unsafe when the type annotation contains any comments (#14458)
Some checks are pending
CI / Determine changes (push) Waiting to run
CI / cargo fmt (push) Waiting to run
CI / cargo clippy (push) Blocked by required conditions
CI / cargo test (linux) (push) Blocked by required conditions
CI / cargo test (windows) (push) Blocked by required conditions
CI / cargo test (wasm) (push) Blocked by required conditions
CI / cargo build (release) (push) Blocked by required conditions
CI / cargo build (msrv) (push) Blocked by required conditions
CI / cargo fuzz (push) Blocked by required conditions
CI / Fuzz the parser (push) Blocked by required conditions
CI / test scripts (push) Blocked by required conditions
CI / ecosystem (push) Blocked by required conditions
CI / cargo shear (push) Blocked by required conditions
CI / python package (push) Waiting to run
CI / pre-commit (push) Waiting to run
CI / mkdocs (push) Waiting to run
CI / formatter instabilities and black similarity (push) Blocked by required conditions
CI / test ruff-lsp (push) Blocked by required conditions
CI / benchmarks (push) Blocked by required conditions

This commit is contained in:
Micha Reiser 2024-11-19 15:24:02 +01:00 committed by GitHub
parent 5f09d4a90a
commit dbbe7a773c
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 69 additions and 21 deletions

View file

@ -50,3 +50,10 @@ def func() -> Generator[str, None, None]:
async def func() -> AsyncGenerator[str, None]:
yield "hello"
async def func() -> AsyncGenerator[ # type: ignore
str,
None
]:
yield "hello"

View file

@ -1,4 +1,4 @@
use ruff_diagnostics::{AlwaysFixableViolation, Diagnostic, Edit, Fix};
use ruff_diagnostics::{AlwaysFixableViolation, Applicability, Diagnostic, Edit, Fix};
use ruff_macros::{derive_message_formats, violation};
use ruff_python_ast::{self as ast, Expr};
use ruff_text_size::{Ranged, TextRange};
@ -44,6 +44,9 @@ use crate::checkers::ast::Checker;
/// yield 42
/// ```
///
/// ## Fix safety
/// This rule's fix is marked as safe, unless the type annotation contains comments.
///
/// ## References
/// - [PEP 696 Type Defaults for Type Parameters](https://peps.python.org/pep-0696/)
/// - [Annotating generators and coroutines](https://docs.python.org/3/library/typing.html#annotating-generators-and-coroutines)
@ -93,26 +96,39 @@ pub(crate) fn unnecessary_default_type_args(checker: &mut Checker, expr: &Expr)
}
let mut diagnostic = Diagnostic::new(UnnecessaryDefaultTypeArgs, expr.range());
diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
checker
.generator()
.expr(&Expr::Subscript(ast::ExprSubscript {
value: value.clone(),
slice: Box::new(if let [elt] = valid_elts.as_slice() {
elt.clone()
} else {
Expr::Tuple(ast::ExprTuple {
elts: valid_elts,
ctx: ast::ExprContext::Load,
range: TextRange::default(),
parenthesized: true,
})
}),
ctx: ast::ExprContext::Load,
range: TextRange::default(),
})),
expr.range(),
)));
let applicability = if checker
.comment_ranges()
.has_comments(expr, checker.source())
{
Applicability::Unsafe
} else {
Applicability::Safe
};
diagnostic.set_fix(Fix::applicable_edit(
Edit::range_replacement(
checker
.generator()
.expr(&Expr::Subscript(ast::ExprSubscript {
value: value.clone(),
slice: Box::new(if let [elt] = valid_elts.as_slice() {
elt.clone()
} else {
Expr::Tuple(ast::ExprTuple {
elts: valid_elts,
ctx: ast::ExprContext::Load,
range: TextRange::default(),
parenthesized: true,
})
}),
ctx: ast::ExprContext::Load,
range: TextRange::default(),
})),
expr.range(),
),
applicability,
));
checker.diagnostics.push(diagnostic);
}

View file

@ -108,3 +108,28 @@ UP043.py:51:21: UP043 [*] Unnecessary default type arguments
51 |-async def func() -> AsyncGenerator[str, None]:
51 |+async def func() -> AsyncGenerator[str]:
52 52 | yield "hello"
53 53 |
54 54 |
UP043.py:55:21: UP043 [*] Unnecessary default type arguments
|
55 | async def func() -> AsyncGenerator[ # type: ignore
| _____________________^
56 | | str,
57 | | None
58 | | ]:
| |_^ UP043
59 | yield "hello"
|
= help: Remove default type arguments
Unsafe fix
52 52 | yield "hello"
53 53 |
54 54 |
55 |-async def func() -> AsyncGenerator[ # type: ignore
56 |- str,
57 |- None
58 |-]:
55 |+async def func() -> AsyncGenerator[str]:
59 56 | yield "hello"