Skip to content

Commit

Permalink
RUF031: Ignore unparenthesized tuples in subscripts when the subscr…
Browse files Browse the repository at this point in the history
…ipt is obviously a type annotation or type alias (#12762)
  • Loading branch information
AlexWaygood committed Aug 9, 2024
1 parent c4e6519 commit 83db48d
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 4 deletions.
10 changes: 9 additions & 1 deletion crates/ruff_linter/resources/test/fixtures/ruff/RUF031.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,12 @@
# Should keep these parentheses in
# Python <=3.10 to avoid syntax error.
# 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
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,12 @@
# Should keep these parentheses in
# Python <=3.10 to avoid syntax error.
# 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
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ use crate::{checkers::ast::Checker, settings::types::PythonVersion};
/// [`lint.ruff.parenthesize-tuple-in-subscript`]. By default, the use of
/// 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?
/// It is good to be consistent and, depending on the codebase, one or the other
/// convention may be preferred.
Expand Down Expand Up @@ -58,16 +62,20 @@ impl AlwaysFixableViolation for IncorrectlyParenthesizedTupleInSubscript {
/// RUF031
pub(crate) fn subscript_with_parenthesized_tuple(checker: &mut Checker, subscript: &ExprSubscript) {
let prefer_parentheses = checker.settings.ruff.parenthesize_tuple_in_subscript;

let Some(tuple_subscript) = subscript.slice.as_tuple_expr() else {
return;
};

if tuple_subscript.parenthesized == prefer_parentheses || tuple_subscript.elts.is_empty() {
return;
}

// 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) {
return;
}

// Removing parentheses in the presence of unpacking leads
// to a syntax error in Python 3.10.
// This is no longer a syntax error starting in Python 3.11
Expand All @@ -78,6 +86,14 @@ pub(crate) fn subscript_with_parenthesized_tuple(checker: &mut Checker, subscrip
{
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 source_range = subscript.slice.range();
let new_source = if prefer_parentheses {
Expand All @@ -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()
};
let edit = Edit::range_replacement(new_source, source_range);

checker.diagnostics.push(
Diagnostic::new(
IncorrectlyParenthesizedTupleInSubscript { prefer_parentheses },
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,14 +174,19 @@ RUF031.py:36:3: RUF031 [*] Avoid parentheses for tuples in subscripts.
|
34 | # Python <=3.10 to avoid syntax error.
35 | # https://github.com/astral-sh/ruff/issues/12776
36 | d[(*foo,bar)]
36 | d[(*foo,bar)]
| ^^^^^^^^^^ RUF031
37 |
38 | x: dict[str, int] # tuples inside type annotations should never be altered
|
= help: Remove the parentheses.

Safe fix
33 33 | # Should keep these parentheses in
34 34 | # Python <=3.10 to avoid syntax error.
35 35 | # https://github.com/astral-sh/ruff/issues/12776
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 |

0 comments on commit 83db48d

Please sign in to comment.