diff --git a/crates/ruff_python_formatter/src/expression/expr_list.rs b/crates/ruff_python_formatter/src/expression/expr_list.rs index 8e3badce51..16896dac16 100644 --- a/crates/ruff_python_formatter/src/expression/expr_list.rs +++ b/crates/ruff_python_formatter/src/expression/expr_list.rs @@ -52,23 +52,7 @@ impl FormatNodeRule for FormatExprList { "A non-empty expression list has dangling comments" ); - let items = format_with(|f| { - let mut iter = elts.iter(); - - if let Some(first) = iter.next() { - write!(f, [first.format()])?; - } - - for item in iter { - write!(f, [text(","), soft_line_break_or_space(), item.format()])?; - } - - if !elts.is_empty() { - write!(f, [if_group_breaks(&text(","))])?; - } - - Ok(()) - }); + let items = format_with(|f| f.join_comma_separated().nodes(elts.iter()).finish()); write!( f, 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 6e6ec5275c..a28e9d0841 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 @@ -145,16 +145,8 @@ if True: # looping over a 1-tuple should also not get wrapped for x in (1,): -@@ -63,14 +42,10 @@ - for (x,) in (1,), (2,), (3,): - pass - --[ -- 1, -- 2, -- 3, --] -+[1, 2, 3] +@@ -70,7 +49,7 @@ + ] division_result_tuple = (6 / 2,) -print("foo %r", (foo.bar,)) @@ -162,7 +154,7 @@ if True: if True: IGNORED_TYPES_FOR_ATTRIBUTE_CHECKING = ( -@@ -79,21 +54,6 @@ +@@ -79,21 +58,6 @@ ) if True: @@ -236,7 +228,11 @@ for x in (1,): for (x,) in (1,), (2,), (3,): pass -[1, 2, 3] +[ + 1, + 2, + 3, +] division_result_tuple = (6 / 2,) NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) 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 2778d433ad..c975d624f6 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 @@ -307,7 +307,7 @@ instruction()#comment with bad spacing while True: if False: continue -@@ -141,24 +111,19 @@ +@@ -141,10 +111,7 @@ # and round and round we go # let's return @@ -318,15 +318,8 @@ instruction()#comment with bad spacing + return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) --CONFIG_FILES = ( -- [ -- CONFIG_FILE, -- ] -- + SHARED_CONFIG_FILES -- + USER_CONFIG_FILES --) # type: Final -+CONFIG_FILES = [CONFIG_FILE] + SHARED_CONFIG_FILES + USER_CONFIG_FILES # type: Final - + CONFIG_FILES = ( +@@ -158,7 +125,11 @@ class Test: def _init_host(self, parsed) -> None: @@ -339,7 +332,7 @@ instruction()#comment with bad spacing pass -@@ -167,7 +132,7 @@ +@@ -167,7 +138,7 @@ ####################### @@ -469,7 +462,13 @@ def inline_comments_in_brackets_ruin_everything(): return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -CONFIG_FILES = [CONFIG_FILE] + SHARED_CONFIG_FILES + USER_CONFIG_FILES # type: Final +CONFIG_FILES = ( + [ + CONFIG_FILE, + ] + + SHARED_CONFIG_FILES + + USER_CONFIG_FILES +) # type: Final class Test: 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 0b3a703534..c1c18a580f 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 @@ -274,7 +274,7 @@ last_call() Name None True -@@ -30,98 +31,83 @@ +@@ -30,33 +31,39 @@ -1 ~int and not v1 ^ 123 + v2 | True (~int) and (not ((v1 ^ (123 + v2)) | True)) @@ -337,32 +337,27 @@ last_call() () (1,) (1, 2) - (1, 2, 3) - [] - [1, 2, 3, 4, 5, 6, 7, 8, 9, (10 or A), (11 or B), (12 or C)] --[ -- 1, -- 2, -- 3, --] +@@ -68,60 +75,51 @@ + 2, + 3, + ] -[*a] -[*range(10)] --[ -- *a, -- 4, -- 5, --] -+[1, 2, 3] +[*NOT_YET_IMPLEMENTED_ExprStarred] +[*NOT_YET_IMPLEMENTED_ExprStarred] -+[*NOT_YET_IMPLEMENTED_ExprStarred, 4, 5] -+[4, *NOT_YET_IMPLEMENTED_ExprStarred, 5] [ -- 4, - *a, -- 5, --] --[ ++ *NOT_YET_IMPLEMENTED_ExprStarred, + 4, + 5, + ] + [ + 4, +- *a, ++ *NOT_YET_IMPLEMENTED_ExprStarred, + 5, + ] + [ this_is_a_very_long_variable_which_will_force_a_delimiter_split, element, another, @@ -432,7 +427,7 @@ last_call() (1).real (1.0).real ....__class__ -@@ -130,34 +116,28 @@ +@@ -130,34 +128,28 @@ tuple[str, ...] tuple[str, int, float, dict[str, int]] tuple[ @@ -480,7 +475,7 @@ last_call() numpy[0, :] numpy[:, i] numpy[0, :2] -@@ -171,25 +151,32 @@ +@@ -171,25 +163,32 @@ numpy[1 : c + 1, c] numpy[-(c + 1) :, d] numpy[:, l[-2]] @@ -523,7 +518,7 @@ last_call() "priority": 1, "import_session_id": 1, **kwargs, -@@ -198,35 +185,21 @@ +@@ -198,35 +197,21 @@ b = (1,) c = 1 d = (1,) + a + (2,) @@ -532,17 +527,6 @@ last_call() -g = 1, *"ten" -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 --) --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() +e = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +f = 1, *NOT_YET_IMPLEMENTED_ExprStarred +g = 1, *NOT_YET_IMPLEMENTED_ExprStarred @@ -550,6 +534,20 @@ last_call() + (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) + ) +-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( @@ -559,10 +557,7 @@ last_call() - models.Customer.id.asc(), - ) - .all() -+what_is_up_with_those_new_coord_names = ( -+ (coord_names | NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)) -+ - NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - ) +-) -Ø = set() -authors.łukasz.say_thanks() +result = NOT_IMPLEMENTED_call() @@ -572,7 +567,7 @@ last_call() mapping = { A: 0.25 * (10.0 / 12), B: 0.1 * (10.0 / 12), -@@ -236,31 +209,29 @@ +@@ -236,31 +221,29 @@ def gen(): @@ -617,7 +612,7 @@ last_call() ... for j in 1 + (2 + 3): ... -@@ -272,7 +243,7 @@ +@@ -272,7 +255,7 @@ addr_proto, addr_canonname, addr_sockaddr, @@ -626,7 +621,7 @@ last_call() pass a = ( aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp -@@ -291,9 +262,9 @@ +@@ -291,9 +274,9 @@ is not qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz ) if ( @@ -639,7 +634,7 @@ last_call() ): return True if ( -@@ -327,13 +298,18 @@ +@@ -327,13 +310,18 @@ ): return True if ( @@ -661,7 +656,7 @@ last_call() ^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l**aaaaaaaa.m // aaaaaaaa.n ): return True -@@ -341,7 +317,8 @@ +@@ -341,7 +329,8 @@ ~aaaaaaaaaaaaaaaa.a + aaaaaaaaaaaaaaaa.b - aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e @@ -671,7 +666,7 @@ last_call() ^ aaaaaaaaaaaaaaaa.i << aaaaaaaaaaaaaaaa.k >> aaaaaaaaaaaaaaaa.l**aaaaaaaaaaaaaaaa.m // aaaaaaaaaaaaaaaa.n -@@ -366,5 +343,5 @@ +@@ -366,5 +355,5 @@ ^ bbbb.a & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ^ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ) @@ -755,11 +750,23 @@ NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false (1, 2, 3) [] [1, 2, 3, 4, 5, 6, 7, 8, 9, (10 or A), (11 or B), (12 or C)] -[1, 2, 3] +[ + 1, + 2, + 3, +] [*NOT_YET_IMPLEMENTED_ExprStarred] [*NOT_YET_IMPLEMENTED_ExprStarred] -[*NOT_YET_IMPLEMENTED_ExprStarred, 4, 5] -[4, *NOT_YET_IMPLEMENTED_ExprStarred, 5] +[ + *NOT_YET_IMPLEMENTED_ExprStarred, + 4, + 5, +] +[ + 4, + *NOT_YET_IMPLEMENTED_ExprStarred, + 5, +] [ this_is_a_very_long_variable_which_will_force_a_delimiter_split, element, diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff3.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff3.py.snap index 9dacee57d5..42ebc85486 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff3.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtonoff3.py.snap @@ -29,35 +29,50 @@ x = [ ```diff --- Black +++ Ruff -@@ -1,15 +1,9 @@ +@@ -1,14 +1,18 @@ # fmt: off --x = [ + x = [ - 1, 2, - 3, 4, --] -+x = [1, 2, 3, 4] ++ 1, ++ 2, ++ 3, ++ 4, + ] # fmt: on # fmt: off --x = [ + x = [ - 1, 2, - 3, 4, --] -+x = [1, 2, 3, 4] ++ 1, ++ 2, ++ 3, ++ 4, + ] # fmt: on - x = [1, 2, 3, 4] ``` ## Ruff Output ```py # fmt: off -x = [1, 2, 3, 4] +x = [ + 1, + 2, + 3, + 4, +] # fmt: on # fmt: off -x = [1, 2, 3, 4] +x = [ + 1, + 2, + 3, + 4, +] # fmt: on x = [1, 2, 3, 4] diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip2.py.snap index 487290c418..6b686d5412 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip2.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip2.py.snap @@ -15,22 +15,19 @@ l3 = ["I have", "trailing comma", "so I should be braked",] ```diff --- Black +++ Ruff -@@ -3,9 +3,9 @@ +@@ -3,7 +3,11 @@ "into multiple lines", "because it is way too long", ] -l2 = ["But this list shouldn't", "even though it also has", "way too many characters in it"] # fmt: skip --l3 = [ -- "I have", -- "trailing comma", -- "so I should be braked", --] +l2 = [ + "But this list shouldn't", + "even though it also has", + "way too many characters in it", +] # fmt: skip -+l3 = ["I have", "trailing comma", "so I should be braked"] + l3 = [ + "I have", + "trailing comma", ``` ## Ruff Output @@ -46,7 +43,11 @@ l2 = [ "even though it also has", "way too many characters in it", ] # fmt: skip -l3 = ["I have", "trailing comma", "so I should be braked"] +l3 = [ + "I have", + "trailing comma", + "so I should be braked", +] ``` ## Black Output diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip4.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip4.py.snap deleted file mode 100644 index 93b2d701b1..0000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@fmtskip4.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/fmtskip4.py ---- -## Input - -```py -a = 2 -# fmt: skip -l = [1, 2, 3,] -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,7 +1,3 @@ - a = 2 - # fmt: skip --l = [ -- 1, -- 2, -- 3, --] -+l = [1, 2, 3] -``` - -## Ruff Output - -```py -a = 2 -# fmt: skip -l = [1, 2, 3] -``` - -## Black Output - -```py -a = 2 -# fmt: skip -l = [ - 1, - 2, - 3, -] -``` - - 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 e98815a64f..2a55c63e83 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 @@ -97,7 +97,7 @@ some_module.some_function( if ( a == { -@@ -47,23 +43,17 @@ +@@ -47,22 +43,24 @@ "f": 6, "g": 7, "h": 8, @@ -112,23 +112,24 @@ some_module.some_function( -def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( - Set["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] -): -- json = { -- "k": { -- "k2": { -- "k3": [ -- 1, -- ] -- } -- } -- } +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: -+ json = {"k": {"k2": {"k3": [1]}}} + json = { + "k": { + "k2": { + "k3": [ + 1, +- ] +- } +- } ++ ], ++ }, ++ }, + } - # The type annotation shouldn't get a trailing comma since that would change its type. -@@ -80,35 +70,16 @@ +@@ -80,35 +78,16 @@ pass @@ -228,7 +229,15 @@ def f( def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ]: - json = {"k": {"k2": {"k3": [1]}}} + json = { + "k": { + "k2": { + "k3": [ + 1, + ], + }, + }, + } # The type annotation shouldn't get a trailing comma since that would change its type. diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@one_element_subscript.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@one_element_subscript.py.snap index 68bddbd301..1db4d103ba 100644 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@one_element_subscript.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@one_element_subscript.py.snap @@ -24,7 +24,7 @@ list_of_types = [tuple[int,],] ```diff --- Black +++ Ruff -@@ -1,22 +1,17 @@ +@@ -1,16 +1,15 @@ # We should not treat the trailing comma # in a single-element subscript. -a: tuple[int,] @@ -48,14 +48,13 @@ list_of_types = [tuple[int,],] ] # Magic commas still work as expected for non-subscripts. --small_list = [ -- 1, --] --list_of_types = [ +@@ -18,5 +17,5 @@ + 1, + ] + list_of_types = [ - tuple[int,], --] -+small_list = [1] -+list_of_types = [tuple[(int,)]] ++ tuple[(int,)], + ] ``` ## Ruff Output @@ -76,8 +75,12 @@ d = tuple[ ] # Magic commas still work as expected for non-subscripts. -small_list = [1] -list_of_types = [tuple[(int,)]] +small_list = [ + 1, +] +list_of_types = [ + tuple[(int,)], +] ``` ## Black Output 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 4fccb92505..ae72b77fdb 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,35 @@ +@@ -1,25 +1,39 @@ # We should not remove the trailing comma in a single-element subscript. -a: tuple[int,] -b = tuple[int,] @@ -78,9 +78,14 @@ func( +] # Remove commas for non-subscripts. - small_list = [1] +-small_list = [1] -list_of_types = [tuple[int,]] -+list_of_types = [tuple[(int,)]] ++small_list = [ ++ 1, ++] ++list_of_types = [ ++ tuple[(int,)], ++] small_set = {1} -set_of_types = {tuple[int,]} +set_of_types = {tuple[(int,)]} @@ -124,8 +129,12 @@ d = tuple[ ] # Remove commas for non-subscripts. -small_list = [1] -list_of_types = [tuple[(int,)]] +small_list = [ + 1, +] +list_of_types = [ + tuple[(int,)], +] small_set = {1} set_of_types = {tuple[(int,)]} diff --git a/crates/ruff_python_formatter/tests/snapshots/format@expression__compare.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@expression__compare.py.snap index 3e5eab9002..6031fbadf8 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@expression__compare.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@expression__compare.py.snap @@ -102,7 +102,10 @@ a < b > c == d ( aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - < [bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, ff] + < [ + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb, + ff, + ] < [ccccccccccccccccccccccccccccc, dddd] < ddddddddddddddddddddddddddddddddddddddddddd )