Parenthesize with statements (#5758)

<!--
Thank you for contributing to Ruff! To help us out with reviewing,
please consider the following:

- Does this pull request include a summary of the change? (See below.)
- Does this pull request include a descriptive title?
- Does this pull request include references to any relevant issues?
-->

## Summary

This PR improves the parentheses handling for with items to get closer
to black's formatting.

### Case 1:

```python
# Black / Input
with (
    [
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
        "bbbbbbbbbb",
        "cccccccccccccccccccccccccccccccccccccccccc",
        dddddddddddddddddddddddddddddddd,
    ] as example1,
    aaaaaaaaaaaaaaaaaaaaaaaaaa
    + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
    + cccccccccccccccccccccccccccc
    + ddddddddddddddddd as example2,
    CtxManager2() as example2,
    CtxManager2() as example2,
    CtxManager2() as example2,
):
    ...

# Before
with (
    [
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
        "bbbbbbbbbb",
        "cccccccccccccccccccccccccccccccccccccccccc",
        dddddddddddddddddddddddddddddddd,
    ] as example1,
    (
        aaaaaaaaaaaaaaaaaaaaaaaaaa
        + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
        + cccccccccccccccccccccccccccc
        + ddddddddddddddddd
    ) as example2,
    CtxManager2() as example2,
    CtxManager2() as example2,
    CtxManager2() as example2,
):
    ...
```

Notice how Ruff wraps the binary expression in an extra set of
parentheses


### Case 2:
Black does not expand the with-items if the with has no parentheses:

```python
# Black / Input
with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as c:
    ...

# Before
with (
    aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as c
):
    ...
```

Or 

```python
# Black / Input
with [
    "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
    "bbbbbbbbbb",
    "cccccccccccccccccccccccccccccccccccccccccc",
    dddddddddddddddddddddddddddddddd,
] as example1, aaaaaaaaaaaaaaaaaaaaaaaaaa * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb * cccccccccccccccccccccccccccc + ddddddddddddddddd as example2, CtxManager222222222222222() as example2:
    ...

# Before (Same as Case 1)
with (
    [
        "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
        "bbbbbbbbbb",
        "cccccccccccccccccccccccccccccccccccccccccc",
        dddddddddddddddddddddddddddddddd,
    ] as example1,
    (
        aaaaaaaaaaaaaaaaaaaaaaaaaa
        * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
        * cccccccccccccccccccccccccccc
        + ddddddddddddddddd
    ) as example2,
    CtxManager222222222222222() as example2,
):
    ...

```
## Test Plan

I added new snapshot tests

Improves the django similarity index from 0.973 to 0.977
This commit is contained in:
Micha Reiser 2023-07-15 17:03:09 +02:00 committed by GitHub
parent e1c119fde3
commit 3cda89ecaf
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 443 additions and 141 deletions

View file

@ -93,23 +93,7 @@ async def main():
```diff
--- Black
+++ Ruff
@@ -8,28 +8,33 @@
# Remove brackets for short coroutine/task
async def main():
- await asyncio.sleep(1)
+ await (asyncio.sleep(1))
async def main():
- await asyncio.sleep(1)
+ await (asyncio.sleep(1))
async def main():
- await asyncio.sleep(1)
+ await (asyncio.sleep(1))
@@ -21,7 +21,10 @@
# Check comments
async def main():
@ -121,48 +105,21 @@ async def main():
async def main():
- await asyncio.sleep(1) # Hello
+ await (
+ asyncio.sleep(1) # Hello
+ )
async def main():
- await asyncio.sleep(1) # Hello
+ await (asyncio.sleep(1)) # Hello
# Long lines
@@ -60,7 +65,7 @@
# Cr@zY Br@ck3Tz
async def main():
- await black(1)
+ await (black(1))
# Keep brackets around non power operations and nested awaits
@@ -78,16 +83,16 @@
@@ -78,7 +81,7 @@
async def main():
- await (yield x)
+ await (NOT_YET_IMPLEMENTED_ExprYield)
+ await NOT_YET_IMPLEMENTED_ExprYield
async def main():
- await (await asyncio.sleep(1))
+ await (await (asyncio.sleep(1)))
async def main():
- await (await (await (await (await asyncio.sleep(1)))))
+ await (await (await (await (await (asyncio.sleep(1))))))
@@ -90,4 +93,4 @@
async def main():
- await (yield)
+ await (NOT_YET_IMPLEMENTED_ExprYield)
+ await NOT_YET_IMPLEMENTED_ExprYield
```
## Ruff Output
@ -178,15 +135,15 @@ async def main():
# Remove brackets for short coroutine/task
async def main():
await (asyncio.sleep(1))
await asyncio.sleep(1)
async def main():
await (asyncio.sleep(1))
await asyncio.sleep(1)
async def main():
await (asyncio.sleep(1))
await asyncio.sleep(1)
# Check comments
@ -198,13 +155,11 @@ async def main():
async def main():
await (
asyncio.sleep(1) # Hello
)
await asyncio.sleep(1) # Hello
async def main():
await (asyncio.sleep(1)) # Hello
await asyncio.sleep(1) # Hello
# Long lines
@ -235,7 +190,7 @@ async def main():
# Cr@zY Br@ck3Tz
async def main():
await (black(1))
await black(1)
# Keep brackets around non power operations and nested awaits
@ -253,19 +208,19 @@ async def main():
async def main():
await (NOT_YET_IMPLEMENTED_ExprYield)
await NOT_YET_IMPLEMENTED_ExprYield
async def main():
await (await (asyncio.sleep(1)))
await (await asyncio.sleep(1))
async def main():
await (await (await (await (await (asyncio.sleep(1))))))
await (await (await (await (await asyncio.sleep(1)))))
async def main():
await (NOT_YET_IMPLEMENTED_ExprYield)
await NOT_YET_IMPLEMENTED_ExprYield
```
## Black Output

View file

@ -46,9 +46,6 @@ with (a,): # magic trailing comma
with (a): # should remove brackets
...
# TODO: black doesn't wrap this, but maybe we want to anyway?
# if we do want to wrap, do we prefer to wrap the entire WithItem or to let the
# WithItem allow the `aa + bb` content expression to be wrapped
with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as c:
...
@ -58,14 +55,70 @@ with (name_2 for name_0 in name_4):
pass
with (a, *b):
pass
with (
# leading comment
a) as b: ...
with (
# leading comment
a as b
): ...
with (a # trailing same line comment
# trailing own line comment
) as b: ...
with (
a # trailing same line comment
# trailing own line comment
as b
): ...
with (a # trailing same line comment
# trailing own line comment
) as b: ...
with (
(a
# trailing own line comment
)
as # trailing as same line comment
b # trailing b same line comment
): ...
with (
[
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"bbbbbbbbbb",
"cccccccccccccccccccccccccccccccccccccccccc",
dddddddddddddddddddddddddddddddd,
] as example1,
aaaaaaaaaaaaaaaaaaaaaaaaaa
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+ cccccccccccccccccccccccccccc
+ ddddddddddddddddd as example2,
CtxManager2() as example2,
CtxManager2() as example2,
CtxManager2() as example2,
):
...
with [
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"bbbbbbbbbb",
"cccccccccccccccccccccccccccccccccccccccccc",
dddddddddddddddddddddddddddddddd,
] as example1, aaaaaaaaaaaaaaaaaaaaaaaaaa * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb * cccccccccccccccccccccccccccc + ddddddddddddddddd as example2, CtxManager222222222222222() as example2:
...
```
## Output
```py
with (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa,
):
with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa, aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa:
...
# trailing
@ -105,12 +158,7 @@ with (
with a: # should remove brackets
...
# TODO: black doesn't wrap this, but maybe we want to anyway?
# if we do want to wrap, do we prefer to wrap the entire WithItem or to let the
# WithItem allow the `aa + bb` content expression to be wrapped
with (
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as c
):
with aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb as c:
...
@ -119,6 +167,72 @@ with (NOT_YET_IMPLEMENTED_generator_key for NOT_YET_IMPLEMENTED_generator_key in
pass
with (a, *b):
pass
with (
# leading comment
a
) as b:
...
with (
# leading comment
a as b
):
...
with (
a # trailing same line comment
# trailing own line comment
) as b:
...
with (
a # trailing same line comment
# trailing own line comment
) as b:
...
with (
a # trailing same line comment
# trailing own line comment
) as b:
...
with (
(
a
# trailing own line comment
) as b # trailing as same line comment # trailing b same line comment
):
...
with (
[
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"bbbbbbbbbb",
"cccccccccccccccccccccccccccccccccccccccccc",
dddddddddddddddddddddddddddddddd,
] as example1,
aaaaaaaaaaaaaaaaaaaaaaaaaa
+ bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+ cccccccccccccccccccccccccccc
+ ddddddddddddddddd as example2,
CtxManager2() as example2,
CtxManager2() as example2,
CtxManager2() as example2,
):
...
with [
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"bbbbbbbbbb",
"cccccccccccccccccccccccccccccccccccccccccc",
dddddddddddddddddddddddddddddddd,
] as example1, aaaaaaaaaaaaaaaaaaaaaaaaaa * bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb * cccccccccccccccccccccccccccc + ddddddddddddddddd as example2, CtxManager222222222222222() as example2:
...
```