From 55ec09515c0647a276678a00c5a15da2176043b8 Mon Sep 17 00:00:00 2001 From: Dan Date: Sat, 21 Mar 2026 00:26:40 -0400 Subject: [PATCH 1/2] fix-19864 --- .../test/fixtures/pyupgrade/UP018.py | 16 + .../rules/pyupgrade/rules/native_literals.rs | 73 +++-- ...er__rules__pyupgrade__tests__UP018.py.snap | 279 ++++++++++++++++++ 3 files changed, 349 insertions(+), 19 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018.py b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018.py index 86b8d9aebfc4be..65525c56afcabc 100644 --- a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018.py +++ b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018.py @@ -94,3 +94,19 @@ # t-strings are not native literals str(t"hey") + +# UP018 - Extended detections +str("A" "B") +str( + "A" + "B" +) +str(object="!") +complex(1j) +complex(real=1j) +complex() +complex(0j) +complex(real=0j) +(complex(0j)).real +complex(1j).real +complex(real=1j).real diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs index c1b6d0d5404fb2..368501b34dc32b 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs @@ -16,6 +16,7 @@ enum LiteralType { Int, Float, Bool, + Complex, } impl FromStr for LiteralType { @@ -28,6 +29,7 @@ impl FromStr for LiteralType { "int" => Ok(LiteralType::Int), "float" => Ok(LiteralType::Float), "bool" => Ok(LiteralType::Bool), + "complex" => Ok(LiteralType::Complex), _ => Err(()), } } @@ -63,6 +65,15 @@ impl LiteralType { } .into(), LiteralType::Bool => ast::ExprBooleanLiteral::default().into(), + LiteralType::Complex => ast::ExprNumberLiteral { + value: ast::Number::Complex { + real: 0.0, + imag: 0.0, + }, + range: TextRange::default(), + node_index: ruff_python_ast::AtomicNodeIndex::NONE, + } + .into(), } } } @@ -78,7 +89,7 @@ impl TryFrom> for LiteralType { match value { ast::Number::Int(_) => Ok(LiteralType::Int), ast::Number::Float(_) => Ok(LiteralType::Float), - ast::Number::Complex { .. } => Err(()), + ast::Number::Complex { .. } => Ok(LiteralType::Complex), } } LiteralExpressionRef::BooleanLiteral(_) => Ok(LiteralType::Bool), @@ -97,12 +108,13 @@ impl fmt::Display for LiteralType { LiteralType::Int => fmt.write_str("int"), LiteralType::Float => fmt.write_str("float"), LiteralType::Bool => fmt.write_str("bool"), + LiteralType::Complex => fmt.write_str("complex"), } } } /// ## What it does -/// Checks for unnecessary calls to `str`, `bytes`, `int`, `float`, and `bool`. +/// Checks for unnecessary calls to `str`, `bytes`, `int`, `float`, `bool`, and `complex`. /// /// ## Why is this bad? /// The mentioned constructors can be replaced with their respective literal @@ -127,6 +139,7 @@ impl fmt::Display for LiteralType { /// - [Python documentation: `int`](https://docs.python.org/3/library/functions.html#int) /// - [Python documentation: `float`](https://docs.python.org/3/library/functions.html#float) /// - [Python documentation: `bool`](https://docs.python.org/3/library/functions.html#bool) +/// - [Python documentation: `complex`](https://docs.python.org/3/library/functions.html#complex) #[derive(ViolationMetadata)] #[violation_metadata(stable_since = "v0.0.193")] pub(crate) struct NativeLiterals { @@ -148,10 +161,23 @@ impl AlwaysFixableViolation for NativeLiterals { LiteralType::Int => "Replace with integer literal".to_string(), LiteralType::Float => "Replace with float literal".to_string(), LiteralType::Bool => "Replace with boolean literal".to_string(), + LiteralType::Complex => "Replace with complex literal".to_string(), } } } +/// Returns `true` if the keyword argument is redundant for the given builtin. +fn is_redundant_keyword(builtin: &str, keyword: &ast::Keyword) -> bool { + let Some(arg) = keyword.arg.as_ref() else { + return false; + }; + match builtin { + "str" => arg == "object", + "complex" => arg == "real", + _ => false, + } +} + /// UP018 pub(crate) fn native_literals( checker: &Checker, @@ -171,17 +197,21 @@ pub(crate) fn native_literals( node_index: _, } = call; - if !keywords.is_empty() || args.len() > 1 { - return; - } - - let tokens = checker.tokens(); let semantic = checker.semantic(); let Some(builtin) = semantic.resolve_builtin_symbol(func) else { return; }; + let call_arg = match (args.as_ref(), keywords.as_ref()) { + ([], []) => None, + ([arg], []) => Some(arg), + ([], [keyword]) if is_redundant_keyword(builtin, keyword) => Some(&keyword.value), + _ => return, + }; + + let tokens = checker.tokens(); + let Ok(literal_type) = LiteralType::from_str(builtin) else { return; }; @@ -198,19 +228,20 @@ pub(crate) fn native_literals( } } - match args.first() { + match call_arg { None => { - // Do not suggest fix for attribute access on an int like `int().attribute` - // Ex) `int().denominator` is valid but `0.denominator` is not - if literal_type == LiteralType::Int && matches!(parent_expr, Some(Expr::Attribute(_))) { - return; - } - let mut diagnostic = checker.report_diagnostic(NativeLiterals { literal_type }, call.range()); let expr = literal_type.as_zero_value_expr(checker); - let content = checker.generator().expr(&expr); + let mut content = checker.generator().expr(&expr); + + // Attribute access on an integer requires the integer to be parenthesized to disambiguate from a float + // Ex) `(0).denominator` is valid but `0.denominator` is not + if literal_type == LiteralType::Int && matches!(parent_expr, Some(Expr::Attribute(_))) { + content = format!("({content})"); + } + diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement( content, call.range(), @@ -218,10 +249,6 @@ pub(crate) fn native_literals( } Some(arg) => { let (has_unary_op, literal_expr) = if let Some(literal_expr) = arg.as_literal_expr() { - // Skip implicit concatenated strings. - if literal_expr.is_implicit_concatenated() { - return; - } (false, literal_expr) } else if let Expr::UnaryOp(ast::ExprUnaryOp { op: UnaryOp::UAdd | UnaryOp::USub, @@ -269,6 +296,14 @@ pub(crate) fn native_literals( // Expressions including newlines must be parenthesised to be valid syntax (_, _, true) if find_newline(arg_code).is_some() => format!("({arg_code})"), + // Implicitly concatenated strings spanning multiple lines must be parenthesized + (_, LiteralType::Str | LiteralType::Bytes, _) + if literal_expr.is_implicit_concatenated() + && find_newline(arg_code).is_some() => + { + format!("({arg_code})") + } + // Attribute access on an integer requires the integer to be parenthesized to disambiguate from a float // Ex) `(7).denominator` is valid but `7.denominator` is not // Note that floats do not have this problem diff --git a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP018.py.snap b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP018.py.snap index 05c508ea6f12a9..567f638b77558b 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP018.py.snap +++ b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP018.py.snap @@ -1,6 +1,68 @@ --- source: crates/ruff_linter/src/rules/pyupgrade/mod.rs --- +UP018 [*] Unnecessary `str` call (rewrite as a literal) + --> UP018.py:8:1 + | + 6 | str("foo", **k) + 7 | str("foo", encoding="UTF-8") + 8 | / str("foo" + 9 | | "bar") + | |__________^ +10 | str(b"foo") +11 | bytes("foo", encoding="UTF-8") + | +help: Replace with string literal +5 | str(**k) +6 | str("foo", **k) +7 | str("foo", encoding="UTF-8") + - str("foo" +8 + ("foo" +9 | "bar") +10 | str(b"foo") +11 | bytes("foo", encoding="UTF-8") + +UP018 [*] Unnecessary `bytes` call (rewrite as a literal) + --> UP018.py:15:1 + | +13 | bytes("foo", *a) +14 | bytes("foo", **a) +15 | / bytes(b"foo" +16 | | b"bar") + | |_____________^ +17 | bytes("foo") +18 | bytes(1) + | +help: Replace with bytes literal +12 | bytes(*a) +13 | bytes("foo", *a) +14 | bytes("foo", **a) + - bytes(b"foo" +15 + (b"foo" +16 | b"bar") +17 | bytes("foo") +18 | bytes(1) + +UP018 [*] Unnecessary `int` call (rewrite as a literal) + --> UP018.py:34:1 + | +32 | bool(b"") +33 | bool(1.0) +34 | int().denominator + | ^^^^^ +35 | +36 | # These become literals + | +help: Replace with integer literal +31 | bool("") +32 | bool(b"") +33 | bool(1.0) + - int().denominator +34 + (0).denominator +35 | +36 | # These become literals +37 | str() + UP018 [*] Unnecessary `str` call (rewrite as a literal) --> UP018.py:37:1 | @@ -667,3 +729,220 @@ help: Replace with boolean literal 93 | 94 | 95 | # t-strings are not native literals + +UP018 [*] Unnecessary `str` call (rewrite as a literal) + --> UP018.py:99:1 + | + 98 | # UP018 - Extended detections + 99 | str("A" "B") + | ^^^^^^^^^^^^ +100 | str( +101 | "A" + | +help: Replace with string literal +96 | str(t"hey") +97 | +98 | # UP018 - Extended detections + - str("A" "B") +99 + "A" "B" +100 | str( +101 | "A" +102 | "B" + +UP018 [*] Unnecessary `str` call (rewrite as a literal) + --> UP018.py:100:1 + | + 98 | # UP018 - Extended detections + 99 | str("A" "B") +100 | / str( +101 | | "A" +102 | | "B" +103 | | ) + | |_^ +104 | str(object="!") +105 | complex(1j) + | +help: Replace with string literal +97 | +98 | # UP018 - Extended detections +99 | str("A" "B") + - str( + - "A" + - "B" + - ) +100 + ("A" +101 + "B") +102 | str(object="!") +103 | complex(1j) +104 | complex(real=1j) + +UP018 [*] Unnecessary `str` call (rewrite as a literal) + --> UP018.py:104:1 + | +102 | "B" +103 | ) +104 | str(object="!") + | ^^^^^^^^^^^^^^^ +105 | complex(1j) +106 | complex(real=1j) + | +help: Replace with string literal +101 | "A" +102 | "B" +103 | ) + - str(object="!") +104 + "!" +105 | complex(1j) +106 | complex(real=1j) +107 | complex() + +UP018 [*] Unnecessary `complex` call (rewrite as a literal) + --> UP018.py:105:1 + | +103 | ) +104 | str(object="!") +105 | complex(1j) + | ^^^^^^^^^^^ +106 | complex(real=1j) +107 | complex() + | +help: Replace with complex literal +102 | "B" +103 | ) +104 | str(object="!") + - complex(1j) +105 + 1j +106 | complex(real=1j) +107 | complex() +108 | complex(0j) + +UP018 [*] Unnecessary `complex` call (rewrite as a literal) + --> UP018.py:106:1 + | +104 | str(object="!") +105 | complex(1j) +106 | complex(real=1j) + | ^^^^^^^^^^^^^^^^ +107 | complex() +108 | complex(0j) + | +help: Replace with complex literal +103 | ) +104 | str(object="!") +105 | complex(1j) + - complex(real=1j) +106 + 1j +107 | complex() +108 | complex(0j) +109 | complex(real=0j) + +UP018 [*] Unnecessary `complex` call (rewrite as a literal) + --> UP018.py:107:1 + | +105 | complex(1j) +106 | complex(real=1j) +107 | complex() + | ^^^^^^^^^ +108 | complex(0j) +109 | complex(real=0j) + | +help: Replace with complex literal +104 | str(object="!") +105 | complex(1j) +106 | complex(real=1j) + - complex() +107 + 0j +108 | complex(0j) +109 | complex(real=0j) +110 | (complex(0j)).real + +UP018 [*] Unnecessary `complex` call (rewrite as a literal) + --> UP018.py:108:1 + | +106 | complex(real=1j) +107 | complex() +108 | complex(0j) + | ^^^^^^^^^^^ +109 | complex(real=0j) +110 | (complex(0j)).real + | +help: Replace with complex literal +105 | complex(1j) +106 | complex(real=1j) +107 | complex() + - complex(0j) +108 + 0j +109 | complex(real=0j) +110 | (complex(0j)).real +111 | complex(1j).real + +UP018 [*] Unnecessary `complex` call (rewrite as a literal) + --> UP018.py:109:1 + | +107 | complex() +108 | complex(0j) +109 | complex(real=0j) + | ^^^^^^^^^^^^^^^^ +110 | (complex(0j)).real +111 | complex(1j).real + | +help: Replace with complex literal +106 | complex(real=1j) +107 | complex() +108 | complex(0j) + - complex(real=0j) +109 + 0j +110 | (complex(0j)).real +111 | complex(1j).real +112 | complex(real=1j).real + +UP018 [*] Unnecessary `complex` call (rewrite as a literal) + --> UP018.py:110:2 + | +108 | complex(0j) +109 | complex(real=0j) +110 | (complex(0j)).real + | ^^^^^^^^^^^ +111 | complex(1j).real +112 | complex(real=1j).real + | +help: Replace with complex literal +107 | complex() +108 | complex(0j) +109 | complex(real=0j) + - (complex(0j)).real +110 + (0j).real +111 | complex(1j).real +112 | complex(real=1j).real + +UP018 [*] Unnecessary `complex` call (rewrite as a literal) + --> UP018.py:111:1 + | +109 | complex(real=0j) +110 | (complex(0j)).real +111 | complex(1j).real + | ^^^^^^^^^^^ +112 | complex(real=1j).real + | +help: Replace with complex literal +108 | complex(0j) +109 | complex(real=0j) +110 | (complex(0j)).real + - complex(1j).real +111 + 1j.real +112 | complex(real=1j).real + +UP018 [*] Unnecessary `complex` call (rewrite as a literal) + --> UP018.py:112:1 + | +110 | (complex(0j)).real +111 | complex(1j).real +112 | complex(real=1j).real + | ^^^^^^^^^^^^^^^^ + | +help: Replace with complex literal +109 | complex(real=0j) +110 | (complex(0j)).real +111 | complex(1j).real + - complex(real=1j).real +112 + 1j.real From 2b55744f3e9ed0f9205b6cb3924810caff23feb4 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Mon, 30 Mar 2026 10:56:31 +0200 Subject: [PATCH 2/2] Code review feedback --- .../test/fixtures/pyupgrade/UP018.py | 1 + .../rules/pyupgrade/rules/native_literals.rs | 3 + ...er__rules__pyupgrade__tests__UP018.py.snap | 272 ++++++++++-------- 3 files changed, 150 insertions(+), 126 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018.py b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018.py index 65525c56afcabc..32f3f6fad51128 100644 --- a/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018.py +++ b/crates/ruff_linter/resources/test/fixtures/pyupgrade/UP018.py @@ -97,6 +97,7 @@ # UP018 - Extended detections str("A" "B") +str("A" "B").lower() str( "A" "B" diff --git a/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs b/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs index 368501b34dc32b..df90a5ac055f09 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs +++ b/crates/ruff_linter/src/rules/pyupgrade/rules/native_literals.rs @@ -173,6 +173,9 @@ fn is_redundant_keyword(builtin: &str, keyword: &ast::Keyword) -> bool { }; match builtin { "str" => arg == "object", + // Python 3.14 emits a `SyntaxWarning` for `complex(real=1j)`. While this + // does change the behavior, upgrading it to 1j is very much in the spirit of this rule + // and removing the `SyntaxWarning` is a nice side effect. "complex" => arg == "real", _ => false, } diff --git a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP018.py.snap b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP018.py.snap index 567f638b77558b..febc64ee3734bb 100644 --- a/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP018.py.snap +++ b/crates/ruff_linter/src/rules/pyupgrade/snapshots/ruff_linter__rules__pyupgrade__tests__UP018.py.snap @@ -736,8 +736,8 @@ UP018 [*] Unnecessary `str` call (rewrite as a literal) 98 | # UP018 - Extended detections 99 | str("A" "B") | ^^^^^^^^^^^^ -100 | str( -101 | "A" +100 | str("A" "B").lower() +101 | str( | help: Replace with string literal 96 | str(t"hey") @@ -745,204 +745,224 @@ help: Replace with string literal 98 | # UP018 - Extended detections - str("A" "B") 99 + "A" "B" -100 | str( -101 | "A" -102 | "B" +100 | str("A" "B").lower() +101 | str( +102 | "A" UP018 [*] Unnecessary `str` call (rewrite as a literal) --> UP018.py:100:1 | - 98 | # UP018 - Extended detections + 98 | # UP018 - Extended detections + 99 | str("A" "B") +100 | str("A" "B").lower() + | ^^^^^^^^^^^^ +101 | str( +102 | "A" + | +help: Replace with string literal +97 | +98 | # UP018 - Extended detections +99 | str("A" "B") + - str("A" "B").lower() +100 + "A" "B".lower() +101 | str( +102 | "A" +103 | "B" + +UP018 [*] Unnecessary `str` call (rewrite as a literal) + --> UP018.py:101:1 + | 99 | str("A" "B") -100 | / str( -101 | | "A" -102 | | "B" -103 | | ) +100 | str("A" "B").lower() +101 | / str( +102 | | "A" +103 | | "B" +104 | | ) | |_^ -104 | str(object="!") -105 | complex(1j) +105 | str(object="!") +106 | complex(1j) | help: Replace with string literal -97 | 98 | # UP018 - Extended detections 99 | str("A" "B") +100 | str("A" "B").lower() - str( - "A" - "B" - ) -100 + ("A" -101 + "B") -102 | str(object="!") -103 | complex(1j) -104 | complex(real=1j) +101 + ("A" +102 + "B") +103 | str(object="!") +104 | complex(1j) +105 | complex(real=1j) UP018 [*] Unnecessary `str` call (rewrite as a literal) - --> UP018.py:104:1 + --> UP018.py:105:1 | -102 | "B" -103 | ) -104 | str(object="!") +103 | "B" +104 | ) +105 | str(object="!") | ^^^^^^^^^^^^^^^ -105 | complex(1j) -106 | complex(real=1j) +106 | complex(1j) +107 | complex(real=1j) | help: Replace with string literal -101 | "A" -102 | "B" -103 | ) +102 | "A" +103 | "B" +104 | ) - str(object="!") -104 + "!" -105 | complex(1j) -106 | complex(real=1j) -107 | complex() +105 + "!" +106 | complex(1j) +107 | complex(real=1j) +108 | complex() UP018 [*] Unnecessary `complex` call (rewrite as a literal) - --> UP018.py:105:1 + --> UP018.py:106:1 | -103 | ) -104 | str(object="!") -105 | complex(1j) +104 | ) +105 | str(object="!") +106 | complex(1j) | ^^^^^^^^^^^ -106 | complex(real=1j) -107 | complex() +107 | complex(real=1j) +108 | complex() | help: Replace with complex literal -102 | "B" -103 | ) -104 | str(object="!") +103 | "B" +104 | ) +105 | str(object="!") - complex(1j) -105 + 1j -106 | complex(real=1j) -107 | complex() -108 | complex(0j) +106 + 1j +107 | complex(real=1j) +108 | complex() +109 | complex(0j) UP018 [*] Unnecessary `complex` call (rewrite as a literal) - --> UP018.py:106:1 + --> UP018.py:107:1 | -104 | str(object="!") -105 | complex(1j) -106 | complex(real=1j) +105 | str(object="!") +106 | complex(1j) +107 | complex(real=1j) | ^^^^^^^^^^^^^^^^ -107 | complex() -108 | complex(0j) +108 | complex() +109 | complex(0j) | help: Replace with complex literal -103 | ) -104 | str(object="!") -105 | complex(1j) +104 | ) +105 | str(object="!") +106 | complex(1j) - complex(real=1j) -106 + 1j -107 | complex() -108 | complex(0j) -109 | complex(real=0j) +107 + 1j +108 | complex() +109 | complex(0j) +110 | complex(real=0j) UP018 [*] Unnecessary `complex` call (rewrite as a literal) - --> UP018.py:107:1 + --> UP018.py:108:1 | -105 | complex(1j) -106 | complex(real=1j) -107 | complex() +106 | complex(1j) +107 | complex(real=1j) +108 | complex() | ^^^^^^^^^ -108 | complex(0j) -109 | complex(real=0j) +109 | complex(0j) +110 | complex(real=0j) | help: Replace with complex literal -104 | str(object="!") -105 | complex(1j) -106 | complex(real=1j) +105 | str(object="!") +106 | complex(1j) +107 | complex(real=1j) - complex() -107 + 0j -108 | complex(0j) -109 | complex(real=0j) -110 | (complex(0j)).real +108 + 0j +109 | complex(0j) +110 | complex(real=0j) +111 | (complex(0j)).real UP018 [*] Unnecessary `complex` call (rewrite as a literal) - --> UP018.py:108:1 + --> UP018.py:109:1 | -106 | complex(real=1j) -107 | complex() -108 | complex(0j) +107 | complex(real=1j) +108 | complex() +109 | complex(0j) | ^^^^^^^^^^^ -109 | complex(real=0j) -110 | (complex(0j)).real +110 | complex(real=0j) +111 | (complex(0j)).real | help: Replace with complex literal -105 | complex(1j) -106 | complex(real=1j) -107 | complex() +106 | complex(1j) +107 | complex(real=1j) +108 | complex() - complex(0j) -108 + 0j -109 | complex(real=0j) -110 | (complex(0j)).real -111 | complex(1j).real +109 + 0j +110 | complex(real=0j) +111 | (complex(0j)).real +112 | complex(1j).real UP018 [*] Unnecessary `complex` call (rewrite as a literal) - --> UP018.py:109:1 + --> UP018.py:110:1 | -107 | complex() -108 | complex(0j) -109 | complex(real=0j) +108 | complex() +109 | complex(0j) +110 | complex(real=0j) | ^^^^^^^^^^^^^^^^ -110 | (complex(0j)).real -111 | complex(1j).real +111 | (complex(0j)).real +112 | complex(1j).real | help: Replace with complex literal -106 | complex(real=1j) -107 | complex() -108 | complex(0j) +107 | complex(real=1j) +108 | complex() +109 | complex(0j) - complex(real=0j) -109 + 0j -110 | (complex(0j)).real -111 | complex(1j).real -112 | complex(real=1j).real +110 + 0j +111 | (complex(0j)).real +112 | complex(1j).real +113 | complex(real=1j).real UP018 [*] Unnecessary `complex` call (rewrite as a literal) - --> UP018.py:110:2 + --> UP018.py:111:2 | -108 | complex(0j) -109 | complex(real=0j) -110 | (complex(0j)).real +109 | complex(0j) +110 | complex(real=0j) +111 | (complex(0j)).real | ^^^^^^^^^^^ -111 | complex(1j).real -112 | complex(real=1j).real +112 | complex(1j).real +113 | complex(real=1j).real | help: Replace with complex literal -107 | complex() -108 | complex(0j) -109 | complex(real=0j) +108 | complex() +109 | complex(0j) +110 | complex(real=0j) - (complex(0j)).real -110 + (0j).real -111 | complex(1j).real -112 | complex(real=1j).real +111 + (0j).real +112 | complex(1j).real +113 | complex(real=1j).real UP018 [*] Unnecessary `complex` call (rewrite as a literal) - --> UP018.py:111:1 + --> UP018.py:112:1 | -109 | complex(real=0j) -110 | (complex(0j)).real -111 | complex(1j).real +110 | complex(real=0j) +111 | (complex(0j)).real +112 | complex(1j).real | ^^^^^^^^^^^ -112 | complex(real=1j).real +113 | complex(real=1j).real | help: Replace with complex literal -108 | complex(0j) -109 | complex(real=0j) -110 | (complex(0j)).real +109 | complex(0j) +110 | complex(real=0j) +111 | (complex(0j)).real - complex(1j).real -111 + 1j.real -112 | complex(real=1j).real +112 + 1j.real +113 | complex(real=1j).real UP018 [*] Unnecessary `complex` call (rewrite as a literal) - --> UP018.py:112:1 + --> UP018.py:113:1 | -110 | (complex(0j)).real -111 | complex(1j).real -112 | complex(real=1j).real +111 | (complex(0j)).real +112 | complex(1j).real +113 | complex(real=1j).real | ^^^^^^^^^^^^^^^^ | help: Replace with complex literal -109 | complex(real=0j) -110 | (complex(0j)).real -111 | complex(1j).real +110 | complex(real=0j) +111 | (complex(0j)).real +112 | complex(1j).real - complex(real=1j).real -112 + 1j.real +113 + 1j.real