mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 20:10:09 +00:00
Ruff 2024.2 style (#9639)
This commit is contained in:
parent
0293908b71
commit
a6f32ddc5e
47 changed files with 835 additions and 2362 deletions
|
@ -10,7 +10,6 @@ use ruff_text_size::{Ranged, TextLen, TextRange};
|
|||
use crate::comments::SourceComment;
|
||||
use crate::context::NodeLevel;
|
||||
use crate::prelude::*;
|
||||
use crate::preview::is_blank_line_after_nested_stub_class_enabled;
|
||||
use crate::statement::suite::should_insert_blank_line_after_class_in_stub_file;
|
||||
|
||||
/// Formats the leading comments of a node.
|
||||
|
@ -544,10 +543,7 @@ pub(crate) fn empty_lines_before_trailing_comments<'a>(
|
|||
// Black has different rules for stub vs. non-stub and top level vs. indented
|
||||
let empty_lines = match (f.options().source_type(), f.context().node_level()) {
|
||||
(PySourceType::Stub, NodeLevel::TopLevel(_)) => 1,
|
||||
(PySourceType::Stub, _) => u32::from(
|
||||
is_blank_line_after_nested_stub_class_enabled(f.context())
|
||||
&& node_kind == NodeKind::StmtClassDef,
|
||||
),
|
||||
(PySourceType::Stub, _) => u32::from(node_kind == NodeKind::StmtClassDef),
|
||||
(_, NodeLevel::TopLevel(_)) => 2,
|
||||
(_, _) => 1,
|
||||
};
|
||||
|
|
|
@ -99,6 +99,7 @@ impl<'a> PyFormatContext<'a> {
|
|||
}
|
||||
|
||||
/// Returns `true` if preview mode is enabled.
|
||||
#[allow(unused)]
|
||||
pub(crate) const fn is_preview(&self) -> bool {
|
||||
self.options.preview().is_enabled()
|
||||
}
|
||||
|
|
|
@ -20,7 +20,6 @@ use crate::expression::parentheses::{
|
|||
};
|
||||
use crate::expression::OperatorPrecedence;
|
||||
use crate::prelude::*;
|
||||
use crate::preview::is_fix_power_op_line_length_enabled;
|
||||
use crate::string::{AnyString, FormatStringContinuation};
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
|
@ -722,9 +721,7 @@ impl Format<PyFormatContext<'_>> for FlatBinaryExpressionSlice<'_> {
|
|||
{
|
||||
hard_line_break().fmt(f)?;
|
||||
} else if is_pow {
|
||||
if is_fix_power_op_line_length_enabled(f.context()) {
|
||||
in_parentheses_only_if_group_breaks(&space()).fmt(f)?;
|
||||
}
|
||||
in_parentheses_only_if_group_breaks(&space()).fmt(f)?;
|
||||
} else {
|
||||
space().fmt(f)?;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ use crate::expression::is_expression_huggable;
|
|||
use crate::expression::parentheses::{empty_parenthesized, parenthesized, Parentheses};
|
||||
use crate::other::commas;
|
||||
use crate::prelude::*;
|
||||
use crate::preview::is_multiline_string_handling_enabled;
|
||||
use crate::string::AnyString;
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -238,10 +237,6 @@ fn is_huggable_string_argument(
|
|||
arguments: &Arguments,
|
||||
context: &PyFormatContext,
|
||||
) -> bool {
|
||||
if !is_multiline_string_handling_enabled(context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if string.is_implicit_concatenated() || !string.is_multiline(context.source()) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -9,7 +9,6 @@ use ruff_text_size::Ranged;
|
|||
use crate::comments::{dangling_open_parenthesis_comments, trailing_comments};
|
||||
use crate::context::{FStringState, NodeLevel, WithFStringState, WithNodeLevel};
|
||||
use crate::prelude::*;
|
||||
use crate::preview::is_hex_codes_in_unicode_sequences_enabled;
|
||||
use crate::string::normalize_string;
|
||||
use crate::verbatim::verbatim_text;
|
||||
|
||||
|
@ -62,7 +61,6 @@ impl Format<PyFormatContext<'_>> for FormatFStringLiteralElement<'_> {
|
|||
0,
|
||||
self.context.quotes(),
|
||||
self.context.prefix(),
|
||||
is_hex_codes_in_unicode_sequences_enabled(f.context()),
|
||||
true,
|
||||
);
|
||||
match &normalized {
|
||||
|
|
|
@ -7,7 +7,6 @@ use crate::expression::parentheses::{
|
|||
is_expression_parenthesized, parenthesized, Parentheses, Parenthesize,
|
||||
};
|
||||
use crate::prelude::*;
|
||||
use crate::preview::is_wrap_multiple_context_managers_in_parens_enabled;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FormatWithItem;
|
||||
|
@ -30,9 +29,7 @@ impl FormatNodeRule<WithItem> for FormatWithItem {
|
|||
);
|
||||
|
||||
// Remove the parentheses of the `with_items` if the with statement adds parentheses
|
||||
if f.context().node_level().is_parenthesized()
|
||||
&& is_wrap_multiple_context_managers_in_parens_enabled(f.context())
|
||||
{
|
||||
if f.context().node_level().is_parenthesized() {
|
||||
if is_parenthesized {
|
||||
// ...except if the with item is parenthesized, then use this with item as a preferred breaking point
|
||||
// or when it has comments, then parenthesize it to prevent comments from moving.
|
||||
|
|
|
@ -4,12 +4,8 @@
|
|||
//! to stable. The challenge with directly using [`is_preview`](PyFormatContext::is_preview) is that it is unclear
|
||||
//! for which specific feature this preview check is for. Having named functions simplifies the promotion:
|
||||
//! Simply delete the function and let Rust tell you which checks you have to remove.
|
||||
use crate::PyFormatContext;
|
||||
|
||||
/// Returns `true` if the [`fix_power_op_line_length`](https://github.com/astral-sh/ruff/issues/8938) preview style is enabled.
|
||||
pub(crate) const fn is_fix_power_op_line_length_enabled(context: &PyFormatContext) -> bool {
|
||||
context.is_preview()
|
||||
}
|
||||
use crate::PyFormatContext;
|
||||
|
||||
/// Returns `true` if the [`hug_parens_with_braces_and_square_brackets`](https://github.com/astral-sh/ruff/issues/8279) preview style is enabled.
|
||||
pub(crate) const fn is_hug_parens_with_braces_and_square_brackets_enabled(
|
||||
|
@ -18,70 +14,6 @@ pub(crate) const fn is_hug_parens_with_braces_and_square_brackets_enabled(
|
|||
context.is_preview()
|
||||
}
|
||||
|
||||
/// Returns `true` if the [`prefer_splitting_right_hand_side_of_assignments`](https://github.com/astral-sh/ruff/issues/6975) preview style is enabled.
|
||||
pub(crate) const fn is_prefer_splitting_right_hand_side_of_assignments_enabled(
|
||||
context: &PyFormatContext,
|
||||
) -> bool {
|
||||
context.is_preview()
|
||||
}
|
||||
|
||||
/// Returns `true` if the [`parenthesize_long_type_hints`](https://github.com/astral-sh/ruff/issues/8894) preview style is enabled.
|
||||
pub(crate) const fn is_parenthesize_long_type_hints_enabled(context: &PyFormatContext) -> bool {
|
||||
context.is_preview()
|
||||
}
|
||||
|
||||
/// Returns `true` if the [`no_blank_line_before_class_docstring`] preview style is enabled.
|
||||
///
|
||||
/// [`no_blank_line_before_class_docstring`]: https://github.com/astral-sh/ruff/issues/8888
|
||||
pub(crate) const fn is_no_blank_line_before_class_docstring_enabled(
|
||||
context: &PyFormatContext,
|
||||
) -> bool {
|
||||
context.is_preview()
|
||||
}
|
||||
|
||||
/// Returns `true` if the [`wrap_multiple_context_managers_in_parens`](https://github.com/astral-sh/ruff/issues/8889) preview style is enabled.
|
||||
///
|
||||
/// Unlike Black, we re-use the same preview style feature flag for [`improved_async_statements_handling`](https://github.com/astral-sh/ruff/issues/8890)
|
||||
pub(crate) const fn is_wrap_multiple_context_managers_in_parens_enabled(
|
||||
context: &PyFormatContext,
|
||||
) -> bool {
|
||||
context.is_preview()
|
||||
}
|
||||
|
||||
/// Returns `true` if the [`blank_line_after_nested_stub_class`](https://github.com/astral-sh/ruff/issues/8891) preview style is enabled.
|
||||
pub(crate) const fn is_blank_line_after_nested_stub_class_enabled(
|
||||
context: &PyFormatContext,
|
||||
) -> bool {
|
||||
context.is_preview()
|
||||
}
|
||||
|
||||
/// Returns `true` if the [`module_docstring_newlines`](https://github.com/astral-sh/ruff/issues/7995) preview style is enabled.
|
||||
pub(crate) const fn is_module_docstring_newlines_enabled(context: &PyFormatContext) -> bool {
|
||||
context.is_preview()
|
||||
}
|
||||
|
||||
/// Returns `true` if the [`dummy_implementations`](https://github.com/astral-sh/ruff/issues/8357) preview style is enabled.
|
||||
pub(crate) const fn is_dummy_implementations_enabled(context: &PyFormatContext) -> bool {
|
||||
context.is_preview()
|
||||
}
|
||||
|
||||
/// Returns `true` if the [`hex_codes_in_unicode_sequences`](https://github.com/psf/black/pull/2916) preview style is enabled.
|
||||
pub(crate) const fn is_hex_codes_in_unicode_sequences_enabled(context: &PyFormatContext) -> bool {
|
||||
context.is_preview()
|
||||
}
|
||||
|
||||
/// Returns `true` if the [`multiline_string_handling`](https://github.com/astral-sh/ruff/issues/8896) preview style is enabled.
|
||||
pub(crate) const fn is_multiline_string_handling_enabled(context: &PyFormatContext) -> bool {
|
||||
context.is_preview()
|
||||
}
|
||||
|
||||
/// Returns `true` if the [`multiline_string_handling`](https://github.com/astral-sh/ruff/pull/9725) preview style is enabled.
|
||||
/// Black does not [`format docstrings`](https://github.com/psf/black/issues/3493) so we keep this
|
||||
/// preview for compatibility with Black.
|
||||
pub(crate) const fn is_format_module_docstring_enabled(context: &PyFormatContext) -> bool {
|
||||
context.is_preview()
|
||||
}
|
||||
|
||||
/// Returns `true` if the [`f-string formatting`](https://github.com/astral-sh/ruff/issues/7594) preview style is enabled.
|
||||
pub(crate) fn is_f_string_formatting_enabled(context: &PyFormatContext) -> bool {
|
||||
context.is_preview()
|
||||
|
|
|
@ -8,7 +8,6 @@ use ruff_python_trivia::{SimpleToken, SimpleTokenKind, SimpleTokenizer};
|
|||
use ruff_text_size::{Ranged, TextRange, TextSize};
|
||||
|
||||
use crate::comments::{leading_alternate_branch_comments, trailing_comments, SourceComment};
|
||||
use crate::preview::is_dummy_implementations_enabled;
|
||||
use crate::statement::suite::{contains_only_an_ellipsis, SuiteKind};
|
||||
use crate::verbatim::write_suppressed_clause_header;
|
||||
use crate::{has_skip_comment, prelude::*};
|
||||
|
@ -405,8 +404,7 @@ impl Format<PyFormatContext<'_>> for FormatClauseBody<'_> {
|
|||
// In stable, stubs are only collapsed in stub files, in preview stubs in functions
|
||||
// or classes are collapsed too
|
||||
let should_collapse_stub = f.options().source_type().is_stub()
|
||||
|| (is_dummy_implementations_enabled(f.context())
|
||||
&& matches!(self.kind, SuiteKind::Function | SuiteKind::Class));
|
||||
|| matches!(self.kind, SuiteKind::Function | SuiteKind::Class);
|
||||
|
||||
if should_collapse_stub
|
||||
&& contains_only_an_ellipsis(self.body, f.context().comments())
|
||||
|
|
|
@ -2,12 +2,8 @@ use ruff_formatter::write;
|
|||
use ruff_python_ast::StmtAnnAssign;
|
||||
|
||||
use crate::comments::SourceComment;
|
||||
use crate::expression::is_splittable_expression;
|
||||
use crate::expression::parentheses::Parentheses;
|
||||
use crate::expression::{has_parentheses, is_splittable_expression};
|
||||
use crate::preview::{
|
||||
is_parenthesize_long_type_hints_enabled,
|
||||
is_prefer_splitting_right_hand_side_of_assignments_enabled,
|
||||
};
|
||||
use crate::statement::stmt_assign::{
|
||||
AnyAssignmentOperator, AnyBeforeOperator, FormatStatementsLastExpression,
|
||||
};
|
||||
|
@ -30,13 +26,7 @@ impl FormatNodeRule<StmtAnnAssign> for FormatStmtAnnAssign {
|
|||
write!(f, [target.format(), token(":"), space()])?;
|
||||
|
||||
if let Some(value) = value {
|
||||
if is_prefer_splitting_right_hand_side_of_assignments_enabled(f.context())
|
||||
// The `has_parentheses` check can be removed when stabilizing `is_parenthesize_long_type_hints`.
|
||||
// because `is_splittable_expression` covers both.
|
||||
&& (has_parentheses(annotation, f.context()).is_some()
|
||||
|| (is_parenthesize_long_type_hints_enabled(f.context())
|
||||
&& is_splittable_expression(annotation, f.context())))
|
||||
{
|
||||
if is_splittable_expression(annotation, f.context()) {
|
||||
FormatStatementsLastExpression::RightToLeft {
|
||||
before_operator: AnyBeforeOperator::Expression(annotation),
|
||||
operator: AnyAssignmentOperator::Assign,
|
||||
|
@ -47,23 +37,20 @@ impl FormatNodeRule<StmtAnnAssign> for FormatStmtAnnAssign {
|
|||
} else {
|
||||
// Remove unnecessary parentheses around the annotation if the parenthesize long type hints preview style is enabled.
|
||||
// Ensure we keep the parentheses if the annotation has any comments.
|
||||
if is_parenthesize_long_type_hints_enabled(f.context()) {
|
||||
if f.context().comments().has_leading(annotation.as_ref())
|
||||
|| f.context().comments().has_trailing(annotation.as_ref())
|
||||
{
|
||||
annotation
|
||||
.format()
|
||||
.with_options(Parentheses::Always)
|
||||
.fmt(f)?;
|
||||
} else {
|
||||
annotation
|
||||
.format()
|
||||
.with_options(Parentheses::Never)
|
||||
.fmt(f)?;
|
||||
}
|
||||
if f.context().comments().has_leading(annotation.as_ref())
|
||||
|| f.context().comments().has_trailing(annotation.as_ref())
|
||||
{
|
||||
annotation
|
||||
.format()
|
||||
.with_options(Parentheses::Always)
|
||||
.fmt(f)?;
|
||||
} else {
|
||||
annotation.format().fmt(f)?;
|
||||
annotation
|
||||
.format()
|
||||
.with_options(Parentheses::Never)
|
||||
.fmt(f)?;
|
||||
}
|
||||
|
||||
write!(
|
||||
f,
|
||||
[
|
||||
|
@ -83,11 +70,7 @@ impl FormatNodeRule<StmtAnnAssign> for FormatStmtAnnAssign {
|
|||
// Decimal # the user's age, used to determine if it's safe for them to use ruff
|
||||
// )
|
||||
// ```
|
||||
if is_parenthesize_long_type_hints_enabled(f.context()) {
|
||||
FormatStatementsLastExpression::left_to_right(annotation, item).fmt(f)?;
|
||||
} else {
|
||||
annotation.format().fmt(f)?;
|
||||
}
|
||||
FormatStatementsLastExpression::left_to_right(annotation, item).fmt(f)?;
|
||||
}
|
||||
|
||||
if f.options().source_type().is_ipynb()
|
||||
|
|
|
@ -16,10 +16,6 @@ use crate::expression::{
|
|||
can_omit_optional_parentheses, has_own_parentheses, has_parentheses,
|
||||
maybe_parenthesize_expression,
|
||||
};
|
||||
use crate::preview::{
|
||||
is_parenthesize_long_type_hints_enabled,
|
||||
is_prefer_splitting_right_hand_side_of_assignments_enabled,
|
||||
};
|
||||
use crate::statement::trailing_semicolon;
|
||||
use crate::{has_skip_comment, prelude::*};
|
||||
|
||||
|
@ -44,53 +40,47 @@ impl FormatNodeRule<StmtAssign> for FormatStmtAssign {
|
|||
preserve_parentheses: true,
|
||||
};
|
||||
|
||||
if is_prefer_splitting_right_hand_side_of_assignments_enabled(f.context()) {
|
||||
// Avoid parenthesizing the value if the last target before the assigned value expands.
|
||||
if let Some((last, head)) = rest.split_last() {
|
||||
format_first.fmt(f)?;
|
||||
// Avoid parenthesizing the value if the last target before the assigned value expands.
|
||||
if let Some((last, head)) = rest.split_last() {
|
||||
format_first.fmt(f)?;
|
||||
|
||||
for target in head {
|
||||
FormatTargetWithEqualOperator {
|
||||
target,
|
||||
preserve_parentheses: false,
|
||||
}
|
||||
.fmt(f)?;
|
||||
}
|
||||
|
||||
FormatStatementsLastExpression::RightToLeft {
|
||||
before_operator: AnyBeforeOperator::Expression(last),
|
||||
operator: AnyAssignmentOperator::Assign,
|
||||
value,
|
||||
statement: item.into(),
|
||||
for target in head {
|
||||
FormatTargetWithEqualOperator {
|
||||
target,
|
||||
preserve_parentheses: false,
|
||||
}
|
||||
.fmt(f)?;
|
||||
}
|
||||
// Avoid parenthesizing the value for single-target assignments where the
|
||||
// target has its own parentheses (list, dict, tuple, ...) and the target expands.
|
||||
else if has_target_own_parentheses(first, f.context())
|
||||
&& !is_expression_parenthesized(
|
||||
first.into(),
|
||||
f.context().comments().ranges(),
|
||||
f.context().source(),
|
||||
)
|
||||
{
|
||||
FormatStatementsLastExpression::RightToLeft {
|
||||
before_operator: AnyBeforeOperator::Expression(first),
|
||||
operator: AnyAssignmentOperator::Assign,
|
||||
value,
|
||||
statement: item.into(),
|
||||
}
|
||||
.fmt(f)?;
|
||||
}
|
||||
// For single targets that have no split points, parenthesize the value only
|
||||
// if it makes it fit. Otherwise omit the parentheses.
|
||||
else {
|
||||
format_first.fmt(f)?;
|
||||
FormatStatementsLastExpression::left_to_right(value, item).fmt(f)?;
|
||||
}
|
||||
} else {
|
||||
write!(f, [format_first, FormatTargets { targets: rest }])?;
|
||||
|
||||
FormatStatementsLastExpression::RightToLeft {
|
||||
before_operator: AnyBeforeOperator::Expression(last),
|
||||
operator: AnyAssignmentOperator::Assign,
|
||||
value,
|
||||
statement: item.into(),
|
||||
}
|
||||
.fmt(f)?;
|
||||
}
|
||||
// Avoid parenthesizing the value for single-target assignments where the
|
||||
// target has its own parentheses (list, dict, tuple, ...) and the target expands.
|
||||
else if has_target_own_parentheses(first, f.context())
|
||||
&& !is_expression_parenthesized(
|
||||
first.into(),
|
||||
f.context().comments().ranges(),
|
||||
f.context().source(),
|
||||
)
|
||||
{
|
||||
FormatStatementsLastExpression::RightToLeft {
|
||||
before_operator: AnyBeforeOperator::Expression(first),
|
||||
operator: AnyAssignmentOperator::Assign,
|
||||
value,
|
||||
statement: item.into(),
|
||||
}
|
||||
.fmt(f)?;
|
||||
}
|
||||
// For single targets that have no split points, parenthesize the value only
|
||||
// if it makes it fit. Otherwise omit the parentheses.
|
||||
else {
|
||||
format_first.fmt(f)?;
|
||||
FormatStatementsLastExpression::left_to_right(value, item).fmt(f)?;
|
||||
}
|
||||
|
||||
|
@ -114,77 +104,6 @@ impl FormatNodeRule<StmtAssign> for FormatStmtAssign {
|
|||
}
|
||||
}
|
||||
|
||||
/// Formats the targets so that they split left-to right.
|
||||
#[derive(Debug)]
|
||||
struct FormatTargets<'a> {
|
||||
targets: &'a [Expr],
|
||||
}
|
||||
|
||||
impl Format<PyFormatContext<'_>> for FormatTargets<'_> {
|
||||
fn fmt(&self, f: &mut PyFormatter) -> FormatResult<()> {
|
||||
if let Some((first, rest)) = self.targets.split_first() {
|
||||
let comments = f.context().comments();
|
||||
|
||||
let parenthesize = if comments.has_leading(first) || comments.has_trailing(first) {
|
||||
ParenthesizeTarget::Always
|
||||
} else if has_target_own_parentheses(first, f.context()) {
|
||||
ParenthesizeTarget::Never
|
||||
} else {
|
||||
ParenthesizeTarget::IfBreaks
|
||||
};
|
||||
|
||||
let group_id = if parenthesize == ParenthesizeTarget::Never {
|
||||
Some(f.group_id("assignment_parentheses"))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let format_first = format_with(|f: &mut PyFormatter| {
|
||||
let mut f = WithNodeLevel::new(NodeLevel::Expression(group_id), f);
|
||||
match parenthesize {
|
||||
ParenthesizeTarget::Always => {
|
||||
write!(f, [first.format().with_options(Parentheses::Always)])
|
||||
}
|
||||
ParenthesizeTarget::Never => {
|
||||
write!(f, [first.format().with_options(Parentheses::Never)])
|
||||
}
|
||||
ParenthesizeTarget::IfBreaks => {
|
||||
write!(
|
||||
f,
|
||||
[
|
||||
if_group_breaks(&token("(")),
|
||||
soft_block_indent(&first.format().with_options(Parentheses::Never)),
|
||||
if_group_breaks(&token(")"))
|
||||
]
|
||||
)
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
write!(
|
||||
f,
|
||||
[group(&format_args![
|
||||
format_first,
|
||||
space(),
|
||||
token("="),
|
||||
space(),
|
||||
FormatTargets { targets: rest }
|
||||
])
|
||||
.with_group_id(group_id)]
|
||||
)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
enum ParenthesizeTarget {
|
||||
Always,
|
||||
Never,
|
||||
IfBreaks,
|
||||
}
|
||||
|
||||
/// Formats a single target with the equal operator.
|
||||
struct FormatTargetWithEqualOperator<'a> {
|
||||
target: &'a Expr,
|
||||
|
@ -693,9 +612,7 @@ impl Format<PyFormatContext<'_>> for AnyBeforeOperator<'_> {
|
|||
}
|
||||
// Never parenthesize targets that come with their own parentheses, e.g. don't parenthesize lists or dictionary literals.
|
||||
else if should_parenthesize_target(expression, f.context()) {
|
||||
if is_parenthesize_long_type_hints_enabled(f.context())
|
||||
&& can_omit_optional_parentheses(expression, f.context())
|
||||
{
|
||||
if can_omit_optional_parentheses(expression, f.context()) {
|
||||
optional_parentheses(&expression.format().with_options(Parentheses::Never))
|
||||
.fmt(f)
|
||||
} else {
|
||||
|
|
|
@ -3,7 +3,6 @@ use ruff_python_ast::StmtAugAssign;
|
|||
|
||||
use crate::comments::SourceComment;
|
||||
use crate::expression::parentheses::is_expression_parenthesized;
|
||||
use crate::preview::is_prefer_splitting_right_hand_side_of_assignments_enabled;
|
||||
use crate::statement::stmt_assign::{
|
||||
has_target_own_parentheses, AnyAssignmentOperator, AnyBeforeOperator,
|
||||
FormatStatementsLastExpression,
|
||||
|
@ -24,8 +23,7 @@ impl FormatNodeRule<StmtAugAssign> for FormatStmtAugAssign {
|
|||
range: _,
|
||||
} = item;
|
||||
|
||||
if is_prefer_splitting_right_hand_side_of_assignments_enabled(f.context())
|
||||
&& has_target_own_parentheses(target, f.context())
|
||||
if has_target_own_parentheses(target, f.context())
|
||||
&& !is_expression_parenthesized(
|
||||
target.into(),
|
||||
f.context().comments().ranges(),
|
||||
|
|
|
@ -2,7 +2,6 @@ use ruff_formatter::write;
|
|||
use ruff_python_ast::StmtTypeAlias;
|
||||
|
||||
use crate::comments::SourceComment;
|
||||
use crate::preview::is_prefer_splitting_right_hand_side_of_assignments_enabled;
|
||||
use crate::statement::stmt_assign::{
|
||||
AnyAssignmentOperator, AnyBeforeOperator, FormatStatementsLastExpression,
|
||||
};
|
||||
|
@ -23,17 +22,13 @@ impl FormatNodeRule<StmtTypeAlias> for FormatStmtTypeAlias {
|
|||
write!(f, [token("type"), space(), name.as_ref().format()])?;
|
||||
|
||||
if let Some(type_params) = type_params {
|
||||
if is_prefer_splitting_right_hand_side_of_assignments_enabled(f.context()) {
|
||||
return FormatStatementsLastExpression::RightToLeft {
|
||||
before_operator: AnyBeforeOperator::TypeParams(type_params),
|
||||
operator: AnyAssignmentOperator::Assign,
|
||||
value,
|
||||
statement: item.into(),
|
||||
}
|
||||
.fmt(f);
|
||||
};
|
||||
|
||||
write!(f, [type_params.format()])?;
|
||||
return FormatStatementsLastExpression::RightToLeft {
|
||||
before_operator: AnyBeforeOperator::TypeParams(type_params),
|
||||
operator: AnyAssignmentOperator::Assign,
|
||||
value,
|
||||
statement: item.into(),
|
||||
}
|
||||
.fmt(f);
|
||||
}
|
||||
|
||||
write!(
|
||||
|
|
|
@ -12,7 +12,6 @@ use crate::expression::parentheses::{
|
|||
};
|
||||
use crate::other::commas;
|
||||
use crate::prelude::*;
|
||||
use crate::preview::is_wrap_multiple_context_managers_in_parens_enabled;
|
||||
use crate::statement::clause::{clause_body, clause_header, ClauseHeader};
|
||||
use crate::{PyFormatOptions, PythonVersion};
|
||||
|
||||
|
@ -152,8 +151,7 @@ fn should_parenthesize(
|
|||
return Ok(ParenthesizeWith::IfExpands);
|
||||
}
|
||||
|
||||
let can_parenthesize = (is_wrap_multiple_context_managers_in_parens_enabled(context)
|
||||
&& options.target_version() >= PythonVersion::Py39)
|
||||
let can_parenthesize = options.target_version() >= PythonVersion::Py39
|
||||
|| are_with_items_parenthesized(with, context)?;
|
||||
|
||||
if !can_parenthesize {
|
||||
|
@ -176,9 +174,7 @@ fn should_parenthesize(
|
|||
// Preserve the parentheses around the context expression instead of parenthesizing the entire
|
||||
// with items.
|
||||
ParenthesizeWith::UnlessCommented
|
||||
} else if is_wrap_multiple_context_managers_in_parens_enabled(context)
|
||||
&& can_omit_optional_parentheses(&single.context_expr, context)
|
||||
{
|
||||
} else if can_omit_optional_parentheses(&single.context_expr, context) {
|
||||
ParenthesizeWith::Optional
|
||||
} else {
|
||||
ParenthesizeWith::IfExpands
|
||||
|
|
|
@ -13,11 +13,6 @@ use crate::comments::{
|
|||
use crate::context::{NodeLevel, TopLevelStatementPosition, WithIndentLevel, WithNodeLevel};
|
||||
use crate::expression::expr_string_literal::ExprStringLiteralKind;
|
||||
use crate::prelude::*;
|
||||
use crate::preview::{
|
||||
is_blank_line_after_nested_stub_class_enabled, is_dummy_implementations_enabled,
|
||||
is_format_module_docstring_enabled, is_module_docstring_newlines_enabled,
|
||||
is_no_blank_line_before_class_docstring_enabled,
|
||||
};
|
||||
use crate::statement::stmt_expr::FormatStmtExpr;
|
||||
use crate::verbatim::{
|
||||
suppressed_node, write_suppressed_statements_starting_with_leading_comment,
|
||||
|
@ -102,7 +97,7 @@ impl FormatRule<Suite, PyFormatContext<'_>> for FormatSuite {
|
|||
SuiteChildStatement::Other(first)
|
||||
}
|
||||
|
||||
SuiteKind::Function => {
|
||||
SuiteKind::Function | SuiteKind::Class | SuiteKind::TopLevel => {
|
||||
if let Some(docstring) =
|
||||
DocstringStmt::try_from_statement(first, self.kind, source_type)
|
||||
{
|
||||
|
@ -111,53 +106,6 @@ impl FormatRule<Suite, PyFormatContext<'_>> for FormatSuite {
|
|||
SuiteChildStatement::Other(first)
|
||||
}
|
||||
}
|
||||
|
||||
SuiteKind::Class => {
|
||||
if let Some(docstring) =
|
||||
DocstringStmt::try_from_statement(first, self.kind, source_type)
|
||||
{
|
||||
if !comments.has_leading(first)
|
||||
&& lines_before(first.start(), source) > 1
|
||||
&& !source_type.is_stub()
|
||||
&& !is_no_blank_line_before_class_docstring_enabled(f.context())
|
||||
{
|
||||
// Allow up to one empty line before a class docstring, e.g., this is
|
||||
// stable formatting:
|
||||
//
|
||||
// ```python
|
||||
// class Test:
|
||||
//
|
||||
// """Docstring"""
|
||||
// ```
|
||||
//
|
||||
// But, in preview mode, we don't want to allow any empty lines before a
|
||||
// class docstring, e.g., this is preview formatting:
|
||||
//
|
||||
// ```python
|
||||
// class Test:
|
||||
// """Docstring"""
|
||||
// ```
|
||||
empty_line().fmt(f)?;
|
||||
}
|
||||
|
||||
SuiteChildStatement::Docstring(docstring)
|
||||
} else {
|
||||
SuiteChildStatement::Other(first)
|
||||
}
|
||||
}
|
||||
SuiteKind::TopLevel => {
|
||||
if is_format_module_docstring_enabled(f.context()) {
|
||||
if let Some(docstring) =
|
||||
DocstringStmt::try_from_statement(first, self.kind, source_type)
|
||||
{
|
||||
SuiteChildStatement::Docstring(docstring)
|
||||
} else {
|
||||
SuiteChildStatement::Other(first)
|
||||
}
|
||||
} else {
|
||||
SuiteChildStatement::Other(first)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let first_comments = comments.leading_dangling_trailing(first);
|
||||
|
@ -188,16 +136,12 @@ impl FormatRule<Suite, PyFormatContext<'_>> for FormatSuite {
|
|||
&& self.kind == SuiteKind::Class
|
||||
{
|
||||
true
|
||||
} else if is_module_docstring_newlines_enabled(f.context())
|
||||
&& self.kind == SuiteKind::TopLevel
|
||||
&& DocstringStmt::try_from_statement(first.statement(), self.kind, source_type)
|
||||
.is_some()
|
||||
{
|
||||
// Only in preview mode, insert a newline after a module level docstring, but treat
|
||||
// it as a docstring otherwise. See: https://github.com/psf/black/pull/3932.
|
||||
true
|
||||
} else {
|
||||
false
|
||||
// Insert a newline after a module level docstring, but treat
|
||||
// it as a docstring otherwise. See: https://github.com/psf/black/pull/3932.
|
||||
self.kind == SuiteKind::TopLevel
|
||||
&& DocstringStmt::try_from_statement(first.statement(), self.kind, source_type)
|
||||
.is_some()
|
||||
};
|
||||
|
||||
(first.statement(), empty_line_after_docstring)
|
||||
|
@ -284,20 +228,19 @@ impl FormatRule<Suite, PyFormatContext<'_>> for FormatSuite {
|
|||
} else {
|
||||
// Preserve empty lines after a stub implementation but don't insert a new one if there isn't any present in the source.
|
||||
// This is useful when having multiple function overloads that should be grouped to getter by omitting new lines between them.
|
||||
let is_preceding_stub_function_without_empty_line =
|
||||
is_dummy_implementations_enabled(f.context())
|
||||
&& following.is_function_def_stmt()
|
||||
&& preceding
|
||||
.as_function_def_stmt()
|
||||
.is_some_and(|preceding_stub| {
|
||||
contains_only_an_ellipsis(
|
||||
&preceding_stub.body,
|
||||
f.context().comments(),
|
||||
) && lines_after_ignoring_end_of_line_trivia(
|
||||
preceding_stub.end(),
|
||||
f.context().source(),
|
||||
) < 2
|
||||
});
|
||||
let is_preceding_stub_function_without_empty_line = following
|
||||
.is_function_def_stmt()
|
||||
&& preceding
|
||||
.as_function_def_stmt()
|
||||
.is_some_and(|preceding_stub| {
|
||||
contains_only_an_ellipsis(
|
||||
&preceding_stub.body,
|
||||
f.context().comments(),
|
||||
) && lines_after_ignoring_end_of_line_trivia(
|
||||
preceding_stub.end(),
|
||||
f.context().source(),
|
||||
) < 2
|
||||
});
|
||||
|
||||
if !is_preceding_stub_function_without_empty_line {
|
||||
match self.kind {
|
||||
|
@ -529,11 +472,10 @@ pub(crate) fn should_insert_blank_line_after_class_in_stub_file(
|
|||
following: Option<AnyNodeRef<'_>>,
|
||||
context: &PyFormatContext,
|
||||
) -> bool {
|
||||
if !(is_blank_line_after_nested_stub_class_enabled(context)
|
||||
&& context.options().source_type().is_stub())
|
||||
{
|
||||
if !context.options().source_type().is_stub() {
|
||||
return false;
|
||||
}
|
||||
|
||||
let comments = context.comments();
|
||||
match preceding.as_stmt_class_def() {
|
||||
Some(class) if contains_only_an_ellipsis(&class.body, comments) => {
|
||||
|
|
|
@ -8,7 +8,7 @@ use ruff_text_size::{Ranged, TextRange};
|
|||
use crate::context::FStringState;
|
||||
use crate::options::PythonVersion;
|
||||
use crate::prelude::*;
|
||||
use crate::preview::{is_f_string_formatting_enabled, is_hex_codes_in_unicode_sequences_enabled};
|
||||
use crate::preview::is_f_string_formatting_enabled;
|
||||
use crate::string::{QuoteChar, Quoting, StringPart, StringPrefix, StringQuotes};
|
||||
use crate::QuoteStyle;
|
||||
|
||||
|
@ -18,7 +18,6 @@ pub(crate) struct StringNormalizer {
|
|||
parent_docstring_quote_char: Option<QuoteChar>,
|
||||
f_string_state: FStringState,
|
||||
target_version: PythonVersion,
|
||||
normalize_hex: bool,
|
||||
format_fstring: bool,
|
||||
}
|
||||
|
||||
|
@ -30,7 +29,6 @@ impl StringNormalizer {
|
|||
parent_docstring_quote_char: context.docstring(),
|
||||
f_string_state: context.f_string_state(),
|
||||
target_version: context.options().target_version(),
|
||||
normalize_hex: is_hex_codes_in_unicode_sequences_enabled(context),
|
||||
format_fstring: is_f_string_formatting_enabled(context),
|
||||
}
|
||||
}
|
||||
|
@ -195,7 +193,6 @@ impl StringNormalizer {
|
|||
first_quote_or_escape_offset,
|
||||
quote_selection.quotes,
|
||||
string.prefix(),
|
||||
self.normalize_hex,
|
||||
// TODO: Remove the `b'{'` in `choose_quotes` when promoting the
|
||||
// `format_fstring` preview style
|
||||
self.format_fstring,
|
||||
|
@ -454,7 +451,6 @@ pub(crate) fn normalize_string(
|
|||
start_offset: usize,
|
||||
quotes: StringQuotes,
|
||||
prefix: StringPrefix,
|
||||
normalize_hex: bool,
|
||||
format_fstring: bool,
|
||||
) -> Cow<str> {
|
||||
// The normalized string if `input` is not yet normalized.
|
||||
|
@ -506,7 +502,7 @@ pub(crate) fn normalize_string(
|
|||
if next == '\\' {
|
||||
// Skip over escaped backslashes
|
||||
chars.next();
|
||||
} else if normalize_hex {
|
||||
} else {
|
||||
// Length of the `\` plus the length of the escape sequence character (`u` | `U` | `x`)
|
||||
let escape_start_len = '\\'.len_utf8() + next.len_utf8();
|
||||
if let Some(normalised) = UnicodeEscape::new(next, !prefix.is_byte())
|
||||
|
@ -738,7 +734,6 @@ mod tests {
|
|||
},
|
||||
StringPrefix::BYTE,
|
||||
true,
|
||||
true,
|
||||
);
|
||||
|
||||
assert_eq!(r"\x89\x50\x4e\x47\x0d\x0a\x1a\x0a", &normalized);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue