Fix instability with await fluent style#8676
Conversation
| async def main(): | ||
| - await asyncio.sleep(1) # Hello | ||
| + await ( | ||
| + asyncio.sleep(1) # Hello | ||
| + ) |
There was a problem hiding this comment.
This is arguably correct for ruff
There was a problem hiding this comment.
This seems like really weird formatting. Why is this correct?
There was a problem hiding this comment.
Note that we don't expand, we just keep
async def main():
await asyncio.sleep(1) # Hello
await (
asyncio.sleep(1) # Hello
)as-is
There was a problem hiding this comment.
Okay that's good to know. I guess that's okay. A little weird but fits with previous choices?
There was a problem hiding this comment.
Why does this work with IfBreaks?
There was a problem hiding this comment.
In yield we use Parenthesize::Optional...
There was a problem hiding this comment.
I tried that too for that same reason, but it introduced new black deviations:
# 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))
|
| token("await"), | ||
| space(), | ||
| maybe_parenthesize_expression(value, item, Parenthesize::IfRequired) | ||
| maybe_parenthesize_expression(value, item, Parenthesize::IfBreaks) |
There was a problem hiding this comment.
Should this be IfBreaksOrIfRequired?
There was a problem hiding this comment.
That one would regress asyncio.gather
# Long lines
async def main():
- await asyncio.gather(
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
- asyncio.sleep(1),
+ await (
+ asyncio.gather(
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ asyncio.sleep(1),
+ )
)(i'm happy too implement a different solution btw, this was just the solution that i found to work best by trial and error)
There was a problem hiding this comment.
Ahh yeah, I agree that that's worse. I feel like I need to have a better understanding of why these Parenthesize values are leading to these changes before I'd be comfortable approving. Why does IfBreaks break that way? Will using IfBreaks ever lead to syntax errors?
There was a problem hiding this comment.
No, that's handled by OptionalParentheses::Multiline
There was a problem hiding this comment.
I'll make some better examples why we get this behavior
There was a problem hiding this comment.
Thank you, I'm trying to make sure I play Micha and really understand the impact of formatting changes before approving.
There was a problem hiding this comment.
From the perspective of the await, it needs OptionalParentheses::Never because the child is already parenthesized, and we're preferring those parentheses over adding them around the await. For the await's child, we have four options:
- Optional: Add parentheses if the child breaks, which we want e.g. for
asyncio.gather. Keeps the child's parentheses from the source code, which we want to remove. - IfBreaks: Add parentheses if the child breaks, which we want e.g. for
asyncio.gather. Discards child parentheses, which we want. - IfRequired: Discards child parentheses, which we want. Also discards them when the child breaks but has its own inner parentheses, which would lead to e.g.
, which don't want.
await asyncio.gather( fut1, fut2, )
- IfBreaksOrIfRequired: Special case for return type annotations.
I added comments to the parentheses types to make them better understandable in the future
Fix an instability where await was followed by a breaking fluent style expression:
Note that this technically a minor style change (see ecosystem check)