diff --git a/Cargo.lock b/Cargo.lock index f52c559219..287b62671a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2111,7 +2111,7 @@ dependencies = [ [[package]] name = "ruff_text_size" version = "0.0.0" -source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8078663b6c914c1cb86993e427764f7c422fc12c#8078663b6c914c1cb86993e427764f7c422fc12c" +source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=c174bbf1f29527edd43d432326327f16f47ab9e0#c174bbf1f29527edd43d432326327f16f47ab9e0" dependencies = [ "schemars", "serde", @@ -2199,7 +2199,7 @@ dependencies = [ [[package]] name = "rustpython-ast" version = "0.2.0" -source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8078663b6c914c1cb86993e427764f7c422fc12c#8078663b6c914c1cb86993e427764f7c422fc12c" +source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=c174bbf1f29527edd43d432326327f16f47ab9e0#c174bbf1f29527edd43d432326327f16f47ab9e0" dependencies = [ "is-macro", "num-bigint", @@ -2210,7 +2210,7 @@ dependencies = [ [[package]] name = "rustpython-format" version = "0.2.0" -source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8078663b6c914c1cb86993e427764f7c422fc12c#8078663b6c914c1cb86993e427764f7c422fc12c" +source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=c174bbf1f29527edd43d432326327f16f47ab9e0#c174bbf1f29527edd43d432326327f16f47ab9e0" dependencies = [ "bitflags 2.3.2", "itertools", @@ -2222,7 +2222,7 @@ dependencies = [ [[package]] name = "rustpython-literal" version = "0.2.0" -source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8078663b6c914c1cb86993e427764f7c422fc12c#8078663b6c914c1cb86993e427764f7c422fc12c" +source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=c174bbf1f29527edd43d432326327f16f47ab9e0#c174bbf1f29527edd43d432326327f16f47ab9e0" dependencies = [ "hexf-parse", "is-macro", @@ -2234,7 +2234,7 @@ dependencies = [ [[package]] name = "rustpython-parser" version = "0.2.0" -source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8078663b6c914c1cb86993e427764f7c422fc12c#8078663b6c914c1cb86993e427764f7c422fc12c" +source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=c174bbf1f29527edd43d432326327f16f47ab9e0#c174bbf1f29527edd43d432326327f16f47ab9e0" dependencies = [ "anyhow", "is-macro", @@ -2257,7 +2257,7 @@ dependencies = [ [[package]] name = "rustpython-parser-core" version = "0.2.0" -source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=8078663b6c914c1cb86993e427764f7c422fc12c#8078663b6c914c1cb86993e427764f7c422fc12c" +source = "git+https://github.com/astral-sh/RustPython-Parser.git?rev=c174bbf1f29527edd43d432326327f16f47ab9e0#c174bbf1f29527edd43d432326327f16f47ab9e0" dependencies = [ "is-macro", "memchr", diff --git a/Cargo.toml b/Cargo.toml index 047c7994ce..d48fedbf29 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -50,14 +50,14 @@ toml = { version = "0.7.2" } # v0.0.1 libcst = { git = "https://github.com/charliermarsh/LibCST", rev = "80e4c1399f95e5beb532fdd1e209ad2dbb470438" } -# Please tag the RustPython version everytime you update its revision here. +# Please tag the RustPython version everytime you update its revision here and in fuzz/Cargo.toml # Tagging the version ensures that older ruff versions continue to build from source even when we rebase our RustPython fork. -# Current tag: v0.0.6 -ruff_text_size = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8078663b6c914c1cb86993e427764f7c422fc12c" } -rustpython-ast = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8078663b6c914c1cb86993e427764f7c422fc12c" , default-features = false, features = ["num-bigint"]} -rustpython-format = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8078663b6c914c1cb86993e427764f7c422fc12c", default-features = false, features = ["num-bigint"] } -rustpython-literal = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8078663b6c914c1cb86993e427764f7c422fc12c", default-features = false } -rustpython-parser = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8078663b6c914c1cb86993e427764f7c422fc12c" , default-features = false, features = ["full-lexer", "num-bigint"] } +# Current tag: v0.0.7 +ruff_text_size = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "c174bbf1f29527edd43d432326327f16f47ab9e0" } +rustpython-ast = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "c174bbf1f29527edd43d432326327f16f47ab9e0" , default-features = false, features = ["num-bigint"]} +rustpython-format = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "c174bbf1f29527edd43d432326327f16f47ab9e0", default-features = false, features = ["num-bigint"] } +rustpython-literal = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "c174bbf1f29527edd43d432326327f16f47ab9e0", default-features = false } +rustpython-parser = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "c174bbf1f29527edd43d432326327f16f47ab9e0" , default-features = false, features = ["full-lexer", "num-bigint"] } [profile.release] lto = "fat" diff --git a/crates/ruff/src/test.rs b/crates/ruff/src/test.rs index d1682617d1..1c2eb7aefb 100644 --- a/crates/ruff/src/test.rs +++ b/crates/ruff/src/test.rs @@ -15,6 +15,7 @@ use ruff_python_ast::source_code::{Indexer, Locator, SourceFileBuilder, Stylist} use crate::autofix::{fix_file, FixResult}; use crate::directives; +#[cfg(not(fuzzing))] use crate::jupyter::Notebook; use crate::linter::{check_path, LinterResult}; use crate::message::{Emitter, EmitterContext, Message, TextEmitter}; diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/call.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/call.py new file mode 100644 index 0000000000..7a32b6cd28 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/call.py @@ -0,0 +1,83 @@ +from unittest.mock import MagicMock + + +def f(*args, **kwargs): + pass + +this_is_a_very_long_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd = 1 +session = MagicMock() +models = MagicMock() + +f() + +f(1) + +f(x=2) + +f(1, x=2) + +f( + this_is_a_very_long_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd +) +f( + this_is_a_very_long_keyword_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd=1 +) + +f( + 1, + mixed_very_long_arguments=1, +) + +f( + this_is_a_very_long_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd, + these_arguments_have_values_that_need_to_break_because_they_are_too_long1=(100000 - 100000000000), + these_arguments_have_values_that_need_to_break_because_they_are_too_long2="akshfdlakjsdfad" + "asdfasdfa", + these_arguments_have_values_that_need_to_break_because_they_are_too_long3=session, +) + +f( + # dangling comment +) + + +f( + only=1, short=1, arguments=1 +) + +f( + hey_this_is_a_long_call, it_has_funny_attributes_that_breaks_into_three_lines=1 +) + +f( + hey_this_is_a_very_long_call=1, it_has_funny_attributes_asdf_asdf=1, too_long_for_the_line=1, really=True +) + +# TODO(konstin): Call chains/fluent interface (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains) +result = ( + session.query(models.Customer.id) + .filter( + models.Customer.account_id == 10000, + models.Customer.email == "user@example.org", + ) + .order_by(models.Customer.id.asc()) + .all() +) +# TODO(konstin): Black has this special case for comment placement where everything stays in one line +f( + "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa" +) + +f( + session, + b=1, + ** # oddly placed end-of-line comment + dict() +) +f( + session, + b=1, + ** + # oddly placed own line comment + dict() +) + diff --git a/crates/ruff_python_formatter/src/comments/placement.rs b/crates/ruff_python_formatter/src/comments/placement.rs index f46f9b841a..2f72f863d8 100644 --- a/crates/ruff_python_formatter/src/comments/placement.rs +++ b/crates/ruff_python_formatter/src/comments/placement.rs @@ -989,7 +989,7 @@ fn handle_dict_unpacking_comment<'a>( match comment.enclosing_node() { // TODO: can maybe also add AnyNodeRef::Arguments here, but tricky to test due to // https://github.com/astral-sh/ruff/issues/5176 - AnyNodeRef::ExprDict(_) => {} + AnyNodeRef::ExprDict(_) | AnyNodeRef::Keyword(_) => {} _ => { return CommentPlacement::Default(comment); } @@ -1015,12 +1015,22 @@ fn handle_dict_unpacking_comment<'a>( ) .skip_trivia(); + // if the remaining tokens from the previous node are exactly `**`, + // re-assign the comment to the one that follows the stars + let mut count = 0; + // we start from the preceding node but we skip its token for token in tokens.by_ref() { // Skip closing parentheses that are not part of the node range if token.kind == TokenKind::RParen { continue; } + // The Keyword case + if token.kind == TokenKind::Star { + count += 1; + break; + } + // The dict case debug_assert!( matches!( token, @@ -1034,9 +1044,6 @@ fn handle_dict_unpacking_comment<'a>( break; } - // if the remaining tokens from the previous node is exactly `**`, - // re-assign the comment to the one that follows the stars - let mut count = 0; for token in tokens { if token.kind != TokenKind::Star { return CommentPlacement::Default(comment); @@ -1050,19 +1057,19 @@ fn handle_dict_unpacking_comment<'a>( CommentPlacement::Default(comment) } -// Own line comments coming after the node are always dangling comments -// ```python -// ( -// a -// # trailing a comment -// . # dangling comment -// # or this -// b -// ) -// ``` +/// Own line comments coming after the node are always dangling comments +/// ```python +/// ( +/// a +/// # trailing a comment +/// . # dangling comment +/// # or this +/// b +/// ) +/// ``` fn handle_attribute_comment<'a>( comment: DecoratedComment<'a>, - locator: &Locator, + _locator: &Locator, ) -> CommentPlacement<'a> { let Some(attribute) = comment.enclosing_node().expr_attribute() else { return CommentPlacement::Default(comment); @@ -1073,14 +1080,13 @@ fn handle_attribute_comment<'a>( return CommentPlacement::Default(comment); } - let between_value_and_attr = TextRange::new(attribute.value.end(), attribute.attr.start()); - - let dot = SimpleTokenizer::new(locator.contents(), between_value_and_attr) - .skip_trivia() - .next() - .expect("Expected the `.` character after the value"); - - if TextRange::new(dot.end(), attribute.attr.start()).contains(comment.slice().start()) { + if TextRange::new(attribute.value.end(), attribute.attr.start()) + .contains(comment.slice().start()) + { + // ```text + // value . attr + // ^^^^^^^ the range of dangling comments + // ``` if comment.line_position().is_end_of_line() { // Attach to node with b // ```python diff --git a/crates/ruff_python_formatter/src/expression/expr_call.rs b/crates/ruff_python_formatter/src/expression/expr_call.rs index 2e48d6aa56..0c9f7f443d 100644 --- a/crates/ruff_python_formatter/src/expression/expr_call.rs +++ b/crates/ruff_python_formatter/src/expression/expr_call.rs @@ -1,8 +1,10 @@ -use crate::comments::Comments; +use crate::builders::PyFormatterExtensions; +use crate::comments::{dangling_comments, Comments}; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; -use crate::{not_yet_implemented_custom_text, FormatNodeRule, PyFormatter}; +use crate::{AsFormat, FormatNodeRule, PyFormatter}; +use ruff_formatter::prelude::{format_with, group, soft_block_indent, text}; use ruff_formatter::{write, Buffer, FormatResult}; use rustpython_parser::ast::ExprCall; @@ -11,19 +13,75 @@ pub struct FormatExprCall; impl FormatNodeRule for FormatExprCall { fn fmt_fields(&self, item: &ExprCall, f: &mut PyFormatter) -> FormatResult<()> { - if item.args.is_empty() && item.keywords.is_empty() { - write!( + let ExprCall { + range: _, + func, + args, + keywords, + } = item; + + // We have a case with `f()` without any argument, which is a special case because we can + // have a comment with no node attachment inside: + // ```python + // f( + // # This function has a dangling comment + // ) + // ``` + if args.is_empty() && keywords.is_empty() { + let comments = f.context().comments().clone(); + let comments = comments.dangling_comments(item); + return write!( f, - [not_yet_implemented_custom_text("NOT_IMPLEMENTED_call()")] - ) - } else { - write!( - f, - [not_yet_implemented_custom_text( - "NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)" - )] - ) + [ + func.format(), + text("("), + dangling_comments(comments), + text(")") + ] + ); } + + let all_args = format_with(|f| { + f.join_comma_separated() + .entries( + // We have the parentheses from the call so the arguments never need any + args.iter() + .map(|arg| (arg, arg.format().with_options(Parenthesize::Never))), + ) + .nodes(keywords.iter()) + .finish() + }); + + write!( + f, + [ + func.format(), + text("("), + // The outer group is for things like + // ```python + // get_collection( + // hey_this_is_a_very_long_call, + // it_has_funny_attributes_asdf_asdf, + // too_long_for_the_line, + // really=True, + // ) + // ``` + // The inner group is for things like: + // ```python + // get_collection( + // hey_this_is_a_very_long_call, it_has_funny_attributes_asdf_asdf, really=True + // ) + // ``` + // TODO(konstin): Doesn't work see wrongly formatted test + &group(&soft_block_indent(&group(&all_args))), + text(")") + ] + ) + } + + fn fmt_dangling_comments(&self, _node: &ExprCall, _f: &mut PyFormatter) -> FormatResult<()> { + // Handled in `fmt_fields` + Ok(()) } } diff --git a/crates/ruff_python_formatter/src/other/keyword.rs b/crates/ruff_python_formatter/src/other/keyword.rs index d93a56d66a..47d3db19fc 100644 --- a/crates/ruff_python_formatter/src/other/keyword.rs +++ b/crates/ruff_python_formatter/src/other/keyword.rs @@ -13,10 +13,11 @@ impl FormatNodeRule for FormatKeyword { arg, value, } = item; - if let Some(argument) = arg { - write!(f, [argument.format(), text("=")])?; + if let Some(arg) = arg { + write!(f, [arg.format(), text("="), value.format()]) + } else { + // Comments after the stars are reassigned as trailing value comments + write!(f, [text("**"), value.format()]) } - - value.format().fmt(f) } } diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@attribute_access_on_number_literals.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@attribute_access_on_number_literals.py.snap index cfa4c7cd05..86e302320a 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@attribute_access_on_number_literals.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@attribute_access_on_number_literals.py.snap @@ -34,14 +34,18 @@ y = 100(no) ```diff --- Black +++ Ruff -@@ -1,22 +1,22 @@ --x = (123456789).bit_count() --x = (123456).__abs__() +@@ -1,19 +1,19 @@ + x = (123456789).bit_count() + x = (123456).__abs__() -x = (0.1).is_integer() -x = (1.0).imag -x = (1e1).imag -x = (1e-1).real --x = (123456789.123456789).hex() ++x = (.1).is_integer() ++x = (1.).imag ++x = (1E+1).imag ++x = (1E-1).real + x = (123456789.123456789).hex() -x = (123456789.123456789e123456789).real -x = (123456789e123456789).conjugate() -x = 123456789j.real @@ -49,58 +53,46 @@ y = 100(no) -x = 0xB1ACC.conjugate() -x = 0b1011.conjugate() -x = 0o777.real --x = (0.000000006).hex() --x = -100.0000j -+x = NOT_IMPLEMENTED_call() -+x = NOT_IMPLEMENTED_call() -+x = NOT_IMPLEMENTED_call() -+x = (1.).imag -+x = (1E+1).imag -+x = (1E-1).real -+x = NOT_IMPLEMENTED_call() +x = (123456789.123456789E123456789).real -+x = NOT_IMPLEMENTED_call() ++x = (123456789E123456789).conjugate() +x = 123456789J.real -+x = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+x = NOT_IMPLEMENTED_call() -+x = NOT_IMPLEMENTED_call() ++x = 123456789.123456789J.__add__((0b1011).bit_length()) ++x = (0XB1ACC).conjugate() ++x = (0B1011).conjugate() +x = (0O777).real -+x = NOT_IMPLEMENTED_call() + x = (0.000000006).hex() +-x = -100.0000j +x = -100.0000J if (10).real: ... - - y = 100[no] --y = 100(no) -+y = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ``` ## Ruff Output ```py -x = NOT_IMPLEMENTED_call() -x = NOT_IMPLEMENTED_call() -x = NOT_IMPLEMENTED_call() +x = (123456789).bit_count() +x = (123456).__abs__() +x = (.1).is_integer() x = (1.).imag x = (1E+1).imag x = (1E-1).real -x = NOT_IMPLEMENTED_call() +x = (123456789.123456789).hex() x = (123456789.123456789E123456789).real -x = NOT_IMPLEMENTED_call() +x = (123456789E123456789).conjugate() x = 123456789J.real -x = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -x = NOT_IMPLEMENTED_call() -x = NOT_IMPLEMENTED_call() +x = 123456789.123456789J.__add__((0b1011).bit_length()) +x = (0XB1ACC).conjugate() +x = (0B1011).conjugate() x = (0O777).real -x = NOT_IMPLEMENTED_call() +x = (0.000000006).hex() x = -100.0000J if (10).real: ... y = 100[no] -y = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +y = 100(no) ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@beginning_backslash.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@beginning_backslash.py.snap deleted file mode 100644 index 1bd0c3f921..0000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@beginning_backslash.py.snap +++ /dev/null @@ -1,39 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/beginning_backslash.py ---- -## Input - -```py -\ - - - - - -print("hello, world") -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1 +1 @@ --print("hello, world") -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -``` - -## Ruff Output - -```py -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -``` - -## Black Output - -```py -print("hello, world") -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@collections.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@collections.py.snap index a28e9d0841..51c59c4e9d 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@collections.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@collections.py.snap @@ -123,12 +123,11 @@ if True: -} +c = {1, 2, 3} x = (1,) --y = (narf(),) + y = (narf(),) -nested = { - (1, 2, 3), - (4, 5, 6), -} -+y = (NOT_IMPLEMENTED_call(),) +nested = {(1, 2, 3), (4, 5, 6)} nested_no_trailing_comma = {(1, 2, 3), (4, 5, 6)} nested_long_lines = [ @@ -145,40 +144,6 @@ if True: # looping over a 1-tuple should also not get wrapped for x in (1,): -@@ -70,7 +49,7 @@ - ] - - division_result_tuple = (6 / 2,) --print("foo %r", (foo.bar,)) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - if True: - IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = ( -@@ -79,21 +58,6 @@ - ) - - if True: -- ec2client.get_waiter("instance_stopped").wait( -- InstanceIds=[instance.id], -- WaiterConfig={ -- "Delay": 5, -- }, -- ) -- ec2client.get_waiter("instance_stopped").wait( -- InstanceIds=[instance.id], -- WaiterConfig={ -- "Delay": 5, -- }, -- ) -- ec2client.get_waiter("instance_stopped").wait( -- InstanceIds=[instance.id], -- WaiterConfig={ -- "Delay": 5, -- }, -- ) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ``` ## Ruff Output @@ -201,7 +166,7 @@ a = {1, 2, 3} b = {1, 2, 3} c = {1, 2, 3} x = (1,) -y = (NOT_IMPLEMENTED_call(),) +y = (narf(),) nested = {(1, 2, 3), (4, 5, 6)} nested_no_trailing_comma = {(1, 2, 3), (4, 5, 6)} nested_long_lines = [ @@ -235,7 +200,7 @@ for (x,) in (1,), (2,), (3,): ] division_result_tuple = (6 / 2,) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +print("foo %r", (foo.bar,)) if True: IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = ( @@ -244,9 +209,24 @@ if True: ) if True: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + ec2client.get_waiter("instance_stopped").wait( + InstanceIds=[instance.id], + WaiterConfig={ + "Delay": 5, + }, + ) + ec2client.get_waiter("instance_stopped").wait( + InstanceIds=[instance.id], + WaiterConfig={ + "Delay": 5, + }, + ) + ec2client.get_waiter("instance_stopped").wait( + InstanceIds=[instance.id], + WaiterConfig={ + "Delay": 5, + }, + ) ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments.py.snap index 1317f43548..30b27344f0 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments.py.snap @@ -130,42 +130,16 @@ async def wat(): # Some comment before a function. -@@ -35,20 +32,24 @@ +@@ -35,7 +32,7 @@ Possibly many lines. """ # FIXME: Some comment about why this function is crap but still in production. - import inner_imports + NOT_YET_IMPLEMENTED_StmtImport -- if inner_imports.are_evil(): -+ if NOT_IMPLEMENTED_call(): + if inner_imports.are_evil(): # Explains why we have this if. - # In great detail indeed. -- x = X() -- return x.method1() # type: ignore -+ x = NOT_IMPLEMENTED_call() -+ return NOT_IMPLEMENTED_call() # type: ignore - - # This return is also commented for some reason. - return default - - - # Explains why we use global state. --GLOBAL_STATE = {"a": a(1), "b": a(2), "c": a(3)} -+GLOBAL_STATE = { -+ "a": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), -+ "b": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), -+ "c": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), -+} - - - # Another comment! -@@ -78,19 +79,18 @@ - #'

This is pweave!

- - --@fast(really=True) -+@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@@ -82,8 +79,7 @@ async def wat(): # This comment, for some reason \ # contains a trailing backslash. @@ -174,12 +148,8 @@ async def wat(): + NOT_YET_IMPLEMENTED_StmtAsyncWith # Some more comments # Comment after ending a block. if result: -- print("A OK", file=sys.stdout) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - # Comment between things. -- print() -+ NOT_IMPLEMENTED_call() - + print("A OK", file=sys.stdout) +@@ -93,4 +89,4 @@ # Some closing comments. # Maybe Vim or Emacs directives for formatting. @@ -227,22 +197,18 @@ def function(default=None): # FIXME: Some comment about why this function is crap but still in production. NOT_YET_IMPLEMENTED_StmtImport - if NOT_IMPLEMENTED_call(): + if inner_imports.are_evil(): # Explains why we have this if. # In great detail indeed. - x = NOT_IMPLEMENTED_call() - return NOT_IMPLEMENTED_call() # type: ignore + x = X() + return x.method1() # type: ignore # This return is also commented for some reason. return default # Explains why we use global state. -GLOBAL_STATE = { - "a": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), - "b": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), - "c": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), -} +GLOBAL_STATE = {"a": a(1), "b": a(2), "c": a(3)} # Another comment! @@ -272,16 +238,16 @@ class Foo: #'

This is pweave!

-@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@fast(really=True) async def wat(): # This comment, for some reason \ # contains a trailing backslash. NOT_YET_IMPLEMENTED_StmtAsyncWith # Some more comments # Comment after ending a block. if result: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("A OK", file=sys.stdout) # Comment between things. - NOT_IMPLEMENTED_call() + print() # Some closing comments. diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments2.py.snap index c975d624f6..0b4edc1d0f 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments2.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments2.py.snap @@ -189,36 +189,16 @@ instruction()#comment with bad spacing # Please keep __all__ alphabetized within each category. -@@ -37,31 +33,35 @@ - # builtin types and objects - type, - object, -- object(), -- Exception(), -+ NOT_IMPLEMENTED_call(), -+ NOT_IMPLEMENTED_call(), - 42, - 100.0, - "spam", +@@ -45,7 +41,7 @@ # user-defined types and objects Cheese, -- Cheese("Wensleydale"), + Cheese("Wensleydale"), - SubBytes(b"spam"), -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), ++ SubBytes(b"NOT_YET_IMPLEMENTED_BYTE_STRING"), ] if "PYTHON" in os.environ: -- add_compiler(compiler_from_env()) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - else: - # for compiler in compilers.values(): - # add_compiler(compiler) -- add_compiler(compilers[(7.0, 32)]) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - # add_compiler(compilers[(7.1, 64)]) - - +@@ -60,8 +56,12 @@ # Comment before function. def inline_comments_in_brackets_ruin_everything(): if typedargslist: @@ -232,7 +212,7 @@ instruction()#comment with bad spacing children[0], body, children[-1], # type: ignore -@@ -72,14 +72,18 @@ +@@ -72,7 +72,11 @@ body, parameters.children[-1], # )2 ] @@ -245,42 +225,10 @@ instruction()#comment with bad spacing if ( self._proc is not None # has the child process finished? - and self._returncode is None - # the child process has finished, but the - # transport hasn't been notified yet? -- and self._proc.poll() is None -+ and NOT_IMPLEMENTED_call() is None - ): - pass - # no newline before or after -@@ -91,48 +95,14 @@ - ] - - # no newline after -- call( -- arg1, -- arg2, -- """ --short --""", -- arg3=True, -- ) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - ############################################################################ - -- call2( -- # short -- arg1, -- # but -- arg2, -- # multiline -- """ --short --""", -- # yup -- arg3=True, -- ) +@@ -114,25 +118,9 @@ + # yup + arg3=True, + ) - lcomp = [ - element for element in collection if element is not None # yup # yup # right - ] @@ -300,26 +248,25 @@ instruction()#comment with bad spacing - # right - if element is not None - ] -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + lcomp = [i for i in []] + lcomp2 = [i for i in []] + lcomp3 = [i for i in []] while True: if False: continue -@@ -141,10 +111,7 @@ - # and round and round we go - +@@ -143,7 +131,10 @@ # let's return -- return Node( -- syms.simple_stmt, + return Node( + syms.simple_stmt, - [Node(statement, result), Leaf(token.NEWLINE, "\n")], # FIXME: \r\n? -- ) -+ return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ [ ++ Node(statement, result), ++ Leaf(token.NEWLINE, "\n"), # FIXME: \r\n? ++ ], + ) - CONFIG_FILES = ( -@@ -158,7 +125,11 @@ +@@ -158,7 +149,11 @@ class Test: def _init_host(self, parsed) -> None: @@ -327,20 +274,11 @@ instruction()#comment with bad spacing + if ( + parsed.hostname + is None # type: ignore -+ or not NOT_IMPLEMENTED_call() ++ or not parsed.hostname.strip() + ): pass -@@ -167,7 +138,7 @@ - ####################### - - --instruction() # comment with bad spacing -+NOT_IMPLEMENTED_call() # comment with bad spacing - - # END COMMENTS - # MORE END COMMENTS ``` ## Ruff Output @@ -381,23 +319,23 @@ not_shareables = [ # builtin types and objects type, object, - NOT_IMPLEMENTED_call(), - NOT_IMPLEMENTED_call(), + object(), + Exception(), 42, 100.0, "spam", # user-defined types and objects Cheese, - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), + Cheese("Wensleydale"), + SubBytes(b"NOT_YET_IMPLEMENTED_BYTE_STRING"), ] if "PYTHON" in os.environ: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + add_compiler(compiler_from_env()) else: # for compiler in compilers.values(): # add_compiler(compiler) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + add_compiler(compilers[(7.0, 32)]) # add_compiler(compilers[(7.1, 64)]) @@ -431,7 +369,7 @@ def inline_comments_in_brackets_ruin_everything(): and self._returncode is None # the child process has finished, but the # transport hasn't been notified yet? - and NOT_IMPLEMENTED_call() is None + and self._proc.poll() is None ): pass # no newline before or after @@ -443,11 +381,29 @@ def inline_comments_in_brackets_ruin_everything(): ] # no newline after - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + call( + arg1, + arg2, + """ +short +""", + arg3=True, + ) ############################################################################ - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + call2( + # short + arg1, + # but + arg2, + # multiline + """ +short +""", + # yup + arg3=True, + ) lcomp = [i for i in []] lcomp2 = [i for i in []] lcomp3 = [i for i in []] @@ -459,7 +415,13 @@ def inline_comments_in_brackets_ruin_everything(): # and round and round we go # let's return - return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + return Node( + syms.simple_stmt, + [ + Node(statement, result), + Leaf(token.NEWLINE, "\n"), # FIXME: \r\n? + ], + ) CONFIG_FILES = ( @@ -476,7 +438,7 @@ class Test: if ( parsed.hostname is None # type: ignore - or not NOT_IMPLEMENTED_call() + or not parsed.hostname.strip() ): pass @@ -486,7 +448,7 @@ class Test: ####################### -NOT_IMPLEMENTED_call() # comment with bad spacing +instruction() # comment with bad spacing # END COMMENTS # MORE END COMMENTS diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments3.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments3.py.snap index 5bd61dca47..a656b77f09 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments3.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments3.py.snap @@ -60,7 +60,7 @@ def func(): ```diff --- Black +++ Ruff -@@ -6,43 +6,16 @@ +@@ -6,14 +6,7 @@ x = """ a really long string """ @@ -74,40 +74,17 @@ def func(): - ] + lcomp3 = [i for i in []] # Capture each of the exceptions in the MultiError along with each of their causes and contexts -- if isinstance(exc_value, MultiError): -+ if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): + if isinstance(exc_value, MultiError): embedded = [] - for exc in exc_value.exceptions: - if exc not in _seen: -- embedded.append( -- # This should be left alone (before) -- traceback.TracebackException.from_exception( -- exc, -- limit=limit, -- lookup_lines=lookup_lines, -- capture_locals=capture_locals, -- # copy the set of _seen exceptions so that duplicates -- # shared between sub-exceptions are not omitted -- _seen=set(_seen), +@@ -29,7 +22,7 @@ + # copy the set of _seen exceptions so that duplicates + # shared between sub-exceptions are not omitted + _seen=set(_seen), - ) -- # This should be left alone (after) -- ) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ ), + # This should be left alone (after) + ) - # everything is fine if the expression isn't nested -- traceback.TracebackException.from_exception( -- exc, -- limit=limit, -- lookup_lines=lookup_lines, -- capture_locals=capture_locals, -- # copy the set of _seen exceptions so that duplicates -- # shared between sub-exceptions are not omitted -- _seen=set(_seen), -- ) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - - # %% ``` ## Ruff Output @@ -123,14 +100,34 @@ def func(): """ lcomp3 = [i for i in []] # Capture each of the exceptions in the MultiError along with each of their causes and contexts - if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): + if isinstance(exc_value, MultiError): embedded = [] for exc in exc_value.exceptions: if exc not in _seen: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + embedded.append( + # This should be left alone (before) + traceback.TracebackException.from_exception( + exc, + limit=limit, + lookup_lines=lookup_lines, + capture_locals=capture_locals, + # copy the set of _seen exceptions so that duplicates + # shared between sub-exceptions are not omitted + _seen=set(_seen), + ), + # This should be left alone (after) + ) # everything is fine if the expression isn't nested - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + traceback.TracebackException.from_exception( + exc, + limit=limit, + lookup_lines=lookup_lines, + capture_locals=capture_locals, + # copy the set of _seen exceptions so that duplicates + # shared between sub-exceptions are not omitted + _seen=set(_seen), + ) # %% diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments4.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments4.py.snap index 7b3c1751cc..2358992e6c 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments4.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments4.py.snap @@ -106,7 +106,7 @@ def foo3(list_a, list_b): ```diff --- Black +++ Ruff -@@ -1,94 +1,28 @@ +@@ -1,9 +1,5 @@ -from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( - MyLovelyCompanyTeamProjectComponent, # NOT DRY -) @@ -118,72 +118,27 @@ def foo3(list_a, list_b): class C: -- @pytest.mark.parametrize( -- ("post_data", "message"), -- [ -- # metadata_version errors. -- ( -- {}, -- "None is an invalid value for Metadata-Version. Error: This field is" -- " required. see" -- " https://packaging.python.org/specifications/core-metadata", -- ), -- ( -- {"metadata_version": "-1"}, -- "'-1' is an invalid value for Metadata-Version. Error: Unknown Metadata" -- " Version see" -- " https://packaging.python.org/specifications/core-metadata", -- ), -- # name errors. -- ( -- {"metadata_version": "1.2"}, -- "'' is an invalid value for Name. Error: This field is required. see" -- " https://packaging.python.org/specifications/core-metadata", -- ), -- ( -- {"metadata_version": "1.2", "name": "foo-"}, -- "'foo-' is an invalid value for Name. Error: Must start and end with a" -- " letter or numeral and contain only ascii numeric and '.', '_' and" -- " '-'. see https://packaging.python.org/specifications/core-metadata", -- ), -- # version errors. -- ( -- {"metadata_version": "1.2", "name": "example"}, -- "'' is an invalid value for Version. Error: This field is required. see" -- " https://packaging.python.org/specifications/core-metadata", -- ), -- ( -- {"metadata_version": "1.2", "name": "example", "version": "dog"}, -- "'dog' is an invalid value for Version. Error: Must start and end with" -- " a letter or numeral and contain only ascii numeric and '.', '_' and" -- " '-'. see https://packaging.python.org/specifications/core-metadata", -- ), -- ], -- ) -+ @NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - def test_fails_invalid_post_data( - self, pyramid_config, db_request, post_data, message - ): -- pyramid_config.testing_securitypolicy(userid=1) -- db_request.POST = MultiDict(post_data) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ db_request.POST = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - +@@ -58,37 +54,28 @@ def foo(list_a, list_b): -- results = ( + results = ( - User.query.filter(User.foo == "bar") - .filter( # Because foo. -- db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) ++ User.query.filter(User.foo == "bar").filter( # Because foo. + db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) - ) - .filter(User.xyz.is_(None)) -- # Another comment about the filtering on is_quux goes here. ++ ).filter(User.xyz.is_(None)). + # Another comment about the filtering on is_quux goes here. - .filter(db.not_(User.is_pending.astext.cast(db.Boolean).is_(True))) - .order_by(User.created_at.desc()) - .with_for_update(key_share=True) - .all() - ) -+ results = NOT_IMPLEMENTED_call() ++ filter ++ )(db.not_(User.is_pending.astext.cast(db.Boolean).is_(True))).order_by( ++ User.created_at.desc() ++ ).with_for_update(key_share=True).all() return results @@ -196,7 +151,9 @@ def foo3(list_a, list_b): - ) - .filter(User.xyz.is_(None)) - ) -+ return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ return User.query.filter(User.foo == "bar").filter( ++ db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) ++ ).filter(User.xyz.is_(None)) def foo3(list_a, list_b): @@ -204,10 +161,11 @@ def foo3(list_a, list_b): # Standalone comment but weirdly placed. - User.query.filter(User.foo == "bar") - .filter( -- db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) ++ User.query.filter(User.foo == "bar").filter( + db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) - ) - .filter(User.xyz.is_(None)) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ ).filter(User.xyz.is_(None)) ) ``` @@ -219,28 +177,81 @@ NOT_YET_IMPLEMENTED_StmtImportFrom class C: - @NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + @pytest.mark.parametrize( + ("post_data", "message"), + [ + # metadata_version errors. + ( + {}, + "None is an invalid value for Metadata-Version. Error: This field is" + " required. see" + " https://packaging.python.org/specifications/core-metadata", + ), + ( + {"metadata_version": "-1"}, + "'-1' is an invalid value for Metadata-Version. Error: Unknown Metadata" + " Version see" + " https://packaging.python.org/specifications/core-metadata", + ), + # name errors. + ( + {"metadata_version": "1.2"}, + "'' is an invalid value for Name. Error: This field is required. see" + " https://packaging.python.org/specifications/core-metadata", + ), + ( + {"metadata_version": "1.2", "name": "foo-"}, + "'foo-' is an invalid value for Name. Error: Must start and end with a" + " letter or numeral and contain only ascii numeric and '.', '_' and" + " '-'. see https://packaging.python.org/specifications/core-metadata", + ), + # version errors. + ( + {"metadata_version": "1.2", "name": "example"}, + "'' is an invalid value for Version. Error: This field is required. see" + " https://packaging.python.org/specifications/core-metadata", + ), + ( + {"metadata_version": "1.2", "name": "example", "version": "dog"}, + "'dog' is an invalid value for Version. Error: Must start and end with" + " a letter or numeral and contain only ascii numeric and '.', '_' and" + " '-'. see https://packaging.python.org/specifications/core-metadata", + ), + ], + ) def test_fails_invalid_post_data( self, pyramid_config, db_request, post_data, message ): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - db_request.POST = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + pyramid_config.testing_securitypolicy(userid=1) + db_request.POST = MultiDict(post_data) def foo(list_a, list_b): - results = NOT_IMPLEMENTED_call() + results = ( + User.query.filter(User.foo == "bar").filter( # Because foo. + db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) + ).filter(User.xyz.is_(None)). + # Another comment about the filtering on is_quux goes here. + filter + )(db.not_(User.is_pending.astext.cast(db.Boolean).is_(True))).order_by( + User.created_at.desc() + ).with_for_update(key_share=True).all() return results def foo2(list_a, list_b): # Standalone comment reasonably placed. - return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + return User.query.filter(User.foo == "bar").filter( + db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) + ).filter(User.xyz.is_(None)) def foo3(list_a, list_b): return ( # Standalone comment but weirdly placed. - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + User.query.filter(User.foo == "bar").filter( + db.or_(User.field_a.astext.in_(list_a), User.field_b.astext.in_(list_b)) + ).filter(User.xyz.is_(None)) ) ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments5.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments5.py.snap index 68ef84e041..2a8d41d0ae 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments5.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments5.py.snap @@ -85,38 +85,14 @@ if __name__ == "__main__": ```diff --- Black +++ Ruff -@@ -1,6 +1,6 @@ - while True: - if something.changed: -- do.stuff() # trailing comment -+ NOT_IMPLEMENTED_call() # trailing comment - # Comment belongs to the `if` block. - # This one belongs to the `while` block. +@@ -20,14 +20,9 @@ + with open(some_temp_file) as f: + data = f.read() -@@ -8,26 +8,21 @@ - - # This one is properly standalone now. - --for i in range(100): -+for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - # first we do this - if i % 33 == 0: - break - - # then we do this -- print(i) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - # and finally we loop around - --with open(some_temp_file) as f: -- data = f.read() -- -try: - with open(some_other_file) as w: - w.write(data) -+with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) as f: -+ data = NOT_IMPLEMENTED_call() - +- -except OSError: - print("problems") +NOT_YET_IMPLEMENTED_StmtTry @@ -126,30 +102,6 @@ if __name__ == "__main__": # leading function comment -@@ -42,7 +37,7 @@ - # leading 1 - @deco1 - # leading 2 --@deco2(with_args=True) -+@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - # leading 3 - @deco3 - def decorated1(): -@@ -52,7 +47,7 @@ - # leading 1 - @deco1 - # leading 2 --@deco2(with_args=True) -+@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - # leading function comment - def decorated1(): - ... -@@ -70,4 +65,4 @@ - - - if __name__ == "__main__": -- main() -+ NOT_IMPLEMENTED_call() ``` ## Ruff Output @@ -157,7 +109,7 @@ if __name__ == "__main__": ```py while True: if something.changed: - NOT_IMPLEMENTED_call() # trailing comment + do.stuff() # trailing comment # Comment belongs to the `if` block. # This one belongs to the `while` block. @@ -165,17 +117,17 @@ while True: # This one is properly standalone now. -for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): +for i in range(100): # first we do this if i % 33 == 0: break # then we do this - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print(i) # and finally we loop around -with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) as f: - data = NOT_IMPLEMENTED_call() +with open(some_temp_file) as f: + data = f.read() NOT_YET_IMPLEMENTED_StmtTry @@ -194,7 +146,7 @@ def wat(): # leading 1 @deco1 # leading 2 -@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@deco2(with_args=True) # leading 3 @deco3 def decorated1(): @@ -204,7 +156,7 @@ def decorated1(): # leading 1 @deco1 # leading 2 -@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@deco2(with_args=True) # leading function comment def decorated1(): ... @@ -222,7 +174,7 @@ def g(): if __name__ == "__main__": - NOT_IMPLEMENTED_call() + main() ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments6.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments6.py.snap index 120d15c6fe..8c11b63f62 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments6.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments6.py.snap @@ -136,44 +136,30 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite def f( -@@ -49,10 +49,11 @@ +@@ -49,9 +49,7 @@ element = 0 # type: int another_element = 1 # type: float another_element_with_long_name = 2 # type: int - another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style = ( - 3 - ) # type: int -- an_element_with_a_long_value = calls() or more_calls() and more() # type: bool + another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style = 3 # type: int -+ an_element_with_a_long_value = ( -+ NOT_IMPLEMENTED_call() -+ or NOT_IMPLEMENTED_call() and NOT_IMPLEMENTED_call() -+ ) # type: bool + an_element_with_a_long_value = calls() or more_calls() and more() # type: bool tup = ( - another_element, -@@ -86,33 +87,20 @@ - def func( - a=some_list[0], # type: int - ): # type: () -> int -- c = call( -- 0.0123, -- 0.0456, -- 0.0789, -- 0.0123, -- 0.0456, -- 0.0789, -- 0.0123, -- 0.0456, -- 0.0789, -- a[-1], # type: ignore -- ) -+ c = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@@ -100,19 +98,35 @@ + ) -- c = call( + c = call( - "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa" # type: ignore -- ) -+ c = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ "aaaaaaaa", ++ "aaaaaaaa", ++ "aaaaaaaa", ++ "aaaaaaaa", ++ "aaaaaaaa", ++ "aaaaaaaa", ++ "aaaaaaaa", # type: ignore + ) -result = ( # aaa @@ -189,14 +175,21 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite + + AAAAAAAAAAAAA +) # type: ignore --call_to_some_function_asdf( -- foo, + call_to_some_function_asdf( + foo, - [AAAAAAAAAAAAAAAAAAAAAAA, AAAAAAAAAAAAAAAAAAAAAAA, AAAAAAAAAAAAAAAAAAAAAAA, BBBBBBBBBBBB], # type: ignore --) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ [ ++ AAAAAAAAAAAAAAAAAAAAAAA, ++ AAAAAAAAAAAAAAAAAAAAAAA, ++ AAAAAAAAAAAAAAAAAAAAAAA, ++ BBBBBBBBBBBB, ++ ], # type: ignore + ) -aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*items))) # type: ignore[arg-type] -+aaaaaaaaaaaaa, bbbbbbbbb = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) # type: ignore[arg-type] ++aaaaaaaaaaaaa, bbbbbbbbb = map( ++ list, map(itertools.chain.from_iterable, zip(*NOT_YET_IMPLEMENTED_ExprStarred)) ++) # type: ignore[arg-type] ``` ## Ruff Output @@ -254,10 +247,7 @@ def f( another_element = 1 # type: float another_element_with_long_name = 2 # type: int another_really_really_long_element_with_a_unnecessarily_long_name_to_describe_what_it_does_enterprise_style = 3 # type: int - an_element_with_a_long_value = ( - NOT_IMPLEMENTED_call() - or NOT_IMPLEMENTED_call() and NOT_IMPLEMENTED_call() - ) # type: bool + an_element_with_a_long_value = calls() or more_calls() and more() # type: bool tup = ( another_element, @@ -291,9 +281,28 @@ def f( def func( a=some_list[0], # type: int ): # type: () -> int - c = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + c = call( + 0.0123, + 0.0456, + 0.0789, + 0.0123, + 0.0456, + 0.0789, + 0.0123, + 0.0456, + 0.0789, + a[-1], # type: ignore + ) - c = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + c = call( + "aaaaaaaa", + "aaaaaaaa", + "aaaaaaaa", + "aaaaaaaa", + "aaaaaaaa", + "aaaaaaaa", + "aaaaaaaa", # type: ignore + ) result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # aaa @@ -305,9 +314,19 @@ AAAAAAAAAAAAA = ( + AAAAAAAAAAAAA ) # type: ignore -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +call_to_some_function_asdf( + foo, + [ + AAAAAAAAAAAAAAAAAAAAAAA, + AAAAAAAAAAAAAAAAAAAAAAA, + AAAAAAAAAAAAAAAAAAAAAAA, + BBBBBBBBBBBB, + ], # type: ignore +) -aaaaaaaaaaaaa, bbbbbbbbb = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) # type: ignore[arg-type] +aaaaaaaaaaaaa, bbbbbbbbb = map( + list, map(itertools.chain.from_iterable, zip(*NOT_YET_IMPLEMENTED_ExprStarred)) +) # type: ignore[arg-type] ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments9.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments9.py.snap index b6b4ce39f0..2399d84c1b 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments9.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments9.py.snap @@ -151,33 +151,6 @@ def bar(): ```diff --- Black +++ Ruff -@@ -59,7 +59,7 @@ - @deco1 - # leading 2 - # leading 2 extra --@deco2(with_args=True) -+@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - # leading 3 - @deco3 - # leading 4 -@@ -73,7 +73,7 @@ - # leading 1 - @deco1 - # leading 2 --@deco2(with_args=True) -+@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - # leading 3 that already has an empty line - @deco3 -@@ -88,7 +88,7 @@ - # leading 1 - @deco1 - # leading 2 --@deco2(with_args=True) -+@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - # leading 3 - @deco3 - @@ -106,7 +106,6 @@ # Another leading comment def another_inline(): @@ -260,7 +233,7 @@ some = statement @deco1 # leading 2 # leading 2 extra -@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@deco2(with_args=True) # leading 3 @deco3 # leading 4 @@ -274,7 +247,7 @@ some = statement # leading 1 @deco1 # leading 2 -@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@deco2(with_args=True) # leading 3 that already has an empty line @deco3 @@ -289,7 +262,7 @@ some = statement # leading 1 @deco1 # leading 2 -@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@deco2(with_args=True) # leading 3 @deco3 diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments_non_breaking_space.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments_non_breaking_space.py.snap index cae2d7d069..12fd5c1269 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments_non_breaking_space.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@comments_non_breaking_space.py.snap @@ -31,7 +31,7 @@ def function(a:int=42): ```diff --- Black +++ Ruff -@@ -1,22 +1,17 @@ +@@ -1,9 +1,4 @@ -from .config import ( - ConfigTypeAttributes, - Int, @@ -42,11 +42,7 @@ def function(a:int=42): result = 1 # A simple comment result = (1,) # Another one - - result = 1 #  type: ignore - result = 1 # This comment is talking about type: ignore --square = Square(4) #  type: Optional[Square] -+square = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) #  type: Optional[Square] +@@ -14,9 +9,9 @@ def function(a: int = 42): @@ -71,7 +67,7 @@ result = (1,) # Another one result = 1 #  type: ignore result = 1 # This comment is talking about type: ignore -square = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) #  type: Optional[Square] +square = Square(4) #  type: Optional[Square] def function(a: int = 42): diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@composition.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@composition.py.snap index 127846ac18..deda69dc2e 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@composition.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@composition.py.snap @@ -193,69 +193,41 @@ class C: ```diff --- Black +++ Ruff -@@ -1,23 +1,10 @@ - class C: - def test(self) -> None: -- with patch("black.out", print): -- self.assertEqual( -- unstyle(str(report)), "1 file reformatted, 1 file failed to reformat." -- ) -- self.assertEqual( -- unstyle(str(report)), -- "1 file reformatted, 1 file left unchanged, 1 file failed to reformat.", -- ) -- self.assertEqual( -- unstyle(str(report)), -- "2 files reformatted, 1 file left unchanged, 1 file failed to" -- " reformat.", -- ) -- self.assertEqual( -- unstyle(str(report)), -- "2 files reformatted, 2 files left unchanged, 2 files failed to" -- " reformat.", -- ) -+ with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - for i in (a,): - if ( - # Rule 1 -@@ -27,133 +14,46 @@ - ): +@@ -28,8 +28,8 @@ while ( # Just a comment -- call() -- # Another -+ NOT_IMPLEMENTED_call() - ): -- print(i) -- xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy( -- push_manager=context.request.resource_manager, -- max_items_to_push=num_items, -- batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE, -- ).push( -- # Only send the first n items. + call() ++ ): + # Another +- ): + print(i) + xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy( + push_manager=context.request.resource_manager, +@@ -37,7 +37,7 @@ + batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE, + ).push( + # Only send the first n items. - items=items[:num_items] -- ) -+ # Another -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ xxxxxxxxxxxxxxxx = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ items=items[:num_items], + ) return ( 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s' - % (test.name, test.filename, lineno, lname, err) - ) - +@@ -47,113 +47,46 @@ def omitting_trailers(self) -> None: -- get_collection( -- hey_this_is_a_very_long_call, it_has_funny_attributes, really=True + get_collection( + hey_this_is_a_very_long_call, it_has_funny_attributes, really=True - )[OneLevelIndex] -- get_collection( -- hey_this_is_a_very_long_call, it_has_funny_attributes, really=True ++ )[ ++ OneLevelIndex ++ ] + get_collection( + hey_this_is_a_very_long_call, it_has_funny_attributes, really=True - )[OneLevelIndex][TwoLevelIndex][ThreeLevelIndex][FourLevelIndex] -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex] -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex][TwoLevelIndex][ ++ )[ ++ OneLevelIndex ++ ][ ++ TwoLevelIndex ++ ][ + ThreeLevelIndex + ][ + FourLevelIndex @@ -263,10 +235,11 @@ class C: d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][ 22 ] -- assignment = ( + assignment = ( - some.rather.elaborate.rule() and another.rule.ending_with.index[123] -- ) -+ assignment = NOT_IMPLEMENTED_call() and another.rule.ending_with.index[123] ++ some.rather.elaborate.rule() ++ and another.rule.ending_with.index[123] + ) def easy_asserts(self) -> None: - assert { @@ -376,7 +349,7 @@ class C: %3d 0 LOAD_FAST 1 (x) 2 LOAD_CONST 1 (1) 4 COMPARE_OP 2 (==) -@@ -161,21 +61,8 @@ +@@ -161,21 +94,8 @@ 8 STORE_ATTR 0 (x) 10 LOAD_CONST 0 (None) 12 RETURN_VALUE @@ -408,11 +381,24 @@ class C: ```py class C: def test(self) -> None: - with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + with patch("black.out", print): + self.assertEqual( + unstyle(str(report)), "1 file reformatted, 1 file failed to reformat." + ) + self.assertEqual( + unstyle(str(report)), + "1 file reformatted, 1 file left unchanged, 1 file failed to reformat.", + ) + self.assertEqual( + unstyle(str(report)), + "2 files reformatted, 1 file left unchanged, 1 file failed to" + " reformat.", + ) + self.assertEqual( + unstyle(str(report)), + "2 files reformatted, 2 files left unchanged, 2 files failed to" + " reformat.", + ) for i in (a,): if ( # Rule 1 @@ -422,19 +408,36 @@ class C: ): while ( # Just a comment - NOT_IMPLEMENTED_call() + call() ): # Another - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - xxxxxxxxxxxxxxxx = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print(i) + xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy( + push_manager=context.request.resource_manager, + max_items_to_push=num_items, + batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE, + ).push( + # Only send the first n items. + items=items[:num_items], + ) return ( 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s' % (test.name, test.filename, lineno, lname, err) ) def omitting_trailers(self) -> None: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex] - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex][TwoLevelIndex][ + get_collection( + hey_this_is_a_very_long_call, it_has_funny_attributes, really=True + )[ + OneLevelIndex + ] + get_collection( + hey_this_is_a_very_long_call, it_has_funny_attributes, really=True + )[ + OneLevelIndex + ][ + TwoLevelIndex + ][ ThreeLevelIndex ][ FourLevelIndex @@ -442,7 +445,10 @@ class C: d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][ 22 ] - assignment = NOT_IMPLEMENTED_call() and another.rule.ending_with.index[123] + assignment = ( + some.rather.elaborate.rule() + and another.rule.ending_with.index[123] + ) def easy_asserts(self) -> None: NOT_YET_IMPLEMENTED_StmtAssert diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@composition_no_trailing_comma.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@composition_no_trailing_comma.py.snap index 21c7c8dc7b..993bab559a 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@composition_no_trailing_comma.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@composition_no_trailing_comma.py.snap @@ -193,69 +193,41 @@ class C: ```diff --- Black +++ Ruff -@@ -1,23 +1,10 @@ - class C: - def test(self) -> None: -- with patch("black.out", print): -- self.assertEqual( -- unstyle(str(report)), "1 file reformatted, 1 file failed to reformat." -- ) -- self.assertEqual( -- unstyle(str(report)), -- "1 file reformatted, 1 file left unchanged, 1 file failed to reformat.", -- ) -- self.assertEqual( -- unstyle(str(report)), -- "2 files reformatted, 1 file left unchanged, 1 file failed to" -- " reformat.", -- ) -- self.assertEqual( -- unstyle(str(report)), -- "2 files reformatted, 2 files left unchanged, 2 files failed to" -- " reformat.", -- ) -+ with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - for i in (a,): - if ( - # Rule 1 -@@ -27,133 +14,46 @@ - ): +@@ -28,8 +28,8 @@ while ( # Just a comment -- call() -- # Another -+ NOT_IMPLEMENTED_call() - ): -- print(i) -- xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy( -- push_manager=context.request.resource_manager, -- max_items_to_push=num_items, -- batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE, -- ).push( -- # Only send the first n items. + call() ++ ): + # Another +- ): + print(i) + xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy( + push_manager=context.request.resource_manager, +@@ -37,7 +37,7 @@ + batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE, + ).push( + # Only send the first n items. - items=items[:num_items] -- ) -+ # Another -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ xxxxxxxxxxxxxxxx = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ items=items[:num_items], + ) return ( 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s' - % (test.name, test.filename, lineno, lname, err) - ) - +@@ -47,113 +47,46 @@ def omitting_trailers(self) -> None: -- get_collection( -- hey_this_is_a_very_long_call, it_has_funny_attributes, really=True + get_collection( + hey_this_is_a_very_long_call, it_has_funny_attributes, really=True - )[OneLevelIndex] -- get_collection( -- hey_this_is_a_very_long_call, it_has_funny_attributes, really=True ++ )[ ++ OneLevelIndex ++ ] + get_collection( + hey_this_is_a_very_long_call, it_has_funny_attributes, really=True - )[OneLevelIndex][TwoLevelIndex][ThreeLevelIndex][FourLevelIndex] -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex] -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex][TwoLevelIndex][ ++ )[ ++ OneLevelIndex ++ ][ ++ TwoLevelIndex ++ ][ + ThreeLevelIndex + ][ + FourLevelIndex @@ -263,10 +235,11 @@ class C: d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][ 22 ] -- assignment = ( + assignment = ( - some.rather.elaborate.rule() and another.rule.ending_with.index[123] -- ) -+ assignment = NOT_IMPLEMENTED_call() and another.rule.ending_with.index[123] ++ some.rather.elaborate.rule() ++ and another.rule.ending_with.index[123] + ) def easy_asserts(self) -> None: - assert { @@ -376,7 +349,7 @@ class C: %3d 0 LOAD_FAST 1 (x) 2 LOAD_CONST 1 (1) 4 COMPARE_OP 2 (==) -@@ -161,21 +61,8 @@ +@@ -161,21 +94,8 @@ 8 STORE_ATTR 0 (x) 10 LOAD_CONST 0 (None) 12 RETURN_VALUE @@ -408,11 +381,24 @@ class C: ```py class C: def test(self) -> None: - with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + with patch("black.out", print): + self.assertEqual( + unstyle(str(report)), "1 file reformatted, 1 file failed to reformat." + ) + self.assertEqual( + unstyle(str(report)), + "1 file reformatted, 1 file left unchanged, 1 file failed to reformat.", + ) + self.assertEqual( + unstyle(str(report)), + "2 files reformatted, 1 file left unchanged, 1 file failed to" + " reformat.", + ) + self.assertEqual( + unstyle(str(report)), + "2 files reformatted, 2 files left unchanged, 2 files failed to" + " reformat.", + ) for i in (a,): if ( # Rule 1 @@ -422,19 +408,36 @@ class C: ): while ( # Just a comment - NOT_IMPLEMENTED_call() + call() ): # Another - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - xxxxxxxxxxxxxxxx = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print(i) + xxxxxxxxxxxxxxxx = Yyyy2YyyyyYyyyyy( + push_manager=context.request.resource_manager, + max_items_to_push=num_items, + batch_size=Yyyy2YyyyYyyyyYyyy.FULL_SIZE, + ).push( + # Only send the first n items. + items=items[:num_items], + ) return ( 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s' % (test.name, test.filename, lineno, lname, err) ) def omitting_trailers(self) -> None: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex] - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)[OneLevelIndex][TwoLevelIndex][ + get_collection( + hey_this_is_a_very_long_call, it_has_funny_attributes, really=True + )[ + OneLevelIndex + ] + get_collection( + hey_this_is_a_very_long_call, it_has_funny_attributes, really=True + )[ + OneLevelIndex + ][ + TwoLevelIndex + ][ ThreeLevelIndex ][ FourLevelIndex @@ -442,7 +445,10 @@ class C: d[0][1][2][3][4][5][6][7][8][9][10][11][12][13][14][15][16][17][18][19][20][21][ 22 ] - assignment = NOT_IMPLEMENTED_call() and another.rule.ending_with.index[123] + assignment = ( + some.rather.elaborate.rule() + and another.rule.ending_with.index[123] + ) def easy_asserts(self) -> None: NOT_YET_IMPLEMENTED_StmtAssert diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@empty_lines.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@empty_lines.py.snap index b8e1bf9f55..598235141b 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@empty_lines.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@empty_lines.py.snap @@ -104,7 +104,7 @@ def g(): ```diff --- Black +++ Ruff -@@ -16,32 +16,40 @@ +@@ -16,7 +16,7 @@ if t == token.COMMENT: # another trailing comment return DOUBLESPACE @@ -113,9 +113,7 @@ def g(): prev = leaf.prev_sibling if not prev: -- prevp = preceding_leaf(p) -+ prevp = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - if not prevp or prevp.type in OPENING_BRACKETS: +@@ -25,23 +25,31 @@ return NO if prevp.type == token.EQUAL: @@ -169,7 +167,7 @@ def g(): def g(): NO = "" SPACE = " " -@@ -67,11 +74,11 @@ +@@ -67,7 +74,7 @@ return DOUBLESPACE # Another comment because more comments @@ -178,11 +176,6 @@ def g(): prev = leaf.prev_sibling if not prev: -- prevp = preceding_leaf(p) -+ prevp = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - if not prevp or prevp.type in OPENING_BRACKETS: - # Start of the line or a bracketed expression. @@ -79,11 +86,15 @@ return NO @@ -233,7 +226,7 @@ def f(): prev = leaf.prev_sibling if not prev: - prevp = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + prevp = preceding_leaf(p) if not prevp or prevp.type in OPENING_BRACKETS: return NO @@ -291,7 +284,7 @@ def g(): prev = leaf.prev_sibling if not prev: - prevp = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + prevp = preceding_leaf(p) if not prevp or prevp.type in OPENING_BRACKETS: # Start of the line or a bracketed expression. diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@expression.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@expression.py.snap index c1c18a580f..9a1f301091 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@expression.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@expression.py.snap @@ -337,7 +337,7 @@ last_call() () (1,) (1, 2) -@@ -68,60 +75,51 @@ +@@ -68,40 +75,37 @@ 2, 3, ] @@ -395,39 +395,19 @@ last_call() +{NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} Python3 > Python2 > COBOL Life is Life --call() --call(arg) --call(kwarg="hey") --call(arg, kwarg="hey") --call(arg, another, kwarg="hey", **kwargs) --call( -- this_is_a_very_long_variable_which_will_force_a_delimiter_split, -- arg, -- another, -- kwarg="hey", -- **kwargs, --) # note: no trailing comma pre-3.6 + call() +@@ -116,8 +120,8 @@ + kwarg="hey", + **kwargs, + ) # note: no trailing comma pre-3.6 -call(*gidgets[:2]) -call(a, *gidgets[:2]) --call(**self.screen_kwargs) --call(b, **self.screen_kwargs) -+NOT_IMPLEMENTED_call() -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) # note: no trailing comma pre-3.6 -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++call(*NOT_YET_IMPLEMENTED_ExprStarred) ++call(a, *NOT_YET_IMPLEMENTED_ExprStarred) + call(**self.screen_kwargs) + call(b, **self.screen_kwargs) lukasz.langa.pl --call.me(maybe) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - (1).real - (1.0).real - ....__class__ -@@ -130,34 +128,28 @@ +@@ -130,34 +134,28 @@ tuple[str, ...] tuple[str, int, float, dict[str, int]] tuple[ @@ -475,7 +455,7 @@ last_call() numpy[0, :] numpy[:, i] numpy[0, :2] -@@ -171,25 +163,32 @@ +@@ -171,20 +169,27 @@ numpy[1 : c + 1, c] numpy[-(c + 1) :, d] numpy[:, l[-2]] @@ -511,34 +491,19 @@ last_call() { "id": "1", "type": "type", -- "started_at": now(), -- "ended_at": now() + timedelta(days=10), -+ "started_at": NOT_IMPLEMENTED_call(), -+ "ended_at": NOT_IMPLEMENTED_call() + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), - "priority": 1, - "import_session_id": 1, - **kwargs, -@@ -198,35 +197,21 @@ - b = (1,) +@@ -199,32 +204,22 @@ c = 1 d = (1,) + a + (2,) --e = (1,).count(1) + e = (1,).count(1) -f = 1, *range(10) -g = 1, *"ten" --what_is_up_with_those_new_coord_names = (coord_names + set(vars_to_create)) + set( -- vars_to_remove -+e = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +f = 1, *NOT_YET_IMPLEMENTED_ExprStarred +g = 1, *NOT_YET_IMPLEMENTED_ExprStarred -+what_is_up_with_those_new_coord_names = ( -+ (coord_names + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) -+ + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + what_is_up_with_those_new_coord_names = (coord_names + set(vars_to_create)) + set( + vars_to_remove ) --what_is_up_with_those_new_coord_names = (coord_names | set(vars_to_create)) - set( -- vars_to_remove -+what_is_up_with_those_new_coord_names = ( -+ (coord_names | NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) -+ - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + what_is_up_with_those_new_coord_names = (coord_names | set(vars_to_create)) - set( + vars_to_remove ) -result = ( - session.query(models.Customer.id) @@ -558,16 +523,18 @@ last_call() - ) - .all() -) --Ø = set() --authors.łukasz.say_thanks() -+result = NOT_IMPLEMENTED_call() -+result = NOT_IMPLEMENTED_call() -+Ø = NOT_IMPLEMENTED_call() -+NOT_IMPLEMENTED_call() ++result = session.query(models.Customer.id).filter( ++ models.Customer.account_id == account_id, models.Customer.email == email_address ++).order_by(models.Customer.id.asc()).all() ++result = session.query(models.Customer.id).filter( ++ models.Customer.account_id == account_id, models.Customer.email == email_address ++).order_by( ++ models.Customer.id.asc(), ++).all() + Ø = set() + authors.łukasz.say_thanks() mapping = { - A: 0.25 * (10.0 / 12), - B: 0.1 * (10.0 / 12), -@@ -236,31 +221,29 @@ +@@ -236,29 +231,27 @@ def gen(): @@ -582,8 +549,7 @@ last_call() async def f(): -- await some.complicated[0].call(with_args=(True or (1 is not 1))) -+ await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + await some.complicated[0].call(with_args=(True or (1 is not 1))) -print(*[] or [1]) @@ -594,9 +560,9 @@ last_call() - force=False -), "Short message" -assert parens is TooMany -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++print(*NOT_YET_IMPLEMENTED_ExprStarred) ++print(**NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false) ++print(*NOT_YET_IMPLEMENTED_ExprStarred) +NOT_YET_IMPLEMENTED_StmtAssert +NOT_YET_IMPLEMENTED_StmtAssert +NOT_YET_IMPLEMENTED_StmtAssert @@ -607,34 +573,9 @@ last_call() -for z in (i for i in (1, 2, 3)): +for z in (i for i in []): ... --for i in call(): -+for i in NOT_IMPLEMENTED_call(): + for i in call(): ... - for j in 1 + (2 + 3): - ... -@@ -272,7 +255,7 @@ - addr_proto, - addr_canonname, - addr_sockaddr, --) in socket.getaddrinfo("google.com", "http"): -+) in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - pass - a = ( - aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp -@@ -291,9 +274,9 @@ - is not qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz - ) - if ( -- threading.current_thread() != threading.main_thread() -- and threading.current_thread() != threading.main_thread() -- or signal.getsignal(signal.SIGINT) != signal.default_int_handler -+ NOT_IMPLEMENTED_call() != NOT_IMPLEMENTED_call() -+ and NOT_IMPLEMENTED_call() != NOT_IMPLEMENTED_call() -+ or NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) != signal.default_int_handler - ): - return True - if ( -@@ -327,13 +310,18 @@ +@@ -327,13 +320,18 @@ ): return True if ( @@ -656,7 +597,7 @@ last_call() ^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l**aaaaaaaa.m // aaaaaaaa.n ): return True -@@ -341,7 +329,8 @@ +@@ -341,7 +339,8 @@ ~aaaaaaaaaaaaaaaa.a + aaaaaaaaaaaaaaaa.b - aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e @@ -666,13 +607,6 @@ last_call() ^ aaaaaaaaaaaaaaaa.i << aaaaaaaaaaaaaaaa.k >> aaaaaaaaaaaaaaaa.l**aaaaaaaaaaaaaaaa.m // aaaaaaaaaaaaaaaa.n -@@ -366,5 +355,5 @@ - ^ bbbb.a & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - ^ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - ) --last_call() -+NOT_IMPLEMENTED_call() - # standalone comment at ENDMARKER ``` ## Ruff Output @@ -788,18 +722,24 @@ NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} Python3 > Python2 > COBOL Life is Life -NOT_IMPLEMENTED_call() -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) # note: no trailing comma pre-3.6 -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +call() +call(arg) +call(kwarg="hey") +call(arg, kwarg="hey") +call(arg, another, kwarg="hey", **kwargs) +call( + this_is_a_very_long_variable_which_will_force_a_delimiter_split, + arg, + another, + kwarg="hey", + **kwargs, +) # note: no trailing comma pre-3.6 +call(*NOT_YET_IMPLEMENTED_ExprStarred) +call(a, *NOT_YET_IMPLEMENTED_ExprStarred) +call(**self.screen_kwargs) +call(b, **self.screen_kwargs) lukasz.langa.pl -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +call.me(maybe) (1).real (1.0).real ....__class__ @@ -867,8 +807,8 @@ SomeName { "id": "1", "type": "type", - "started_at": NOT_IMPLEMENTED_call(), - "ended_at": NOT_IMPLEMENTED_call() + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), + "started_at": now(), + "ended_at": now() + timedelta(days=10), "priority": 1, "import_session_id": 1, **kwargs, @@ -877,21 +817,25 @@ a = (1,) b = (1,) c = 1 d = (1,) + a + (2,) -e = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +e = (1,).count(1) f = 1, *NOT_YET_IMPLEMENTED_ExprStarred g = 1, *NOT_YET_IMPLEMENTED_ExprStarred -what_is_up_with_those_new_coord_names = ( - (coord_names + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) - + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +what_is_up_with_those_new_coord_names = (coord_names + set(vars_to_create)) + set( + vars_to_remove ) -what_is_up_with_those_new_coord_names = ( - (coord_names | NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) - - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +what_is_up_with_those_new_coord_names = (coord_names | set(vars_to_create)) - set( + vars_to_remove ) -result = NOT_IMPLEMENTED_call() -result = NOT_IMPLEMENTED_call() -Ø = NOT_IMPLEMENTED_call() -NOT_IMPLEMENTED_call() +result = session.query(models.Customer.id).filter( + models.Customer.account_id == account_id, models.Customer.email == email_address +).order_by(models.Customer.id.asc()).all() +result = session.query(models.Customer.id).filter( + models.Customer.account_id == account_id, models.Customer.email == email_address +).order_by( + models.Customer.id.asc(), +).all() +Ø = set() +authors.łukasz.say_thanks() mapping = { A: 0.25 * (10.0 / 12), B: 0.1 * (10.0 / 12), @@ -908,12 +852,12 @@ def gen(): async def f(): - await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + await some.complicated[0].call(with_args=(True or (1 is not 1))) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +print(*NOT_YET_IMPLEMENTED_ExprStarred) +print(**NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false) +print(*NOT_YET_IMPLEMENTED_ExprStarred) NOT_YET_IMPLEMENTED_StmtAssert NOT_YET_IMPLEMENTED_StmtAssert NOT_YET_IMPLEMENTED_StmtAssert @@ -923,7 +867,7 @@ for y in (): ... for z in (i for i in []): ... -for i in NOT_IMPLEMENTED_call(): +for i in call(): ... for j in 1 + (2 + 3): ... @@ -935,7 +879,7 @@ for ( addr_proto, addr_canonname, addr_sockaddr, -) in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): +) in socket.getaddrinfo("google.com", "http"): pass a = ( aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp @@ -954,9 +898,9 @@ a = ( is not qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz ) if ( - NOT_IMPLEMENTED_call() != NOT_IMPLEMENTED_call() - and NOT_IMPLEMENTED_call() != NOT_IMPLEMENTED_call() - or NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) != signal.default_int_handler + threading.current_thread() != threading.main_thread() + and threading.current_thread() != threading.main_thread() + or signal.getsignal(signal.SIGINT) != signal.default_int_handler ): return True if ( @@ -1035,7 +979,7 @@ bbbb >> bbbb * bbbb ^ bbbb.a & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ^ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ) -NOT_IMPLEMENTED_call() +last_call() # standalone comment at ENDMARKER ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff.py.snap index 4e210b4109..e8c3771da6 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff.py.snap @@ -202,11 +202,11 @@ d={'a':1, #!/usr/bin/env python3 -import asyncio -import sys -- --from third_party import X, Y, Z +NOT_YET_IMPLEMENTED_StmtImport +NOT_YET_IMPLEMENTED_StmtImport +-from third_party import X, Y, Z +- -from library import some_connection, some_decorator +NOT_YET_IMPLEMENTED_StmtImportFrom @@ -240,10 +240,10 @@ d={'a':1, + NOT_YET_IMPLEMENTED_StmtRaise + if False: + ... -+ for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ for i in range(10): ++ print(i) + continue -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ exec("new-style exec", {}, {}) + return None + + @@ -254,7 +254,7 @@ d={'a':1, - await asyncio.sleep(1) + "Single-line docstring. Multiline is harder to reformat." + NOT_YET_IMPLEMENTED_StmtAsyncWith -+ await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ await asyncio.sleep(1) + + @asyncio.coroutine @@ -264,7 +264,7 @@ d={'a':1, -) -def function_signature_stress_test(number:int,no_annotation=None,text:str='default',* ,debug:bool=False,**kwargs) -> str: - return text[number:-1] -+@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++@some_decorator(with_args=True, many_args=[1, 2, 3]) +def function_signature_stress_test( + number: int, + no_annotation=None, @@ -291,12 +291,12 @@ d={'a':1, + h="", + i=r"", +): -+ offset = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ offset = attr.ib(default=attr.Factory(lambda x: True)) + NOT_YET_IMPLEMENTED_StmtAssert def spaces_types( -@@ -51,68 +72,66 @@ +@@ -51,7 +72,7 @@ d: dict = {}, e: bool = True, f: int = -1, @@ -305,13 +305,7 @@ d={'a':1, h: str = "", i: str = r"", ): - ... - - --def spaces2(result=_core.Value(None)): -+def spaces2(result=NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)): - ... - +@@ -64,55 +85,55 @@ something = { # fmt: off @@ -381,11 +375,13 @@ d={'a':1, - models.Customer.email == email_address)\ - .order_by(models.Customer.id.asc())\ - .all() -+ result = NOT_IMPLEMENTED_call() ++ result = session.query(models.Customer.id).filter( ++ models.Customer.account_id == account_id, models.Customer.email == email_address ++ ).order_by(models.Customer.id.asc()).all() # fmt: on -@@ -133,10 +152,10 @@ +@@ -133,10 +154,10 @@ """Another known limitation.""" # fmt: on # fmt: off @@ -393,92 +389,41 @@ d={'a':1, - and_=indeed . it is not formatted - because . the . handling . inside . generate_ignored_nodes() - now . considers . multiple . fmt . directives . within . one . prefix -+ this = NOT_IMPLEMENTED_call() ++ this = should.not_be.formatted() + and_ = indeed.it is not formatted -+ NOT_IMPLEMENTED_call() ++ because.the.handling.inside.generate_ignored_nodes() + now.considers.multiple.fmt.directives.within.one.prefix # fmt: on # fmt: off # ...but comments still get reformatted even though they should not be -@@ -145,43 +164,11 @@ - - def long_lines(): - if True: -- typedargslist.extend( -- gen_annotated_params( -- ast_args.kwonlyargs, -- ast_args.kw_defaults, -- parameters, -- implicit_default=True, +@@ -151,12 +172,10 @@ + ast_args.kw_defaults, + parameters, + implicit_default=True, - ) -- ) -- # fmt: off ++ ), + ) + # fmt: off - a = ( - unnecessary_bracket() - ) -- # fmt: on -- _type_comment_re = re.compile( -- r""" -- ^ -- [\t ]* -- \#[ ]type:[ ]* -- (?P -- [^#\t\n]+? -- ) -- (? to match -- # a trailing space which is why we need the silliness below -- (? -- (?:\#[^\n]*)? -- \n? -- ) -- $ -- """, -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ a = unnecessary_bracket() + # fmt: on + _type_comment_re = re.compile( + r""" +@@ -179,7 +198,8 @@ + $ + """, # fmt: off - re.MULTILINE|re.VERBOSE -+ a = NOT_IMPLEMENTED_call() ++ re.MULTILINE ++ | re.VERBOSE, # fmt: on -- ) -+ _type_comment_re = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + ) - - def single_literal_yapf_disable(): -@@ -189,36 +176,9 @@ - BAZ = {(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)} # yapf: disable - - --cfg.rule( -- "Default", -- "address", -- xxxx_xxxx=["xxx-xxxxxx-xxxxxxxxxx"], -- xxxxxx="xx_xxxxx", -- xxxxxxx="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", -- xxxxxxxxx_xxxx=True, -- xxxxxxxx_xxxxxxxxxx=False, -- xxxxxx_xxxxxx=2, -- xxxxxx_xxxxx_xxxxxxxx=70, -- xxxxxx_xxxxxx_xxxxx=True, -- # fmt: off -- xxxxxxx_xxxxxxxxxxxx={ -- "xxxxxxxx": { -- "xxxxxx": False, -- "xxxxxxx": False, -- "xxxx_xxxxxx": "xxxxx", -- }, -- "xxxxxxxx-xxxxx": { -- "xxxxxx": False, -- "xxxxxxx": True, -- "xxxx_xxxxxx": "xxxxxx", -- }, -- }, -- # fmt: on -- xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=5, --) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@@ -217,8 +237,7 @@ + xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=5, + ) # fmt: off -yield 'hello' +NOT_YET_IMPLEMENTED_ExprYield @@ -518,21 +463,21 @@ def func_no_args(): NOT_YET_IMPLEMENTED_StmtRaise if False: ... - for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + for i in range(10): + print(i) continue - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + exec("new-style exec", {}, {}) return None async def coroutine(arg, exec=False): "Single-line docstring. Multiline is harder to reformat." NOT_YET_IMPLEMENTED_StmtAsyncWith - await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + await asyncio.sleep(1) @asyncio.coroutine -@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@some_decorator(with_args=True, many_args=[1, 2, 3]) def function_signature_stress_test( number: int, no_annotation=None, @@ -556,7 +501,7 @@ def spaces( h="", i=r"", ): - offset = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + offset = attr.ib(default=attr.Factory(lambda x: True)) NOT_YET_IMPLEMENTED_StmtAssert @@ -574,7 +519,7 @@ def spaces_types( ... -def spaces2(result=NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)): +def spaces2(result=_core.Value(None)): ... @@ -626,7 +571,9 @@ def yield_expr(): def example(session): # fmt: off - result = NOT_IMPLEMENTED_call() + result = session.query(models.Customer.id).filter( + models.Customer.account_id == account_id, models.Customer.email == email_address + ).order_by(models.Customer.id.asc()).all() # fmt: on @@ -647,9 +594,9 @@ def on_and_off_broken(): """Another known limitation.""" # fmt: on # fmt: off - this = NOT_IMPLEMENTED_call() + this = should.not_be.formatted() and_ = indeed.it is not formatted - NOT_IMPLEMENTED_call() + because.the.handling.inside.generate_ignored_nodes() now.considers.multiple.fmt.directives.within.one.prefix # fmt: on # fmt: off @@ -659,11 +606,42 @@ def on_and_off_broken(): def long_lines(): if True: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + typedargslist.extend( + gen_annotated_params( + ast_args.kwonlyargs, + ast_args.kw_defaults, + parameters, + implicit_default=True, + ), + ) # fmt: off - a = NOT_IMPLEMENTED_call() + a = unnecessary_bracket() # fmt: on - _type_comment_re = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + _type_comment_re = re.compile( + r""" + ^ + [\t ]* + \#[ ]type:[ ]* + (?P + [^#\t\n]+? + ) + (? to match + # a trailing space which is why we need the silliness below + (? + (?:\#[^\n]*)? + \n? + ) + $ + """, + # fmt: off + re.MULTILINE + | re.VERBOSE, + # fmt: on + ) def single_literal_yapf_disable(): @@ -671,7 +649,33 @@ def single_literal_yapf_disable(): BAZ = {(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)} # yapf: disable -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +cfg.rule( + "Default", + "address", + xxxx_xxxx=["xxx-xxxxxx-xxxxxxxxxx"], + xxxxxx="xx_xxxxx", + xxxxxxx="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", + xxxxxxxxx_xxxx=True, + xxxxxxxx_xxxxxxxxxx=False, + xxxxxx_xxxxxx=2, + xxxxxx_xxxxx_xxxxxxxx=70, + xxxxxx_xxxxxx_xxxxx=True, + # fmt: off + xxxxxxx_xxxxxxxxxxxx={ + "xxxxxxxx": { + "xxxxxx": False, + "xxxxxxx": False, + "xxxx_xxxxxx": "xxxxx", + }, + "xxxxxxxx-xxxxx": { + "xxxxxx": False, + "xxxxxxx": True, + "xxxx_xxxxxx": "xxxxxx", + }, + }, + # fmt: on + xxxxxxxxxx_xxxxxxxxxxx_xxxxxxx_xxxxxxxxx=5, +) # fmt: off NOT_YET_IMPLEMENTED_ExprYield # No formatting to the end of the file diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff2.py.snap index 548b61e58d..56b345fae1 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff2.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff2.py.snap @@ -52,7 +52,7 @@ def test_calculate_fades(): ```diff --- Black +++ Ruff -@@ -1,40 +1,38 @@ +@@ -1,40 +1,44 @@ -import pytest +NOT_YET_IMPLEMENTED_StmtImport @@ -68,11 +68,15 @@ def test_calculate_fades(): -@pytest.mark.parametrize('test', [ - - # Test don't manage the volume -- [ ++@pytest.mark.parametrize( ++ "test", + [ - ('stuff', 'in') -- ], ++ # Test don't manage the volume ++ [("stuff", "in")], + ], -]) -+@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++) def test_fader(test): pass @@ -120,7 +124,13 @@ TmEx = 2 # Test data: # Position, Volume, State, TmSt/TmEx/None, [call, [arg1...]] -@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@pytest.mark.parametrize( + "test", + [ + # Test don't manage the volume + [("stuff", "in")], + ], +) def test_fader(test): pass diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff4.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff4.py.snap index 63a650ff45..89b2436af1 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff4.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff4.py.snap @@ -25,27 +25,30 @@ def f(): pass ```diff --- Black +++ Ruff -@@ -1,20 +1,10 @@ +@@ -1,8 +1,12 @@ # fmt: off -@test([ - 1, 2, - 3, 4, -]) -+@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++@test( ++ [ ++ 1, ++ 2, ++ 3, ++ 4, ++ ], ++) # fmt: on def f(): pass - - --@test( -- [ -- 1, -- 2, -- 3, -- 4, +@@ -14,7 +18,7 @@ + 2, + 3, + 4, - ] --) -+@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ ], + ) def f(): pass ``` @@ -54,13 +57,27 @@ def f(): pass ```py # fmt: off -@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@test( + [ + 1, + 2, + 3, + 4, + ], +) # fmt: on def f(): pass -@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@test( + [ + 1, + 2, + 3, + 4, + ], +) def f(): pass ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff5.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff5.py.snap index 3bbc9eaea4..5cc5334320 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff5.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff5.py.snap @@ -96,44 +96,27 @@ elif unformatted: ```diff --- Black +++ Ruff -@@ -1,33 +1,15 @@ - # Regression test for https://github.com/psf/black/issues/3129. --setup( -- entry_points={ -- # fmt: off -- "console_scripts": [ -- "foo-bar" -- "=foo.bar.:main", +@@ -5,8 +5,8 @@ + "console_scripts": [ + "foo-bar" + "=foo.bar.:main", - # fmt: on - ] # Includes an formatted indentation. -- }, --) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - - # Regression test for https://github.com/psf/black/issues/2015. --run( -- # fmt: off -- [ -- "ls", -- "-la", -- ] -- # fmt: on -- + path, -- check=True, --) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - ++ # fmt: on ++ ], # Includes an formatted indentation. + }, + ) +@@ -27,7 +27,7 @@ # Regression test for https://github.com/psf/black/issues/3026. def test_func(): # yapf: disable - if unformatted( args ): -+ if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): ++ if unformatted(args): return True # yapf: enable elif b: -@@ -39,12 +21,12 @@ +@@ -39,10 +39,10 @@ # Regression test for https://github.com/psf/black/issues/2567. if True: # fmt: off @@ -141,17 +124,14 @@ elif unformatted: - # fmt: on - print ( "This won't be formatted" ) - print ( "This won't be formatted either" ) -+ for _ in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): ++ for _ in range(1): + # fmt: on -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ print("This won't be formatted") ++ print("This won't be formatted either") else: -- print("This will be formatted") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("This will be formatted") - - # Regression test for https://github.com/psf/black/issues/3184. -@@ -52,29 +34,27 @@ +@@ -52,14 +52,12 @@ async def call(param): if param: # fmt: off @@ -161,17 +141,15 @@ elif unformatted: + if param[0:4] in ("ABCD", "EFGH"): # fmt: on - print ( "This won't be formatted" ) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ print("This won't be formatted") elif param[0:4] in ("ZZZZ",): - print ( "This won't be formatted either" ) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ print("This won't be formatted either") -- print("This will be formatted") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("This will be formatted") - - # Regression test for https://github.com/psf/black/issues/2985. +@@ -68,13 +66,13 @@ class Named(t.Protocol): # fmt: off @property @@ -187,32 +165,49 @@ elif unformatted: # fmt: on -@@ -82,6 +62,6 @@ +@@ -82,6 +80,6 @@ if x: return x # fmt: off -elif unformatted: +elif unformatted: # fmt: on -- will_be_formatted() -+ NOT_IMPLEMENTED_call() + will_be_formatted() ``` ## Ruff Output ```py # Regression test for https://github.com/psf/black/issues/3129. -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +setup( + entry_points={ + # fmt: off + "console_scripts": [ + "foo-bar" + "=foo.bar.:main", + # fmt: on + ], # Includes an formatted indentation. + }, +) # Regression test for https://github.com/psf/black/issues/2015. -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +run( + # fmt: off + [ + "ls", + "-la", + ] + # fmt: on + + path, + check=True, +) # Regression test for https://github.com/psf/black/issues/3026. def test_func(): # yapf: disable - if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): + if unformatted(args): return True # yapf: enable elif b: @@ -224,12 +219,12 @@ def test_func(): # Regression test for https://github.com/psf/black/issues/2567. if True: # fmt: off - for _ in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): + for _ in range(1): # fmt: on - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("This won't be formatted") + print("This won't be formatted either") else: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("This will be formatted") # Regression test for https://github.com/psf/black/issues/3184. @@ -239,12 +234,12 @@ class A: # fmt: off if param[0:4] in ("ABCD", "EFGH"): # fmt: on - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("This won't be formatted") elif param[0:4] in ("ZZZZ",): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("This won't be formatted either") - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("This will be formatted") # Regression test for https://github.com/psf/black/issues/2985. @@ -267,7 +262,7 @@ if x: # fmt: off elif unformatted: # fmt: on - NOT_IMPLEMENTED_call() + will_be_formatted() ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip5.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip5.py.snap index 156c1d3712..cb7904beff 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip5.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip5.py.snap @@ -21,7 +21,7 @@ else: ```diff --- Black +++ Ruff -@@ -1,9 +1,10 @@ +@@ -1,7 +1,8 @@ a, b, c = 3, 4, 5 if ( a == 3 @@ -30,11 +30,7 @@ else: + != 9 # fmt: skip and c is not None ): -- print("I'm good!") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - else: -- print("I'm bad") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("I'm good!") ``` ## Ruff Output @@ -47,9 +43,9 @@ if ( != 9 # fmt: skip and c is not None ): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("I'm good!") else: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("I'm bad") ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip6.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip6.py.snap deleted file mode 100644 index 5c22c86651..0000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip6.py.snap +++ /dev/null @@ -1,49 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fmtskip6.py ---- -## Input - -```py -class A: - def f(self): - for line in range(10): - if True: - pass # fmt: skip -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,5 +1,5 @@ - class A: - def f(self): -- for line in range(10): -+ for line in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - if True: - pass # fmt: skip -``` - -## Ruff Output - -```py -class A: - def f(self): - for line in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - if True: - pass # fmt: skip -``` - -## Black Output - -```py -class A: - def f(self): - for line in range(10): - if True: - pass # fmt: skip -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip8.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip8.py.snap index 5e791205c3..133a41b6cf 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip8.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip8.py.snap @@ -77,65 +77,54 @@ async def test_async_with(): @@ -1,62 +1,55 @@ # Make sure a leading comment is not removed. -def some_func( unformatted, args ): # fmt: skip -- print("I am some_func") +def some_func(unformatted, args): # fmt: skip -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("I am some_func") return 0 # Make sure this comment is not removed. # Make sure a leading comment is not removed. -async def some_async_func( unformatted, args): # fmt: skip -- print("I am some_async_func") -- await asyncio.sleep(1) +async def some_async_func(unformatted, args): # fmt: skip -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("I am some_async_func") + await asyncio.sleep(1) # Make sure a leading comment is not removed. -class SomeClass( Unformatted, SuperClasses ): # fmt: skip - def some_method( self, unformatted, args ): # fmt: skip -- print("I am some_method") +class SomeClass(Unformatted, SuperClasses): # fmt: skip + def some_method(self, unformatted, args): # fmt: skip -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("I am some_method") return 0 - async def some_async_method( self, unformatted, args ): # fmt: skip -- print("I am some_async_method") -- await asyncio.sleep(1) + async def some_async_method(self, unformatted, args): # fmt: skip -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("I am some_async_method") + await asyncio.sleep(1) # Make sure a leading comment is not removed. -if unformatted_call( args ): # fmt: skip -- print("First branch") -+if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): # fmt: skip -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++if unformatted_call(args): # fmt: skip + print("First branch") # Make sure this is not removed. -elif another_unformatted_call( args ): # fmt: skip -- print("Second branch") ++elif another_unformatted_call(args): # fmt: skip + print("Second branch") -else : # fmt: skip -- print("Last branch") -+elif NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): # fmt: skip -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +else: # fmt: skip -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("Last branch") -while some_condition( unformatted, args ): # fmt: skip -- print("Do something") -+while NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): # fmt: skip -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++while some_condition(unformatted, args): # fmt: skip + print("Do something") -for i in some_iter( unformatted, args ): # fmt: skip -- print("Do something") -+for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): # fmt: skip -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++for i in some_iter(unformatted, args): # fmt: skip + print("Do something") async def test_async_for(): @@ -154,9 +143,8 @@ async def test_async_with(): -with give_me_context( unformatted, args ): # fmt: skip -- print("Do something") -+with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): # fmt: skip -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++with give_me_context(unformatted, args): # fmt: skip + print("Do something") async def test_async_with(): @@ -170,44 +158,44 @@ async def test_async_with(): ```py # Make sure a leading comment is not removed. def some_func(unformatted, args): # fmt: skip - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("I am some_func") return 0 # Make sure this comment is not removed. # Make sure a leading comment is not removed. async def some_async_func(unformatted, args): # fmt: skip - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("I am some_async_func") + await asyncio.sleep(1) # Make sure a leading comment is not removed. class SomeClass(Unformatted, SuperClasses): # fmt: skip def some_method(self, unformatted, args): # fmt: skip - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("I am some_method") return 0 async def some_async_method(self, unformatted, args): # fmt: skip - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("I am some_async_method") + await asyncio.sleep(1) # Make sure a leading comment is not removed. -if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): # fmt: skip - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +if unformatted_call(args): # fmt: skip + print("First branch") # Make sure this is not removed. -elif NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): # fmt: skip - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +elif another_unformatted_call(args): # fmt: skip + print("Second branch") else: # fmt: skip - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("Last branch") -while NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): # fmt: skip - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +while some_condition(unformatted, args): # fmt: skip + print("Do something") -for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): # fmt: skip - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +for i in some_iter(unformatted, args): # fmt: skip + print("Do something") async def test_async_for(): @@ -217,8 +205,8 @@ async def test_async_for(): NOT_YET_IMPLEMENTED_StmtTry -with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): # fmt: skip - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +with give_me_context(unformatted, args): # fmt: skip + print("Do something") async def test_async_with(): diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function.py.snap index 2be379cb33..7562820a71 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function.py.snap @@ -107,7 +107,7 @@ def __await__(): return (yield) ```diff --- Black +++ Ruff -@@ -1,12 +1,11 @@ +@@ -1,20 +1,19 @@ #!/usr/bin/env python3 -import asyncio -import sys @@ -118,14 +118,14 @@ def __await__(): return (yield) +NOT_YET_IMPLEMENTED_StmtImportFrom -from library import some_connection, some_decorator -- --f"trigger 3.6 mode" +NOT_YET_IMPLEMENTED_StmtImportFrom +NOT_YET_IMPLEMENTED_ExprJoinedStr +-f"trigger 3.6 mode" +- def func_no_args(): -@@ -14,25 +13,24 @@ + a b c if True: @@ -133,31 +133,17 @@ def __await__(): return (yield) + NOT_YET_IMPLEMENTED_StmtRaise if False: ... -- for i in range(10): -- print(i) -+ for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - continue -- exec("new-style exec", {}, {}) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - return None - + for i in range(10): +@@ -26,8 +25,7 @@ async def coroutine(arg, exec=False): "Single-line docstring. Multiline is harder to reformat." - async with some_connection() as conn: - await conn.do_what_i_mean("SELECT bobby, tables FROM xkcd", timeout=2) -- await asyncio.sleep(1) + NOT_YET_IMPLEMENTED_StmtAsyncWith -+ await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + await asyncio.sleep(1) - @asyncio.coroutine --@some_decorator(with_args=True, many_args=[1, 2, 3]) -+@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - def function_signature_stress_test( - number: int, - no_annotation=None, @@ -41,12 +39,22 @@ debug: bool = False, **kwargs, @@ -180,12 +166,12 @@ def __await__(): return (yield) + h="", + i=r"", +): -+ offset = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ offset = attr.ib(default=attr.Factory(lambda x: True)) + NOT_YET_IMPLEMENTED_StmtAssert def spaces_types( -@@ -56,70 +64,26 @@ +@@ -56,7 +64,7 @@ d: dict = {}, e: bool = True, f: int = -1, @@ -194,12 +180,11 @@ def __await__(): return (yield) h: str = "", i: str = r"", ): - ... +@@ -64,19 +72,16 @@ --def spaces2(result=_core.Value(None)): + def spaces2(result=_core.Value(None)): - assert fut is self._read_fut, (fut, self._read_fut) -+def spaces2(result=NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)): + NOT_YET_IMPLEMENTED_StmtAssert @@ -213,57 +198,44 @@ def __await__(): return (yield) - .order_by(models.Customer.id.asc()) - .all() - ) -+ result = NOT_IMPLEMENTED_call() ++ result = session.query(models.Customer.id).filter( ++ models.Customer.account_id ++ == account_id, ++ models.Customer.email ++ == email_address, ++ ).order_by(models.Customer.id.asc()).all() def long_lines(): - if True: -- typedargslist.extend( -- gen_annotated_params( -- ast_args.kwonlyargs, -- ast_args.kw_defaults, -- parameters, -- implicit_default=True, +@@ -87,7 +92,7 @@ + ast_args.kw_defaults, + parameters, + implicit_default=True, - ) -- ) -- typedargslist.extend( -- gen_annotated_params( -- ast_args.kwonlyargs, -- ast_args.kw_defaults, -- parameters, -- implicit_default=True, -- # trailing standalone comment ++ ), + ) + typedargslist.extend( + gen_annotated_params( +@@ -96,7 +101,7 @@ + parameters, + implicit_default=True, + # trailing standalone comment - ) -- ) -- _type_comment_re = re.compile( -- r""" -- ^ -- [\t ]* -- \#[ ]type:[ ]* -- (?P -- [^#\t\n]+? -- ) -- (? to match -- # a trailing space which is why we need the silliness below -- (? -- (?:\#[^\n]*)? -- \n? -- ) -- $ -- """, ++ ), + ) + _type_comment_re = re.compile( + r""" +@@ -118,7 +123,8 @@ + ) + $ + """, - re.MULTILINE | re.VERBOSE, -- ) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ _type_comment_re = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ re.MULTILINE ++ | re.VERBOSE, + ) - def trailing_comma(): -@@ -135,14 +99,8 @@ +@@ -135,14 +141,8 @@ a, **kwargs, ) -> A: @@ -303,21 +275,21 @@ def func_no_args(): NOT_YET_IMPLEMENTED_StmtRaise if False: ... - for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + for i in range(10): + print(i) continue - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + exec("new-style exec", {}, {}) return None async def coroutine(arg, exec=False): "Single-line docstring. Multiline is harder to reformat." NOT_YET_IMPLEMENTED_StmtAsyncWith - await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + await asyncio.sleep(1) @asyncio.coroutine -@NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@some_decorator(with_args=True, many_args=[1, 2, 3]) def function_signature_stress_test( number: int, no_annotation=None, @@ -340,7 +312,7 @@ def spaces( h="", i=r"", ): - offset = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + offset = attr.ib(default=attr.Factory(lambda x: True)) NOT_YET_IMPLEMENTED_StmtAssert @@ -358,19 +330,61 @@ def spaces_types( ... -def spaces2(result=NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)): +def spaces2(result=_core.Value(None)): NOT_YET_IMPLEMENTED_StmtAssert def example(session): - result = NOT_IMPLEMENTED_call() + result = session.query(models.Customer.id).filter( + models.Customer.account_id + == account_id, + models.Customer.email + == email_address, + ).order_by(models.Customer.id.asc()).all() def long_lines(): if True: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - _type_comment_re = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + typedargslist.extend( + gen_annotated_params( + ast_args.kwonlyargs, + ast_args.kw_defaults, + parameters, + implicit_default=True, + ), + ) + typedargslist.extend( + gen_annotated_params( + ast_args.kwonlyargs, + ast_args.kw_defaults, + parameters, + implicit_default=True, + # trailing standalone comment + ), + ) + _type_comment_re = re.compile( + r""" + ^ + [\t ]* + \#[ ]type:[ ]* + (?P + [^#\t\n]+? + ) + (? to match + # a trailing space which is why we need the silliness below + (? + (?:\#[^\n]*)? + \n? + ) + $ + """, + re.MULTILINE + | re.VERBOSE, + ) def trailing_comma(): diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function2.py.snap index fe0456ee1f..bcd7954313 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function2.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function2.py.snap @@ -65,42 +65,7 @@ with hmm_but_this_should_get_two_preceding_newlines(): ```diff --- Black +++ Ruff -@@ -2,17 +2,11 @@ - a, - **kwargs, - ) -> A: -- with cache_dir(): -+ with NOT_IMPLEMENTED_call(): - if something: -- result = CliRunner().invoke( -- black.main, [str(src1), str(src2), "--diff", "--check"] -- ) -- limited.append(-limited.pop()) # negate top -- return A( -- very_long_argument_name1=very_long_value_for_the_argument, -- very_long_argument_name2=-very.long.value.for_the_argument, -- **kwargs, -- ) -+ result = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) # negate top -+ return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - - def g(): -@@ -21,45 +15,31 @@ - def inner(): - pass - -- print("Inner defs should breathe a little.") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - - def h(): - def inner(): - pass - -- print("Inner defs should breathe a little.") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@@ -32,34 +32,20 @@ if os.name == "posix": @@ -116,28 +81,26 @@ with hmm_but_this_should_get_two_preceding_newlines(): - - def i_should_be_followed_by_only_one_newline(): - pass -- ++ NOT_YET_IMPLEMENTED_StmtTry + - except ImportError: - - def i_should_be_followed_by_only_one_newline(): - pass -+ NOT_YET_IMPLEMENTED_StmtTry - +- elif False: - class IHopeYouAreHavingALovelyDay: def __call__(self): -- print("i_should_be_followed_by_only_one_newline") + print("i_should_be_followed_by_only_one_newline") - -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) else: - def foo(): pass - --with hmm_but_this_should_get_two_preceding_newlines(): -+with NOT_IMPLEMENTED_call(): + with hmm_but_this_should_get_two_preceding_newlines(): pass ``` @@ -148,11 +111,17 @@ def f( a, **kwargs, ) -> A: - with NOT_IMPLEMENTED_call(): + with cache_dir(): if something: - result = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) # negate top - return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + result = CliRunner().invoke( + black.main, [str(src1), str(src2), "--diff", "--check"] + ) + limited.append(-limited.pop()) # negate top + return A( + very_long_argument_name1=very_long_value_for_the_argument, + very_long_argument_name2=-very.long.value.for_the_argument, + **kwargs, + ) def g(): @@ -161,14 +130,14 @@ def g(): def inner(): pass - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("Inner defs should breathe a little.") def h(): def inner(): pass - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("Inner defs should breathe a little.") if os.name == "posix": @@ -182,12 +151,12 @@ elif os.name == "nt": elif False: class IHopeYouAreHavingALovelyDay: def __call__(self): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("i_should_be_followed_by_only_one_newline") else: def foo(): pass -with NOT_IMPLEMENTED_call(): +with hmm_but_this_should_get_two_preceding_newlines(): pass ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function_trailing_comma.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function_trailing_comma.py.snap index 2a55c63e83..747b512442 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function_trailing_comma.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@function_trailing_comma.py.snap @@ -73,20 +73,16 @@ some_module.some_function( ```diff --- Black +++ Ruff -@@ -24,18 +24,14 @@ - def f( - a: int = 1, - ): -- call( -- arg={ -- "explode": "this", +@@ -27,7 +27,7 @@ + call( + arg={ + "explode": "this", - } -- ) -- call2( -- arg=[1, 2, 3], -- ) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ }, + ) + call2( + arg=[1, 2, 3], +@@ -35,7 +35,9 @@ x = { "a": 1, "b": 2, @@ -97,7 +93,7 @@ some_module.some_function( if ( a == { -@@ -47,22 +43,24 @@ +@@ -47,22 +49,24 @@ "f": 6, "g": 7, "h": 8, @@ -129,7 +125,7 @@ some_module.some_function( } -@@ -80,35 +78,16 @@ +@@ -80,18 +84,14 @@ pass @@ -137,8 +133,9 @@ some_module.some_function( - also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black( - this_shouldn_t_get_a_trailing_comma_too - ) --): -+def func() -> NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): ++def func() -> also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black( ++ this_shouldn_t_get_a_trailing_comma_too + ): pass @@ -146,29 +143,11 @@ some_module.some_function( - also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black( - this_shouldn_t_get_a_trailing_comma_too - ) --): -+def func() -> NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): ++def func() -> also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black( ++ this_shouldn_t_get_a_trailing_comma_too + ): pass - - # Make sure inner one-element tuple won't explode --some_module.some_function( -- argument1, (one_element_tuple,), argument4, argument5, argument6 --) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - # Inner trailing comma causes outer to explode --some_module.some_function( -- argument1, -- ( -- one, -- two, -- ), -- argument4, -- argument5, -- argument6, --) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ``` ## Ruff Output @@ -200,8 +179,14 @@ def f2( def f( a: int = 1, ): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + call( + arg={ + "explode": "this", + }, + ) + call2( + arg=[1, 2, 3], + ) x = { "a": 1, "b": 2, @@ -254,19 +239,34 @@ def some_method_with_a_really_long_name( pass -def func() -> NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): +def func() -> also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black( + this_shouldn_t_get_a_trailing_comma_too +): pass -def func() -> NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): +def func() -> also_super_long_type_annotation_that_may_cause_an_AST_related_crash_in_black( + this_shouldn_t_get_a_trailing_comma_too +): pass # Make sure inner one-element tuple won't explode -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +some_module.some_function( + argument1, (one_element_tuple,), argument4, argument5, argument6 +) # Inner trailing comma causes outer to explode -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +some_module.some_function( + argument1, + ( + one, + two, + ), + argument4, + argument5, + argument6, +) ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@power_op_spacing.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@power_op_spacing.py.snap index ea7c78d2a9..2a803075f6 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@power_op_spacing.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@power_op_spacing.py.snap @@ -75,84 +75,67 @@ return np.divide( ```diff --- Black +++ Ruff -@@ -12,52 +12,45 @@ - - - a = 5**~4 --b = 5 ** f() -+b = 5 ** NOT_IMPLEMENTED_call() +@@ -15,38 +15,38 @@ + b = 5 ** f() c = -(5**2) d = 5 ** f["hi"] -e = lazy(lambda **kwargs: 5) --f = f() ** 5 -+e = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+f = NOT_IMPLEMENTED_call() ** 5 ++e = lazy(lambda x: True) + f = f() ** 5 g = a.b**c.d --h = 5 ** funcs.f() --i = funcs.f() ** 5 --j = super().name ** 5 + h = 5 ** funcs.f() + i = funcs.f() ** 5 + j = super().name ** 5 -k = [(2**idx, value) for idx, value in pairs] --l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) -+h = 5 ** NOT_IMPLEMENTED_call() -+i = NOT_IMPLEMENTED_call() ** 5 -+j = NOT_IMPLEMENTED_call().name ** 5 +k = [i for i in []] -+l = mod.weights_[0] == NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) m = [([2**63], [1, 2**63])] n = count <= 10**5 --o = settings(max_examples=10**6) + o = settings(max_examples=10**6) -p = {(k, k**2): v**2 for k, v in pairs} -q = [10**i for i in range(6)] -+o = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} +q = [i for i in []] r = x**y a = 5.0**~4.0 --b = 5.0 ** f() -+b = 5.0 ** NOT_IMPLEMENTED_call() + b = 5.0 ** f() c = -(5.0**2.0) d = 5.0 ** f["hi"] -e = lazy(lambda **kwargs: 5) --f = f() ** 5.0 -+e = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+f = NOT_IMPLEMENTED_call() ** 5.0 ++e = lazy(lambda x: True) + f = f() ** 5.0 g = a.b**c.d --h = 5.0 ** funcs.f() --i = funcs.f() ** 5.0 --j = super().name ** 5.0 + h = 5.0 ** funcs.f() + i = funcs.f() ** 5.0 + j = super().name ** 5.0 -k = [(2.0**idx, value) for idx, value in pairs] --l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) -+h = 5.0 ** NOT_IMPLEMENTED_call() -+i = NOT_IMPLEMENTED_call() ** 5.0 -+j = NOT_IMPLEMENTED_call().name ** 5.0 +k = [i for i in []] -+l = mod.weights_[0] == NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) m = [([2.0**63.0], [1.0, 2**63.0])] n = count <= 10**5.0 --o = settings(max_examples=10**6.0) + o = settings(max_examples=10**6.0) -p = {(k, k**2): v**2.0 for k, v in pairs} -q = [10.5**i for i in range(6)] -+o = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} +q = [i for i in []] # WE SHOULD DEFINITELY NOT EAT THESE COMMENTS (https://github.com/psf/black/issues/2873) --if hasattr(view, "sum_of_weights"): -- return np.divide( # type: ignore[no-any-return] -- view.variance, # type: ignore[union-attr] -- view.sum_of_weights, # type: ignore[union-attr] -- out=np.full(view.sum_of_weights.shape, np.nan), # type: ignore[union-attr] +@@ -55,9 +55,11 @@ + view.variance, # type: ignore[union-attr] + view.sum_of_weights, # type: ignore[union-attr] + out=np.full(view.sum_of_weights.shape, np.nan), # type: ignore[union-attr] - where=view.sum_of_weights**2 > view.sum_of_weights_squared, # type: ignore[union-attr] -- ) -+if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): -+ return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ where=view.sum_of_weights**2 ++ > view.sum_of_weights_squared, # type: ignore[union-attr] + ) --return np.divide( + return np.divide( - where=view.sum_of_weights_of_weight_long**2 > view.sum_of_weights_squared, # type: ignore --) -+return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ where=view.sum_of_weights_of_weight_long**2 ++ > view.sum_of_weights_squared, # type: ignore + ) ``` ## Ruff Output @@ -172,48 +155,57 @@ def function_dont_replace_spaces(): a = 5**~4 -b = 5 ** NOT_IMPLEMENTED_call() +b = 5 ** f() c = -(5**2) d = 5 ** f["hi"] -e = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -f = NOT_IMPLEMENTED_call() ** 5 +e = lazy(lambda x: True) +f = f() ** 5 g = a.b**c.d -h = 5 ** NOT_IMPLEMENTED_call() -i = NOT_IMPLEMENTED_call() ** 5 -j = NOT_IMPLEMENTED_call().name ** 5 +h = 5 ** funcs.f() +i = funcs.f() ** 5 +j = super().name ** 5 k = [i for i in []] -l = mod.weights_[0] == NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) m = [([2**63], [1, 2**63])] n = count <= 10**5 -o = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +o = settings(max_examples=10**6) p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} q = [i for i in []] r = x**y a = 5.0**~4.0 -b = 5.0 ** NOT_IMPLEMENTED_call() +b = 5.0 ** f() c = -(5.0**2.0) d = 5.0 ** f["hi"] -e = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -f = NOT_IMPLEMENTED_call() ** 5.0 +e = lazy(lambda x: True) +f = f() ** 5.0 g = a.b**c.d -h = 5.0 ** NOT_IMPLEMENTED_call() -i = NOT_IMPLEMENTED_call() ** 5.0 -j = NOT_IMPLEMENTED_call().name ** 5.0 +h = 5.0 ** funcs.f() +i = funcs.f() ** 5.0 +j = super().name ** 5.0 k = [i for i in []] -l = mod.weights_[0] == NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +l = mod.weights_[0] == pytest.approx(0.95**100, abs=0.001) m = [([2.0**63.0], [1.0, 2**63.0])] n = count <= 10**5.0 -o = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +o = settings(max_examples=10**6.0) p = {NOT_IMPLEMENTED_dict_key: NOT_IMPLEMENTED_dict_value for key, value in NOT_IMPLEMENTED_dict} q = [i for i in []] # WE SHOULD DEFINITELY NOT EAT THESE COMMENTS (https://github.com/psf/black/issues/2873) -if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +if hasattr(view, "sum_of_weights"): + return np.divide( # type: ignore[no-any-return] + view.variance, # type: ignore[union-attr] + view.sum_of_weights, # type: ignore[union-attr] + out=np.full(view.sum_of_weights.shape, np.nan), # type: ignore[union-attr] + where=view.sum_of_weights**2 + > view.sum_of_weights_squared, # type: ignore[union-attr] + ) -return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +return np.divide( + where=view.sum_of_weights_of_weight_long**2 + > view.sum_of_weights_squared, # type: ignore +) ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@prefer_rhs_split_reformatted.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@prefer_rhs_split_reformatted.py.snap deleted file mode 100644 index 855222248f..0000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@prefer_rhs_split_reformatted.py.snap +++ /dev/null @@ -1,94 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/prefer_rhs_split_reformatted.py ---- -## Input - -```py -# Test cases separate from `prefer_rhs_split.py` that contains unformatted source. - -# Left hand side fits in a single line but will still be exploded by the -# magic trailing comma. -first_value, (m1, m2,), third_value = xxxxxx_yyyyyy_zzzzzz_wwwwww_uuuuuuu_vvvvvvvvvvv( - arg1, - arg2, -) - -# Make when when the left side of assignment plus the opening paren "... = (" is -# exactly line length limit + 1, it won't be split like that. -xxxxxxxxx_yyy_zzzzzzzz[xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxxx=1)] = 1 -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -9,13 +9,10 @@ - m2, - ), - third_value, --) = xxxxxx_yyyyyy_zzzzzz_wwwwww_uuuuuuu_vvvvvvvvvvv( -- arg1, -- arg2, --) -+) = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - # Make when when the left side of assignment plus the opening paren "... = (" is - # exactly line length limit + 1, it won't be split like that. - xxxxxxxxx_yyy_zzzzzzzz[ -- xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxxx=1) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - ] = 1 -``` - -## Ruff Output - -```py -# Test cases separate from `prefer_rhs_split.py` that contains unformatted source. - -# Left hand side fits in a single line but will still be exploded by the -# magic trailing comma. -( - first_value, - ( - m1, - m2, - ), - third_value, -) = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - -# Make when when the left side of assignment plus the opening paren "... = (" is -# exactly line length limit + 1, it won't be split like that. -xxxxxxxxx_yyy_zzzzzzzz[ - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -] = 1 -``` - -## Black Output - -```py -# Test cases separate from `prefer_rhs_split.py` that contains unformatted source. - -# Left hand side fits in a single line but will still be exploded by the -# magic trailing comma. -( - first_value, - ( - m1, - m2, - ), - third_value, -) = xxxxxx_yyyyyy_zzzzzz_wwwwww_uuuuuuu_vvvvvvvvvvv( - arg1, - arg2, -) - -# Make when when the left side of assignment plus the opening paren "... = (" is -# exactly line length limit + 1, it won't be split like that. -xxxxxxxxx_yyy_zzzzzzzz[ - xx.xxxxxx(x_yyy_zzzzzz.xxxxx[0]), x_yyy_zzzzzz.xxxxxx(xxxx=1) -] = 1 -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_await_parens.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_await_parens.py.snap index d702a291b9..e77d6934e3 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_await_parens.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_await_parens.py.snap @@ -93,31 +93,28 @@ async def main(): ```diff --- Black +++ Ruff -@@ -1,66 +1,57 @@ +@@ -1,4 +1,4 @@ -import asyncio +NOT_YET_IMPLEMENTED_StmtImport # Control example - async def main(): -- await asyncio.sleep(1) -+ await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - +@@ -8,59 +8,70 @@ # Remove brackets for short coroutine/task async def main(): - await asyncio.sleep(1) -+ await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) ++ await (asyncio.sleep(1)) async def main(): - await asyncio.sleep(1) -+ await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) ++ await (asyncio.sleep(1)) async def main(): - await asyncio.sleep(1) -+ await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) ++ await (asyncio.sleep(1)) # Check comments @@ -125,7 +122,7 @@ async def main(): - await asyncio.sleep(1) # Hello + ( + await # Hello -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ asyncio.sleep(1) + ) @@ -133,14 +130,14 @@ async def main(): - await asyncio.sleep(1) # Hello + ( + await ( -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) # Hello ++ asyncio.sleep(1) # Hello + ) + ) async def main(): - await asyncio.sleep(1) # Hello -+ await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) # Hello ++ await (asyncio.sleep(1)) # Hello # Long lines @@ -153,8 +150,17 @@ async def main(): - asyncio.sleep(1), - asyncio.sleep(1), - asyncio.sleep(1), -- ) -+ await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ ( ++ await asyncio.gather( ++ asyncio.sleep(1), ++ asyncio.sleep(1), ++ asyncio.sleep(1), ++ asyncio.sleep(1), ++ asyncio.sleep(1), ++ asyncio.sleep(1), ++ asyncio.sleep(1), ++ ) + ) # Same as above but with magic trailing comma in function @@ -167,27 +173,27 @@ async def main(): - asyncio.sleep(1), - asyncio.sleep(1), - asyncio.sleep(1), -- ) -+ await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ ( ++ await asyncio.gather( ++ asyncio.sleep(1), ++ asyncio.sleep(1), ++ asyncio.sleep(1), ++ asyncio.sleep(1), ++ asyncio.sleep(1), ++ asyncio.sleep(1), ++ asyncio.sleep(1), ++ ) + ) # Cr@zY Br@ck3Tz async def main(): - await black(1) -+ await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) ++ await (black(1)) # Keep brackets around non power operations and nested awaits -@@ -69,7 +60,7 @@ - - - async def main(): -- await (await asyncio.sleep(1)) -+ await (await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) - - - # It's awaits all the way down... -@@ -78,16 +69,16 @@ +@@ -78,16 +89,16 @@ async def main(): @@ -197,12 +203,12 @@ async def main(): async def main(): - await (await asyncio.sleep(1)) -+ await (await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg))) ++ await (await (asyncio.sleep(1))) async def main(): - await (await (await (await (await asyncio.sleep(1))))) -+ await (await (await (await (await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)))))) ++ await (await (await (await (await (asyncio.sleep(1)))))) async def main(): @@ -218,55 +224,75 @@ NOT_YET_IMPLEMENTED_StmtImport # Control example async def main(): - await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + await asyncio.sleep(1) # Remove brackets for short coroutine/task async def main(): - await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) + await (asyncio.sleep(1)) async def main(): - await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) + await (asyncio.sleep(1)) async def main(): - await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) + await (asyncio.sleep(1)) # Check comments async def main(): ( await # Hello - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + asyncio.sleep(1) ) async def main(): ( await ( - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) # Hello + asyncio.sleep(1) # Hello ) ) async def main(): - await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) # Hello + await (asyncio.sleep(1)) # Hello # Long lines async def main(): - await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + ( + await asyncio.gather( + asyncio.sleep(1), + asyncio.sleep(1), + asyncio.sleep(1), + asyncio.sleep(1), + asyncio.sleep(1), + asyncio.sleep(1), + asyncio.sleep(1), + ) + ) # Same as above but with magic trailing comma in function async def main(): - await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + ( + await asyncio.gather( + asyncio.sleep(1), + asyncio.sleep(1), + asyncio.sleep(1), + asyncio.sleep(1), + asyncio.sleep(1), + asyncio.sleep(1), + asyncio.sleep(1), + ) + ) # Cr@zY Br@ck3Tz async def main(): - await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) + await (black(1)) # Keep brackets around non power operations and nested awaits @@ -275,7 +301,7 @@ async def main(): async def main(): - await (await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) + await (await asyncio.sleep(1)) # It's awaits all the way down... @@ -288,11 +314,11 @@ async def main(): async def main(): - await (await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg))) + await (await (asyncio.sleep(1))) async def main(): - await (await (await (await (await (NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)))))) + await (await (await (await (await (asyncio.sleep(1)))))) async def main(): diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_for_brackets.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_for_brackets.py.snap index 87a792c38b..a6a1c1c29f 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_for_brackets.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_for_brackets.py.snap @@ -31,71 +31,56 @@ for (((((k, v))))) in d.items(): ```diff --- Black +++ Ruff -@@ -1,27 +1,22 @@ - # Only remove tuple brackets after `for` --for k, v in d.items(): -- print(k, v) -+for k, v in NOT_IMPLEMENTED_call(): -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - +@@ -5,7 +5,7 @@ # Don't touch tuple brackets after `in` for module in (core, _unicodefun): -- if hasattr(module, "_verify_python3_env"): + if hasattr(module, "_verify_python3_env"): - module._verify_python3_env = lambda: None -+ if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): + module._verify_python3_env = lambda x: True # Brackets remain for long for loop lines for ( - why_would_anyone_choose_to_name_a_loop_variable_with_a_name_this_long, - i_dont_know_but_we_should_still_check_the_behaviour_if_they_do, --) in d.items(): -- print(k, v) -+) in NOT_IMPLEMENTED_call(): -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - --for ( -- k, -- v, +@@ -17,9 +17,7 @@ + for ( + k, + v, -) in ( - dfkasdjfldsjflkdsjflkdsjfdslkfjldsjfgkjdshgkljjdsfldgkhsdofudsfudsofajdslkfjdslkfjldisfjdffjsdlkfjdlkjjkdflskadjldkfjsalkfjdasj.items() -): -- print(k, v) -+for k, v in NOT_IMPLEMENTED_call(): -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++) in dfkasdjfldsjflkdsjflkdsjfdslkfjldsjfgkjdshgkljjdsfldgkhsdofudsfudsofajdslkfjdslkfjldisfjdffjsdlkfjdlkjjkdflskadjldkfjsalkfjdasj.items(): + print(k, v) # Test deeply nested brackets --for k, v in d.items(): -- print(k, v) -+for k, v in NOT_IMPLEMENTED_call(): -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ``` ## Ruff Output ```py # Only remove tuple brackets after `for` -for k, v in NOT_IMPLEMENTED_call(): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +for k, v in d.items(): + print(k, v) # Don't touch tuple brackets after `in` for module in (core, _unicodefun): - if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): + if hasattr(module, "_verify_python3_env"): module._verify_python3_env = lambda x: True # Brackets remain for long for loop lines for ( why_would_anyone_choose_to_name_a_loop_variable_with_a_name_this_long, i_dont_know_but_we_should_still_check_the_behaviour_if_they_do, -) in NOT_IMPLEMENTED_call(): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +) in d.items(): + print(k, v) -for k, v in NOT_IMPLEMENTED_call(): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +for ( + k, + v, +) in dfkasdjfldsjflkdsjflkdsjfdslkfjldsjfgkjdshgkljjdsfldgkhsdofudsfudsofajdslkfjdslkfjldisfjdffjsdlkfjdlkjjkdflskadjldkfjsalkfjdasj.items(): + print(k, v) # Test deeply nested brackets -for k, v in NOT_IMPLEMENTED_call(): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +for k, v in d.items(): + print(k, v) ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_newline_after_code_block_open.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_newline_after_code_block_open.py.snap index fef152f5d3..f9095f8b6f 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_newline_after_code_block_open.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_newline_after_code_block_open.py.snap @@ -120,116 +120,32 @@ with open("/path/to/file.txt", mode="r") as read_file: ```diff --- Black +++ Ruff -@@ -1,78 +1,78 @@ +@@ -1,4 +1,4 @@ -import random +NOT_YET_IMPLEMENTED_StmtImport def foo1(): -- print("The newline above me should be deleted!") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +@@ -27,16 +27,16 @@ - def foo2(): -- print("All the newlines above me should be deleted!") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - - def foo3(): -- print("No newline above me!") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - -- print("There is a newline above me, and that's OK!") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - - def foo4(): - # There is a comment here - -- print("The newline above me should not be deleted!") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - - class Foo: - def bar(self): -- print("The newline above me should be deleted!") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - --for i in range(5): + for i in range(5): - print(f"{i}) The line above me should be removed!") -+for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ print(NOT_YET_IMPLEMENTED_ExprJoinedStr) --for i in range(5): + for i in range(5): - print(f"{i}) The lines above me should be removed!") -+for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ print(NOT_YET_IMPLEMENTED_ExprJoinedStr) --for i in range(5): -- for j in range(7): + for i in range(5): + for j in range(7): - print(f"{i}) The lines above me should be removed!") -+for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): -+ for j in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ print(NOT_YET_IMPLEMENTED_ExprJoinedStr) --if random.randint(0, 3) == 0: -- print("The new line above me is about to be removed!") -+if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) == 0: -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - --if random.randint(0, 3) == 0: -- print("The new lines above me is about to be removed!") -+if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) == 0: -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - --if random.randint(0, 3) == 0: -- if random.uniform(0, 1) > 0.5: -- print("Two lines above me are about to be removed!") -+if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) == 0: -+ if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) > 0.5: -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - - while True: -- print("The newline above me should be deleted!") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - - while True: -- print("The newlines above me should be deleted!") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - - while True: - while False: -- print("The newlines above me should be deleted!") -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - --with open("/path/to/file.txt", mode="w") as file: -- file.write("The new line above me is about to be removed!") -+with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) as file: -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - --with open("/path/to/file.txt", mode="w") as file: -- file.write("The new lines above me is about to be removed!") -+with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) as file: -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - --with open("/path/to/file.txt", mode="r") as read_file: -- with open("/path/to/output_file.txt", mode="w") as write_file: -- write_file.writelines(read_file.readlines()) -+with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) as read_file: -+ with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) as write_file: -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + if random.randint(0, 3) == 0: ``` ## Ruff Output @@ -239,80 +155,80 @@ NOT_YET_IMPLEMENTED_StmtImport def foo1(): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("The newline above me should be deleted!") def foo2(): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("All the newlines above me should be deleted!") def foo3(): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("No newline above me!") - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("There is a newline above me, and that's OK!") def foo4(): # There is a comment here - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("The newline above me should not be deleted!") class Foo: def bar(self): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("The newline above me should be deleted!") -for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +for i in range(5): + print(NOT_YET_IMPLEMENTED_ExprJoinedStr) -for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +for i in range(5): + print(NOT_YET_IMPLEMENTED_ExprJoinedStr) -for i in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - for j in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +for i in range(5): + for j in range(7): + print(NOT_YET_IMPLEMENTED_ExprJoinedStr) -if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) == 0: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +if random.randint(0, 3) == 0: + print("The new line above me is about to be removed!") -if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) == 0: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +if random.randint(0, 3) == 0: + print("The new lines above me is about to be removed!") -if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) == 0: - if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) > 0.5: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +if random.randint(0, 3) == 0: + if random.uniform(0, 1) > 0.5: + print("Two lines above me are about to be removed!") while True: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("The newline above me should be deleted!") while True: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("The newlines above me should be deleted!") while True: while False: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("The newlines above me should be deleted!") -with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) as file: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +with open("/path/to/file.txt", mode="w") as file: + file.write("The new line above me is about to be removed!") -with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) as file: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +with open("/path/to/file.txt", mode="w") as file: + file.write("The new lines above me is about to be removed!") -with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) as read_file: - with NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) as write_file: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +with open("/path/to/file.txt", mode="r") as read_file: + with open("/path/to/output_file.txt", mode="w") as write_file: + write_file.writelines(read_file.readlines()) ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_parens.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_parens.py.snap index 1ed5be6a16..bb59ae6651 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_parens.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@remove_parens.py.snap @@ -67,15 +67,7 @@ def example8(): ```diff --- Black +++ Ruff -@@ -1,20 +1,12 @@ - x = 1 - x = 1.2 - --data = ( -- "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" --).encode() -+data = NOT_IMPLEMENTED_call() - +@@ -8,13 +8,7 @@ async def show_status(): while True: @@ -90,7 +82,7 @@ def example8(): def example(): -@@ -30,15 +22,11 @@ +@@ -30,15 +24,11 @@ def example2(): @@ -108,7 +100,7 @@ def example8(): def example4(): -@@ -50,35 +38,11 @@ +@@ -50,35 +40,11 @@ def example6(): @@ -154,7 +146,9 @@ def example8(): x = 1 x = 1.2 -data = NOT_IMPLEMENTED_call() +data = ( + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +).encode() async def show_status(): diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@skip_magic_trailing_comma.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@skip_magic_trailing_comma.py.snap index ae72b77fdb..d87ef4d8a0 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@skip_magic_trailing_comma.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@skip_magic_trailing_comma.py.snap @@ -59,7 +59,7 @@ func( ```diff --- Black +++ Ruff -@@ -1,25 +1,39 @@ +@@ -1,25 +1,58 @@ # We should not remove the trailing comma in a single-element subscript. -a: tuple[int,] -b = tuple[int,] @@ -95,10 +95,20 @@ func( # Trailing commas in multiple chained non-nested parens. -zero(one).two(three).four(five) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++zero( ++ one, ++).two( ++ three, ++).four( ++ five, ++) -func1(arg1).func2(arg2).func3(arg3).func4(arg4).func5(arg5) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++func1(arg1).func2( ++ arg2, ++).func3(arg3).func4( ++ arg4, ++).func5(arg5) -(a, b, c, d) = func1(arg1) and func2(arg2) +( @@ -106,10 +116,19 @@ func( + b, + c, + d, -+) = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) and NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++) = func1(arg1) and func2(arg2) -func(argument1, (one, two), argument4, argument5, argument6) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++func( ++ argument1, ++ ( ++ one, ++ two, ++ ), ++ argument4, ++ argument5, ++ argument6, ++) ``` ## Ruff Output @@ -142,18 +161,37 @@ set_of_types = {tuple[(int,)]} small_tuple = (1,) # Trailing commas in multiple chained non-nested parens. -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +zero( + one, +).two( + three, +).four( + five, +) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +func1(arg1).func2( + arg2, +).func3(arg3).func4( + arg4, +).func5(arg5) ( a, b, c, d, -) = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) and NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +) = func1(arg1) and func2(arg2) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +func( + argument1, + ( + one, + two, + ), + argument4, + argument5, + argument6, +) ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@slices.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@slices.py.snap index ec47eb18f9..699c559a0b 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@slices.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@slices.py.snap @@ -75,7 +75,7 @@ x[ ```diff --- Black +++ Ruff -@@ -4,30 +4,35 @@ +@@ -4,30 +4,30 @@ slice[d::d] slice[0] slice[-1] @@ -111,16 +111,11 @@ x[ ham[lower:upper], ham[lower:upper:], ham[lower::step] # ham[lower+offset : upper+offset] -ham[: upper_fn(x) : step_fn(x)], ham[:: step_fn(x)] -+( -+ ham[ -+ : NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) : NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ ], -+ ham[ :: NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)], -+) ++ham[ : upper_fn(x) : step_fn(x)], ham[ :: step_fn(x)] ham[lower + offset : upper + offset] slice[::, ::] -@@ -50,10 +55,14 @@ +@@ -50,10 +50,14 @@ slice[ # A 1 @@ -172,12 +167,7 @@ async def f(): ham[1:9], ham[1:9:3], ham[:9:3], ham[1::3], ham[1:9:] ham[lower:upper], ham[lower:upper:], ham[lower::step] # ham[lower+offset : upper+offset] -( - ham[ - : NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) : NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - ], - ham[ :: NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)], -) +ham[ : upper_fn(x) : step_fn(x)], ham[ :: step_fn(x)] ham[lower + offset : upper + offset] slice[::, ::] diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@torture.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@torture.py.snap index ec5eeae618..246fcc69bc 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@torture.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@torture.py.snap @@ -64,16 +64,14 @@ assert ( importA 0 -@@ -24,35 +14,34 @@ - +@@ -25,34 +15,33 @@ class A: def foo(self): -- for _ in range(10): + for _ in range(10): - aaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbb.cccccccccc( - xxxxxxxxxxxx - ) # pylint: disable=no-member -+ for _ in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): -+ aaaaaaaaaaaaaaaaaaa = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ aaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbb.cccccccccc(xxxxxxxxxxxx) # pylint: disable=no-member def test(self, othr): @@ -146,8 +144,8 @@ importA class A: def foo(self): - for _ in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): - aaaaaaaaaaaaaaaaaaa = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + for _ in range(10): + aaaaaaaaaaaaaaaaaaa = bbbbbbbbbbbbbbb.cccccccccc(xxxxxxxxxxxx) # pylint: disable=no-member def test(self, othr): diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_comma_optional_parens1.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_comma_optional_parens1.py.snap index 177fde22db..35f9fc85aa 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_comma_optional_parens1.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_comma_optional_parens1.py.snap @@ -37,7 +37,7 @@ class A: ```diff --- Black +++ Ruff -@@ -1,34 +1,32 @@ +@@ -1,18 +1,16 @@ -if e1234123412341234.winerror not in ( - _winapi.ERROR_SEM_TIMEOUT, - _winapi.ERROR_PIPE_BUSY, @@ -45,7 +45,7 @@ class A: +if ( + e1234123412341234.winerror + not in (_winapi.ERROR_SEM_TIMEOUT, _winapi.ERROR_PIPE_BUSY) -+ or NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++ or _check_timeout(t) +): pass @@ -58,20 +58,14 @@ class A: - ) - + 1 - ) -+ new_id = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + 1 ++ new_id = max( ++ Vegetable.objects.order_by("-id")[0].id, ++ Mineral.objects.order_by("-id")[0].id, ++ ) + 1 class X: - def get_help_text(self): -- return ngettext( -- "Your password must contain at least %(min_length)d character.", -- "Your password must contain at least %(min_length)d characters.", -- self.min_length, -- ) % {"min_length": self.min_length} -+ return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) % { -+ "min_length": self.min_length, -+ } - +@@ -26,9 +24,14 @@ class A: def b(self): @@ -99,20 +93,25 @@ class A: if ( e1234123412341234.winerror not in (_winapi.ERROR_SEM_TIMEOUT, _winapi.ERROR_PIPE_BUSY) - or NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + or _check_timeout(t) ): pass if x: if y: - new_id = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + 1 + new_id = max( + Vegetable.objects.order_by("-id")[0].id, + Mineral.objects.order_by("-id")[0].id, + ) + 1 class X: def get_help_text(self): - return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) % { - "min_length": self.min_length, - } + return ngettext( + "Your password must contain at least %(min_length)d character.", + "Your password must contain at least %(min_length)d characters.", + self.min_length, + ) % {"min_length": self.min_length} class A: diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_comma_optional_parens2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_comma_optional_parens2.py.snap index c4dddaa5b1..bc155f8982 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_comma_optional_parens2.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_comma_optional_parens2.py.snap @@ -22,8 +22,8 @@ if (e123456.get_tk_patchlevel() >= (8, 6, 0, 'final') or - 8, -) <= get_tk_patchlevel() < (8, 6): +if ( -+ NOT_IMPLEMENTED_call() >= (8, 6, 0, "final") -+ or (8, 5, 8) <= NOT_IMPLEMENTED_call() < (8, 6) ++ e123456.get_tk_patchlevel() >= (8, 6, 0, "final") ++ or (8, 5, 8) <= get_tk_patchlevel() < (8, 6) +): pass ``` @@ -32,8 +32,8 @@ if (e123456.get_tk_patchlevel() >= (8, 6, 0, 'final') or ```py if ( - NOT_IMPLEMENTED_call() >= (8, 6, 0, "final") - or (8, 5, 8) <= NOT_IMPLEMENTED_call() < (8, 6) + e123456.get_tk_patchlevel() >= (8, 6, 0, "final") + or (8, 5, 8) <= get_tk_patchlevel() < (8, 6) ): pass ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_comma_optional_parens3.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_comma_optional_parens3.py.snap deleted file mode 100644 index 3a574ac557..0000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_comma_optional_parens3.py.snap +++ /dev/null @@ -1,63 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/trailing_comma_optional_parens3.py ---- -## Input - -```py -if True: - if True: - if True: - return _( - "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas " - + "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.", - "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe", - ) % {"reported_username": reported_username, "report_reason": report_reason} -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,8 +1,7 @@ - if True: - if True: - if True: -- return _( -- "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas " -- + "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.", -- "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe", -- ) % {"reported_username": reported_username, "report_reason": report_reason} -+ return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) % { -+ "reported_username": reported_username, -+ "report_reason": report_reason, -+ } -``` - -## Ruff Output - -```py -if True: - if True: - if True: - return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) % { - "reported_username": reported_username, - "report_reason": report_reason, - } -``` - -## Black Output - -```py -if True: - if True: - if True: - return _( - "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweas " - + "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwegqweasdzxcqweasdzxc.", - "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe", - ) % {"reported_username": reported_username, "report_reason": report_reason} -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_commas_in_leading_parts.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_commas_in_leading_parts.py.snap index e799084c77..b50a6c5ff7 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_commas_in_leading_parts.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@trailing_commas_in_leading_parts.py.snap @@ -45,47 +45,29 @@ assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx( ```diff --- Black +++ Ruff -@@ -1,50 +1,26 @@ --zero( -- one, --).two( -- three, --).four( -- five, --) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - --func1(arg1).func2( -- arg2, --).func3(arg3).func4( -- arg4, --).func5(arg5) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - # Inner one-element tuple shouldn't explode --func1(arg1).func2(arg1, (one_tuple,)).func3(arg3) -+NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - - ( - a, +@@ -20,9 +20,7 @@ b, c, d, -) = func1( - arg1 -) and func2(arg2) -+) = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) and NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++) = func1(arg1) and func2(arg2) # Example from https://github.com/psf/black/issues/3229 - def refresh_token(self, device_family, refresh_token, api_key): -- return self.orchestration.refresh_token( -- data={ -- "refreshToken": refresh_token, -- }, -- api_key=api_key, +@@ -32,19 +30,18 @@ + "refreshToken": refresh_token, + }, + api_key=api_key, - )["extensions"]["sdk"]["token"] -+ return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)["extensions"]["sdk"]["token"] ++ )[ ++ "extensions" ++ ][ ++ "sdk" ++ ][ ++ "token" ++ ] # Edge case where a bug in a working-in-progress version of @@ -108,24 +90,45 @@ assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx( ## Ruff Output ```py -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +zero( + one, +).two( + three, +).four( + five, +) -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +func1(arg1).func2( + arg2, +).func3(arg3).func4( + arg4, +).func5(arg5) # Inner one-element tuple shouldn't explode -NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +func1(arg1).func2(arg1, (one_tuple,)).func3(arg3) ( a, b, c, d, -) = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) and NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +) = func1(arg1) and func2(arg2) # Example from https://github.com/psf/black/issues/3229 def refresh_token(self, device_family, refresh_token, api_key): - return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)["extensions"]["sdk"]["token"] + return self.orchestration.refresh_token( + data={ + "refreshToken": refresh_token, + }, + api_key=api_key, + )[ + "extensions" + ][ + "sdk" + ][ + "token" + ] # Edge case where a bug in a working-in-progress version of diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@tupleassign.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@tupleassign.py.snap index d54c56272e..6e9dbd02a2 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@tupleassign.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@tupleassign.py.snap @@ -28,10 +28,9 @@ this_will_be_wrapped_in_parens, = struct.unpack(b"12345678901234567890") # This is as well. -(this_will_be_wrapped_in_parens,) = struct.unpack(b"12345678901234567890") -+(this_will_be_wrapped_in_parens,) = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) ++(this_will_be_wrapped_in_parens,) = struct.unpack(b"NOT_YET_IMPLEMENTED_BYTE_STRING") --(a,) = call() -+(a,) = NOT_IMPLEMENTED_call() + (a,) = call() ``` ## Ruff Output @@ -46,9 +45,9 @@ this_will_be_wrapped_in_parens, = struct.unpack(b"12345678901234567890") ) = 1, 2, 3 # This is as well. -(this_will_be_wrapped_in_parens,) = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +(this_will_be_wrapped_in_parens,) = struct.unpack(b"NOT_YET_IMPLEMENTED_BYTE_STRING") -(a,) = NOT_IMPLEMENTED_call() +(a,) = call() ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap index 77901f7b5c..bbff73657c 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__attribute.py.snap @@ -113,31 +113,30 @@ x53 = ( ```py NOT_YET_IMPLEMENTED_StmtImportFrom -a = NOT_IMPLEMENTED_call() +a = Namespace() ( - a + a. # comment - .b # trailing comment + b # trailing comment ) ( - a + a. # comment - .b # trailing dot comment # trailing identifier comment + b # trailing dot comment # trailing identifier comment ) ( - a + a. # comment - .b # trailing identifier comment + b # trailing identifier comment ) ( - a + a. # comment - . # in between b # trailing dot comment # trailing identifier comment ) @@ -150,9 +149,8 @@ a.aaaaaaaaaaaaaaaaaaaaa.lllllllllllllllllllllllllllloooooooooong.chaaaaaaaaaaaaa # chain if and only if we need them, that is if there are own line comments inside # the chain. x1 = ( - a.b + a.b. # comment 1 - . # comment 3 c.d # comment 2 ) @@ -163,15 +161,15 @@ x21 = ( a.b # trailing name end-of-line ) x22 = ( - a + a. # outermost leading own line - .b # outermost trailing end-of-line + b # outermost trailing end-of-line ) x31 = ( - a + a. # own line between nodes 1 - .b + b ) x321 = a.b # end-of-line dot comment x322 = a.b.c # end-of-line dot comment 2 @@ -181,9 +179,9 @@ x331 = ( b ) x332 = ( - "" + "". # own line between nodes - .find + find ) x8 = (a + a).b diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__binary.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__binary.py.snap index 84c5af2a92..59fcae973c 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__binary.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__binary.py.snap @@ -217,7 +217,9 @@ for user_id in set(target_user_ids) - {u.user_id for u in updates}: # Black breaks the right side first for the following expressions: -aaaaaaaaaaaaaa + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +aaaaaaaaaaaaaa + caaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaal( + argument1, argument2, argument3 +) aaaaaaaaaaaaaa + [ bbbbbbbbbbbbbbbbbbbbbb, ccccccccccccccccccccc, @@ -438,10 +440,10 @@ if ( # Unstable formatting in https://github.com/realtyem/synapse-unraid/blob/unraid_develop/synapse/handlers/presence.py -for ( - user_id -) in NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - {NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}: - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +for user_id in set( + target_user_ids +) - {NOT_IMPLEMENTED_set_value for value in NOT_IMPLEMENTED_set}: + updates.append(UserPresenceState.default(user_id)) ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__boolean_operation.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__boolean_operation.py.snap index ab8e33067f..979f6fb805 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__boolean_operation.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__boolean_operation.py.snap @@ -78,17 +78,17 @@ if ( and self._returncode # the child process has finished, but the # transport hasn't been notified yet? - and NOT_IMPLEMENTED_call() + and self._proc.poll() ): pass if ( self._proc and self._returncode - and NOT_IMPLEMENTED_call() + and self._proc.poll() and self._proc and self._returncode - and NOT_IMPLEMENTED_call() + and self._proc.poll() ): ... diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__slice.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__slice.py.snap index ffc644c26b..1ea479d8c8 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__slice.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__slice.py.snap @@ -159,17 +159,17 @@ def a(): e00 = "e"[:] e01 = "e"[:1] -e02 = "e"[ : NOT_IMPLEMENTED_call()] +e02 = "e"[ : a()] e10 = "e"[1:] e11 = "e"[1:1] -e12 = "e"[1 : NOT_IMPLEMENTED_call()] -e20 = "e"[NOT_IMPLEMENTED_call() :] -e21 = "e"[NOT_IMPLEMENTED_call() : 1] -e22 = "e"[NOT_IMPLEMENTED_call() : NOT_IMPLEMENTED_call()] -e200 = "e"[NOT_IMPLEMENTED_call() : :] -e201 = "e"[NOT_IMPLEMENTED_call() :: 1] -e202 = "e"[NOT_IMPLEMENTED_call() :: NOT_IMPLEMENTED_call()] -e210 = "e"[NOT_IMPLEMENTED_call() : 1 :] +e12 = "e"[1 : a()] +e20 = "e"[a() :] +e21 = "e"[a() : 1] +e22 = "e"[a() : a()] +e200 = "e"[a() : :] +e201 = "e"[a() :: 1] +e202 = "e"[a() :: a()] +e210 = "e"[a() : 1 :] ``` diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__call.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__call.py.snap new file mode 100644 index 0000000000..7c40b005b6 --- /dev/null +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__call.py.snap @@ -0,0 +1,175 @@ +--- +source: crates/ruff_python_formatter/tests/fixtures.rs +input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/statement/call.py +--- +## Input +```py +from unittest.mock import MagicMock + + +def f(*args, **kwargs): + pass + +this_is_a_very_long_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd = 1 +session = MagicMock() +models = MagicMock() + +f() + +f(1) + +f(x=2) + +f(1, x=2) + +f( + this_is_a_very_long_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd +) +f( + this_is_a_very_long_keyword_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd=1 +) + +f( + 1, + mixed_very_long_arguments=1, +) + +f( + this_is_a_very_long_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd, + these_arguments_have_values_that_need_to_break_because_they_are_too_long1=(100000 - 100000000000), + these_arguments_have_values_that_need_to_break_because_they_are_too_long2="akshfdlakjsdfad" + "asdfasdfa", + these_arguments_have_values_that_need_to_break_because_they_are_too_long3=session, +) + +f( + # dangling comment +) + + +f( + only=1, short=1, arguments=1 +) + +f( + hey_this_is_a_long_call, it_has_funny_attributes_that_breaks_into_three_lines=1 +) + +f( + hey_this_is_a_very_long_call=1, it_has_funny_attributes_asdf_asdf=1, too_long_for_the_line=1, really=True +) + +# TODO(konstin): Call chains/fluent interface (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains) +result = ( + session.query(models.Customer.id) + .filter( + models.Customer.account_id == 10000, + models.Customer.email == "user@example.org", + ) + .order_by(models.Customer.id.asc()) + .all() +) +# TODO(konstin): Black has this special case for comment placement where everything stays in one line +f( + "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa" +) + +f( + session, + b=1, + ** # oddly placed end-of-line comment + dict() +) +f( + session, + b=1, + ** + # oddly placed own line comment + dict() +) + +``` + +## Output +```py +NOT_YET_IMPLEMENTED_StmtImportFrom + + +def f(*args, **kwargs): + pass + + +this_is_a_very_long_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd = 1 +session = MagicMock() +models = MagicMock() + +f() + +f(1) + +f(x=2) + +f(1, x=2) + +f( + this_is_a_very_long_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd, +) +f( + this_is_a_very_long_keyword_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd=1, +) + +f( + 1, + mixed_very_long_arguments=1, +) + +f( + this_is_a_very_long_argument_asökdhflakjslaslhfdlaffahflahsöfdhasägporejfäalkdsjäfalisjäfdlkasjd, + these_arguments_have_values_that_need_to_break_because_they_are_too_long1=( + 100000 + - 100000000000 + ), + these_arguments_have_values_that_need_to_break_because_they_are_too_long2="akshfdlakjsdfad" + + "asdfasdfa", + these_arguments_have_values_that_need_to_break_because_they_are_too_long3=session, +) + +f() +# dangling comment + + +f(only=1, short=1, arguments=1) + +f(hey_this_is_a_long_call, it_has_funny_attributes_that_breaks_into_three_lines=1) + +f( + hey_this_is_a_very_long_call=1, + it_has_funny_attributes_asdf_asdf=1, + too_long_for_the_line=1, + really=True, +) + +# TODO(konstin): Call chains/fluent interface (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains) +result = session.query(models.Customer.id).filter( + models.Customer.account_id + == 10000, + models.Customer.email + == "user@example.org", +).order_by(models.Customer.id.asc()).all() +# TODO(konstin): Black has this special case for comment placement where everything stays in one line +f("aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa", "aaaaaaaa") + +f( + session, + b=1, + **dict(), # oddly placed end-of-line comment +) +f( + session, + b=1, + **dict(), + # oddly placed own line comment +) +``` + + + diff --git a/crates/ruff_python_formatter/tests/snapshots/format@statement__while.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@statement__while.py.snap index 3aa590915d..9014bcdd53 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@statement__while.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@statement__while.py.snap @@ -59,16 +59,16 @@ while ( else: ... -while NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) and anotherCondition or aThirdCondition: # comment - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +while some_condition(unformatted, args) and anotherCondition or aThirdCondition: # comment + print("Do something") while ( - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) # trailing some condition + some_condition(unformatted, args) # trailing some condition and anotherCondition or aThirdCondition # trailing third condition ): # comment - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + print("Do something") ``` diff --git a/fuzz/Cargo.toml b/fuzz/Cargo.toml index d1ade6486a..6b24114ad4 100644 --- a/fuzz/Cargo.toml +++ b/fuzz/Cargo.toml @@ -24,8 +24,8 @@ ruff_python_ast = { path = "../crates/ruff_python_ast" } ruff_python_formatter = { path = "../crates/ruff_python_formatter" } similar = { version = "2.2.1" } -# Current tag: v0.0.6 -rustpython-parser = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "8078663b6c914c1cb86993e427764f7c422fc12c" , default-features = false, features = ["full-lexer", "num-bigint"] } +# Current tag: v0.0.7 +rustpython-parser = { git = "https://github.com/astral-sh/RustPython-Parser.git", rev = "c174bbf1f29527edd43d432326327f16f47ab9e0" , default-features = false, features = ["full-lexer", "num-bigint"] } # Prevent this from interfering with workspaces [workspace]