Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix attribute chain own line comments #5340

Merged
merged 2 commits into from
Jun 26, 2023

Conversation

konstin
Copy link
Member

@konstin konstin commented Jun 23, 2023

Motation

Previously,

x = (
    a1
    .a2
    # a
    .  # b
    # c
    a3
)

got formatted as

x = a1.a2
# a
.  # b
# c
a3

which is invalid syntax. This fixes that.

Summary

This implements a basic form of attribute chaining (https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#call-chains) by checking if any inner attribute access contains an own line comment, and if this is the case, adds parentheses around the outermost attribute access while disabling parentheses for all inner attribute expressions. We want to replace this with an implementation that uses recursion or a stack while formatting instead of in needs_parentheses and also includes calls rather sooner than later, but i'm fixing this now because i'm uncomfortable with having known invalid syntax generation in the formatter.

Test Plan

I added new fixtures.

@konstin
Copy link
Member Author

konstin commented Jun 23, 2023

Current dependencies on/for this PR:

This comment was auto-generated by Graphite.

@konstin konstin requested a review from MichaReiser June 23, 2023 16:40
Base automatically changed from refactor_magic_trailing_comma to main June 23, 2023 16:53
@github-actions
Copy link
Contributor

github-actions bot commented Jun 23, 2023

PR Check Results

Ecosystem

✅ ecosystem check detected no changes.

Benchmark

Linux

group                                      main                                   pr
-----                                      ----                                   --
formatter/large/dataset.py                 1.02      8.1±0.05ms     5.0 MB/sec    1.00      8.0±0.05ms     5.1 MB/sec
formatter/numpy/ctypeslib.py               1.02   1879.6±2.98µs     8.9 MB/sec    1.00   1845.5±2.62µs     9.0 MB/sec
formatter/numpy/globals.py                 1.01    223.9±0.44µs    13.2 MB/sec    1.00    221.3±0.37µs    13.3 MB/sec
formatter/pydantic/types.py                1.03      4.2±0.01ms     6.0 MB/sec    1.00      4.1±0.00ms     6.2 MB/sec
linter/all-rules/large/dataset.py          1.01     15.9±0.07ms     2.6 MB/sec    1.00     15.8±0.07ms     2.6 MB/sec
linter/all-rules/numpy/ctypeslib.py        1.00      4.0±0.01ms     4.2 MB/sec    1.00      4.0±0.01ms     4.2 MB/sec
linter/all-rules/numpy/globals.py          1.00    517.6±0.88µs     5.7 MB/sec    1.00    516.5±0.98µs     5.7 MB/sec
linter/all-rules/pydantic/types.py         1.00      7.0±0.03ms     3.6 MB/sec    1.01      7.1±0.04ms     3.6 MB/sec
linter/default-rules/large/dataset.py      1.01      8.0±0.02ms     5.1 MB/sec    1.00      8.0±0.02ms     5.1 MB/sec
linter/default-rules/numpy/ctypeslib.py    1.00   1778.5±1.44µs     9.4 MB/sec    1.00   1772.9±9.98µs     9.4 MB/sec
linter/default-rules/numpy/globals.py      1.00    204.6±1.52µs    14.4 MB/sec    1.00    204.4±0.98µs    14.4 MB/sec
linter/default-rules/pydantic/types.py     1.01      3.7±0.01ms     6.9 MB/sec    1.00      3.7±0.01ms     7.0 MB/sec

Windows

group                                      main                                   pr
-----                                      ----                                   --
formatter/large/dataset.py                 1.00      7.8±0.03ms     5.2 MB/sec    1.11      8.7±0.19ms     4.7 MB/sec
formatter/numpy/ctypeslib.py               1.00  1741.7±10.47µs     9.6 MB/sec    1.09  1897.1±15.26µs     8.8 MB/sec
formatter/numpy/globals.py                 1.00    200.4±1.31µs    14.7 MB/sec    1.06    211.7±5.80µs    13.9 MB/sec
formatter/pydantic/types.py                1.00      4.0±0.02ms     6.4 MB/sec    1.09      4.4±0.03ms     5.8 MB/sec
linter/all-rules/large/dataset.py          1.01     15.2±0.12ms     2.7 MB/sec    1.00     15.1±0.08ms     2.7 MB/sec
linter/all-rules/numpy/ctypeslib.py        1.00      4.1±0.03ms     4.1 MB/sec    1.00      4.1±0.02ms     4.1 MB/sec
linter/all-rules/numpy/globals.py          1.00    426.0±4.54µs     6.9 MB/sec    1.00    426.0±5.04µs     6.9 MB/sec
linter/all-rules/pydantic/types.py         1.00      6.8±0.03ms     3.7 MB/sec    1.00      6.8±0.09ms     3.7 MB/sec
linter/default-rules/large/dataset.py      1.01      7.9±0.04ms     5.1 MB/sec    1.00      7.9±0.02ms     5.2 MB/sec
linter/default-rules/numpy/ctypeslib.py    1.01  1669.5±29.04µs    10.0 MB/sec    1.00  1653.8±10.53µs    10.1 MB/sec
linter/default-rules/numpy/globals.py      1.00    179.0±1.11µs    16.5 MB/sec    1.00    179.2±1.46µs    16.5 MB/sec
linter/default-rules/pydantic/types.py     1.00      3.6±0.02ms     7.1 MB/sec    1.00      3.6±0.03ms     7.0 MB/sec

Comment on lines 48 to 57
x21 = (
a
# trailing name own line
.b
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add one example where the outer most attribute chain has leading and trailing comments too?

Comment on lines +39 to 44
} else if let Expr::Attribute(expr_attribute) = value.as_ref() {
// We're in a attribute chain (`a.b.c`). The outermost node adds parentheses if
// required, the inner ones don't need them so we skip the `Expr` formatting that
// normally adds the parentheses.
expr_attribute.format().fmt(f)?;
} else {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you add a test case where an inner attribute change is parenthesized? I wonder if we need to preserve the parentheses.

@konstin konstin force-pushed the fix_attribute_chain_own_line_comments_rebased branch from 37fdcdd to 8bc2b89 Compare June 26, 2023 09:05
@konstin konstin enabled auto-merge (squash) June 26, 2023 09:06
@konstin konstin merged commit a52cd47 into main Jun 26, 2023
@konstin konstin deleted the fix_attribute_chain_own_line_comments_rebased branch June 26, 2023 09:13
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants