From 5a74a8e5a1420b750c7b7960ce71964ee624f802 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Wed, 5 Jul 2023 15:22:22 -0400 Subject: [PATCH] Avoid syntax errors when rewriting str(dict) in f-strings (#5538) Closes https://github.com/astral-sh/ruff/issues/5530. --- .../ruff/resources/test/fixtures/ruff/RUF010.py | 4 ++++ .../src/rules/pylint/rules/type_bivariance.rs | 8 +++++++- .../pylint/rules/type_param_name_mismatch.rs | 8 +++++++- .../rules/explicit_f_string_type_conversion.rs | 15 ++++++++++++++- ...uff__rules__ruff__tests__RUF010_RUF010.py.snap | 2 ++ 5 files changed, 34 insertions(+), 3 deletions(-) diff --git a/crates/ruff/resources/test/fixtures/ruff/RUF010.py b/crates/ruff/resources/test/fixtures/ruff/RUF010.py index 77e459c21496a..031e08412fb02 100644 --- a/crates/ruff/resources/test/fixtures/ruff/RUF010.py +++ b/crates/ruff/resources/test/fixtures/ruff/RUF010.py @@ -34,3 +34,7 @@ def ascii(arg): " intermediary content " f" that flows {repr(obj)} of type {type(obj)}.{additional_message}" # RUF010 ) + + +# OK +f"{str({})}" diff --git a/crates/ruff/src/rules/pylint/rules/type_bivariance.rs b/crates/ruff/src/rules/pylint/rules/type_bivariance.rs index 724584a96259e..b8f3c98faa8db 100644 --- a/crates/ruff/src/rules/pylint/rules/type_bivariance.rs +++ b/crates/ruff/src/rules/pylint/rules/type_bivariance.rs @@ -74,7 +74,13 @@ impl Violation for TypeBivariance { /// PLC0131 pub(crate) fn type_bivariance(checker: &mut Checker, value: &Expr) { - let Expr::Call(ast::ExprCall { func,args, keywords, .. }) = value else { + let Expr::Call(ast::ExprCall { + func, + args, + keywords, + .. + }) = value + else { return; }; diff --git a/crates/ruff/src/rules/pylint/rules/type_param_name_mismatch.rs b/crates/ruff/src/rules/pylint/rules/type_param_name_mismatch.rs index 88e058312b693..e7bbc7ae04934 100644 --- a/crates/ruff/src/rules/pylint/rules/type_param_name_mismatch.rs +++ b/crates/ruff/src/rules/pylint/rules/type_param_name_mismatch.rs @@ -67,7 +67,13 @@ pub(crate) fn type_param_name_mismatch(checker: &mut Checker, value: &Expr, targ return; }; - let Expr::Call(ast::ExprCall { func, args, keywords, .. }) = value else { + let Expr::Call(ast::ExprCall { + func, + args, + keywords, + .. + }) = value + else { return; }; diff --git a/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs b/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs index 419fd6df410ca..408c4ffbcb2dc 100644 --- a/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs +++ b/crates/ruff/src/rules/ruff/rules/explicit_f_string_type_conversion.rs @@ -88,7 +88,20 @@ pub(crate) fn explicit_f_string_type_conversion( }; // Can't be a conversion otherwise. - if args.len() != 1 || !keywords.is_empty() { + if !keywords.is_empty() { + continue; + } + + // Can't be a conversion otherwise. + let [arg] = args.as_slice() else { + continue; + }; + + // Avoid attempting to rewrite, e.g., `f"{str({})}"`; the curly braces are problematic. + if matches!( + arg, + Expr::Dict(_) | Expr::Set(_) | Expr::DictComp(_) | Expr::SetComp(_) + ) { continue; } diff --git a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF010_RUF010.py.snap b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF010_RUF010.py.snap index ffbb12608b6f9..da5f4232c5eaa 100644 --- a/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF010_RUF010.py.snap +++ b/crates/ruff/src/rules/ruff/snapshots/ruff__rules__ruff__tests__RUF010_RUF010.py.snap @@ -243,5 +243,7 @@ RUF010.py:35:20: RUF010 [*] Use explicit conversion flag 35 |- f" that flows {repr(obj)} of type {type(obj)}.{additional_message}" # RUF010 35 |+ f" that flows {obj!r} of type {type(obj)}.{additional_message}" # RUF010 36 36 | ) +37 37 | +38 38 |