mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-02 06:41:23 +00:00
RUF031
: Ignore unparenthesized tuples in subscripts when the subscript is obviously a type annotation or type alias (#12762)
This commit is contained in:
parent
c4e651921b
commit
83db48d316
4 changed files with 42 additions and 4 deletions
|
@ -34,3 +34,11 @@ d[1,2,:]
|
||||||
# Python <=3.10 to avoid syntax error.
|
# Python <=3.10 to avoid syntax error.
|
||||||
# https://github.com/astral-sh/ruff/issues/12776
|
# https://github.com/astral-sh/ruff/issues/12776
|
||||||
d[(*foo,bar)]
|
d[(*foo,bar)]
|
||||||
|
|
||||||
|
x: dict[str, int] # tuples inside type annotations should never be altered
|
||||||
|
|
||||||
|
import typing
|
||||||
|
|
||||||
|
type Y = typing.Literal[1, 2]
|
||||||
|
Z: typing.TypeAlias = dict[int, int]
|
||||||
|
class Foo(dict[str, int]): pass
|
||||||
|
|
|
@ -34,3 +34,11 @@ d[1,2,:]
|
||||||
# Python <=3.10 to avoid syntax error.
|
# Python <=3.10 to avoid syntax error.
|
||||||
# https://github.com/astral-sh/ruff/issues/12776
|
# https://github.com/astral-sh/ruff/issues/12776
|
||||||
d[(*foo,bar)]
|
d[(*foo,bar)]
|
||||||
|
|
||||||
|
x: dict[str, int] # tuples inside type annotations should never be altered
|
||||||
|
|
||||||
|
import typing
|
||||||
|
|
||||||
|
type Y = typing.Literal[1, 2]
|
||||||
|
Z: typing.TypeAlias = dict[int, int]
|
||||||
|
class Foo(dict[str, int]): pass
|
||||||
|
|
|
@ -13,6 +13,10 @@ use crate::{checkers::ast::Checker, settings::types::PythonVersion};
|
||||||
/// [`lint.ruff.parenthesize-tuple-in-subscript`]. By default, the use of
|
/// [`lint.ruff.parenthesize-tuple-in-subscript`]. By default, the use of
|
||||||
/// parentheses is considered a violation.
|
/// parentheses is considered a violation.
|
||||||
///
|
///
|
||||||
|
/// This rule is not applied inside "typing contexts" (type annotations,
|
||||||
|
/// type aliases and subscripted class bases), as these have their own specific
|
||||||
|
/// conventions around them.
|
||||||
|
///
|
||||||
/// ## Why is this bad?
|
/// ## Why is this bad?
|
||||||
/// It is good to be consistent and, depending on the codebase, one or the other
|
/// It is good to be consistent and, depending on the codebase, one or the other
|
||||||
/// convention may be preferred.
|
/// convention may be preferred.
|
||||||
|
@ -58,16 +62,20 @@ impl AlwaysFixableViolation for IncorrectlyParenthesizedTupleInSubscript {
|
||||||
/// RUF031
|
/// RUF031
|
||||||
pub(crate) fn subscript_with_parenthesized_tuple(checker: &mut Checker, subscript: &ExprSubscript) {
|
pub(crate) fn subscript_with_parenthesized_tuple(checker: &mut Checker, subscript: &ExprSubscript) {
|
||||||
let prefer_parentheses = checker.settings.ruff.parenthesize_tuple_in_subscript;
|
let prefer_parentheses = checker.settings.ruff.parenthesize_tuple_in_subscript;
|
||||||
|
|
||||||
let Some(tuple_subscript) = subscript.slice.as_tuple_expr() else {
|
let Some(tuple_subscript) = subscript.slice.as_tuple_expr() else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if tuple_subscript.parenthesized == prefer_parentheses || tuple_subscript.elts.is_empty() {
|
if tuple_subscript.parenthesized == prefer_parentheses || tuple_subscript.elts.is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Adding parentheses in the presence of a slice leads to a syntax error.
|
// Adding parentheses in the presence of a slice leads to a syntax error.
|
||||||
if prefer_parentheses && tuple_subscript.elts.iter().any(Expr::is_slice_expr) {
|
if prefer_parentheses && tuple_subscript.elts.iter().any(Expr::is_slice_expr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removing parentheses in the presence of unpacking leads
|
// Removing parentheses in the presence of unpacking leads
|
||||||
// to a syntax error in Python 3.10.
|
// to a syntax error in Python 3.10.
|
||||||
// This is no longer a syntax error starting in Python 3.11
|
// This is no longer a syntax error starting in Python 3.11
|
||||||
|
@ -78,6 +86,14 @@ pub(crate) fn subscript_with_parenthesized_tuple(checker: &mut Checker, subscrip
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// subscripts in annotations, type definitions or class bases are typing subscripts.
|
||||||
|
// These have their own special conventions; skip applying the rule in these cases.
|
||||||
|
let semantic = checker.semantic();
|
||||||
|
if semantic.in_annotation() || semantic.in_type_definition() || semantic.in_class_base() {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
let locator = checker.locator();
|
let locator = checker.locator();
|
||||||
let source_range = subscript.slice.range();
|
let source_range = subscript.slice.range();
|
||||||
let new_source = if prefer_parentheses {
|
let new_source = if prefer_parentheses {
|
||||||
|
@ -86,6 +102,7 @@ pub(crate) fn subscript_with_parenthesized_tuple(checker: &mut Checker, subscrip
|
||||||
locator.slice(source_range)[1..source_range.len().to_usize() - 1].to_string()
|
locator.slice(source_range)[1..source_range.len().to_usize() - 1].to_string()
|
||||||
};
|
};
|
||||||
let edit = Edit::range_replacement(new_source, source_range);
|
let edit = Edit::range_replacement(new_source, source_range);
|
||||||
|
|
||||||
checker.diagnostics.push(
|
checker.diagnostics.push(
|
||||||
Diagnostic::new(
|
Diagnostic::new(
|
||||||
IncorrectlyParenthesizedTupleInSubscript { prefer_parentheses },
|
IncorrectlyParenthesizedTupleInSubscript { prefer_parentheses },
|
||||||
|
|
|
@ -176,6 +176,8 @@ RUF031.py:36:3: RUF031 [*] Avoid parentheses for tuples in subscripts.
|
||||||
35 | # https://github.com/astral-sh/ruff/issues/12776
|
35 | # https://github.com/astral-sh/ruff/issues/12776
|
||||||
36 | d[(*foo,bar)]
|
36 | d[(*foo,bar)]
|
||||||
| ^^^^^^^^^^ RUF031
|
| ^^^^^^^^^^ RUF031
|
||||||
|
37 |
|
||||||
|
38 | x: dict[str, int] # tuples inside type annotations should never be altered
|
||||||
|
|
|
|
||||||
= help: Remove the parentheses.
|
= help: Remove the parentheses.
|
||||||
|
|
||||||
|
@ -185,3 +187,6 @@ RUF031.py:36:3: RUF031 [*] Avoid parentheses for tuples in subscripts.
|
||||||
35 35 | # https://github.com/astral-sh/ruff/issues/12776
|
35 35 | # https://github.com/astral-sh/ruff/issues/12776
|
||||||
36 |-d[(*foo,bar)]
|
36 |-d[(*foo,bar)]
|
||||||
36 |+d[*foo,bar]
|
36 |+d[*foo,bar]
|
||||||
|
37 37 |
|
||||||
|
38 38 | x: dict[str, int] # tuples inside type annotations should never be altered
|
||||||
|
39 39 |
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue