Format named expressions (walrus operator) (#5642)

## Summary

Format named expressions (walrus operator) such a `value := f()`. 

Unlike tuples, named expression parentheses are not part of the range
even when mandatory, so mapping optional parentheses to always gives us
decent formatting without implementing all [PEP
572](https://peps.python.org/pep-0572/) rules on when we need
parentheses where other expressions wouldn't. We might want to revisit
this decision later and implement special cases, but for now this gives
us what we need.

## Test Plan

black fixtures, i added some fixtures and checked django and cpython for
stability.

Closes #5613
This commit is contained in:
konsti 2023-07-10 14:32:15 +02:00 committed by GitHub
parent 1e894f328c
commit bd8f65814c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 152 additions and 318 deletions

View file

@ -2,7 +2,8 @@ use crate::comments::Comments;
use crate::expression::parentheses::{
default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize,
};
use crate::{not_yet_implemented, FormatNodeRule, PyFormatter};
use crate::{AsFormat, FormatNodeRule, PyFormatter};
use ruff_formatter::prelude::{space, text};
use ruff_formatter::{write, Buffer, FormatResult};
use rustpython_parser::ast::ExprNamedExpr;
@ -11,7 +12,21 @@ pub struct FormatExprNamedExpr;
impl FormatNodeRule<ExprNamedExpr> for FormatExprNamedExpr {
fn fmt_fields(&self, item: &ExprNamedExpr, f: &mut PyFormatter) -> FormatResult<()> {
write!(f, [not_yet_implemented(item)])
let ExprNamedExpr {
target,
value,
range: _,
} = item;
write!(
f,
[
target.format(),
space(),
text(":="),
space(),
value.format(),
]
)
}
}
@ -22,6 +37,11 @@ impl NeedsParentheses for ExprNamedExpr {
source: &str,
comments: &Comments,
) -> Parentheses {
default_expression_needs_parentheses(self.into(), parenthesize, source, comments)
match default_expression_needs_parentheses(self.into(), parenthesize, source, comments) {
// Unlike tuples, named expression parentheses are not part of the range even when
// mandatory. See [PEP 572](https://peps.python.org/pep-0572/) for details.
Parentheses::Optional => Parentheses::Always,
parentheses => parentheses,
}
}
}