Skip to content

Preserve required annotation parentheses in annotated assignments#23865

Merged
MichaReiser merged 1 commit intomainfrom
charlie/ann
Mar 10, 2026
Merged

Preserve required annotation parentheses in annotated assignments#23865
MichaReiser merged 1 commit intomainfrom
charlie/ann

Conversation

@charliermarsh
Copy link
Copy Markdown
Member

Summary

Previously, we were forcing Parentheses::Never unless the annotation had comments.

Closes #23864.

@charliermarsh charliermarsh added bug Something isn't working formatter Related to the formatter labels Mar 10, 2026
@charliermarsh charliermarsh marked this pull request as ready for review March 10, 2026 13:24
@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot bot commented Mar 10, 2026

ruff-ecosystem results

Formatter (stable)

✅ ecosystem check detected no format changes.

Formatter (preview)

✅ ecosystem check detected no format changes.

Copy link
Copy Markdown
Member

@MichaReiser MichaReiser left a comment

Choose a reason for hiding this comment

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

Nice, thank you

@MichaReiser MichaReiser merged commit 4f836b4 into main Mar 10, 2026
45 checks passed
@MichaReiser MichaReiser deleted the charlie/ann branch March 10, 2026 13:34
charliermarsh added a commit that referenced this pull request Mar 11, 2026
## Summary

This is a follow-up to #23865 generated by prompted Codex as follows:

> Can you find another bug like
#23864 in the formatter for us
to fix?

Here are some examples that previously had their parentheses stripped
(producing syntax errors) but now format correctly:

```python
# Annotated assignments with named expressions
x: (value := int) = 1     # was formatted as: x: value := int = 1

# Annotated assignments with yield
def f():
    y: (yield 1) = 1       # was formatted as: y: yield 1 = 1
    z: (yield 1)            # was formatted as: z: yield 1

# Annotated assignments with await
async def g():
    a: (await g()) = 1      # was formatted as: a: await g() = 1
    b: (await g())           # was formatted as: b: await g()

# Return annotations with await
async def h() -> (await g()):  # was formatted as: async def h() -> await g():
    pass

# Type aliases
type X = (value := int)    # was formatted as: type X = value := int
```

In each case, the parentheses are required for the expression to be
syntactically valid, but the formatter was previously stripping them.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working formatter Related to the formatter

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Formatter incorrectly strips parentheses around named expressions in type annotation positions

2 participants