mirror of
https://github.com/astral-sh/ruff.git
synced 2025-09-26 20:09:22 +00:00
format ExprJoinedStr (#5932)
This commit is contained in:
parent
ba990b676f
commit
07468f8be9
18 changed files with 221 additions and 747 deletions
7
crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/joined_string.py
vendored
Normal file
7
crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/joined_string.py
vendored
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
(
|
||||||
|
f'{one}'
|
||||||
|
f'{two}'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
rf"Not-so-tricky \"quote"
|
|
@ -7,7 +7,9 @@ use ruff_python_ast::str::is_implicit_concatenation;
|
||||||
|
|
||||||
use crate::expression::number::{FormatComplex, FormatFloat, FormatInt};
|
use crate::expression::number::{FormatComplex, FormatFloat, FormatInt};
|
||||||
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses};
|
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses};
|
||||||
use crate::expression::string::{FormatString, StringLayout, StringPrefix, StringQuotes};
|
use crate::expression::string::{
|
||||||
|
AnyString, FormatString, StringLayout, StringPrefix, StringQuotes,
|
||||||
|
};
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::FormatNodeRule;
|
use crate::FormatNodeRule;
|
||||||
|
|
||||||
|
@ -56,7 +58,9 @@ impl FormatNodeRule<ExprConstant> for FormatExprConstant {
|
||||||
ExprConstantLayout::Default => StringLayout::Default,
|
ExprConstantLayout::Default => StringLayout::Default,
|
||||||
ExprConstantLayout::String(layout) => layout,
|
ExprConstantLayout::String(layout) => layout,
|
||||||
};
|
};
|
||||||
FormatString::new(item).with_layout(string_layout).fmt(f)
|
FormatString::new(&AnyString::Constant(item))
|
||||||
|
.with_layout(string_layout)
|
||||||
|
.fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
|
use super::string::{AnyString, FormatString};
|
||||||
use crate::context::PyFormatContext;
|
use crate::context::PyFormatContext;
|
||||||
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses};
|
use crate::expression::parentheses::{NeedsParentheses, OptionalParentheses};
|
||||||
use crate::{not_yet_implemented_custom_text, FormatNodeRule, PyFormatter};
|
use crate::prelude::*;
|
||||||
use ruff_formatter::{write, Buffer, FormatResult};
|
use crate::{FormatNodeRule, PyFormatter};
|
||||||
|
use ruff_formatter::FormatResult;
|
||||||
use ruff_python_ast::node::AnyNodeRef;
|
use ruff_python_ast::node::AnyNodeRef;
|
||||||
use ruff_python_ast::ExprJoinedStr;
|
use ruff_python_ast::ExprJoinedStr;
|
||||||
|
|
||||||
|
@ -9,13 +11,8 @@ use ruff_python_ast::ExprJoinedStr;
|
||||||
pub struct FormatExprJoinedStr;
|
pub struct FormatExprJoinedStr;
|
||||||
|
|
||||||
impl FormatNodeRule<ExprJoinedStr> for FormatExprJoinedStr {
|
impl FormatNodeRule<ExprJoinedStr> for FormatExprJoinedStr {
|
||||||
fn fmt_fields(&self, _item: &ExprJoinedStr, f: &mut PyFormatter) -> FormatResult<()> {
|
fn fmt_fields(&self, item: &ExprJoinedStr, f: &mut PyFormatter) -> FormatResult<()> {
|
||||||
write!(
|
FormatString::new(&AnyString::JoinedStr(item)).fmt(f)
|
||||||
f,
|
|
||||||
[not_yet_implemented_custom_text(
|
|
||||||
r#"f"NOT_YET_IMPLEMENTED_ExprJoinedStr""#
|
|
||||||
)]
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
|
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use ruff_python_ast::{ExprConstant, Ranged};
|
use ruff_python_ast::node::AnyNodeRef;
|
||||||
|
use ruff_python_ast::{self as ast, ExprConstant, ExprJoinedStr, Ranged};
|
||||||
use ruff_python_parser::lexer::{lex_starts_at, LexicalError, LexicalErrorType};
|
use ruff_python_parser::lexer::{lex_starts_at, LexicalError, LexicalErrorType};
|
||||||
use ruff_python_parser::{Mode, Tok};
|
use ruff_python_parser::{Mode, Tok};
|
||||||
|
use ruff_source_file::Locator;
|
||||||
use ruff_text_size::{TextLen, TextRange, TextSize};
|
use ruff_text_size::{TextLen, TextRange, TextSize};
|
||||||
|
|
||||||
use ruff_formatter::{format_args, write, FormatError};
|
use ruff_formatter::{format_args, write, FormatError};
|
||||||
|
@ -13,11 +15,62 @@ use crate::comments::{leading_comments, trailing_comments};
|
||||||
use crate::expression::parentheses::{
|
use crate::expression::parentheses::{
|
||||||
in_parentheses_only_group, in_parentheses_only_soft_line_break_or_space,
|
in_parentheses_only_group, in_parentheses_only_soft_line_break_or_space,
|
||||||
};
|
};
|
||||||
|
use crate::expression::Expr;
|
||||||
use crate::prelude::*;
|
use crate::prelude::*;
|
||||||
use crate::QuoteStyle;
|
use crate::QuoteStyle;
|
||||||
|
|
||||||
|
#[derive(Copy, Clone)]
|
||||||
|
enum Quoting {
|
||||||
|
CanChange,
|
||||||
|
Preserve,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(super) enum AnyString<'a> {
|
||||||
|
Constant(&'a ExprConstant),
|
||||||
|
JoinedStr(&'a ExprJoinedStr),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> AnyString<'a> {
|
||||||
|
fn quoting(&self, locator: &Locator) -> Quoting {
|
||||||
|
match self {
|
||||||
|
Self::Constant(_) => Quoting::CanChange,
|
||||||
|
Self::JoinedStr(joined_str) => {
|
||||||
|
if joined_str.values.iter().any(|value| match value {
|
||||||
|
Expr::FormattedValue(ast::ExprFormattedValue { range, .. }) => {
|
||||||
|
let string_content = locator.slice(*range);
|
||||||
|
string_content.contains(['"', '\''])
|
||||||
|
}
|
||||||
|
_ => false,
|
||||||
|
}) {
|
||||||
|
Quoting::Preserve
|
||||||
|
} else {
|
||||||
|
Quoting::CanChange
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Ranged for AnyString<'_> {
|
||||||
|
fn range(&self) -> TextRange {
|
||||||
|
match self {
|
||||||
|
Self::Constant(expr) => expr.range(),
|
||||||
|
Self::JoinedStr(expr) => expr.range(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> From<&AnyString<'a>> for AnyNodeRef<'a> {
|
||||||
|
fn from(value: &AnyString<'a>) -> Self {
|
||||||
|
match value {
|
||||||
|
AnyString::Constant(expr) => AnyNodeRef::ExprConstant(expr),
|
||||||
|
AnyString::JoinedStr(expr) => AnyNodeRef::ExprJoinedStr(expr),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub(super) struct FormatString<'a> {
|
pub(super) struct FormatString<'a> {
|
||||||
constant: &'a ExprConstant,
|
string: &'a AnyString<'a>,
|
||||||
layout: StringLayout,
|
layout: StringLayout,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,10 +83,12 @@ pub enum StringLayout {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FormatString<'a> {
|
impl<'a> FormatString<'a> {
|
||||||
pub(super) fn new(constant: &'a ExprConstant) -> Self {
|
pub(super) fn new(string: &'a AnyString) -> Self {
|
||||||
debug_assert!(constant.value.is_str() || constant.value.is_bytes());
|
if let AnyString::Constant(constant) = string {
|
||||||
|
debug_assert!(constant.value.is_str() || constant.value.is_bytes());
|
||||||
|
}
|
||||||
Self {
|
Self {
|
||||||
constant,
|
string,
|
||||||
layout: StringLayout::Default,
|
layout: StringLayout::Default,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -48,30 +103,33 @@ impl<'a> Format<PyFormatContext<'_>> for FormatString<'a> {
|
||||||
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
||||||
match self.layout {
|
match self.layout {
|
||||||
StringLayout::Default => {
|
StringLayout::Default => {
|
||||||
let string_range = self.constant.range();
|
let string_range = self.string.range();
|
||||||
let string_content = f.context().locator().slice(string_range);
|
let string_content = f.context().locator().slice(string_range);
|
||||||
|
|
||||||
if is_implicit_concatenation(string_content) {
|
if is_implicit_concatenation(string_content) {
|
||||||
in_parentheses_only_group(&FormatStringContinuation::new(self.constant)).fmt(f)
|
in_parentheses_only_group(&FormatStringContinuation::new(self.string)).fmt(f)
|
||||||
} else {
|
} else {
|
||||||
FormatStringPart::new(string_range).fmt(f)
|
FormatStringPart::new(string_range, self.string.quoting(&f.context().locator()))
|
||||||
|
.fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StringLayout::ImplicitConcatenatedBinaryLeftSide => {
|
StringLayout::ImplicitConcatenatedBinaryLeftSide => {
|
||||||
FormatStringContinuation::new(self.constant).fmt(f)
|
FormatStringContinuation::new(self.string).fmt(f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FormatStringContinuation<'a> {
|
struct FormatStringContinuation<'a> {
|
||||||
constant: &'a ExprConstant,
|
string: &'a AnyString<'a>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> FormatStringContinuation<'a> {
|
impl<'a> FormatStringContinuation<'a> {
|
||||||
fn new(constant: &'a ExprConstant) -> Self {
|
fn new(string: &'a AnyString<'a>) -> Self {
|
||||||
debug_assert!(constant.value.is_str() || constant.value.is_bytes());
|
if let AnyString::Constant(constant) = string {
|
||||||
Self { constant }
|
debug_assert!(constant.value.is_str() || constant.value.is_bytes());
|
||||||
|
}
|
||||||
|
Self { string }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,9 +137,9 @@ impl Format<PyFormatContext<'_>> for FormatStringContinuation<'_> {
|
||||||
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
fn fmt(&self, f: &mut Formatter<PyFormatContext<'_>>) -> FormatResult<()> {
|
||||||
let comments = f.context().comments().clone();
|
let comments = f.context().comments().clone();
|
||||||
let locator = f.context().locator();
|
let locator = f.context().locator();
|
||||||
let mut dangling_comments = comments.dangling_comments(self.constant);
|
let mut dangling_comments = comments.dangling_comments(self.string);
|
||||||
|
|
||||||
let string_range = self.constant.range();
|
let string_range = self.string.range();
|
||||||
let string_content = locator.slice(string_range);
|
let string_content = locator.slice(string_range);
|
||||||
|
|
||||||
// The AST parses implicit concatenation as a single string.
|
// The AST parses implicit concatenation as a single string.
|
||||||
|
@ -155,7 +213,7 @@ impl Format<PyFormatContext<'_>> for FormatStringContinuation<'_> {
|
||||||
joiner.entry(&format_args![
|
joiner.entry(&format_args![
|
||||||
line_suffix_boundary(),
|
line_suffix_boundary(),
|
||||||
leading_comments(leading_part_comments),
|
leading_comments(leading_part_comments),
|
||||||
FormatStringPart::new(token_range),
|
FormatStringPart::new(token_range, self.string.quoting(&locator)),
|
||||||
trailing_comments(trailing_part_comments)
|
trailing_comments(trailing_part_comments)
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -178,11 +236,15 @@ impl Format<PyFormatContext<'_>> for FormatStringContinuation<'_> {
|
||||||
|
|
||||||
struct FormatStringPart {
|
struct FormatStringPart {
|
||||||
part_range: TextRange,
|
part_range: TextRange,
|
||||||
|
quoting: Quoting,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FormatStringPart {
|
impl FormatStringPart {
|
||||||
const fn new(range: TextRange) -> Self {
|
const fn new(range: TextRange, quoting: Quoting) -> Self {
|
||||||
Self { part_range: range }
|
Self {
|
||||||
|
part_range: range,
|
||||||
|
quoting,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,10 +266,15 @@ impl Format<PyFormatContext<'_>> for FormatStringPart {
|
||||||
|
|
||||||
let raw_content = &string_content[relative_raw_content_range];
|
let raw_content = &string_content[relative_raw_content_range];
|
||||||
let is_raw_string = prefix.is_raw_string();
|
let is_raw_string = prefix.is_raw_string();
|
||||||
let preferred_quotes = if is_raw_string {
|
let preferred_quotes = match self.quoting {
|
||||||
preferred_quotes_raw(raw_content, quotes, f.options().quote_style())
|
Quoting::Preserve => quotes,
|
||||||
} else {
|
Quoting::CanChange => {
|
||||||
preferred_quotes(raw_content, quotes, f.options().quote_style())
|
if is_raw_string {
|
||||||
|
preferred_quotes_raw(raw_content, quotes, f.options().quote_style())
|
||||||
|
} else {
|
||||||
|
preferred_quotes(raw_content, quotes, f.options().quote_style())
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
write!(f, [prefix, preferred_quotes])?;
|
write!(f, [prefix, preferred_quotes])?;
|
||||||
|
|
|
@ -44,7 +44,7 @@ class DebugVisitor(Visitor[T]):
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -3,24 +3,29 @@
|
@@ -3,24 +3,24 @@
|
||||||
tree_depth: int = 0
|
tree_depth: int = 0
|
||||||
|
|
||||||
def visit_default(self, node: LN) -> Iterator[T]:
|
def visit_default(self, node: LN) -> Iterator[T]:
|
||||||
|
@ -53,30 +53,25 @@ class DebugVisitor(Visitor[T]):
|
||||||
if isinstance(node, Node):
|
if isinstance(node, Node):
|
||||||
_type = type_repr(node.type)
|
_type = type_repr(node.type)
|
||||||
- out(f'{indent}{_type}', fg='yellow')
|
- out(f'{indent}{_type}', fg='yellow')
|
||||||
+ out(f"NOT_YET_IMPLEMENTED_ExprJoinedStr", fg="yellow")
|
+ out(f"{indent}{_type}", fg="yellow")
|
||||||
self.tree_depth += 1
|
self.tree_depth += 1
|
||||||
for child in node.children:
|
for child in node.children:
|
||||||
yield from self.visit(child)
|
yield from self.visit(child)
|
||||||
|
|
||||||
self.tree_depth -= 1
|
self.tree_depth -= 1
|
||||||
- out(f'{indent}/{_type}', fg='yellow', bold=False)
|
- out(f'{indent}/{_type}', fg='yellow', bold=False)
|
||||||
+ out(f"NOT_YET_IMPLEMENTED_ExprJoinedStr", fg="yellow", bold=False)
|
+ out(f"{indent}/{_type}", fg="yellow", bold=False)
|
||||||
else:
|
else:
|
||||||
_type = token.tok_name.get(node.type, str(node.type))
|
_type = token.tok_name.get(node.type, str(node.type))
|
||||||
- out(f'{indent}{_type}', fg='blue', nl=False)
|
- out(f'{indent}{_type}', fg='blue', nl=False)
|
||||||
+ out(f"NOT_YET_IMPLEMENTED_ExprJoinedStr", fg="blue", nl=False)
|
+ out(f"{indent}{_type}", fg="blue", nl=False)
|
||||||
if node.prefix:
|
if node.prefix:
|
||||||
# We don't have to handle prefixes for `Node` objects since
|
# We don't have to handle prefixes for `Node` objects since
|
||||||
# that delegates to the first child anyway.
|
# that delegates to the first child anyway.
|
||||||
- out(f' {node.prefix!r}', fg='green', bold=False, nl=False)
|
- out(f' {node.prefix!r}', fg='green', bold=False, nl=False)
|
||||||
- out(f' {node.value!r}', fg='blue', bold=False)
|
- out(f' {node.value!r}', fg='blue', bold=False)
|
||||||
+ out(
|
+ out(f" {node.prefix!r}", fg="green", bold=False, nl=False)
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
+ out(f" {node.value!r}", fg="blue", bold=False)
|
||||||
+ fg="green",
|
|
||||||
+ bold=False,
|
|
||||||
+ nl=False,
|
|
||||||
+ )
|
|
||||||
+ out(f"NOT_YET_IMPLEMENTED_ExprJoinedStr", fg="blue", bold=False)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def show(cls, code: str) -> None:
|
def show(cls, code: str) -> None:
|
||||||
|
@ -93,26 +88,21 @@ class DebugVisitor(Visitor[T]):
|
||||||
indent = " " * (2 * self.tree_depth)
|
indent = " " * (2 * self.tree_depth)
|
||||||
if isinstance(node, Node):
|
if isinstance(node, Node):
|
||||||
_type = type_repr(node.type)
|
_type = type_repr(node.type)
|
||||||
out(f"NOT_YET_IMPLEMENTED_ExprJoinedStr", fg="yellow")
|
out(f"{indent}{_type}", fg="yellow")
|
||||||
self.tree_depth += 1
|
self.tree_depth += 1
|
||||||
for child in node.children:
|
for child in node.children:
|
||||||
yield from self.visit(child)
|
yield from self.visit(child)
|
||||||
|
|
||||||
self.tree_depth -= 1
|
self.tree_depth -= 1
|
||||||
out(f"NOT_YET_IMPLEMENTED_ExprJoinedStr", fg="yellow", bold=False)
|
out(f"{indent}/{_type}", fg="yellow", bold=False)
|
||||||
else:
|
else:
|
||||||
_type = token.tok_name.get(node.type, str(node.type))
|
_type = token.tok_name.get(node.type, str(node.type))
|
||||||
out(f"NOT_YET_IMPLEMENTED_ExprJoinedStr", fg="blue", nl=False)
|
out(f"{indent}{_type}", fg="blue", nl=False)
|
||||||
if node.prefix:
|
if node.prefix:
|
||||||
# We don't have to handle prefixes for `Node` objects since
|
# We don't have to handle prefixes for `Node` objects since
|
||||||
# that delegates to the first child anyway.
|
# that delegates to the first child anyway.
|
||||||
out(
|
out(f" {node.prefix!r}", fg="green", bold=False, nl=False)
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
out(f" {node.value!r}", fg="blue", bold=False)
|
||||||
fg="green",
|
|
||||||
bold=False,
|
|
||||||
nl=False,
|
|
||||||
)
|
|
||||||
out(f"NOT_YET_IMPLEMENTED_ExprJoinedStr", fg="blue", bold=False)
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def show(cls, code: str) -> None:
|
def show(cls, code: str) -> None:
|
||||||
|
|
|
@ -27,7 +27,7 @@ def do_not_touch_this_prefix3():
|
||||||
|
|
||||||
def do_not_touch_this_prefix2():
|
def do_not_touch_this_prefix2():
|
||||||
- FR'There was a bug where docstring prefixes would be normalized even with -S.'
|
- FR'There was a bug where docstring prefixes would be normalized even with -S.'
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
+ Rf"There was a bug where docstring prefixes would be normalized even with -S."
|
||||||
|
|
||||||
|
|
||||||
def do_not_touch_this_prefix3():
|
def do_not_touch_this_prefix3():
|
||||||
|
@ -43,7 +43,7 @@ def do_not_touch_this_prefix():
|
||||||
|
|
||||||
|
|
||||||
def do_not_touch_this_prefix2():
|
def do_not_touch_this_prefix2():
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
Rf"There was a bug where docstring prefixes would be normalized even with -S."
|
||||||
|
|
||||||
|
|
||||||
def do_not_touch_this_prefix3():
|
def do_not_touch_this_prefix3():
|
||||||
|
|
|
@ -304,19 +304,23 @@ long_unmergable_string_with_pragma = (
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -143,9 +143,9 @@
|
@@ -143,9 +143,13 @@
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
-fstring = f"f-strings definitely make things more {difficult} than they need to be for {{black}}. But boy they sure are handy. The problem is that some lines will need to have the 'f' whereas others do not. This {line}, for example, needs one."
|
-fstring = f"f-strings definitely make things more {difficult} than they need to be for {{black}}. But boy they sure are handy. The problem is that some lines will need to have the 'f' whereas others do not. This {line}, for example, needs one."
|
||||||
+fstring = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
+fstring = (
|
||||||
|
+ f"f-strings definitely make things more {difficult} than they need to be for {{black}}. But boy they sure are handy. The problem is that some lines will need to have the 'f' whereas others do not. This {line}, for example, needs one."
|
||||||
|
+)
|
||||||
|
|
||||||
-fstring_with_no_fexprs = f"Some regular string that needs to get split certainly but is NOT an fstring by any means whatsoever."
|
-fstring_with_no_fexprs = f"Some regular string that needs to get split certainly but is NOT an fstring by any means whatsoever."
|
||||||
+fstring_with_no_fexprs = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
+fstring_with_no_fexprs = (
|
||||||
|
+ f"Some regular string that needs to get split certainly but is NOT an fstring by any means whatsoever."
|
||||||
|
+)
|
||||||
|
|
||||||
comment_string = "Long lines with inline comments should have their comments appended to the reformatted string's enclosing right parentheses." # This comment gets thrown to the top.
|
comment_string = "Long lines with inline comments should have their comments appended to the reformatted string's enclosing right parentheses." # This comment gets thrown to the top.
|
||||||
|
|
||||||
@@ -165,13 +165,9 @@
|
@@ -165,13 +169,9 @@
|
||||||
|
|
||||||
triple_quote_string = """This is a really really really long triple quote string assignment and it should not be touched."""
|
triple_quote_string = """This is a really really really long triple quote string assignment and it should not be touched."""
|
||||||
|
|
||||||
|
@ -332,7 +336,7 @@ long_unmergable_string_with_pragma = (
|
||||||
"formatting"
|
"formatting"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -221,8 +217,8 @@
|
@@ -221,8 +221,8 @@
|
||||||
func_with_bad_comma(
|
func_with_bad_comma(
|
||||||
(
|
(
|
||||||
"This is a really long string argument to a function that has a trailing comma"
|
"This is a really long string argument to a function that has a trailing comma"
|
||||||
|
@ -343,12 +347,14 @@ long_unmergable_string_with_pragma = (
|
||||||
)
|
)
|
||||||
|
|
||||||
func_with_bad_parens_that_wont_fit_in_one_line(
|
func_with_bad_parens_that_wont_fit_in_one_line(
|
||||||
@@ -274,7 +270,7 @@
|
@@ -274,7 +274,9 @@
|
||||||
yield "This is a really long string that can't possibly be expected to fit all together on one line. In fact it may even take up three or more lines... like four or five... but probably just three."
|
yield "This is a really long string that can't possibly be expected to fit all together on one line. In fact it may even take up three or more lines... like four or five... but probably just three."
|
||||||
|
|
||||||
|
|
||||||
-x = f"This is a {{really}} long string that needs to be split without a doubt (i.e. most definitely). In short, this {string} that can't possibly be {{expected}} to fit all together on one line. In {fact} it may even take up three or more lines... like four or five... but probably just four."
|
-x = f"This is a {{really}} long string that needs to be split without a doubt (i.e. most definitely). In short, this {string} that can't possibly be {{expected}} to fit all together on one line. In {fact} it may even take up three or more lines... like four or five... but probably just four."
|
||||||
+x = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
+x = (
|
||||||
|
+ f"This is a {{really}} long string that needs to be split without a doubt (i.e. most definitely). In short, this {string} that can't possibly be {{expected}} to fit all together on one line. In {fact} it may even take up three or more lines... like four or five... but probably just four."
|
||||||
|
+)
|
||||||
|
|
||||||
long_unmergable_string_with_pragma = (
|
long_unmergable_string_with_pragma = (
|
||||||
"This is a really long string that can't be merged because it has a likely pragma at the end" # type: ignore
|
"This is a really long string that can't be merged because it has a likely pragma at the end" # type: ignore
|
||||||
|
@ -502,9 +508,13 @@ old_fmt_string3 = (
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
fstring = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
fstring = (
|
||||||
|
f"f-strings definitely make things more {difficult} than they need to be for {{black}}. But boy they sure are handy. The problem is that some lines will need to have the 'f' whereas others do not. This {line}, for example, needs one."
|
||||||
|
)
|
||||||
|
|
||||||
fstring_with_no_fexprs = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
fstring_with_no_fexprs = (
|
||||||
|
f"Some regular string that needs to get split certainly but is NOT an fstring by any means whatsoever."
|
||||||
|
)
|
||||||
|
|
||||||
comment_string = "Long lines with inline comments should have their comments appended to the reformatted string's enclosing right parentheses." # This comment gets thrown to the top.
|
comment_string = "Long lines with inline comments should have their comments appended to the reformatted string's enclosing right parentheses." # This comment gets thrown to the top.
|
||||||
|
|
||||||
|
@ -629,7 +639,9 @@ def foo():
|
||||||
yield "This is a really long string that can't possibly be expected to fit all together on one line. In fact it may even take up three or more lines... like four or five... but probably just three."
|
yield "This is a really long string that can't possibly be expected to fit all together on one line. In fact it may even take up three or more lines... like four or five... but probably just three."
|
||||||
|
|
||||||
|
|
||||||
x = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
x = (
|
||||||
|
f"This is a {{really}} long string that needs to be split without a doubt (i.e. most definitely). In short, this {string} that can't possibly be {{expected}} to fit all together on one line. In {fact} it may even take up three or more lines... like four or five... but probably just four."
|
||||||
|
)
|
||||||
|
|
||||||
long_unmergable_string_with_pragma = (
|
long_unmergable_string_with_pragma = (
|
||||||
"This is a really long string that can't be merged because it has a likely pragma at the end" # type: ignore
|
"This is a really long string that can't be merged because it has a likely pragma at the end" # type: ignore
|
||||||
|
|
|
@ -69,25 +69,11 @@ f"\"{a}\"{'hello' * b}\"{c}\""
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -15,16 +15,21 @@
|
@@ -24,7 +24,12 @@
|
||||||
"""Here's a " """
|
|
||||||
"""Just a normal triple
|
|
||||||
quote"""
|
|
||||||
-f"just a normal {f} string"
|
|
||||||
-f"""This is a triple-quoted {f}-string"""
|
|
||||||
-f'MOAR {" ".join([])}'
|
|
||||||
-f"MOAR {' '.join([])}"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
r"raw string ftw"
|
|
||||||
r"Date d\'expiration:(.*)"
|
|
||||||
r'Tricky "quote'
|
r'Tricky "quote'
|
||||||
r"Not-so-tricky \"quote"
|
r"Not-so-tricky \"quote"
|
||||||
-rf"{yay}"
|
rf"{yay}"
|
||||||
-"\nThe \"quick\"\nbrown fox\njumps over\nthe 'lazy' dog.\n"
|
-"\nThe \"quick\"\nbrown fox\njumps over\nthe 'lazy' dog.\n"
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+"\n\
|
+"\n\
|
||||||
+The \"quick\"\n\
|
+The \"quick\"\n\
|
||||||
+brown fox\n\
|
+brown fox\n\
|
||||||
|
@ -97,27 +83,6 @@ f"\"{a}\"{'hello' * b}\"{c}\""
|
||||||
re.compile(r'[\\"]')
|
re.compile(r'[\\"]')
|
||||||
"x = ''; y = \"\""
|
"x = ''; y = \"\""
|
||||||
"x = '''; y = \"\""
|
"x = '''; y = \"\""
|
||||||
@@ -39,14 +44,14 @@
|
|
||||||
'\\""'
|
|
||||||
"\\''"
|
|
||||||
"Lots of \\\\\\\\'quotes'"
|
|
||||||
-f'{y * " "} \'{z}\''
|
|
||||||
-f"{{y * \" \"}} '{z}'"
|
|
||||||
-f'\'{z}\' {y * " "}'
|
|
||||||
-f"{y * x} '{z}'"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
"'{z}' {y * \" \"}"
|
|
||||||
"{y * x} '{z}'"
|
|
||||||
|
|
||||||
# We must bail out if changing the quotes would introduce backslashes in f-string
|
|
||||||
# expressions. xref: https://github.com/psf/black/issues/2348
|
|
||||||
-f"\"{b}\"{' ' * (long-len(b)+1)}: \"{sts}\",\n"
|
|
||||||
-f"\"{a}\"{'hello' * b}\"{c}\""
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ruff Output
|
## Ruff Output
|
||||||
|
@ -140,15 +105,15 @@ f"\"{a}\"{'hello' * b}\"{c}\""
|
||||||
"""Here's a " """
|
"""Here's a " """
|
||||||
"""Just a normal triple
|
"""Just a normal triple
|
||||||
quote"""
|
quote"""
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"just a normal {f} string"
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"""This is a triple-quoted {f}-string"""
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f'MOAR {" ".join([])}'
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"MOAR {' '.join([])}"
|
||||||
r"raw string ftw"
|
r"raw string ftw"
|
||||||
r"Date d\'expiration:(.*)"
|
r"Date d\'expiration:(.*)"
|
||||||
r'Tricky "quote'
|
r'Tricky "quote'
|
||||||
r"Not-so-tricky \"quote"
|
r"Not-so-tricky \"quote"
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
rf"{yay}"
|
||||||
"\n\
|
"\n\
|
||||||
The \"quick\"\n\
|
The \"quick\"\n\
|
||||||
brown fox\n\
|
brown fox\n\
|
||||||
|
@ -169,17 +134,17 @@ re.compile(r'[\\"]')
|
||||||
'\\""'
|
'\\""'
|
||||||
"\\''"
|
"\\''"
|
||||||
"Lots of \\\\\\\\'quotes'"
|
"Lots of \\\\\\\\'quotes'"
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f'{y * " "} \'{z}\''
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"{{y * \" \"}} '{z}'"
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f'\'{z}\' {y * " "}'
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"{y * x} '{z}'"
|
||||||
"'{z}' {y * \" \"}"
|
"'{z}' {y * \" \"}"
|
||||||
"{y * x} '{z}'"
|
"{y * x} '{z}'"
|
||||||
|
|
||||||
# We must bail out if changing the quotes would introduce backslashes in f-string
|
# We must bail out if changing the quotes would introduce backslashes in f-string
|
||||||
# expressions. xref: https://github.com/psf/black/issues/2348
|
# expressions. xref: https://github.com/psf/black/issues/2348
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"\"{b}\"{' ' * (long-len(b)+1)}: \"{sts}\",\n"
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"\"{a}\"{'hello' * b}\"{c}\""
|
||||||
```
|
```
|
||||||
|
|
||||||
## Black Output
|
## Black Output
|
||||||
|
|
|
@ -119,21 +119,6 @@ with match() as match:
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -1,12 +1,12 @@
|
|
||||||
re.match()
|
|
||||||
match = a
|
|
||||||
with match() as match:
|
|
||||||
- match = f"{match}"
|
|
||||||
+ match = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
|
|
||||||
re.match()
|
|
||||||
match = a
|
|
||||||
with match() as match:
|
|
||||||
- match = f"{match}"
|
|
||||||
+ match = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
|
|
||||||
|
|
||||||
def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
|
|
||||||
@@ -23,11 +23,7 @@
|
@@ -23,11 +23,7 @@
|
||||||
pygram.python_grammar,
|
pygram.python_grammar,
|
||||||
]
|
]
|
||||||
|
@ -147,12 +132,7 @@ with match() as match:
|
||||||
|
|
||||||
if all(version.is_python2() for version in target_versions):
|
if all(version.is_python2() for version in target_versions):
|
||||||
# Python 2-only code, so try Python 2 grammars.
|
# Python 2-only code, so try Python 2 grammars.
|
||||||
@@ -41,13 +37,11 @@
|
@@ -45,9 +41,7 @@
|
||||||
re.match()
|
|
||||||
match = a
|
|
||||||
with match() as match:
|
|
||||||
- match = f"{match}"
|
|
||||||
+ match = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
|
|
||||||
def test_patma_139(self):
|
def test_patma_139(self):
|
||||||
x = False
|
x = False
|
||||||
|
@ -182,18 +162,6 @@ with match() as match:
|
||||||
|
|
||||||
# At least one of the above branches must have been taken, because every Python
|
# At least one of the above branches must have been taken, because every Python
|
||||||
# version has exactly one of the two 'ASYNC_*' flags
|
# version has exactly one of the two 'ASYNC_*' flags
|
||||||
@@ -99,9 +89,9 @@
|
|
||||||
re.match()
|
|
||||||
match = a
|
|
||||||
with match() as match:
|
|
||||||
- match = f"{match}"
|
|
||||||
+ match = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
|
|
||||||
re.match()
|
|
||||||
match = a
|
|
||||||
with match() as match:
|
|
||||||
- match = f"{match}"
|
|
||||||
+ match = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ruff Output
|
## Ruff Output
|
||||||
|
@ -202,12 +170,12 @@ with match() as match:
|
||||||
re.match()
|
re.match()
|
||||||
match = a
|
match = a
|
||||||
with match() as match:
|
with match() as match:
|
||||||
match = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
match = f"{match}"
|
||||||
|
|
||||||
re.match()
|
re.match()
|
||||||
match = a
|
match = a
|
||||||
with match() as match:
|
with match() as match:
|
||||||
match = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
match = f"{match}"
|
||||||
|
|
||||||
|
|
||||||
def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
|
def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
|
||||||
|
@ -238,7 +206,7 @@ def get_grammars(target_versions: Set[TargetVersion]) -> List[Grammar]:
|
||||||
re.match()
|
re.match()
|
||||||
match = a
|
match = a
|
||||||
with match() as match:
|
with match() as match:
|
||||||
match = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
match = f"{match}"
|
||||||
|
|
||||||
def test_patma_139(self):
|
def test_patma_139(self):
|
||||||
x = False
|
x = False
|
||||||
|
@ -290,12 +258,12 @@ def lib2to3_parse(src_txt: str, target_versions: Iterable[TargetVersion] = ()) -
|
||||||
re.match()
|
re.match()
|
||||||
match = a
|
match = a
|
||||||
with match() as match:
|
with match() as match:
|
||||||
match = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
match = f"{match}"
|
||||||
|
|
||||||
re.match()
|
re.match()
|
||||||
match = a
|
match = a
|
||||||
with match() as match:
|
with match() as match:
|
||||||
match = f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
match = f"{match}"
|
||||||
```
|
```
|
||||||
|
|
||||||
## Black Output
|
## Black Output
|
||||||
|
|
|
@ -62,7 +62,7 @@ def single_quote_docstring_over_line_limit2():
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -1,9 +1,10 @@
|
@@ -1,9 +1,11 @@
|
||||||
def docstring_almost_at_line_limit():
|
def docstring_almost_at_line_limit():
|
||||||
- """long docstring................................................................."""
|
- """long docstring................................................................."""
|
||||||
+ """long docstring.................................................................
|
+ """long docstring.................................................................
|
||||||
|
@ -71,42 +71,11 @@ def single_quote_docstring_over_line_limit2():
|
||||||
|
|
||||||
def docstring_almost_at_line_limit_with_prefix():
|
def docstring_almost_at_line_limit_with_prefix():
|
||||||
- f"""long docstring................................................................"""
|
- f"""long docstring................................................................"""
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
+ f"""long docstring................................................................
|
||||||
|
+ """
|
||||||
|
|
||||||
|
|
||||||
def mulitline_docstring_almost_at_line_limit():
|
def mulitline_docstring_almost_at_line_limit():
|
||||||
@@ -14,10 +15,7 @@
|
|
||||||
|
|
||||||
|
|
||||||
def mulitline_docstring_almost_at_line_limit_with_prefix():
|
|
||||||
- f"""long docstring................................................................
|
|
||||||
-
|
|
||||||
- ..................................................................................
|
|
||||||
- """
|
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_at_line_limit():
|
|
||||||
@@ -25,7 +23,7 @@
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_at_line_limit_with_prefix():
|
|
||||||
- f"""long docstring..............................................................."""
|
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
|
|
||||||
|
|
||||||
def multiline_docstring_at_line_limit():
|
|
||||||
@@ -35,9 +33,7 @@
|
|
||||||
|
|
||||||
|
|
||||||
def multiline_docstring_at_line_limit_with_prefix():
|
|
||||||
- f"""first line----------------------------------------------------------------------
|
|
||||||
-
|
|
||||||
- second line----------------------------------------------------------------------"""
|
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
|
|
||||||
|
|
||||||
def single_quote_docstring_over_line_limit():
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ruff Output
|
## Ruff Output
|
||||||
|
@ -118,7 +87,8 @@ def docstring_almost_at_line_limit():
|
||||||
|
|
||||||
|
|
||||||
def docstring_almost_at_line_limit_with_prefix():
|
def docstring_almost_at_line_limit_with_prefix():
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"""long docstring................................................................
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def mulitline_docstring_almost_at_line_limit():
|
def mulitline_docstring_almost_at_line_limit():
|
||||||
|
@ -129,7 +99,10 @@ def mulitline_docstring_almost_at_line_limit():
|
||||||
|
|
||||||
|
|
||||||
def mulitline_docstring_almost_at_line_limit_with_prefix():
|
def mulitline_docstring_almost_at_line_limit_with_prefix():
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"""long docstring................................................................
|
||||||
|
|
||||||
|
..................................................................................
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
def docstring_at_line_limit():
|
def docstring_at_line_limit():
|
||||||
|
@ -137,7 +110,7 @@ def docstring_at_line_limit():
|
||||||
|
|
||||||
|
|
||||||
def docstring_at_line_limit_with_prefix():
|
def docstring_at_line_limit_with_prefix():
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"""long docstring..............................................................."""
|
||||||
|
|
||||||
|
|
||||||
def multiline_docstring_at_line_limit():
|
def multiline_docstring_at_line_limit():
|
||||||
|
@ -147,7 +120,9 @@ def multiline_docstring_at_line_limit():
|
||||||
|
|
||||||
|
|
||||||
def multiline_docstring_at_line_limit_with_prefix():
|
def multiline_docstring_at_line_limit_with_prefix():
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"""first line----------------------------------------------------------------------
|
||||||
|
|
||||||
|
second line----------------------------------------------------------------------"""
|
||||||
|
|
||||||
|
|
||||||
def single_quote_docstring_over_line_limit():
|
def single_quote_docstring_over_line_limit():
|
||||||
|
|
|
@ -104,32 +104,14 @@ def g():
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -16,7 +16,7 @@
|
@@ -49,7 +49,6 @@
|
||||||
if t == token.COMMENT: # another trailing comment
|
|
||||||
return DOUBLESPACE
|
|
||||||
|
|
||||||
- assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}"
|
|
||||||
+ assert p is not None, f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
|
|
||||||
prev = leaf.prev_sibling
|
|
||||||
if not prev:
|
|
||||||
@@ -48,7 +48,6 @@
|
|
||||||
###############################################################################
|
|
||||||
# SECTION BECAUSE SECTIONS
|
# SECTION BECAUSE SECTIONS
|
||||||
###############################################################################
|
###############################################################################
|
||||||
-
|
|
||||||
|
|
||||||
|
-
|
||||||
def g():
|
def g():
|
||||||
NO = ""
|
NO = ""
|
||||||
@@ -67,7 +66,7 @@
|
SPACE = " "
|
||||||
return DOUBLESPACE
|
|
||||||
|
|
||||||
# Another comment because more comments
|
|
||||||
- assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}"
|
|
||||||
+ assert p is not None, f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
|
|
||||||
prev = leaf.prev_sibling
|
|
||||||
if not prev:
|
|
||||||
```
|
```
|
||||||
|
|
||||||
## Ruff Output
|
## Ruff Output
|
||||||
|
@ -153,7 +135,7 @@ def f():
|
||||||
if t == token.COMMENT: # another trailing comment
|
if t == token.COMMENT: # another trailing comment
|
||||||
return DOUBLESPACE
|
return DOUBLESPACE
|
||||||
|
|
||||||
assert p is not None, f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}"
|
||||||
|
|
||||||
prev = leaf.prev_sibling
|
prev = leaf.prev_sibling
|
||||||
if not prev:
|
if not prev:
|
||||||
|
@ -203,7 +185,7 @@ def g():
|
||||||
return DOUBLESPACE
|
return DOUBLESPACE
|
||||||
|
|
||||||
# Another comment because more comments
|
# Another comment because more comments
|
||||||
assert p is not None, f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
assert p is not None, f"INTERNAL ERROR: hand-made leaf without parent: {leaf!r}"
|
||||||
|
|
||||||
prev = leaf.prev_sibling
|
prev = leaf.prev_sibling
|
||||||
if not prev:
|
if not prev:
|
||||||
|
|
|
@ -198,7 +198,7 @@ d={'a':1,
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -6,10 +6,10 @@
|
@@ -6,8 +6,8 @@
|
||||||
|
|
||||||
from library import some_connection, some_decorator
|
from library import some_connection, some_decorator
|
||||||
# fmt: off
|
# fmt: off
|
||||||
|
@ -207,11 +207,8 @@ d={'a':1,
|
||||||
+from third_party import X, Y, Z
|
+from third_party import X, Y, Z
|
||||||
+
|
+
|
||||||
# fmt: on
|
# fmt: on
|
||||||
-f"trigger 3.6 mode"
|
f"trigger 3.6 mode"
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
# Comment 1
|
# Comment 1
|
||||||
|
|
||||||
# Comment 2
|
|
||||||
@@ -17,26 +17,40 @@
|
@@ -17,26 +17,40 @@
|
||||||
|
|
||||||
# fmt: off
|
# fmt: off
|
||||||
|
@ -403,7 +400,7 @@ from library import some_connection, some_decorator
|
||||||
from third_party import X, Y, Z
|
from third_party import X, Y, Z
|
||||||
|
|
||||||
# fmt: on
|
# fmt: on
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"trigger 3.6 mode"
|
||||||
# Comment 1
|
# Comment 1
|
||||||
|
|
||||||
# Comment 2
|
# Comment 2
|
||||||
|
|
|
@ -1,81 +0,0 @@
|
||||||
---
|
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/fstring.py
|
|
||||||
---
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```py
|
|
||||||
f"f-string without formatted values is just a string"
|
|
||||||
f"{{NOT a formatted value}}"
|
|
||||||
f"{{NOT 'a' \"formatted\" \"value\"}}"
|
|
||||||
f"some f-string with {a} {few():.2f} {formatted.values!r}"
|
|
||||||
f'some f-string with {a} {few(""):.2f} {formatted.values!r}'
|
|
||||||
f"{f'''{'nested'} inner'''} outer"
|
|
||||||
f"\"{f'{nested} inner'}\" outer"
|
|
||||||
f"space between opening braces: { {a for a in (1, 2, 3)}}"
|
|
||||||
f'Hello \'{tricky + "example"}\''
|
|
||||||
f"Tried directories {str(rootdirs)} \
|
|
||||||
but none started with prefix {parentdir_prefix}"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Differences
|
|
||||||
|
|
||||||
```diff
|
|
||||||
--- Black
|
|
||||||
+++ Ruff
|
|
||||||
@@ -1,11 +1,10 @@
|
|
||||||
-f"f-string without formatted values is just a string"
|
|
||||||
-f"{{NOT a formatted value}}"
|
|
||||||
-f'{{NOT \'a\' "formatted" "value"}}'
|
|
||||||
-f"some f-string with {a} {few():.2f} {formatted.values!r}"
|
|
||||||
-f'some f-string with {a} {few(""):.2f} {formatted.values!r}'
|
|
||||||
-f"{f'''{'nested'} inner'''} outer"
|
|
||||||
-f"\"{f'{nested} inner'}\" outer"
|
|
||||||
-f"space between opening braces: { {a for a in (1, 2, 3)}}"
|
|
||||||
-f'Hello \'{tricky + "example"}\''
|
|
||||||
-f"Tried directories {str(rootdirs)} \
|
|
||||||
-but none started with prefix {parentdir_prefix}"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ruff Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
f"f-string without formatted values is just a string"
|
|
||||||
f"{{NOT a formatted value}}"
|
|
||||||
f'{{NOT \'a\' "formatted" "value"}}'
|
|
||||||
f"some f-string with {a} {few():.2f} {formatted.values!r}"
|
|
||||||
f'some f-string with {a} {few(""):.2f} {formatted.values!r}'
|
|
||||||
f"{f'''{'nested'} inner'''} outer"
|
|
||||||
f"\"{f'{nested} inner'}\" outer"
|
|
||||||
f"space between opening braces: { {a for a in (1, 2, 3)}}"
|
|
||||||
f'Hello \'{tricky + "example"}\''
|
|
||||||
f"Tried directories {str(rootdirs)} \
|
|
||||||
but none started with prefix {parentdir_prefix}"
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -107,15 +107,6 @@ def __await__(): return (yield)
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -6,7 +6,7 @@
|
|
||||||
|
|
||||||
from library import some_connection, some_decorator
|
|
||||||
|
|
||||||
-f"trigger 3.6 mode"
|
|
||||||
+f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
|
||||||
|
|
||||||
|
|
||||||
def func_no_args():
|
|
||||||
@@ -65,18 +65,14 @@
|
@@ -65,18 +65,14 @@
|
||||||
|
|
||||||
def spaces2(result=_core.Value(None)):
|
def spaces2(result=_core.Value(None)):
|
||||||
|
@ -153,7 +144,7 @@ from third_party import X, Y, Z
|
||||||
|
|
||||||
from library import some_connection, some_decorator
|
from library import some_connection, some_decorator
|
||||||
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr"
|
f"trigger 3.6 mode"
|
||||||
|
|
||||||
|
|
||||||
def func_no_args():
|
def func_no_args():
|
||||||
|
|
|
@ -1,311 +0,0 @@
|
||||||
---
|
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/remove_newline_after_code_block_open.py
|
|
||||||
---
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```py
|
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
def foo1():
|
|
||||||
|
|
||||||
print("The newline above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
def foo2():
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print("All the newlines above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
def foo3():
|
|
||||||
|
|
||||||
print("No newline above me!")
|
|
||||||
|
|
||||||
print("There is a newline above me, and that's OK!")
|
|
||||||
|
|
||||||
|
|
||||||
def foo4():
|
|
||||||
|
|
||||||
# There is a comment here
|
|
||||||
|
|
||||||
print("The newline above me should not be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
class Foo:
|
|
||||||
def bar(self):
|
|
||||||
|
|
||||||
print("The newline above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
|
|
||||||
print(f"{i}) The line above me should be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print(f"{i}) The lines above me should be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
|
|
||||||
for j in range(7):
|
|
||||||
|
|
||||||
print(f"{i}) The lines above me should be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
if random.randint(0, 3) == 0:
|
|
||||||
|
|
||||||
print("The new line above me is about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
if random.randint(0, 3) == 0:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print("The new lines above me is about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
if random.randint(0, 3) == 0:
|
|
||||||
if random.uniform(0, 1) > 0.5:
|
|
||||||
print("Two lines above me are about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
while True:
|
|
||||||
|
|
||||||
print("The newline above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
while True:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
print("The newlines above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
while True:
|
|
||||||
|
|
||||||
while False:
|
|
||||||
|
|
||||||
print("The newlines above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
with open("/path/to/file.txt", mode="w") as file:
|
|
||||||
|
|
||||||
file.write("The new line above me is about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
with open("/path/to/file.txt", mode="w") as file:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
file.write("The new lines above me is about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
with open("/path/to/file.txt", mode="r") as read_file:
|
|
||||||
|
|
||||||
with open("/path/to/output_file.txt", mode="w") as write_file:
|
|
||||||
|
|
||||||
write_file.writelines(read_file.readlines())
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Differences
|
|
||||||
|
|
||||||
```diff
|
|
||||||
--- Black
|
|
||||||
+++ Ruff
|
|
||||||
@@ -27,16 +27,16 @@
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
- print(f"{i}) The line above me should be removed!")
|
|
||||||
+ print(f"NOT_YET_IMPLEMENTED_ExprJoinedStr")
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
- print(f"{i}) The lines above me should be removed!")
|
|
||||||
+ print(f"NOT_YET_IMPLEMENTED_ExprJoinedStr")
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
for j in range(7):
|
|
||||||
- print(f"{i}) The lines above me should be removed!")
|
|
||||||
+ print(f"NOT_YET_IMPLEMENTED_ExprJoinedStr")
|
|
||||||
|
|
||||||
|
|
||||||
if random.randint(0, 3) == 0:
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ruff Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
def foo1():
|
|
||||||
print("The newline above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
def foo2():
|
|
||||||
print("All the newlines above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
def foo3():
|
|
||||||
print("No newline above me!")
|
|
||||||
|
|
||||||
print("There is a newline above me, and that's OK!")
|
|
||||||
|
|
||||||
|
|
||||||
def foo4():
|
|
||||||
# There is a comment here
|
|
||||||
|
|
||||||
print("The newline above me should not be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
class Foo:
|
|
||||||
def bar(self):
|
|
||||||
print("The newline above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
print(f"NOT_YET_IMPLEMENTED_ExprJoinedStr")
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
print(f"NOT_YET_IMPLEMENTED_ExprJoinedStr")
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
for j in range(7):
|
|
||||||
print(f"NOT_YET_IMPLEMENTED_ExprJoinedStr")
|
|
||||||
|
|
||||||
|
|
||||||
if random.randint(0, 3) == 0:
|
|
||||||
print("The new line above me is about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
if random.randint(0, 3) == 0:
|
|
||||||
print("The new lines above me is about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
if random.randint(0, 3) == 0:
|
|
||||||
if random.uniform(0, 1) > 0.5:
|
|
||||||
print("Two lines above me are about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
while True:
|
|
||||||
print("The newline above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
while True:
|
|
||||||
print("The newlines above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
while True:
|
|
||||||
while False:
|
|
||||||
print("The newlines above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
with open("/path/to/file.txt", mode="w") as file:
|
|
||||||
file.write("The new line above me is about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
with open("/path/to/file.txt", mode="w") as file:
|
|
||||||
file.write("The new lines above me is about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
with open("/path/to/file.txt", mode="r") as read_file:
|
|
||||||
with open("/path/to/output_file.txt", mode="w") as write_file:
|
|
||||||
write_file.writelines(read_file.readlines())
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
import random
|
|
||||||
|
|
||||||
|
|
||||||
def foo1():
|
|
||||||
print("The newline above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
def foo2():
|
|
||||||
print("All the newlines above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
def foo3():
|
|
||||||
print("No newline above me!")
|
|
||||||
|
|
||||||
print("There is a newline above me, and that's OK!")
|
|
||||||
|
|
||||||
|
|
||||||
def foo4():
|
|
||||||
# There is a comment here
|
|
||||||
|
|
||||||
print("The newline above me should not be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
class Foo:
|
|
||||||
def bar(self):
|
|
||||||
print("The newline above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
print(f"{i}) The line above me should be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
print(f"{i}) The lines above me should be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
for i in range(5):
|
|
||||||
for j in range(7):
|
|
||||||
print(f"{i}) The lines above me should be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
if random.randint(0, 3) == 0:
|
|
||||||
print("The new line above me is about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
if random.randint(0, 3) == 0:
|
|
||||||
print("The new lines above me is about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
if random.randint(0, 3) == 0:
|
|
||||||
if random.uniform(0, 1) > 0.5:
|
|
||||||
print("Two lines above me are about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
while True:
|
|
||||||
print("The newline above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
while True:
|
|
||||||
print("The newlines above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
while True:
|
|
||||||
while False:
|
|
||||||
print("The newlines above me should be deleted!")
|
|
||||||
|
|
||||||
|
|
||||||
with open("/path/to/file.txt", mode="w") as file:
|
|
||||||
file.write("The new line above me is about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
with open("/path/to/file.txt", mode="w") as file:
|
|
||||||
file.write("The new lines above me is about to be removed!")
|
|
||||||
|
|
||||||
|
|
||||||
with open("/path/to/file.txt", mode="r") as read_file:
|
|
||||||
with open("/path/to/output_file.txt", mode="w") as write_file:
|
|
||||||
write_file.writelines(read_file.readlines())
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -67,18 +67,20 @@ def example8():
|
||||||
```diff
|
```diff
|
||||||
--- Black
|
--- Black
|
||||||
+++ Ruff
|
+++ Ruff
|
||||||
@@ -10,9 +10,7 @@
|
@@ -11,8 +11,10 @@
|
||||||
while True:
|
|
||||||
try:
|
try:
|
||||||
if report_host:
|
if report_host:
|
||||||
- data = (
|
data = (
|
||||||
- f"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
- f"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
- ).encode()
|
- ).encode()
|
||||||
+ data = (f"NOT_YET_IMPLEMENTED_ExprJoinedStr").encode()
|
+ (
|
||||||
|
+ f"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
+ ).encode()
|
||||||
|
+ )
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -30,15 +28,11 @@
|
@@ -30,15 +32,11 @@
|
||||||
|
|
||||||
|
|
||||||
def example2():
|
def example2():
|
||||||
|
@ -113,7 +115,11 @@ async def show_status():
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
if report_host:
|
if report_host:
|
||||||
data = (f"NOT_YET_IMPLEMENTED_ExprJoinedStr").encode()
|
data = (
|
||||||
|
(
|
||||||
|
f"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
||||||
|
).encode()
|
||||||
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
|
@ -1,120 +0,0 @@
|
||||||
---
|
|
||||||
source: crates/ruff_python_formatter/tests/fixtures.rs
|
|
||||||
input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/string_prefixes.py
|
|
||||||
---
|
|
||||||
## Input
|
|
||||||
|
|
||||||
```py
|
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
name = "Łukasz"
|
|
||||||
(f"hello {name}", F"hello {name}")
|
|
||||||
(b"", B"")
|
|
||||||
(u"", U"")
|
|
||||||
(r"", R"")
|
|
||||||
|
|
||||||
(rf"", fr"", Rf"", fR"", rF"", Fr"", RF"", FR"")
|
|
||||||
(rb"", br"", Rb"", bR"", rB"", Br"", RB"", BR"")
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_singleline():
|
|
||||||
R"""2020 was one hell of a year. The good news is that we were able to"""
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_multiline():
|
|
||||||
R"""
|
|
||||||
clear out all of the issues opened in that time :p
|
|
||||||
"""
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Differences
|
|
||||||
|
|
||||||
```diff
|
|
||||||
--- Black
|
|
||||||
+++ Ruff
|
|
||||||
@@ -1,12 +1,21 @@
|
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
name = "Łukasz"
|
|
||||||
-(f"hello {name}", f"hello {name}")
|
|
||||||
+(f"NOT_YET_IMPLEMENTED_ExprJoinedStr", f"NOT_YET_IMPLEMENTED_ExprJoinedStr")
|
|
||||||
(b"", b"")
|
|
||||||
("", "")
|
|
||||||
(r"", R"")
|
|
||||||
|
|
||||||
-(rf"", rf"", Rf"", Rf"", rf"", rf"", Rf"", Rf"")
|
|
||||||
+(
|
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
+ f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
+)
|
|
||||||
(rb"", rb"", Rb"", Rb"", rb"", rb"", Rb"", Rb"")
|
|
||||||
|
|
||||||
|
|
||||||
```
|
|
||||||
|
|
||||||
## Ruff Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
name = "Łukasz"
|
|
||||||
(f"NOT_YET_IMPLEMENTED_ExprJoinedStr", f"NOT_YET_IMPLEMENTED_ExprJoinedStr")
|
|
||||||
(b"", b"")
|
|
||||||
("", "")
|
|
||||||
(r"", R"")
|
|
||||||
|
|
||||||
(
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
f"NOT_YET_IMPLEMENTED_ExprJoinedStr",
|
|
||||||
)
|
|
||||||
(rb"", rb"", Rb"", Rb"", rb"", rb"", Rb"", Rb"")
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_singleline():
|
|
||||||
R"""2020 was one hell of a year. The good news is that we were able to"""
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_multiline():
|
|
||||||
R"""
|
|
||||||
clear out all of the issues opened in that time :p
|
|
||||||
"""
|
|
||||||
```
|
|
||||||
|
|
||||||
## Black Output
|
|
||||||
|
|
||||||
```py
|
|
||||||
#!/usr/bin/env python3
|
|
||||||
|
|
||||||
name = "Łukasz"
|
|
||||||
(f"hello {name}", f"hello {name}")
|
|
||||||
(b"", b"")
|
|
||||||
("", "")
|
|
||||||
(r"", R"")
|
|
||||||
|
|
||||||
(rf"", rf"", Rf"", Rf"", rf"", rf"", Rf"", Rf"")
|
|
||||||
(rb"", rb"", Rb"", Rb"", rb"", rb"", Rb"", Rb"")
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_singleline():
|
|
||||||
R"""2020 was one hell of a year. The good news is that we were able to"""
|
|
||||||
|
|
||||||
|
|
||||||
def docstring_multiline():
|
|
||||||
R"""
|
|
||||||
clear out all of the issues opened in that time :p
|
|
||||||
"""
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
---
|
||||||
|
source: crates/ruff_python_formatter/tests/fixtures.rs
|
||||||
|
input_file: crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/joined_string.py
|
||||||
|
---
|
||||||
|
## Input
|
||||||
|
```py
|
||||||
|
(
|
||||||
|
f'{one}'
|
||||||
|
f'{two}'
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
rf"Not-so-tricky \"quote"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Output
|
||||||
|
```py
|
||||||
|
(f"{one}" f"{two}")
|
||||||
|
|
||||||
|
|
||||||
|
rf'Not-so-tricky "quote'
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue