Commit Graph

898 Commits

Author SHA1 Message Date
Brent Westbrook 65c943568c
Merge branch 'brent/fix-kwargs' into brent/indent-lambda-params 2025-12-09 15:42:05 -05:00
Brent Westbrook b0a82983af
avoid breaking when the first parameter has leading comments 2025-12-09 15:32:24 -05:00
Brent Westbrook 90f43bde84
add broken test cases
the new leading comment is causing the whole Parameters list to break. these
cases should instead format like:

```py
(
    lambda
    # comment
    *x, **y: x
)

(
    lambda
    # comment 2
    *x, **y: x
)
```

without line breaks in the parameter list
2025-12-09 15:06:48 -05:00
Brent Westbrook 4ffbd496e3
Merge branch 'main' into brent/indent-lambda-params 2025-12-09 14:34:28 -05:00
Brent Westbrook 0bec5c0362
Fix comment placement in lambda parameters (#21868)
Summary
--

This PR makes two changes to comment placement in lambda parameters.
First, we
now insert a line break if the first parameter has a leading comment:

```py
# input
(
    lambda
    * # comment 2
    x:
    x
)

# main
(
    lambda # comment 2
    *x: x
)

# this PR
(
    lambda
	# comment 2
    *x: x
)
```

Note the missing space in the output from main. This case is currently
unstable
on main. Also note that the new formatting is more consistent with our
stable
formatting in cases where the lambda has its own dangling comment:

```py
# input
(
    lambda # comment 1
    * # comment 2
    x:
    x
)

# output
(
    lambda  # comment 1
    # comment 2
    *x: x
)
```

and when a parameter without a comment precedes the split `*x`:

```py
# input
(
    lambda y,
    * # comment 2
    x:
    x
)

# output
(
    lambda y,
    # comment 2
    *x: x
)
```

This does change the stable formatting, but I think such cases are rare
(expecting zero hits in the ecosystem report), this fixes an existing
instability, and it should not change any code we've previously
formatted.

Second, this PR modifies the comment placement such that `# comment 2`
in these
outputs is still a leading comment on the parameter. This is also not
the case
on main, where it becomes a [dangling lambda
comment](https://play.ruff.rs/3b29bb7e-70e4-4365-88e0-e60fe1857a35?secondary=Comments).
This doesn't cause any
instability that I'm aware of on main, but it does cause problems when
trying to
adjust the placement of dangling lambda comments in #21385. Changing the
placement in this way should not affect any formatting here.

Test Plan
--

New lambda tests, plus existing tests covering the cases above with
multiple
comments around the parameters (see lambda.py 122-143, and 122-205 or so
more
broadly)

I also checked manually that the comments are now leading on the
parameter:

```shell
❯ cargo run --bin ruff_python_formatter -- --emit stdout --target-version 3.10 --print-comments <<EOF
(
    lambda
        # comment 2
    *x: x
)
EOF
    Finished `dev` profile [unoptimized + debuginfo] target(s) in 0.15s
     Running `target/debug/ruff_python_formatter --emit stdout --target-version 3.10 --print-comments`
# Comment decoration: Range, Preceding, Following, Enclosing, Comment
21..32, None, Some((Parameters, 37..39)), (ExprLambda, 6..42), "# comment 2"
{
    Node {
        kind: Parameter,
        range: 37..39,
        source: `*x`,
    }: {
        "leading": [
            SourceComment {
                text: "# comment 2",
                position: OwnLine,
                formatted: true,
            },
        ],
        "dangling": [],
        "trailing": [],
    },
}
(
    lambda
    # comment 2
    *x: x
)
```

But I didn't see a great place to put a test like this. Is there
somewhere I can assert this comment placement since it doesn't affect
any formatting yet? Or is it okay to wait until we use this in #21385?
2025-12-09 14:07:48 -05:00
Brent Westbrook 711dd6eed4
pass preview to handle_lambda_comment 2025-12-09 10:27:45 -05:00
Brent Westbrook 21b442a4fc
accept snapshots 2025-12-09 08:53:53 -05:00
Brent Westbrook ea30464a2d
clippy 2025-12-09 08:52:39 -05:00
Brent Westbrook c7b1089631
apply patch
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-12-09 08:51:59 -05:00
Brent Westbrook e8540d9b08
format new dangling comments 2025-12-08 12:56:57 -05:00
Brent Westbrook 8ede14a083
move comments within lambda parameters to dangling lambda comments 2025-12-08 12:29:37 -05:00
Brent Westbrook f20f3e0d49
fix assignment instability without parameters too 2025-12-05 16:08:37 -05:00
Brent Westbrook df42aa29b5
Reapply "try parenthesizing the body without parameters"
This reverts commit 4585a0b3e4.
2025-12-05 16:04:23 -05:00
Brent Westbrook 0710e0bc3e
fix assignment instability with dangling comments 2025-12-05 16:03:46 -05:00
Brent Westbrook 1531c94b4e
revert the last two commits, back to a stable formatting 2025-12-05 15:44:21 -05:00
Brent Westbrook 86406c0bb1
wip 2025-12-05 15:41:49 -05:00
Brent Westbrook 80852c1769
pairing 2025-12-05 15:40:47 -05:00
Brent Westbrook 4d76cd7b15
factor out parameters_have_comments 2025-12-05 14:57:54 -05:00
Brent Westbrook 3c481ba0ed
factor out preview variable 2025-12-05 14:52:16 -05:00
Brent Westbrook 4585a0b3e4
Revert "try parenthesizing the body without parameters"
this is unstable because it moves the comment into a new set of parentheses,
which then means the lambda itself can be unparenthesized

```diff
-a = (
-    lambda: (  # Dangling
-        1
-    )
+a = lambda: (  # Dangling
+    1
 )
```
2025-12-05 13:59:55 -05:00
Brent Westbrook c62390d18c
try parenthesizing the body without parameters 2025-12-05 13:58:33 -05:00
Brent Westbrook 8cbe03b318
add more cases without parameters 2025-12-05 13:58:06 -05:00
Brent Westbrook fe255d1ad2
leading_comments in block 2025-12-05 13:39:37 -05:00
Brent Westbrook c7666423ba
block indent and trailing comments 2025-12-05 13:22:09 -05:00
Brent Westbrook 25d70b408b
more tests 2025-12-05 12:50:18 -05:00
Brent Westbrook 5605387a77
add another dangling case between lambda and parameters 2025-12-05 10:22:32 -05:00
Brent Westbrook dc240a1574
clippy 2025-12-05 09:32:46 -05:00
Brent Westbrook 43b53edcab
improve dangling header comment placement 2025-12-05 09:21:48 -05:00
Brent Westbrook a4b4a82e61
add another dangling eol case 2025-12-05 08:34:55 -05:00
Brent Westbrook 219bbd1ce0
check comment case first 2025-12-05 08:26:58 -05:00
Brent Westbrook dfd3460c7a
add some more tests 2025-12-04 18:02:52 -05:00
Brent Westbrook 08b1da3ab0
mirror comment handling from `maybe_parenthesize_expression`
and update comment
2025-12-04 15:44:36 -05:00
Brent Westbrook 1a3e385a8e
Merge branch 'main' into brent/indent-lambda-params 2025-12-04 10:39:43 -05:00
Brent Westbrook bdd5ba5e7f
gate optional_parentheses branches behind stable 2025-12-04 10:37:33 -05:00
Brent Westbrook 3a20c6f196
copy mapper test case from can_omit_optional_parentheses 2025-12-04 10:25:13 -05:00
Brent Westbrook 2e84402f69
add comments and some supporting tests 2025-12-04 10:08:46 -05:00
Brent Westbrook afb01ce84d
combine preview checks 2025-12-04 09:50:39 -05:00
Brent Westbrook 7dddcc85bc
remove comment
I don't think we can move the `fits_expanded` call into the assignment
formatting because that would wrap the whole lambda in a `fits_expanded`, when we
just want to wrap the lambda body in it instead. if I understand correctly, we'd
need to duplicate basically this whole function to inject `fits_expanded` in the
right place for the lambda formatting in assignments
2025-12-03 14:27:42 -05:00
Brent Westbrook 04963a6b6b
expand parent if the lambda body breaks 2025-12-03 14:16:16 -05:00
Brent Westbrook 258b1fd7eb
add wrapping case from the ecosystem check
the lambda is hugging its enclosing parentheses when it shouldn't be. there
seems to be an issue with `best_fitting!` because moving any of the options
we're passing to it out of `best_fitting!` avoids this behavior.

IR:

```
[
  source_position(0),
  source_position(1),
  "[",
  group(expand: propagated, [
    indent([
      soft_line_break,
      "(",
      group([
        indent([
          soft_line_break,
          "lambda ",
          group(["eval_df, _"]),
          ": ",
          best_fitting([
            [
              [
                <interned 0> [
                  "MetricValue(",
                  group(expand: propagated, [
                    indent([
                      soft_line_break,
                      group(expand: propagated, [
                        "scores=eval_df[",
                        group([
                          indent([soft_line_break, "\"prediction\""]),
                          soft_line_break
                        ]),
                        "].tolist",
                        group(["()"]),
                        ",",
                        soft_line_break_or_space,
                        "aggregate_results={",
                        group([
                          indent([
                            soft_line_break,
                            group([
                              "\"prediction_sum\": sum(",
                              group([
                                indent([
                                  soft_line_break,
                                  group([
                                    "eval_df[",
                                    group([
                                      indent([soft_line_break, "\"prediction\""]),
                                      soft_line_break
                                    ]),
                                    "]"
                                  ])
                                ]),
                                soft_line_break
                              ]),
                              ")"
                            ])
                          ]),
                          soft_line_break
                        ]),
                        "}",
                        if_group_breaks([","]),
                        expand_parent
                      ])
                    ]),
                    soft_line_break
                  ]),
                  ")"
                ]
              ]
            ]
            [[group(expand: true, [<ref interned *0>])]]
            [
              [
                "(",
                indent([hard_line_break, <ref interned *0>]),
                hard_line_break,
                ")"
              ]
            ]
          ])
        ]),
        soft_line_break
      ]),
      ")",
      if_group_breaks([","]),
      expand_parent
    ]),
    soft_line_break
  ]),
  "]",
  source_position(196),
  hard_line_break,
  source_position(196)
]
```
2025-12-03 11:52:48 -05:00
Brent Westbrook a3400a017a
use parenthesize_if_expands for fluent call chains 2025-12-03 11:51:02 -05:00
Brent Westbrook 9ef9d0302d
fix another ecosystem call expansion 2025-12-03 10:06:48 -05:00
Brent Westbrook 6f6c09c72a
fix snapshot changes for cases with comments 2025-12-03 09:45:00 -05:00
Brent Westbrook efa372b379
apply Micha's patch, fixing everything?
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-12-03 09:14:52 -05:00
Brent Westbrook 97850661fd
add too-eagerly parenthesized case from ecosystem
the initial code here is only 83 characters wide, so the call expression should
fit without wrapping the whole body in parens
2025-12-02 15:34:32 -05:00
Brent Westbrook 2e9500209f
avoid nesting groups 2025-12-02 15:30:12 -05:00
Brent Westbrook 972129c0ef
create id only in indented case, update group name 2025-12-02 15:24:31 -05:00
Brent Westbrook 18a3d59352
use write!
Co-authored-by: Micha Reiser <micha@reiser.io>
2025-12-02 15:20:57 -05:00
Micha Reiser 515de2d062
Move `Token`, `TokenKind` and `Tokens` to `ruff-python-ast` (#21760) 2025-12-02 20:10:46 +01:00
Brent Westbrook 89dc1ada39
add a couple more test cases
I tried to get Claude to come up with tests, but most of them weren't very
interesting. I think these two additional types of assignments might be worth
having, though.
2025-12-02 11:47:41 -05:00