From c52aa8f0656f0d17817cbde52c73e362b282a913 Mon Sep 17 00:00:00 2001 From: Micha Reiser Date: Fri, 23 Jun 2023 09:46:05 +0200 Subject: [PATCH] Basic string formatting ## Summary This PR implements formatting for non-f-string Strings that do not use implicit concatenation. Docstring formatting is out of the scope of this PR. ## Test Plan I added a few tests for simple string literals. ## Performance Ouch. This is hitting performance somewhat hard. This is probably because we now iterate each string a couple of times: 1. To detect if it is an implicit string continuation 2. To detect if the string contains any new lines 3. To detect the preferred quote 4. To normalize the string Edit: I integrated the detection of newlines into the preferred quote detection so that we only iterate the string three time. We can probably do better by merging the implicit string continuation with the quote detection and new line detection by iterating till the end of the string part and returning the offset. We then use our simple tokenizer to skip over any comments or whitespace until we find the first non trivia token. From there we keep continue doing this in a loop until we reach the end o the string. I'll leave this improvement for later. --- Cargo.lock | 1 + crates/ruff_python_ast/src/str.rs | 13 +- crates/ruff_python_formatter/Cargo.toml | 1 + .../test/fixtures/ruff/expression/string.py | 52 +++ .../src/expression/expr_constant.rs | 5 +- .../src/expression/mod.rs | 1 + .../src/expression/string.rs | 318 ++++++++++++++++ crates/ruff_python_formatter/src/lib.rs | 56 +-- ...r__tests__black_test__bracketmatch_py.snap | 5 +- ...black_test__class_methods_new_line_py.snap | 87 +---- ...er__tests__black_test__collections_py.snap | 45 +-- ...tter__tests__black_test__comments2_py.snap | 79 +--- ...tter__tests__black_test__comments3_py.snap | 16 +- ...tter__tests__black_test__comments5_py.snap | 8 +- ...tter__tests__black_test__comments6_py.snap | 4 +- ...tter__tests__black_test__comments9_py.snap | 11 +- ..._test__comments_non_breaking_space_py.snap | 14 +- ...atter__tests__black_test__comments_py.snap | 84 ++--- ...est__composition_no_trailing_comma_py.snap | 58 +-- ...er__tests__black_test__composition_py.snap | 58 +-- ...ing_no_extra_empty_line_before_eof_py.snap | 46 --- ...sts__black_test__docstring_preview_py.snap | 44 +-- ...tter__tests__black_test__docstring_py.snap | 347 ++++++++++-------- ...er__tests__black_test__empty_lines_py.snap | 47 +-- ...ter__tests__black_test__expression_py.snap | 159 ++++---- ...tter__tests__black_test__fmtonoff2_py.snap | 5 +- ...tter__tests__black_test__fmtonoff5_py.snap | 21 +- ...atter__tests__black_test__fmtonoff_py.snap | 118 +++--- ...atter__tests__black_test__fmtskip2_py.snap | 47 +-- ...atter__tests__black_test__fmtskip3_py.snap | 13 +- ...atter__tests__black_test__fmtskip7_py.snap | 10 +- ...tter__tests__black_test__function2_py.snap | 18 +- ...atter__tests__black_test__function_py.snap | 35 +- ...lack_test__function_trailing_comma_py.snap | 107 ++---- ..._tests__black_test__import_spacing_py.snap | 6 +- ...ests__black_test__power_op_spacing_py.snap | 10 +- ...__tests__black_test__remove_parens_py.snap | 13 +- ...tests__black_test__string_prefixes_py.snap | 32 +- ...t__trailing_comma_optional_parens1_py.snap | 4 +- ...t__trailing_comma_optional_parens2_py.snap | 4 +- ...t__trailing_comma_optional_parens3_py.snap | 8 +- ...__trailing_commas_in_leading_parts_py.snap | 14 +- ...ests__ruff_test__expression__slice_py.snap | 46 +-- ...sts__ruff_test__expression__string_py.snap | 119 ++++++ ...ests__ruff_test__expression__tuple_py.snap | 165 +++++---- ...r__tests__ruff_test__statement__if_py.snap | 10 +- 46 files changed, 1278 insertions(+), 1086 deletions(-) create mode 100644 crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/string.py create mode 100644 crates/ruff_python_formatter/src/expression/string.rs delete mode 100644 crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__docstring_no_extra_empty_line_before_eof_py.snap create mode 100644 crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__string_py.snap diff --git a/Cargo.lock b/Cargo.lock index 43e96c3a5a..61791812a6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2034,6 +2034,7 @@ name = "ruff_python_formatter" version = "0.0.0" dependencies = [ "anyhow", + "bitflags 2.3.1", "clap", "countme", "insta", diff --git a/crates/ruff_python_ast/src/str.rs b/crates/ruff_python_ast/src/str.rs index bc484d8569..5421641c21 100644 --- a/crates/ruff_python_ast/src/str.rs +++ b/crates/ruff_python_ast/src/str.rs @@ -220,11 +220,15 @@ pub fn is_implicit_concatenation(content: &str) -> bool { let mut rest = &content[leading_quote_str.len()..content.len() - trailing_quote_str.len()]; while let Some(index) = rest.find(trailing_quote_str) { let mut chars = rest[..index].chars().rev(); + if let Some('\\') = chars.next() { - // If the quote is double-escaped, then it's _not_ escaped, so the string is - // implicitly concatenated. - if let Some('\\') = chars.next() { - return true; + if chars.next() == Some('\\') { + // Either `\\'` or `\\\'` need to test one more character + + // If the quote is preceded by `//` then it is not escaped, instead the backslash is escaped. + if chars.next() != Some('\\') { + return true; + } } } else { // If the quote is _not_ escaped, then it's implicitly concatenated. @@ -299,5 +303,6 @@ mod tests { // Negative cases with escaped quotes. assert!(!is_implicit_concatenation(r#""abc\"def""#)); + assert!(!is_implicit_concatenation(r#"'\\\' ""'"#)); } } diff --git a/crates/ruff_python_formatter/Cargo.toml b/crates/ruff_python_formatter/Cargo.toml index 708b77c8f9..0701907975 100644 --- a/crates/ruff_python_formatter/Cargo.toml +++ b/crates/ruff_python_formatter/Cargo.toml @@ -17,6 +17,7 @@ ruff_python_ast = { path = "../ruff_python_ast" } ruff_text_size = { workspace = true } anyhow = { workspace = true } +bitflags = { workspace = true } clap = { workspace = true } countme = "3.0.1" is-macro = { workspace = true } diff --git a/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/string.py b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/string.py new file mode 100644 index 0000000000..7ae9032c80 --- /dev/null +++ b/crates/ruff_python_formatter/resources/test/fixtures/ruff/expression/string.py @@ -0,0 +1,52 @@ +"' test" +'" test' + +"\" test" +'\' test' + +# Prefer single quotes for string with more double quotes +"' \" \" '' \" \" '" + +# Prefer double quotes for string with more single quotes +'\' " " \'\' " " \'' + +# Prefer double quotes for string with equal amount of single and double quotes +'" \' " " \'\'' +"' \" '' \" \" '" + +"\\' \"\"" +'\\\' ""' + + +u"Test" +U"Test" + +r"Test" +R"Test" + +'This string will not include \ +backslashes or newline characters.' + +if True: + 'This string will not include \ + backslashes or newline characters.' + +"""Multiline +String \" +""" + +'''Multiline +String \' +''' + +'''Multiline +String "" +''' + +'''Multiline +String """ +''' + +'''Multiline +String \"\"\" +''' diff --git a/crates/ruff_python_formatter/src/expression/expr_constant.rs b/crates/ruff_python_formatter/src/expression/expr_constant.rs index bdb9b7117c..d1d7de417b 100644 --- a/crates/ruff_python_formatter/src/expression/expr_constant.rs +++ b/crates/ruff_python_formatter/src/expression/expr_constant.rs @@ -2,6 +2,7 @@ use crate::comments::Comments; use crate::expression::parentheses::{ default_expression_needs_parentheses, NeedsParentheses, Parentheses, Parenthesize, }; +use crate::expression::string::FormatString; use crate::prelude::*; use crate::{not_yet_implemented_custom_text, verbatim_text, FormatNodeRule}; use ruff_formatter::write; @@ -28,9 +29,7 @@ impl FormatNodeRule for FormatExprConstant { Constant::Int(_) | Constant::Float(_) | Constant::Complex { .. } => { write!(f, [verbatim_text(item)]) } - Constant::Str(_) => { - not_yet_implemented_custom_text(r#""NOT_YET_IMPLEMENTED_STRING""#).fmt(f) - } + Constant::Str(_) => FormatString::new(item).fmt(f), Constant::Bytes(_) => { not_yet_implemented_custom_text(r#"b"NOT_YET_IMPLEMENTED_BYTE_STRING""#).fmt(f) } diff --git a/crates/ruff_python_formatter/src/expression/mod.rs b/crates/ruff_python_formatter/src/expression/mod.rs index 46214396fc..06292c6447 100644 --- a/crates/ruff_python_formatter/src/expression/mod.rs +++ b/crates/ruff_python_formatter/src/expression/mod.rs @@ -37,6 +37,7 @@ pub(crate) mod expr_unary_op; pub(crate) mod expr_yield; pub(crate) mod expr_yield_from; pub(crate) mod parentheses; +mod string; #[derive(Default)] pub struct FormatExpr { diff --git a/crates/ruff_python_formatter/src/expression/string.rs b/crates/ruff_python_formatter/src/expression/string.rs new file mode 100644 index 0000000000..116226fc1d --- /dev/null +++ b/crates/ruff_python_formatter/src/expression/string.rs @@ -0,0 +1,318 @@ +use crate::prelude::*; +use crate::{not_yet_implemented_custom_text, QuoteStyle}; +use bitflags::bitflags; +use ruff_formatter::{write, FormatError}; +use ruff_python_ast::str::is_implicit_concatenation; +use ruff_text_size::{TextLen, TextRange, TextSize}; +use rustpython_parser::ast::{ExprConstant, Ranged}; +use std::borrow::Cow; + +pub(super) struct FormatString { + string_range: TextRange, +} + +impl FormatString { + pub(super) fn new(constant: &ExprConstant) -> Self { + debug_assert!(constant.value.is_str()); + Self { + string_range: constant.range(), + } + } +} + +impl Format> for FormatString { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + let string_content = f.context().locator().slice(self.string_range); + + if is_implicit_concatenation(string_content) { + not_yet_implemented_custom_text(r#""NOT_YET_IMPLEMENTED" "IMPLICIT_CONCATENATION""#) + .fmt(f) + } else { + FormatStringPart::new(self.string_range).fmt(f) + } + } +} + +struct FormatStringPart { + part_range: TextRange, +} + +impl FormatStringPart { + const fn new(range: TextRange) -> Self { + Self { part_range: range } + } +} + +impl Format> for FormatStringPart { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + let string_content = f.context().locator().slice(self.part_range); + + let prefix = StringPrefix::parse(string_content); + let after_prefix = &string_content[usize::from(prefix.text_len())..]; + + let quotes = StringQuotes::parse(after_prefix).ok_or(FormatError::SyntaxError)?; + let relative_raw_content_range = TextRange::new( + prefix.text_len() + quotes.text_len(), + string_content.text_len() - quotes.text_len(), + ); + let raw_content_range = relative_raw_content_range + self.part_range.start(); + + let raw_content = &string_content[relative_raw_content_range]; + let (preferred_quotes, contains_newlines) = preferred_quotes(raw_content, quotes); + + write!(f, [prefix, preferred_quotes])?; + + let normalized = normalize_quotes(raw_content, preferred_quotes); + + match normalized { + Cow::Borrowed(_) => { + source_text_slice(raw_content_range, contains_newlines).fmt(f)?; + } + Cow::Owned(normalized) => { + dynamic_text(&normalized, Some(raw_content_range.start())).fmt(f)?; + } + } + + preferred_quotes.fmt(f) + } +} + +bitflags! { + #[derive(Copy, Clone, Debug)] + struct StringPrefix: u8 { + const UNICODE = 0b0000_0001; + /// `r"test"` + const RAW = 0b0000_0010; + /// `R"test" + const RAW_UPPER = 0b0000_0100; + const BYTE = 0b0000_1000; + const F_STRING = 0b0001_0000; + } +} + +impl StringPrefix { + fn parse(input: &str) -> StringPrefix { + let chars = input.chars(); + let mut prefix = StringPrefix::empty(); + + for c in chars { + let flag = match c { + 'u' | 'U' => StringPrefix::UNICODE, + 'f' | 'F' => StringPrefix::F_STRING, + 'b' | 'B' => StringPrefix::BYTE, + 'r' => StringPrefix::RAW, + 'R' => StringPrefix::RAW_UPPER, + '\'' | '"' => break, + c => { + unreachable!( + "Unexpected character '{c}' terminating the prefix of a string literal" + ); + } + }; + + prefix |= flag; + } + + prefix + } + + const fn text_len(self) -> TextSize { + TextSize::new(self.bits().count_ones()) + } +} + +impl Format> for StringPrefix { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + // Retain the casing for the raw prefix: + // https://black.readthedocs.io/en/stable/the_black_code_style/current_style.html#r-strings-and-r-strings + if self.contains(StringPrefix::RAW) { + text("r").fmt(f)?; + } else if self.contains(StringPrefix::RAW_UPPER) { + text("R").fmt(f)?; + } + + if self.contains(StringPrefix::BYTE) { + text("b").fmt(f)?; + } + + if self.contains(StringPrefix::F_STRING) { + text("f").fmt(f)?; + } + + // Remove the unicode prefix `u` if any because it is meaningless in Python 3+. + + Ok(()) + } +} + +/// Detects the preferred quotes for `input`. +/// * single quoted strings: The preferred quote style is the one that requires less escape sequences. +/// * triple quoted strings: Use double quotes except the string contains a sequence of `"""`. +fn preferred_quotes(input: &str, quotes: StringQuotes) -> (StringQuotes, ContainsNewlines) { + let mut contains_newlines = ContainsNewlines::No; + + let preferred_style = if quotes.triple { + let mut use_single_quotes = false; + let mut chars = input.chars().peekable(); + + while let Some(c) = chars.next() { + match c { + '\n' | '\r' => contains_newlines = ContainsNewlines::Yes, + '\\' => { + if matches!(chars.peek(), Some('"' | '\\')) { + chars.next(); + } + } + '"' => { + match chars.peek().copied() { + Some('"') => { + // `""` + chars.next(); + + if chars.peek().copied() == Some('"') { + // `"""` + chars.next(); + use_single_quotes = true; + } + } + Some(_) => { + // Single quote, this is ok + } + None => { + // Trailing quote at the end of the comment + use_single_quotes = true; + } + } + } + _ => continue, + } + } + + if use_single_quotes { + QuoteStyle::Single + } else { + QuoteStyle::Double + } + } else { + let mut single_quotes = 0u32; + let mut double_quotes = 0u32; + + for c in input.chars() { + match c { + '\'' => { + single_quotes += 1; + } + + '"' => { + double_quotes += 1; + } + + '\n' | '\r' => { + contains_newlines = ContainsNewlines::Yes; + } + + _ => continue, + } + } + + if double_quotes > single_quotes { + QuoteStyle::Single + } else { + QuoteStyle::Double + } + }; + + ( + StringQuotes { + triple: quotes.triple, + style: preferred_style, + }, + contains_newlines, + ) +} + +#[derive(Copy, Clone, Debug)] +struct StringQuotes { + triple: bool, + style: QuoteStyle, +} + +impl StringQuotes { + fn parse(input: &str) -> Option { + let mut chars = input.chars(); + + let quote_char = chars.next()?; + let style = QuoteStyle::try_from(quote_char).ok()?; + + let triple = chars.next() == Some(quote_char) && chars.next() == Some(quote_char); + + Some(Self { triple, style }) + } + + const fn text_len(self) -> TextSize { + if self.triple { + TextSize::new(3) + } else { + TextSize::new(1) + } + } +} + +impl Format> for StringQuotes { + fn fmt(&self, f: &mut Formatter>) -> FormatResult<()> { + let quotes = match (self.style, self.triple) { + (QuoteStyle::Single, false) => "'", + (QuoteStyle::Single, true) => "'''", + (QuoteStyle::Double, false) => "\"", + (QuoteStyle::Double, true) => "\"\"\"", + }; + + text(quotes).fmt(f) + } +} + +/// Adds the necessary quote escapes and removes unnecessary escape sequences when quoting `input` +/// with the provided `style`. +fn normalize_quotes(input: &str, quotes: StringQuotes) -> Cow { + if quotes.triple { + Cow::Borrowed(input) + } else { + // The normalized string if `input` is not yet normalized. + // `output` must remain empty if `input` is already normalized. + let mut output = String::new(); + // Tracks the last index of `input` that has been written to `output`. + // If `last_index` is `0` at the end, then the input is already normalized and can be returned as is. + let mut last_index = 0; + + let style = quotes.style; + let preferred_quote = style.as_char(); + let opposite_quote = style.opposite().as_char(); + + let mut chars = input.char_indices(); + + while let Some((index, c)) = chars.next() { + if c == '\\' { + if let Some((_, next)) = chars.next() { + if next == opposite_quote { + // Remove the escape by ending before the backslash and starting again with the quote + output.push_str(&input[last_index..index]); + last_index = index + '\\'.len_utf8(); + } + } + } else if c == preferred_quote { + // Escape the quote + output.push_str(&input[last_index..index]); + output.push('\\'); + output.push(c); + last_index = index + preferred_quote.len_utf8(); + } + } + + if last_index == 0 { + Cow::Borrowed(input) + } else { + output.push_str(&input[last_index..]); + Cow::Owned(output) + } + } +} diff --git a/crates/ruff_python_formatter/src/lib.rs b/crates/ruff_python_formatter/src/lib.rs index 0faf824f09..790b08faa9 100644 --- a/crates/ruff_python_formatter/src/lib.rs +++ b/crates/ruff_python_formatter/src/lib.rs @@ -226,6 +226,41 @@ impl Format> for VerbatimText { } } +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +pub enum QuoteStyle { + Single, + Double, +} + +impl QuoteStyle { + pub const fn as_char(self) -> char { + match self { + QuoteStyle::Single => '\'', + QuoteStyle::Double => '"', + } + } + + #[must_use] + pub const fn opposite(self) -> QuoteStyle { + match self { + QuoteStyle::Single => QuoteStyle::Double, + QuoteStyle::Double => QuoteStyle::Single, + } + } +} + +impl TryFrom for QuoteStyle { + type Error = (); + + fn try_from(value: char) -> std::result::Result { + match value { + '\'' => Ok(QuoteStyle::Single), + '"' => Ok(QuoteStyle::Double), + _ => Err(()), + } + } +} + #[cfg(test)] mod tests { use anyhow::Result; @@ -342,29 +377,8 @@ if True: let printed = format_module(&content)?; let formatted_code = printed.as_code(); - let reformatted = - format_module(formatted_code).unwrap_or_else(|err| panic!("Expected formatted code to be valid syntax but it contains syntax errors: {err}\n{formatted_code}")); - ensure_stability_when_formatting_twice(formatted_code); - if reformatted.as_code() != formatted_code { - let diff = TextDiff::from_lines(formatted_code, reformatted.as_code()) - .unified_diff() - .header("Formatted once", "Formatted twice") - .to_string(); - panic!( - r#"Reformatting the formatted code a second time resulted in formatting changes. -{diff} - -Formatted once: -{formatted_code} - -Formatted twice: -{}"#, - reformatted.as_code() - ); - } - let snapshot = format!( r#"## Input {} diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__bracketmatch_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__bracketmatch_py.snap index a04acefcee..548945997c 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__bracketmatch_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__bracketmatch_py.snap @@ -20,8 +20,7 @@ lambda x=lambda y={1: 3}: y['x':lambda y: {1: 2}]: x --- Black +++ Ruff @@ -1,4 +1,4 @@ --for ((x in {}) or {})["a"] in x: -+for ((x in {}) or {})["NOT_YET_IMPLEMENTED_STRING"] in x: + for ((x in {}) or {})["a"] in x: pass -pem_spam = lambda l, spam={"x": 3}: not spam.get(l.strip()) -lambda x=lambda y={1: 3}: y["x" : lambda y: {1: 2}]: x @@ -32,7 +31,7 @@ lambda x=lambda y={1: 3}: y['x':lambda y: {1: 2}]: x ## Ruff Output ```py -for ((x in {}) or {})["NOT_YET_IMPLEMENTED_STRING"] in x: +for ((x in {}) or {})["a"] in x: pass pem_spam = lambda x: True lambda x: True diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__class_methods_new_line_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__class_methods_new_line_py.snap index 3ea7548946..d519958e1a 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__class_methods_new_line_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__class_methods_new_line_py.snap @@ -113,91 +113,38 @@ class ClassWithDecoInitAndVarsAndDocstringWithInner2: ```diff --- Black +++ Ruff -@@ -7,7 +7,7 @@ - - - class ClassWithJustTheDocstring: -- """Just a docstring.""" -+ "NOT_YET_IMPLEMENTED_STRING" - - - class ClassWithInit: -@@ -16,7 +16,7 @@ - - - class ClassWithTheDocstringAndInit: -- """Just a docstring.""" -+ "NOT_YET_IMPLEMENTED_STRING" - - def __init__(self): - pass -@@ -30,8 +30,7 @@ - +@@ -31,7 +31,6 @@ class ClassWithInitAndVarsAndDocstring: -- """Test class""" + """Test class""" - -+ "NOT_YET_IMPLEMENTED_STRING" cls_var = 100 def __init__(self): -@@ -53,8 +52,7 @@ - +@@ -54,7 +53,6 @@ class ClassWithDecoInitAndVarsAndDocstring: -- """Test class""" + """Test class""" - -+ "NOT_YET_IMPLEMENTED_STRING" cls_var = 100 @deco -@@ -69,7 +67,7 @@ - - class ClassSimplestWithInnerWithDocstring: - class Inner: -- """Just a docstring.""" -+ "NOT_YET_IMPLEMENTED_STRING" - - def __init__(self): - pass -@@ -83,7 +81,7 @@ - - - class ClassWithJustTheDocstringWithInner: -- """Just a docstring.""" -+ "NOT_YET_IMPLEMENTED_STRING" - - class Inner: - pass -@@ -108,8 +106,7 @@ - +@@ -109,7 +107,6 @@ class ClassWithInitAndVarsAndDocstringWithInner: -- """Test class""" + """Test class""" - -+ "NOT_YET_IMPLEMENTED_STRING" cls_var = 100 class Inner: -@@ -140,8 +137,7 @@ - +@@ -141,7 +138,6 @@ class ClassWithDecoInitAndVarsAndDocstringWithInner: -- """Test class""" + """Test class""" - -+ "NOT_YET_IMPLEMENTED_STRING" cls_var = 100 class Inner: -@@ -153,7 +149,7 @@ - - - class ClassWithDecoInitAndVarsAndDocstringWithInner2: -- """Test class""" -+ "NOT_YET_IMPLEMENTED_STRING" - - class Inner: - pass ``` ## Ruff Output @@ -212,7 +159,7 @@ class ClassWithSingleField: class ClassWithJustTheDocstring: - "NOT_YET_IMPLEMENTED_STRING" + """Just a docstring.""" class ClassWithInit: @@ -221,7 +168,7 @@ class ClassWithInit: class ClassWithTheDocstringAndInit: - "NOT_YET_IMPLEMENTED_STRING" + """Just a docstring.""" def __init__(self): pass @@ -235,7 +182,7 @@ class ClassWithInitAndVars: class ClassWithInitAndVarsAndDocstring: - "NOT_YET_IMPLEMENTED_STRING" + """Test class""" cls_var = 100 def __init__(self): @@ -257,7 +204,7 @@ class ClassWithDecoInitAndVars: class ClassWithDecoInitAndVarsAndDocstring: - "NOT_YET_IMPLEMENTED_STRING" + """Test class""" cls_var = 100 @deco @@ -272,7 +219,7 @@ class ClassSimplestWithInner: class ClassSimplestWithInnerWithDocstring: class Inner: - "NOT_YET_IMPLEMENTED_STRING" + """Just a docstring.""" def __init__(self): pass @@ -286,7 +233,7 @@ class ClassWithSingleFieldWithInner: class ClassWithJustTheDocstringWithInner: - "NOT_YET_IMPLEMENTED_STRING" + """Just a docstring.""" class Inner: pass @@ -311,7 +258,7 @@ class ClassWithInitAndVarsWithInner: class ClassWithInitAndVarsAndDocstringWithInner: - "NOT_YET_IMPLEMENTED_STRING" + """Test class""" cls_var = 100 class Inner: @@ -342,7 +289,7 @@ class ClassWithDecoInitAndVarsWithInner: class ClassWithDecoInitAndVarsAndDocstringWithInner: - "NOT_YET_IMPLEMENTED_STRING" + """Test class""" cls_var = 100 class Inner: @@ -354,7 +301,7 @@ class ClassWithDecoInitAndVarsAndDocstringWithInner: class ClassWithDecoInitAndVarsAndDocstringWithInner2: - "NOT_YET_IMPLEMENTED_STRING" + """Test class""" class Inner: pass diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__collections_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__collections_py.snap index 4dd883ec2f..1c961a36e7 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__collections_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__collections_py.snap @@ -84,7 +84,7 @@ if True: ```diff --- Black +++ Ruff -@@ -1,61 +1,40 @@ +@@ -1,40 +1,22 @@ -import core, time, a +NOT_YET_IMPLEMENTED_StmtImport @@ -133,29 +133,10 @@ if True: +nested = {(1, 2, 3), (4, 5, 6)} nested_no_trailing_comma = {(1, 2, 3), (4, 5, 6)} nested_long_lines = [ -- "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", -- "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", -- "cccccccccccccccccccccccccccccccccccccccc", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", - (1, 2, 3), -- "dddddddddddddddddddddddddddddddddddddddd", -+ "NOT_YET_IMPLEMENTED_STRING", - ] - { -- "oneple": (1,), -+ "NOT_YET_IMPLEMENTED_STRING": (1,), - } --{"oneple": (1,)} --["ls", "lsoneple/%s" % (foo,)] --x = {"oneple": (1,)} -+{"NOT_YET_IMPLEMENTED_STRING": (1,)} -+["NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING" % (foo,)] -+x = {"NOT_YET_IMPLEMENTED_STRING": (1,)} + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", +@@ -52,10 +34,7 @@ y = { -- "oneple": (1,), -+ "NOT_YET_IMPLEMENTED_STRING": (1,), + "oneple": (1,), } -assert False, ( - "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa wraps %s" @@ -233,20 +214,20 @@ y = (NOT_IMPLEMENTED_call(),) nested = {(1, 2, 3), (4, 5, 6)} nested_no_trailing_comma = {(1, 2, 3), (4, 5, 6)} nested_long_lines = [ - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb", + "cccccccccccccccccccccccccccccccccccccccc", (1, 2, 3), - "NOT_YET_IMPLEMENTED_STRING", + "dddddddddddddddddddddddddddddddddddddddd", ] { - "NOT_YET_IMPLEMENTED_STRING": (1,), + "oneple": (1,), } -{"NOT_YET_IMPLEMENTED_STRING": (1,)} -["NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING" % (foo,)] -x = {"NOT_YET_IMPLEMENTED_STRING": (1,)} +{"oneple": (1,)} +["ls", "lsoneple/%s" % (foo,)] +x = {"oneple": (1,)} y = { - "NOT_YET_IMPLEMENTED_STRING": (1,), + "oneple": (1,), } NOT_YET_IMPLEMENTED_StmtAssert diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments2_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments2_py.snap index 6e43e9b850..07c15327b0 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments2_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments2_py.snap @@ -178,7 +178,7 @@ instruction()#comment with bad spacing ```diff --- Black +++ Ruff -@@ -1,31 +1,27 @@ +@@ -1,9 +1,5 @@ -from com.my_lovely_company.my_lovely_team.my_lovely_project.my_lovely_component import ( - MyLovelyCompanyTeamProjectComponent, # NOT DRY -) @@ -190,43 +190,6 @@ instruction()#comment with bad spacing # Please keep __all__ alphabetized within each category. - __all__ = [ - # Super-special typing primitives. -- "Any", -- "Callable", -- "ClassVar", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", - # ABCs (from collections.abc). -- "AbstractSet", # collections.abc.Set. -- "ByteString", -- "Container", -+ "NOT_YET_IMPLEMENTED_STRING", # collections.abc.Set. -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", - # Concrete collection types. -- "Counter", -- "Deque", -- "Dict", -- "DefaultDict", -- "List", -- "Set", -- "FrozenSet", -- "NamedTuple", # Not really a type. -- "Generator", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", # Not really a type. -+ "NOT_YET_IMPLEMENTED_STRING", - ] - - not_shareables = [ @@ -37,31 +33,35 @@ # builtin types and objects type, @@ -237,8 +200,7 @@ instruction()#comment with bad spacing + NOT_IMPLEMENTED_call(), 42, 100.0, -- "spam", -+ "NOT_YET_IMPLEMENTED_STRING", + "spam", # user-defined types and objects Cheese, - Cheese("Wensleydale"), @@ -247,9 +209,8 @@ instruction()#comment with bad spacing + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), ] --if "PYTHON" in os.environ: + if "PYTHON" in os.environ: - add_compiler(compiler_from_env()) -+if "NOT_YET_IMPLEMENTED_STRING" in os.environ: + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) else: # for compiler in compilers.values(): @@ -400,23 +361,23 @@ NOT_YET_IMPLEMENTED_StmtImportFrom __all__ = [ # Super-special typing primitives. - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", + "Any", + "Callable", + "ClassVar", # ABCs (from collections.abc). - "NOT_YET_IMPLEMENTED_STRING", # collections.abc.Set. - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", + "AbstractSet", # collections.abc.Set. + "ByteString", + "Container", # Concrete collection types. - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", # Not really a type. - "NOT_YET_IMPLEMENTED_STRING", + "Counter", + "Deque", + "Dict", + "DefaultDict", + "List", + "Set", + "FrozenSet", + "NamedTuple", # Not really a type. + "Generator", ] not_shareables = [ @@ -432,14 +393,14 @@ not_shareables = [ NOT_IMPLEMENTED_call(), 42, 100.0, - "NOT_YET_IMPLEMENTED_STRING", + "spam", # user-defined types and objects Cheese, NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), ] -if "NOT_YET_IMPLEMENTED_STRING" in os.environ: +if "PYTHON" in os.environ: NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) else: # for compiler in compilers.values(): diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments3_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments3_py.snap index ef02e64a10..73e02a1e27 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments3_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments3_py.snap @@ -61,13 +61,10 @@ def func(): ```diff --- Black +++ Ruff -@@ -3,46 +3,17 @@ - - # %% - def func(): -- x = """ -- a really long string -- """ +@@ -6,43 +6,16 @@ + x = """ + a really long string + """ - lcomp3 = [ - # This one is actually too long to fit in a single line. - element.split("\n", 1)[0] @@ -76,7 +73,6 @@ def func(): - # right - if element is not None - ] -+ x = "NOT_YET_IMPLEMENTED_STRING" + lcomp3 = [i for i in []] # Capture each of the exceptions in the MultiError along with each of their causes and contexts - if isinstance(exc_value, MultiError): @@ -123,7 +119,9 @@ def func(): # %% def func(): - x = "NOT_YET_IMPLEMENTED_STRING" + x = """ + a really long string + """ lcomp3 = [i for i in []] # Capture each of the exceptions in the MultiError along with each of their causes and contexts if NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg): diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments5_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments5_py.snap index 762929aa96..51320a8e86 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments5_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments5_py.snap @@ -144,13 +144,11 @@ if __name__ == "__main__": # leading function comment def decorated1(): ... -@@ -69,5 +63,5 @@ - ... +@@ -70,4 +64,4 @@ --if __name__ == "__main__": + if __name__ == "__main__": - main() -+if __name__ == "NOT_YET_IMPLEMENTED_STRING": + NOT_IMPLEMENTED_call() ``` @@ -222,7 +220,7 @@ def g(): ... -if __name__ == "NOT_YET_IMPLEMENTED_STRING": +if __name__ == "__main__": NOT_IMPLEMENTED_call() ``` diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments6_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments6_py.snap index abc2ecaafd..86c3b34f2d 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments6_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments6_py.snap @@ -180,7 +180,7 @@ aaaaaaaaaaaaa, bbbbbbbbb = map(list, map(itertools.chain.from_iterable, zip(*ite -result = ( # aaa - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -) -+result = "NOT_YET_IMPLEMENTED_STRING" # aaa ++result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # aaa -AAAAAAAAAAAAA = [AAAAAAAAAAAAA] + SHARED_AAAAAAAAAAAAA + USER_AAAAAAAAAAAAA + AAAAAAAAAAAAA # type: ignore +AAAAAAAAAAAAA = ( @@ -297,7 +297,7 @@ def func( c = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -result = "NOT_YET_IMPLEMENTED_STRING" # aaa +result = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" # aaa AAAAAAAAAAAAA = ( [AAAAAAAAAAAAA] diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments9_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments9_py.snap index 857ff11509..8ae0c972f4 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments9_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments9_py.snap @@ -152,15 +152,6 @@ def bar(): ```diff --- Black +++ Ruff -@@ -44,7 +44,7 @@ - - - class ClassWithDocstring: -- """A docstring.""" -+ "NOT_YET_IMPLEMENTED_STRING" - - - # Leading comment after a class with just a docstring @@ -59,7 +59,7 @@ @deco1 # leading 2 @@ -255,7 +246,7 @@ class MyClassWithComplexLeadingComments: class ClassWithDocstring: - "NOT_YET_IMPLEMENTED_STRING" + """A docstring.""" # Leading comment after a class with just a docstring diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments_non_breaking_space_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments_non_breaking_space_py.snap index 976fcc5d8f..6ff36ce6c3 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments_non_breaking_space_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments_non_breaking_space_py.snap @@ -32,7 +32,7 @@ def function(a:int=42): ```diff --- Black +++ Ruff -@@ -1,23 +1,15 @@ +@@ -1,22 +1,17 @@ -from .config import ( - ConfigTypeAttributes, - Int, @@ -54,11 +54,12 @@ def function(a:int=42): - """This docstring is already formatted - a - b -- """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ """ This docstring is already formatted ++ a ++ b + """ # There's a NBSP + 3 spaces before # And 4 spaces on the next line - pass ``` ## Ruff Output @@ -75,7 +76,10 @@ square = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) #  type: Optional[Square] def function(a: int = 42): - "NOT_YET_IMPLEMENTED_STRING" + """ This docstring is already formatted + a + b + """ # There's a NBSP + 3 spaces before # And 4 spaces on the next line pass diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments_py.snap index ae7d0c0315..cb44cb8f7f 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__comments_py.snap @@ -109,21 +109,15 @@ async def wat(): ```diff --- Black +++ Ruff -@@ -4,21 +4,15 @@ - # - # Has many lines. Many, many lines. - # Many, many, many lines. --"""Module docstring. -+"NOT_YET_IMPLEMENTED_STRING" - --Possibly also many, many lines. --""" -+NOT_YET_IMPLEMENTED_StmtImport -+NOT_YET_IMPLEMENTED_StmtImport +@@ -9,16 +9,13 @@ + Possibly also many, many lines. + """ -import os.path -import sys -- ++NOT_YET_IMPLEMENTED_StmtImport ++NOT_YET_IMPLEMENTED_StmtImport + -import a -from b.c import X # some noqa comment +NOT_YET_IMPLEMENTED_StmtImport @@ -137,15 +131,9 @@ async def wat(): # Some comment before a function. -@@ -30,25 +24,26 @@ - - - def function(default=None): -- """Docstring comes first. -- -- Possibly many lines. -- """ -+ "NOT_YET_IMPLEMENTED_STRING" +@@ -35,20 +32,24 @@ + Possibly many lines. + """ # FIXME: Some comment about why this function is crap but still in production. - import inner_imports + NOT_YET_IMPLEMENTED_StmtImport @@ -166,38 +154,14 @@ async def wat(): # Explains why we use global state. -GLOBAL_STATE = {"a": a(1), "b": a(2), "c": a(3)} +GLOBAL_STATE = { -+ "NOT_YET_IMPLEMENTED_STRING": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), -+ "NOT_YET_IMPLEMENTED_STRING": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), -+ "NOT_YET_IMPLEMENTED_STRING": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), ++ "a": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), ++ "b": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), ++ "c": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), +} # Another comment! -@@ -56,7 +51,7 @@ - - - class Foo: -- """Docstring for class Foo. Example from Sphinx docs.""" -+ "NOT_YET_IMPLEMENTED_STRING" - - #: Doc comment for class attribute Foo.bar. - #: It can have multiple lines. -@@ -65,32 +60,31 @@ - flox = 1.5 #: Doc comment for Foo.flox. One line only. - - baz = 2 -- """Docstring for class attribute Foo.baz.""" -+ "NOT_YET_IMPLEMENTED_STRING" - - def __init__(self): - #: Doc comment for instance attribute qux. - self.qux = 3 - - self.spam = 4 -- """Docstring for instance attribute spam.""" -+ "NOT_YET_IMPLEMENTED_STRING" - - +@@ -78,19 +79,18 @@ #'

This is pweave!

@@ -234,7 +198,10 @@ async def wat(): # # Has many lines. Many, many lines. # Many, many, many lines. -"NOT_YET_IMPLEMENTED_STRING" +"""Module docstring. + +Possibly also many, many lines. +""" NOT_YET_IMPLEMENTED_StmtImport NOT_YET_IMPLEMENTED_StmtImport @@ -254,7 +221,10 @@ y = 1 def function(default=None): - "NOT_YET_IMPLEMENTED_STRING" + """Docstring comes first. + + Possibly many lines. + """ # FIXME: Some comment about why this function is crap but still in production. NOT_YET_IMPLEMENTED_StmtImport @@ -270,9 +240,9 @@ def function(default=None): # Explains why we use global state. GLOBAL_STATE = { - "NOT_YET_IMPLEMENTED_STRING": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), - "NOT_YET_IMPLEMENTED_STRING": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), - "NOT_YET_IMPLEMENTED_STRING": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), + "a": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), + "b": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), + "c": NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), } @@ -281,7 +251,7 @@ GLOBAL_STATE = { class Foo: - "NOT_YET_IMPLEMENTED_STRING" + """Docstring for class Foo. Example from Sphinx docs.""" #: Doc comment for class attribute Foo.bar. #: It can have multiple lines. @@ -290,14 +260,14 @@ class Foo: flox = 1.5 #: Doc comment for Foo.flox. One line only. baz = 2 - "NOT_YET_IMPLEMENTED_STRING" + """Docstring for class attribute Foo.baz.""" def __init__(self): #: Doc comment for instance attribute qux. self.qux = 3 self.spam = 4 - "NOT_YET_IMPLEMENTED_STRING" + """Docstring for instance attribute spam.""" #'

This is pweave!

diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__composition_no_trailing_comma_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__composition_no_trailing_comma_py.snap index 56529790aa..f47fb08de7 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__composition_no_trailing_comma_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__composition_no_trailing_comma_py.snap @@ -194,7 +194,7 @@ class C: ```diff --- Black +++ Ruff -@@ -1,181 +1,46 @@ +@@ -1,159 +1,42 @@ class C: def test(self) -> None: - with patch("black.out", print): @@ -236,17 +236,11 @@ class C: - # Only send the first n items. - items=items[:num_items] - ) -- return ( -- 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s' -- % (test.name, test.filename, lineno, lname, err) + NOT_YET_IMPLEMENTED_StmtWith + xxxxxxxxxxxxxxxx = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ return "NOT_YET_IMPLEMENTED_STRING" % ( -+ test.name, -+ test.filename, -+ lineno, -+ lname, -+ err, + return ( + 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s' + % (test.name, test.filename, lineno, lname, err) ) def omitting_trailers(self) -> None: @@ -373,18 +367,19 @@ class C: + NOT_YET_IMPLEMENTED_StmtAssert - dis_c_instance_method = """\ -- %3d 0 LOAD_FAST 1 (x) -- 2 LOAD_CONST 1 (1) -- 4 COMPARE_OP 2 (==) -- 6 LOAD_FAST 0 (self) -- 8 STORE_ATTR 0 (x) -- 10 LOAD_CONST 0 (None) -- 12 RETURN_VALUE ++ dis_c_instance_method = ( ++ """\ + %3d 0 LOAD_FAST 1 (x) + 2 LOAD_CONST 1 (1) + 4 COMPARE_OP 2 (==) +@@ -161,21 +44,8 @@ + 8 STORE_ATTR 0 (x) + 10 LOAD_CONST 0 (None) + 12 RETURN_VALUE - """ % ( - _C.__init__.__code__.co_firstlineno + 1, -+ dis_c_instance_method = "NOT_YET_IMPLEMENTED_STRING" % ( -+ _C.__init__.__code__.co_firstlineno -+ + 1, ++ """ ++ % (_C.__init__.__code__.co_firstlineno + 1,) ) - assert ( @@ -411,12 +406,9 @@ class C: def test(self) -> None: NOT_YET_IMPLEMENTED_StmtWith xxxxxxxxxxxxxxxx = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - return "NOT_YET_IMPLEMENTED_STRING" % ( - test.name, - test.filename, - lineno, - lname, - err, + return ( + 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s' + % (test.name, test.filename, lineno, lname, err) ) def omitting_trailers(self) -> None: @@ -447,9 +439,17 @@ class C: NOT_YET_IMPLEMENTED_StmtAssert - dis_c_instance_method = "NOT_YET_IMPLEMENTED_STRING" % ( - _C.__init__.__code__.co_firstlineno - + 1, + dis_c_instance_method = ( + """\ + %3d 0 LOAD_FAST 1 (x) + 2 LOAD_CONST 1 (1) + 4 COMPARE_OP 2 (==) + 6 LOAD_FAST 0 (self) + 8 STORE_ATTR 0 (x) + 10 LOAD_CONST 0 (None) + 12 RETURN_VALUE + """ + % (_C.__init__.__code__.co_firstlineno + 1,) ) NOT_YET_IMPLEMENTED_StmtAssert diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__composition_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__composition_py.snap index 09dc5f7269..de890ccedd 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__composition_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__composition_py.snap @@ -194,7 +194,7 @@ class C: ```diff --- Black +++ Ruff -@@ -1,181 +1,46 @@ +@@ -1,159 +1,42 @@ class C: def test(self) -> None: - with patch("black.out", print): @@ -236,17 +236,11 @@ class C: - # Only send the first n items. - items=items[:num_items] - ) -- return ( -- 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s' -- % (test.name, test.filename, lineno, lname, err) + NOT_YET_IMPLEMENTED_StmtWith + xxxxxxxxxxxxxxxx = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -+ return "NOT_YET_IMPLEMENTED_STRING" % ( -+ test.name, -+ test.filename, -+ lineno, -+ lname, -+ err, + return ( + 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s' + % (test.name, test.filename, lineno, lname, err) ) def omitting_trailers(self) -> None: @@ -373,18 +367,19 @@ class C: + NOT_YET_IMPLEMENTED_StmtAssert - dis_c_instance_method = """\ -- %3d 0 LOAD_FAST 1 (x) -- 2 LOAD_CONST 1 (1) -- 4 COMPARE_OP 2 (==) -- 6 LOAD_FAST 0 (self) -- 8 STORE_ATTR 0 (x) -- 10 LOAD_CONST 0 (None) -- 12 RETURN_VALUE ++ dis_c_instance_method = ( ++ """\ + %3d 0 LOAD_FAST 1 (x) + 2 LOAD_CONST 1 (1) + 4 COMPARE_OP 2 (==) +@@ -161,21 +44,8 @@ + 8 STORE_ATTR 0 (x) + 10 LOAD_CONST 0 (None) + 12 RETURN_VALUE - """ % ( - _C.__init__.__code__.co_firstlineno + 1, -+ dis_c_instance_method = "NOT_YET_IMPLEMENTED_STRING" % ( -+ _C.__init__.__code__.co_firstlineno -+ + 1, ++ """ ++ % (_C.__init__.__code__.co_firstlineno + 1,) ) - assert ( @@ -411,12 +406,9 @@ class C: def test(self) -> None: NOT_YET_IMPLEMENTED_StmtWith xxxxxxxxxxxxxxxx = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - return "NOT_YET_IMPLEMENTED_STRING" % ( - test.name, - test.filename, - lineno, - lname, - err, + return ( + 'Utterly failed doctest test for %s\n File "%s", line %s, in %s\n\n%s' + % (test.name, test.filename, lineno, lname, err) ) def omitting_trailers(self) -> None: @@ -447,9 +439,17 @@ class C: NOT_YET_IMPLEMENTED_StmtAssert - dis_c_instance_method = "NOT_YET_IMPLEMENTED_STRING" % ( - _C.__init__.__code__.co_firstlineno - + 1, + dis_c_instance_method = ( + """\ + %3d 0 LOAD_FAST 1 (x) + 2 LOAD_CONST 1 (1) + 4 COMPARE_OP 2 (==) + 6 LOAD_FAST 0 (self) + 8 STORE_ATTR 0 (x) + 10 LOAD_CONST 0 (None) + 12 RETURN_VALUE + """ + % (_C.__init__.__code__.co_firstlineno + 1,) ) NOT_YET_IMPLEMENTED_StmtAssert diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__docstring_no_extra_empty_line_before_eof_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__docstring_no_extra_empty_line_before_eof_py.snap deleted file mode 100644 index d56f37ee25..0000000000 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__docstring_no_extra_empty_line_before_eof_py.snap +++ /dev/null @@ -1,46 +0,0 @@ ---- -source: crates/ruff_python_formatter/src/lib.rs -expression: snapshot -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/simple_cases/docstring_no_extra_empty_line_before_eof.py ---- -## Input - -```py -# Make sure when the file ends with class's docstring, -# It doesn't add extra blank lines. -class ClassWithDocstring: - """A docstring.""" -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -1,4 +1,4 @@ - # Make sure when the file ends with class's docstring, - # It doesn't add extra blank lines. - class ClassWithDocstring: -- """A docstring.""" -+ "NOT_YET_IMPLEMENTED_STRING" -``` - -## Ruff Output - -```py -# Make sure when the file ends with class's docstring, -# It doesn't add extra blank lines. -class ClassWithDocstring: - "NOT_YET_IMPLEMENTED_STRING" -``` - -## Black Output - -```py -# Make sure when the file ends with class's docstring, -# It doesn't add extra blank lines. -class ClassWithDocstring: - """A docstring.""" -``` - - diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__docstring_preview_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__docstring_preview_py.snap index 08eea3e67f..296bb4715d 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__docstring_preview_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__docstring_preview_py.snap @@ -63,10 +63,11 @@ def single_quote_docstring_over_line_limit2(): ```diff --- Black +++ Ruff -@@ -1,48 +1,38 @@ +@@ -1,9 +1,10 @@ def docstring_almost_at_line_limit(): - """long docstring.................................................................""" -+ "NOT_YET_IMPLEMENTED_STRING" ++ """long docstring................................................................. ++ """ def docstring_almost_at_line_limit_with_prefix(): @@ -75,11 +76,7 @@ def single_quote_docstring_over_line_limit2(): def mulitline_docstring_almost_at_line_limit(): -- """long docstring................................................................. -- -- .................................................................................. -- """ -+ "NOT_YET_IMPLEMENTED_STRING" +@@ -14,10 +15,7 @@ def mulitline_docstring_almost_at_line_limit_with_prefix(): @@ -91,8 +88,7 @@ def single_quote_docstring_over_line_limit2(): def docstring_at_line_limit(): -- """long docstring................................................................""" -+ "NOT_YET_IMPLEMENTED_STRING" +@@ -25,7 +23,7 @@ def docstring_at_line_limit_with_prefix(): @@ -101,10 +97,7 @@ def single_quote_docstring_over_line_limit2(): def multiline_docstring_at_line_limit(): -- """first line----------------------------------------------------------------------- -- -- second line----------------------------------------------------------------------""" -+ "NOT_YET_IMPLEMENTED_STRING" +@@ -35,9 +33,7 @@ def multiline_docstring_at_line_limit_with_prefix(): @@ -115,20 +108,14 @@ def single_quote_docstring_over_line_limit2(): def single_quote_docstring_over_line_limit(): -- "We do not want to put the closing quote on a new line as that is invalid (see GH-3141)." -+ "NOT_YET_IMPLEMENTED_STRING" - - - def single_quote_docstring_over_line_limit2(): -- "We do not want to put the closing quote on a new line as that is invalid (see GH-3141)." -+ "NOT_YET_IMPLEMENTED_STRING" ``` ## Ruff Output ```py def docstring_almost_at_line_limit(): - "NOT_YET_IMPLEMENTED_STRING" + """long docstring................................................................. + """ def docstring_almost_at_line_limit_with_prefix(): @@ -136,7 +123,10 @@ def docstring_almost_at_line_limit_with_prefix(): def mulitline_docstring_almost_at_line_limit(): - "NOT_YET_IMPLEMENTED_STRING" + """long docstring................................................................. + + .................................................................................. + """ def mulitline_docstring_almost_at_line_limit_with_prefix(): @@ -144,7 +134,7 @@ def mulitline_docstring_almost_at_line_limit_with_prefix(): def docstring_at_line_limit(): - "NOT_YET_IMPLEMENTED_STRING" + """long docstring................................................................""" def docstring_at_line_limit_with_prefix(): @@ -152,7 +142,9 @@ def docstring_at_line_limit_with_prefix(): def multiline_docstring_at_line_limit(): - "NOT_YET_IMPLEMENTED_STRING" + """first line----------------------------------------------------------------------- + + second line----------------------------------------------------------------------""" def multiline_docstring_at_line_limit_with_prefix(): @@ -160,11 +152,11 @@ def multiline_docstring_at_line_limit_with_prefix(): def single_quote_docstring_over_line_limit(): - "NOT_YET_IMPLEMENTED_STRING" + "We do not want to put the closing quote on a new line as that is invalid (see GH-3141)." def single_quote_docstring_over_line_limit2(): - "NOT_YET_IMPLEMENTED_STRING" + "We do not want to put the closing quote on a new line as that is invalid (see GH-3141)." ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__docstring_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__docstring_py.snap index 784587197d..da177f0353 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__docstring_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__docstring_py.snap @@ -234,18 +234,21 @@ def stable_quote_normalization_with_immediate_inner_single_quote(self): ```diff --- Black +++ Ruff -@@ -1,219 +1,154 @@ +@@ -1,83 +1,85 @@ class MyClass: - """Multiline - class docstring - """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ """ Multiline ++ class docstring ++ """ def method(self): -- """Multiline + """Multiline - method docstring - """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ method docstring ++ """ pass @@ -253,46 +256,53 @@ def stable_quote_normalization_with_immediate_inner_single_quote(self): - """This is a docstring with - some lines of text here - """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ """This is a docstring with ++ some lines of text here ++ """ return def bar(): -- """This is another docstring + """This is another docstring - with more lines of text - """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ with more lines of text ++ """ return def baz(): -- '''"This" is a string with some + '''"This" is a string with some - embedded "quotes"''' -+ "NOT_YET_IMPLEMENTED_STRING" ++ embedded "quotes"''' return def troz(): -- """Indentation with tabs + """Indentation with tabs - is just as OK - """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ is just as OK ++ """ return def zort(): -- """Another + """Another - multiline - docstring - """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ multiline ++ docstring ++ """ pass def poit(): -- """ + """ - Lorem ipsum dolor sit amet. -- ++ Lorem ipsum dolor sit amet. + - Consectetur adipiscing elit: - - sed do eiusmod tempor incididunt ut labore - - dolore magna aliqua @@ -300,112 +310,117 @@ def stable_quote_normalization_with_immediate_inner_single_quote(self): - - quis nostrud exercitation ullamco laboris nisi - - aliquip ex ea commodo consequat - """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ Consectetur adipiscing elit: ++ - sed do eiusmod tempor incididunt ut labore ++ - dolore magna aliqua ++ - enim ad minim veniam ++ - quis nostrud exercitation ullamco laboris nisi ++ - aliquip ex ea commodo consequat ++ """ pass def under_indent(): -- """ + """ - These lines are indented in a way that does not - make sense. - """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ These lines are indented in a way that does not ++make sense. ++ """ pass def over_indent(): -- """ + """ - This has a shallow indent - - But some lines are deeper - - And the closing quote is too deep -- """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ This has a shallow indent ++ - But some lines are deeper ++ - And the closing quote is too deep + """ pass def single_line(): - """But with a newline after it!""" -+ "NOT_YET_IMPLEMENTED_STRING" ++ """But with a newline after it! ++ ++ """ pass - def this(): -- r""" -- 'hey ho' -- """ -+ "NOT_YET_IMPLEMENTED_STRING" - - - def that(): -- """ "hey yah" """ -+ "NOT_YET_IMPLEMENTED_STRING" - +@@ -93,20 +95,25 @@ def and_that(): -- """ + """ - "hey yah" """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ "hey yah" """ def and_this(): - ''' - "hey yah"''' -+ "NOT_YET_IMPLEMENTED_STRING" ++ ''' ++ "hey yah"''' def multiline_whitespace(): - """ """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ """ ++ ++ ++ ++ ++ """ def oneline_whitespace(): - """ """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ """ """ def empty(): -- """""" -+ "NOT_YET_IMPLEMENTED_STRING" - - - def single_quotes(): -- "testing" -+ "NOT_YET_IMPLEMENTED_STRING" +@@ -118,8 +125,8 @@ def believe_it_or_not_this_is_in_the_py_stdlib(): - ''' - "hey yah"''' -+ "NOT_YET_IMPLEMENTED_STRING" ++ ''' ++"hey yah"''' def ignored_docstring(): -- """a => \ --b""" -+ "NOT_YET_IMPLEMENTED_STRING" +@@ -128,31 +135,31 @@ def single_line_docstring_with_whitespace(): - """This should be stripped""" -+ "NOT_YET_IMPLEMENTED_STRING" ++ """ This should be stripped """ def docstring_with_inline_tabs_and_space_indentation(): -- """hey -- -- tab separated value + """hey + + tab separated value - tab at start of line and then a tab separated value - multiple tabs at the beginning and inline - mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. -+ "NOT_YET_IMPLEMENTED_STRING" - +- - line ends with some tabs -- """ ++ tab at start of line and then a tab separated value ++ multiple tabs at the beginning and inline ++ mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. ++ ++ line ends with some tabs + """ + -- def docstring_with_inline_tabs_and_tab_indentation(): -- """hey -- + """hey + - tab separated value - tab at start of line and then a tab separated value - multiple tabs at the beginning and inline @@ -413,242 +428,274 @@ def stable_quote_normalization_with_immediate_inner_single_quote(self): - - line ends with some tabs - """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ tab separated value ++ tab at start of line and then a tab separated value ++ multiple tabs at the beginning and inline ++ mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. ++ ++ line ends with some tabs ++ """ pass - def backslash_space(): -- """\ """ -+ "NOT_YET_IMPLEMENTED_STRING" - - - def multiline_backslash_1(): -- """ -- hey\there\ -- \ """ -+ "NOT_YET_IMPLEMENTED_STRING" - +@@ -168,7 +175,7 @@ def multiline_backslash_2(): -- """ + """ - hey there \ """ -+ "NOT_YET_IMPLEMENTED_STRING" ++ hey there \ """ # Regression test for #3425 - def multiline_backslash_really_long_dont_crash(): -- """ -- hey there hello guten tag hi hoow are you ola zdravstvuyte ciao como estas ca va \ """ -+ "NOT_YET_IMPLEMENTED_STRING" - +@@ -179,7 +186,7 @@ def multiline_backslash_3(): -- """ + """ - already escaped \\""" -+ "NOT_YET_IMPLEMENTED_STRING" ++ already escaped \\ """ def my_god_its_full_of_stars_1(): -- "I'm sorry Dave\u2001" -+ "NOT_YET_IMPLEMENTED_STRING" - +@@ -188,7 +195,7 @@ # the space below is actually a \u2001, removed in output def my_god_its_full_of_stars_2(): - "I'm sorry Dave" -+ "NOT_YET_IMPLEMENTED_STRING" ++ "I'm sorry Dave " def docstring_almost_at_line_limit(): -- """long docstring.................................................................""" -+ "NOT_YET_IMPLEMENTED_STRING" - - - def docstring_almost_at_line_limit2(): -- """long docstring................................................................. -- -- .................................................................................. -- """ -+ "NOT_YET_IMPLEMENTED_STRING" - - - def docstring_at_line_limit(): -- """long docstring................................................................""" -+ "NOT_YET_IMPLEMENTED_STRING" - - - def multiline_docstring_at_line_limit(): -- """first line----------------------------------------------------------------------- -- -- second line----------------------------------------------------------------------""" -+ "NOT_YET_IMPLEMENTED_STRING" - - - def stable_quote_normalization_with_immediate_inner_single_quote(self): -- """' -- -- -- """ -+ "NOT_YET_IMPLEMENTED_STRING" ``` ## Ruff Output ```py class MyClass: - "NOT_YET_IMPLEMENTED_STRING" + """ Multiline + class docstring + """ def method(self): - "NOT_YET_IMPLEMENTED_STRING" + """Multiline + method docstring + """ pass def foo(): - "NOT_YET_IMPLEMENTED_STRING" + """This is a docstring with + some lines of text here + """ return def bar(): - "NOT_YET_IMPLEMENTED_STRING" + """This is another docstring + with more lines of text + """ return def baz(): - "NOT_YET_IMPLEMENTED_STRING" + '''"This" is a string with some + embedded "quotes"''' return def troz(): - "NOT_YET_IMPLEMENTED_STRING" + """Indentation with tabs + is just as OK + """ return def zort(): - "NOT_YET_IMPLEMENTED_STRING" + """Another + multiline + docstring + """ pass def poit(): - "NOT_YET_IMPLEMENTED_STRING" + """ + Lorem ipsum dolor sit amet. + + Consectetur adipiscing elit: + - sed do eiusmod tempor incididunt ut labore + - dolore magna aliqua + - enim ad minim veniam + - quis nostrud exercitation ullamco laboris nisi + - aliquip ex ea commodo consequat + """ pass def under_indent(): - "NOT_YET_IMPLEMENTED_STRING" + """ + These lines are indented in a way that does not +make sense. + """ pass def over_indent(): - "NOT_YET_IMPLEMENTED_STRING" + """ + This has a shallow indent + - But some lines are deeper + - And the closing quote is too deep + """ pass def single_line(): - "NOT_YET_IMPLEMENTED_STRING" + """But with a newline after it! + + """ pass def this(): - "NOT_YET_IMPLEMENTED_STRING" + r""" + 'hey ho' + """ def that(): - "NOT_YET_IMPLEMENTED_STRING" + """ "hey yah" """ def and_that(): - "NOT_YET_IMPLEMENTED_STRING" + """ + "hey yah" """ def and_this(): - "NOT_YET_IMPLEMENTED_STRING" + ''' + "hey yah"''' def multiline_whitespace(): - "NOT_YET_IMPLEMENTED_STRING" + """ + + + + + """ def oneline_whitespace(): - "NOT_YET_IMPLEMENTED_STRING" + """ """ def empty(): - "NOT_YET_IMPLEMENTED_STRING" + """""" def single_quotes(): - "NOT_YET_IMPLEMENTED_STRING" + "testing" def believe_it_or_not_this_is_in_the_py_stdlib(): - "NOT_YET_IMPLEMENTED_STRING" + ''' +"hey yah"''' def ignored_docstring(): - "NOT_YET_IMPLEMENTED_STRING" + """a => \ +b""" def single_line_docstring_with_whitespace(): - "NOT_YET_IMPLEMENTED_STRING" + """ This should be stripped """ def docstring_with_inline_tabs_and_space_indentation(): - "NOT_YET_IMPLEMENTED_STRING" + """hey + + tab separated value + tab at start of line and then a tab separated value + multiple tabs at the beginning and inline + mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. + + line ends with some tabs + """ def docstring_with_inline_tabs_and_tab_indentation(): - "NOT_YET_IMPLEMENTED_STRING" + """hey + + tab separated value + tab at start of line and then a tab separated value + multiple tabs at the beginning and inline + mixed tabs and spaces at beginning. next line has mixed tabs and spaces only. + + line ends with some tabs + """ pass def backslash_space(): - "NOT_YET_IMPLEMENTED_STRING" + """\ """ def multiline_backslash_1(): - "NOT_YET_IMPLEMENTED_STRING" + """ + hey\there\ + \ """ def multiline_backslash_2(): - "NOT_YET_IMPLEMENTED_STRING" + """ + hey there \ """ # Regression test for #3425 def multiline_backslash_really_long_dont_crash(): - "NOT_YET_IMPLEMENTED_STRING" + """ + hey there hello guten tag hi hoow are you ola zdravstvuyte ciao como estas ca va \ """ def multiline_backslash_3(): - "NOT_YET_IMPLEMENTED_STRING" + """ + already escaped \\ """ def my_god_its_full_of_stars_1(): - "NOT_YET_IMPLEMENTED_STRING" + "I'm sorry Dave\u2001" # the space below is actually a \u2001, removed in output def my_god_its_full_of_stars_2(): - "NOT_YET_IMPLEMENTED_STRING" + "I'm sorry Dave " def docstring_almost_at_line_limit(): - "NOT_YET_IMPLEMENTED_STRING" + """long docstring.................................................................""" def docstring_almost_at_line_limit2(): - "NOT_YET_IMPLEMENTED_STRING" + """long docstring................................................................. + + .................................................................................. + """ def docstring_at_line_limit(): - "NOT_YET_IMPLEMENTED_STRING" + """long docstring................................................................""" def multiline_docstring_at_line_limit(): - "NOT_YET_IMPLEMENTED_STRING" + """first line----------------------------------------------------------------------- + + second line----------------------------------------------------------------------""" def stable_quote_normalization_with_immediate_inner_single_quote(self): - "NOT_YET_IMPLEMENTED_STRING" + """' + + + """ ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__empty_lines_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__empty_lines_py.snap index 4bb4e71127..874c26f461 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__empty_lines_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__empty_lines_py.snap @@ -105,23 +105,7 @@ def g(): ```diff --- Black +++ Ruff -@@ -1,11 +1,11 @@ --"""Docstring.""" -+"NOT_YET_IMPLEMENTED_STRING" - - - # leading comment - def f(): -- NO = "" -- SPACE = " " -- DOUBLESPACE = " " -+ NO = "NOT_YET_IMPLEMENTED_STRING" -+ SPACE = "NOT_YET_IMPLEMENTED_STRING" -+ DOUBLESPACE = "NOT_YET_IMPLEMENTED_STRING" - - t = leaf.type - p = leaf.parent # trailing comment -@@ -16,44 +16,51 @@ +@@ -16,32 +16,40 @@ if t == token.COMMENT: # another trailing comment return DOUBLESPACE @@ -178,21 +162,14 @@ def g(): return NO - ############################################################################### +@@ -49,7 +57,6 @@ # SECTION BECAUSE SECTIONS ############################################################################### + - - def g(): -- NO = "" -- SPACE = " " -- DOUBLESPACE = " " -+ NO = "NOT_YET_IMPLEMENTED_STRING" -+ SPACE = "NOT_YET_IMPLEMENTED_STRING" -+ DOUBLESPACE = "NOT_YET_IMPLEMENTED_STRING" - - t = leaf.type - p = leaf.parent + NO = "" + SPACE = " " @@ -67,11 +74,11 @@ return DOUBLESPACE @@ -235,14 +212,14 @@ def g(): ## Ruff Output ```py -"NOT_YET_IMPLEMENTED_STRING" +"""Docstring.""" # leading comment def f(): - NO = "NOT_YET_IMPLEMENTED_STRING" - SPACE = "NOT_YET_IMPLEMENTED_STRING" - DOUBLESPACE = "NOT_YET_IMPLEMENTED_STRING" + NO = "" + SPACE = " " + DOUBLESPACE = " " t = leaf.type p = leaf.parent # trailing comment @@ -295,9 +272,9 @@ def f(): ############################################################################### def g(): - NO = "NOT_YET_IMPLEMENTED_STRING" - SPACE = "NOT_YET_IMPLEMENTED_STRING" - DOUBLESPACE = "NOT_YET_IMPLEMENTED_STRING" + NO = "" + SPACE = " " + DOUBLESPACE = " " t = leaf.type p = leaf.parent diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__expression_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__expression_py.snap index 57371f8bf4..d64a1abf8a 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__expression_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__expression_py.snap @@ -268,15 +268,14 @@ last_call() --- Black +++ Ruff @@ -1,5 +1,6 @@ --"some_string" --b"\\xa3" +... -+"NOT_YET_IMPLEMENTED_STRING" + "some_string" +-b"\\xa3" +b"NOT_YET_IMPLEMENTED_BYTE_STRING" Name None True -@@ -30,98 +31,90 @@ +@@ -30,98 +31,83 @@ -1 ~int and not v1 ^ 123 + v2 | True (~int) and (not ((v1 ^ (123 + v2)) | True)) @@ -303,8 +302,6 @@ last_call() - if (1 if super_long_test_name else 2) - else (str or bytes or None) -) --{"2.7": dead, "3.7": (long_live or die_hard)} --{"2.7": dead, "3.7": (long_live or die_hard), **{"3.6": verygood}} +lambda x: True +lambda x: True +lambda x: True @@ -318,31 +315,24 @@ last_call() +NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false +NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false +(NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false) -+{ -+ "NOT_YET_IMPLEMENTED_STRING": dead, -+ "NOT_YET_IMPLEMENTED_STRING": (long_live or die_hard), -+} -+{ -+ "NOT_YET_IMPLEMENTED_STRING": dead, -+ "NOT_YET_IMPLEMENTED_STRING": (long_live or die_hard), -+ **{"NOT_YET_IMPLEMENTED_STRING": verygood}, -+} + {"2.7": dead, "3.7": (long_live or die_hard)} + {"2.7": dead, "3.7": (long_live or die_hard), **{"3.6": verygood}} {**a, **b, **c} -{"2.7", "3.6", "3.7", "3.8", "3.9", ("4.0" if gilectomy else "3.10")} -({"a": "b"}, (True or False), (+value), "string", b"bytes") or None +{ -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", ++ "2.7", ++ "3.6", ++ "3.7", ++ "3.8", ++ "3.9", + (NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false), +} +( -+ {"NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING"}, ++ {"a": "b"}, + (True or False), + (+value), -+ "NOT_YET_IMPLEMENTED_STRING", ++ "string", + b"NOT_YET_IMPLEMENTED_BYTE_STRING", +) or None () @@ -363,17 +353,17 @@ last_call() - 4, - 5, -] --[ -- 4, -- *a, -- 5, --] +[1, 2, 3] +[NOT_YET_IMPLEMENTED_ExprStarred] +[NOT_YET_IMPLEMENTED_ExprStarred] +[NOT_YET_IMPLEMENTED_ExprStarred, 4, 5] +[4, NOT_YET_IMPLEMENTED_ExprStarred, 5] [ +- 4, +- *a, +- 5, +-] +-[ this_is_a_very_long_variable_which_will_force_a_delimiter_split, element, another, @@ -443,7 +433,7 @@ last_call() (1).real (1.0).real ....__class__ -@@ -130,34 +123,28 @@ +@@ -130,34 +116,28 @@ tuple[str, ...] tuple[str, int, float, dict[str, int]] tuple[ @@ -451,6 +441,9 @@ last_call() - int, - float, - dict[str, int], +-] +-very_long_variable_name_filters: t.List[ +- t.Tuple[str, t.Union[str, t.List[t.Optional[str]]]], + ( + str, + int, @@ -458,9 +451,6 @@ last_call() + dict[str, int], + ) ] --very_long_variable_name_filters: t.List[ -- t.Tuple[str, t.Union[str, t.List[t.Optional[str]]]], --] -xxxx_xxxxx_xxxx_xxx: Callable[..., List[SomeClass]] = classmethod( # type: ignore - sync(async_xxxx_xxx_xxxx_xxxxx_xxxx_xxx.__func__) -) @@ -491,7 +481,7 @@ last_call() numpy[0, :] numpy[:, i] numpy[0, :2] -@@ -171,62 +158,59 @@ +@@ -171,25 +151,32 @@ numpy[1 : c + 1, c] numpy[-(c + 1) :, d] numpy[:, l[-2]] @@ -499,19 +489,15 @@ last_call() +numpy[:, :: -1] numpy[np.newaxis, :] -(str or None) if (sys.version_info[0] > (3,)) else (str or bytes or None) --{"2.7": dead, "3.7": long_live or die_hard} --{"2.7", "3.6", "3.7", "3.8", "3.9", "4.0" if gilectomy else "3.10"} +NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false + {"2.7": dead, "3.7": long_live or die_hard} +-{"2.7", "3.6", "3.7", "3.8", "3.9", "4.0" if gilectomy else "3.10"} +{ -+ "NOT_YET_IMPLEMENTED_STRING": dead, -+ "NOT_YET_IMPLEMENTED_STRING": long_live or die_hard, -+} -+{ -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", ++ "2.7", ++ "3.6", ++ "3.7", ++ "3.8", ++ "3.9", + NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false, +} [1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C] @@ -529,22 +515,16 @@ last_call() +(i for i in []) +(NOT_YET_IMPLEMENTED_ExprStarred,) { -- "id": "1", -- "type": "type", + "id": "1", + "type": "type", - "started_at": now(), - "ended_at": now() + timedelta(days=10), -- "priority": 1, -- "import_session_id": 1, -+ "NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING": NOT_IMPLEMENTED_call(), -+ "NOT_YET_IMPLEMENTED_STRING": NOT_IMPLEMENTED_call() -+ + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), -+ "NOT_YET_IMPLEMENTED_STRING": 1, -+ "NOT_YET_IMPLEMENTED_STRING": 1, ++ "started_at": NOT_IMPLEMENTED_call(), ++ "ended_at": NOT_IMPLEMENTED_call() + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), + "priority": 1, + "import_session_id": 1, **kwargs, - } - a = (1,) +@@ -198,35 +185,21 @@ b = (1,) c = 1 d = (1,) + a + (2,) @@ -593,7 +573,7 @@ last_call() mapping = { A: 0.25 * (10.0 / 12), B: 0.1 * (10.0 / 12), -@@ -236,31 +220,29 @@ +@@ -236,31 +209,29 @@ def gen(): @@ -638,7 +618,7 @@ last_call() ... for j in 1 + (2 + 3): ... -@@ -272,7 +254,7 @@ +@@ -272,7 +243,7 @@ addr_proto, addr_canonname, addr_sockaddr, @@ -647,7 +627,7 @@ last_call() pass a = ( aaaa.bbbb.cccc.dddd.eeee.ffff.gggg.hhhh.iiii.jjjj.kkkk.llll.mmmm.nnnn.oooo.pppp -@@ -291,9 +273,9 @@ +@@ -291,9 +262,9 @@ is not qqqq.rrrr.ssss.tttt.uuuu.vvvv.xxxx.yyyy.zzzz ) if ( @@ -660,7 +640,7 @@ last_call() ): return True if ( -@@ -327,13 +309,18 @@ +@@ -327,13 +298,18 @@ ): return True if ( @@ -682,7 +662,7 @@ last_call() ^ aaaaaaaa.i << aaaaaaaa.k >> aaaaaaaa.l**aaaaaaaa.m // aaaaaaaa.n ): return True -@@ -341,7 +328,8 @@ +@@ -341,7 +317,8 @@ ~aaaaaaaaaaaaaaaa.a + aaaaaaaaaaaaaaaa.b - aaaaaaaaaaaaaaaa.c * aaaaaaaaaaaaaaaa.d @ aaaaaaaaaaaaaaaa.e @@ -692,7 +672,7 @@ last_call() ^ aaaaaaaaaaaaaaaa.i << aaaaaaaaaaaaaaaa.k >> aaaaaaaaaaaaaaaa.l**aaaaaaaaaaaaaaaa.m // aaaaaaaaaaaaaaaa.n -@@ -366,5 +354,5 @@ +@@ -366,5 +343,5 @@ ^ bbbb.a & aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ^ aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ) @@ -705,7 +685,7 @@ last_call() ```py ... -"NOT_YET_IMPLEMENTED_STRING" +"some_string" b"NOT_YET_IMPLEMENTED_BYTE_STRING" Name None @@ -752,29 +732,22 @@ NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false (NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false) -{ - "NOT_YET_IMPLEMENTED_STRING": dead, - "NOT_YET_IMPLEMENTED_STRING": (long_live or die_hard), -} -{ - "NOT_YET_IMPLEMENTED_STRING": dead, - "NOT_YET_IMPLEMENTED_STRING": (long_live or die_hard), - **{"NOT_YET_IMPLEMENTED_STRING": verygood}, -} +{"2.7": dead, "3.7": (long_live or die_hard)} +{"2.7": dead, "3.7": (long_live or die_hard), **{"3.6": verygood}} {**a, **b, **c} { - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", + "2.7", + "3.6", + "3.7", + "3.8", + "3.9", (NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false), } ( - {"NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING"}, + {"a": "b"}, (True or False), (+value), - "NOT_YET_IMPLEMENTED_STRING", + "string", b"NOT_YET_IMPLEMENTED_BYTE_STRING", ) or None () @@ -867,16 +840,13 @@ numpy[:, l[-2]] numpy[:, :: -1] numpy[np.newaxis, :] NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false +{"2.7": dead, "3.7": long_live or die_hard} { - "NOT_YET_IMPLEMENTED_STRING": dead, - "NOT_YET_IMPLEMENTED_STRING": long_live or die_hard, -} -{ - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", + "2.7", + "3.6", + "3.7", + "3.8", + "3.9", NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false, } [1, 2, 3, 4, 5, 6, 7, 8, 9, 10 or A, 11 or B, 12 or C] @@ -889,13 +859,12 @@ SomeName (i for i in []) (NOT_YET_IMPLEMENTED_ExprStarred,) { - "NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING": NOT_IMPLEMENTED_call(), - "NOT_YET_IMPLEMENTED_STRING": NOT_IMPLEMENTED_call() - + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), - "NOT_YET_IMPLEMENTED_STRING": 1, - "NOT_YET_IMPLEMENTED_STRING": 1, + "id": "1", + "type": "type", + "started_at": NOT_IMPLEMENTED_call(), + "ended_at": NOT_IMPLEMENTED_call() + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg), + "priority": 1, + "import_session_id": 1, **kwargs, } a = (1,) diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff2_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff2_py.snap index 8790bc64bf..076c32ce50 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff2_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff2_py.snap @@ -90,9 +90,8 @@ def test_calculate_fades(): + def verify_fader(test): -- """Hey, ho.""" + """Hey, ho.""" - assert test.passed() -+ "NOT_YET_IMPLEMENTED_STRING" + NOT_YET_IMPLEMENTED_StmtAssert + @@ -137,7 +136,7 @@ def verify_fader(test): def verify_fader(test): - "NOT_YET_IMPLEMENTED_STRING" + """Hey, ho.""" NOT_YET_IMPLEMENTED_StmtAssert diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff5_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff5_py.snap index b76dbc5ab7..55baa4ec3a 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff5_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff5_py.snap @@ -152,22 +152,20 @@ elif unformatted: # Regression test for https://github.com/psf/black/issues/3184. -@@ -53,28 +35,29 @@ +@@ -52,29 +34,27 @@ + async def call(param): if param: # fmt: off - if param[0:4] in ( +- if param[0:4] in ( - "ABCD", "EFGH" - ) : -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ ): ++ if param[0:4] in ("ABCD", "EFGH"): # fmt: on - print ( "This won't be formatted" ) + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -- elif param[0:4] in ("ZZZZ",): + elif param[0:4] in ("ZZZZ",): - print ( "This won't be formatted either" ) -+ elif param[0:4] in ("NOT_YET_IMPLEMENTED_STRING",): + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - print("This will be formatted") @@ -190,7 +188,7 @@ elif unformatted: # fmt: on -@@ -82,6 +65,6 @@ +@@ -82,6 +62,6 @@ if x: return x # fmt: off @@ -240,14 +238,11 @@ class A: async def call(param): if param: # fmt: off - if param[0:4] in ( - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - ): + if param[0:4] in ("ABCD", "EFGH"): # fmt: on NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - elif param[0:4] in ("NOT_YET_IMPLEMENTED_STRING",): + elif param[0:4] in ("ZZZZ",): NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff_py.snap index fb89db8d6f..3bf9990399 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtonoff_py.snap @@ -203,14 +203,14 @@ d={'a':1, #!/usr/bin/env python3 -import asyncio -import sys -+NOT_YET_IMPLEMENTED_StmtImport -+NOT_YET_IMPLEMENTED_StmtImport - +- -from third_party import X, Y, Z -+NOT_YET_IMPLEMENTED_StmtImportFrom ++NOT_YET_IMPLEMENTED_StmtImport ++NOT_YET_IMPLEMENTED_StmtImport -from library import some_connection, some_decorator -- ++NOT_YET_IMPLEMENTED_StmtImportFrom + +NOT_YET_IMPLEMENTED_StmtImportFrom # fmt: off -from third_party import (X, @@ -253,7 +253,7 @@ d={'a':1, - async with some_connection() as conn: - await conn.do_what_i_mean('SELECT bobby, tables FROM xkcd', timeout=2) - await asyncio.sleep(1) -+ "NOT_YET_IMPLEMENTED_STRING" ++ "Single-line docstring. Multiline is harder to reformat." + NOT_YET_IMPLEMENTED_StmtAsyncWith + await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + @@ -269,7 +269,7 @@ d={'a':1, +def function_signature_stress_test( + number: int, + no_annotation=None, -+ text: str = "NOT_YET_IMPLEMENTED_STRING", ++ text: str = "default", + *, + debug: bool = False, + **kwargs, @@ -289,24 +289,22 @@ d={'a':1, + e=True, + f=-1, + g=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false, -+ h="NOT_YET_IMPLEMENTED_STRING", -+ i="NOT_YET_IMPLEMENTED_STRING", ++ h="", ++ i=r"", +): + offset = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + NOT_YET_IMPLEMENTED_StmtAssert def spaces_types( -@@ -51,76 +72,71 @@ +@@ -51,68 +72,66 @@ d: dict = {}, e: bool = True, f: int = -1, - g: int = 1 if False else 2, -- h: str = "", -- i: str = r"", + g: int = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false, -+ h: str = "NOT_YET_IMPLEMENTED_STRING", -+ i: str = "NOT_YET_IMPLEMENTED_STRING", + h: str = "", + i: str = r"", ): ... @@ -319,7 +317,7 @@ d={'a':1, something = { # fmt: off - key: 'value', -+ key: "NOT_YET_IMPLEMENTED_STRING", ++ key: "value", } @@ -332,8 +330,8 @@ d={'a':1, - goes + here, - andhere, + ( -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", ++ "some big and", ++ "complex subscript", + # fmt: on + goes + + here, @@ -347,7 +345,7 @@ d={'a':1, - from hello import a, b - 'unformatted' + NOT_YET_IMPLEMENTED_StmtImportFrom -+ "NOT_YET_IMPLEMENTED_STRING" ++ "unformatted" # fmt: on @@ -356,7 +354,7 @@ d={'a':1, - a , b = *hello - 'unformatted' + a, b = NOT_YET_IMPLEMENTED_ExprStarred -+ "NOT_YET_IMPLEMENTED_STRING" ++ "unformatted" # fmt: on @@ -365,15 +363,14 @@ d={'a':1, - yield hello - 'unformatted' + NOT_YET_IMPLEMENTED_ExprYield -+ "NOT_YET_IMPLEMENTED_STRING" ++ "unformatted" # fmt: on -- "formatted" -+ "NOT_YET_IMPLEMENTED_STRING" + "formatted" # fmt: off - ( yield hello ) - 'unformatted' + (NOT_YET_IMPLEMENTED_ExprYield) -+ "NOT_YET_IMPLEMENTED_STRING" ++ "unformatted" # fmt: on @@ -389,21 +386,8 @@ d={'a':1, # fmt: on - def off_and_on_without_data(): -- """All comments here are technically on the same prefix. -- -- The comments between will be formatted. This is a known limitation. -- """ -+ "NOT_YET_IMPLEMENTED_STRING" - # fmt: off - - # hey, that won't work -@@ -130,13 +146,13 @@ - - - def on_and_off_broken(): -- """Another known limitation.""" -+ "NOT_YET_IMPLEMENTED_STRING" +@@ -133,10 +152,10 @@ + """Another known limitation.""" # fmt: on # fmt: off - this=should.not_be.formatted() @@ -417,7 +401,7 @@ d={'a':1, # fmt: on # fmt: off # ...but comments still get reformatted even though they should not be -@@ -145,80 +161,21 @@ +@@ -145,43 +164,11 @@ def long_lines(): if True: @@ -429,13 +413,11 @@ d={'a':1, - implicit_default=True, - ) - ) -+ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) - # fmt: off +- # fmt: off - a = ( - unnecessary_bracket() - ) -+ a = NOT_IMPLEMENTED_call() - # fmt: on +- # fmt: on - _type_comment_re = re.compile( - r""" - ^ @@ -456,16 +438,17 @@ d={'a':1, - ) - $ - """, -- # fmt: off ++ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + # fmt: off - re.MULTILINE|re.VERBOSE -- # fmt: on ++ a = NOT_IMPLEMENTED_call() + # fmt: on - ) + _type_comment_re = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) def single_literal_yapf_disable(): -- """Black does not support this.""" -+ "NOT_YET_IMPLEMENTED_STRING" +@@ -189,36 +176,9 @@ BAZ = {(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)} # yapf: disable @@ -505,7 +488,7 @@ d={'a':1, -d={'a':1, - 'b':2} +l = [1, 2, 3] -+d = {"NOT_YET_IMPLEMENTED_STRING": 1, "NOT_YET_IMPLEMENTED_STRING": 2} ++d = {"a": 1, "b": 2} ``` ## Ruff Output @@ -544,7 +527,7 @@ def func_no_args(): async def coroutine(arg, exec=False): - "NOT_YET_IMPLEMENTED_STRING" + "Single-line docstring. Multiline is harder to reformat." NOT_YET_IMPLEMENTED_StmtAsyncWith await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) @@ -554,7 +537,7 @@ async def coroutine(arg, exec=False): def function_signature_stress_test( number: int, no_annotation=None, - text: str = "NOT_YET_IMPLEMENTED_STRING", + text: str = "default", *, debug: bool = False, **kwargs, @@ -571,8 +554,8 @@ def spaces( e=True, f=-1, g=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false, - h="NOT_YET_IMPLEMENTED_STRING", - i="NOT_YET_IMPLEMENTED_STRING", + h="", + i=r"", ): offset = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) NOT_YET_IMPLEMENTED_StmtAssert @@ -586,8 +569,8 @@ def spaces_types( e: bool = True, f: int = -1, g: int = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false, - h: str = "NOT_YET_IMPLEMENTED_STRING", - i: str = "NOT_YET_IMPLEMENTED_STRING", + h: str = "", + i: str = r"", ): ... @@ -598,7 +581,7 @@ def spaces2(result=NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)): something = { # fmt: off - key: "NOT_YET_IMPLEMENTED_STRING", + key: "value", } @@ -606,8 +589,8 @@ def subscriptlist(): atom[ # fmt: off ( - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", + "some big and", + "complex subscript", # fmt: on goes + here, @@ -619,26 +602,26 @@ def subscriptlist(): def import_as_names(): # fmt: off NOT_YET_IMPLEMENTED_StmtImportFrom - "NOT_YET_IMPLEMENTED_STRING" + "unformatted" # fmt: on def testlist_star_expr(): # fmt: off a, b = NOT_YET_IMPLEMENTED_ExprStarred - "NOT_YET_IMPLEMENTED_STRING" + "unformatted" # fmt: on def yield_expr(): # fmt: off NOT_YET_IMPLEMENTED_ExprYield - "NOT_YET_IMPLEMENTED_STRING" + "unformatted" # fmt: on - "NOT_YET_IMPLEMENTED_STRING" + "formatted" # fmt: off (NOT_YET_IMPLEMENTED_ExprYield) - "NOT_YET_IMPLEMENTED_STRING" + "unformatted" # fmt: on @@ -649,7 +632,10 @@ def example(session): def off_and_on_without_data(): - "NOT_YET_IMPLEMENTED_STRING" + """All comments here are technically on the same prefix. + + The comments between will be formatted. This is a known limitation. + """ # fmt: off # hey, that won't work @@ -659,7 +645,7 @@ def off_and_on_without_data(): def on_and_off_broken(): - "NOT_YET_IMPLEMENTED_STRING" + """Another known limitation.""" # fmt: on # fmt: off this = NOT_IMPLEMENTED_call() @@ -682,7 +668,7 @@ def long_lines(): def single_literal_yapf_disable(): - "NOT_YET_IMPLEMENTED_STRING" + """Black does not support this.""" BAZ = {(1, 2, 3, 4), (5, 6, 7, 8), (9, 10, 11, 12)} # yapf: disable @@ -691,7 +677,7 @@ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) NOT_YET_IMPLEMENTED_ExprYield # No formatting to the end of the file l = [1, 2, 3] -d = {"NOT_YET_IMPLEMENTED_STRING": 1, "NOT_YET_IMPLEMENTED_STRING": 2} +d = {"a": 1, "b": 2} ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip2_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip2_py.snap index 79cc4331e4..13bf3277f2 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip2_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip2_py.snap @@ -16,49 +16,38 @@ l3 = ["I have", "trailing comma", "so I should be braked",] ```diff --- Black +++ Ruff -@@ -1,11 +1,15 @@ - l1 = [ -- "This list should be broken up", -- "into multiple lines", -- "because it is way too long", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", +@@ -3,9 +3,9 @@ + "into multiple lines", + "because it is way too long", ] -l2 = ["But this list shouldn't", "even though it also has", "way too many characters in it"] # fmt: skip -+l2 = [ -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+] # fmt: skip - l3 = [ +-l3 = [ - "I have", - "trailing comma", - "so I should be braked", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING", - ] +-] ++l2 = [ ++ "But this list shouldn't", ++ "even though it also has", ++ "way too many characters in it", ++] # fmt: skip ++l3 = ["I have", "trailing comma", "so I should be braked"] ``` ## Ruff Output ```py l1 = [ - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", + "This list should be broken up", + "into multiple lines", + "because it is way too long", ] l2 = [ - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", + "But this list shouldn't", + "even though it also has", + "way too many characters in it", ] # fmt: skip -l3 = [ - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", -] +l3 = ["I have", "trailing comma", "so I should be braked"] ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip3_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip3_py.snap index 4b45e63eaa..2e54d4b721 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip3_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip3_py.snap @@ -20,7 +20,7 @@ f = ["This is a very long line that should be formatted into a clearer line ", " ```diff --- Black +++ Ruff -@@ -1,10 +1,7 @@ +@@ -1,7 +1,7 @@ a = 3 # fmt: off -b, c = 1, 2 @@ -29,11 +29,7 @@ f = ["This is a very long line that should be formatted into a clearer line ", " +d = 6 # fmt: skip e = 5 # fmt: on --f = [ -- "This is a very long line that should be formatted into a clearer line ", -- "by rearranging.", --] -+f = ["NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING"] + f = [ ``` ## Ruff Output @@ -45,7 +41,10 @@ b, c = 1, 2 d = 6 # fmt: skip e = 5 # fmt: on -f = ["NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING"] +f = [ + "This is a very long line that should be formatted into a clearer line ", + "by rearranging.", +] ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip7_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip7_py.snap index f088f1dd20..4eb0c61744 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip7_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__fmtskip7_py.snap @@ -18,22 +18,20 @@ d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasu --- Black +++ Ruff @@ -1,4 +1,4 @@ --a = "this is some code" + a = "this is some code" -b = 5 # fmt:skip -+a = "NOT_YET_IMPLEMENTED_STRING" +b = 5 # fmt:skip c = 9 # fmt: skip --d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasuperlongstring" # fmt:skip -+d = "NOT_YET_IMPLEMENTED_STRING" # fmt:skip + d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasuperlongstring" # fmt:skip ``` ## Ruff Output ```py -a = "NOT_YET_IMPLEMENTED_STRING" +a = "this is some code" b = 5 # fmt:skip c = 9 # fmt: skip -d = "NOT_YET_IMPLEMENTED_STRING" # fmt:skip +d = "thisisasuperlongstringthisisasuperlongstringthisisasuperlongstringthisisasuperlongstring" # fmt:skip ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function2_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function2_py.snap index a13146444a..2a6e53604d 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function2_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function2_py.snap @@ -66,7 +66,7 @@ with hmm_but_this_should_get_two_preceding_newlines(): ```diff --- Black +++ Ruff -@@ -2,64 +2,41 @@ +@@ -2,17 +2,9 @@ a, **kwargs, ) -> A: @@ -87,9 +87,7 @@ with hmm_but_this_should_get_two_preceding_newlines(): def g(): -- "Docstring." -+ "NOT_YET_IMPLEMENTED_STRING" - +@@ -21,45 +13,30 @@ def inner(): pass @@ -105,15 +103,14 @@ with hmm_but_this_should_get_two_preceding_newlines(): + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) --if os.name == "posix": + if os.name == "posix": - import termios -+if os.name == "NOT_YET_IMPLEMENTED_STRING": + NOT_YET_IMPLEMENTED_StmtImport def i_should_be_followed_by_only_one_newline(): pass - --elif os.name == "nt": + elif os.name == "nt": - try: - import msvcrt - @@ -124,7 +121,6 @@ with hmm_but_this_should_get_two_preceding_newlines(): - - def i_should_be_followed_by_only_one_newline(): - pass -+elif os.name == "NOT_YET_IMPLEMENTED_STRING": + NOT_YET_IMPLEMENTED_StmtTry elif False: @@ -158,7 +154,7 @@ def f( def g(): - "NOT_YET_IMPLEMENTED_STRING" + "Docstring." def inner(): pass @@ -173,12 +169,12 @@ def h(): NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) -if os.name == "NOT_YET_IMPLEMENTED_STRING": +if os.name == "posix": NOT_YET_IMPLEMENTED_StmtImport def i_should_be_followed_by_only_one_newline(): pass -elif os.name == "NOT_YET_IMPLEMENTED_STRING": +elif os.name == "nt": NOT_YET_IMPLEMENTED_StmtTry elif False: diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_py.snap index f51aeec357..da23fa784a 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_py.snap @@ -116,17 +116,17 @@ def __await__(): return (yield) +NOT_YET_IMPLEMENTED_StmtImport -from third_party import X, Y, Z -- --from library import some_connection, some_decorator +NOT_YET_IMPLEMENTED_StmtImportFrom +-from library import some_connection, some_decorator +- -f"trigger 3.6 mode" +NOT_YET_IMPLEMENTED_StmtImportFrom +NOT_YET_IMPLEMENTED_ExprJoinedStr def func_no_args(): -@@ -14,39 +13,48 @@ +@@ -14,25 +13,24 @@ b c if True: @@ -145,11 +145,10 @@ def __await__(): return (yield) async def coroutine(arg, exec=False): -- "Single-line docstring. Multiline is harder to reformat." + "Single-line docstring. Multiline is harder to reformat." - async with some_connection() as conn: - await conn.do_what_i_mean("SELECT bobby, tables FROM xkcd", timeout=2) - await asyncio.sleep(1) -+ "NOT_YET_IMPLEMENTED_STRING" + NOT_YET_IMPLEMENTED_StmtAsyncWith + await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) @@ -160,9 +159,7 @@ def __await__(): return (yield) def function_signature_stress_test( number: int, no_annotation=None, -- text: str = "default", -+ text: str = "NOT_YET_IMPLEMENTED_STRING", - *, +@@ -41,12 +39,22 @@ debug: bool = False, **kwargs, ) -> str: @@ -181,8 +178,8 @@ def __await__(): return (yield) + e=True, + f=-1, + g=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false, -+ h="NOT_YET_IMPLEMENTED_STRING", -+ i="NOT_YET_IMPLEMENTED_STRING", ++ h="", ++ i=r"", +): + offset = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + NOT_YET_IMPLEMENTED_StmtAssert @@ -194,11 +191,9 @@ def __await__(): return (yield) e: bool = True, f: int = -1, - g: int = 1 if False else 2, -- h: str = "", -- i: str = r"", + g: int = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false, -+ h: str = "NOT_YET_IMPLEMENTED_STRING", -+ i: str = "NOT_YET_IMPLEMENTED_STRING", + h: str = "", + i: str = r"", ): ... @@ -317,7 +312,7 @@ def func_no_args(): async def coroutine(arg, exec=False): - "NOT_YET_IMPLEMENTED_STRING" + "Single-line docstring. Multiline is harder to reformat." NOT_YET_IMPLEMENTED_StmtAsyncWith await NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) @@ -327,7 +322,7 @@ async def coroutine(arg, exec=False): def function_signature_stress_test( number: int, no_annotation=None, - text: str = "NOT_YET_IMPLEMENTED_STRING", + text: str = "default", *, debug: bool = False, **kwargs, @@ -343,8 +338,8 @@ def spaces( e=True, f=-1, g=NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false, - h="NOT_YET_IMPLEMENTED_STRING", - i="NOT_YET_IMPLEMENTED_STRING", + h="", + i=r"", ): offset = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) NOT_YET_IMPLEMENTED_StmtAssert @@ -358,8 +353,8 @@ def spaces_types( e: bool = True, f: int = -1, g: int = NOT_IMPLEMENTED_true if NOT_IMPLEMENTED_cond else NOT_IMPLEMENTED_false, - h: str = "NOT_YET_IMPLEMENTED_STRING", - i: str = "NOT_YET_IMPLEMENTED_STRING", + h: str = "", + i: str = r"", ): ... diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_trailing_comma_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_trailing_comma_py.snap index e44027943b..e117c52399 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_trailing_comma_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__function_trailing_comma_py.snap @@ -74,27 +74,7 @@ some_module.some_function( ```diff --- Black +++ Ruff -@@ -2,7 +2,7 @@ - a, - ): - d = { -- "key": "value", -+ "NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING", - } - tup = (1,) - -@@ -12,8 +12,8 @@ - b, - ): - d = { -- "key": "value", -- "key2": "value2", -+ "NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING", -+ "NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING", - } - tup = ( - 1, -@@ -24,45 +24,37 @@ +@@ -24,18 +24,14 @@ def f( a: int = 1, ): @@ -109,36 +89,22 @@ some_module.some_function( + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) + NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) x = { -- "a": 1, -- "b": 2, + "a": 1, + "b": 2, - }["a"] -+ "NOT_YET_IMPLEMENTED_STRING": 1, -+ "NOT_YET_IMPLEMENTED_STRING": 2, + }[ -+ "NOT_YET_IMPLEMENTED_STRING" ++ "a" + ] if ( a == { -- "a": 1, -- "b": 2, -- "c": 3, -- "d": 4, -- "e": 5, -- "f": 6, -- "g": 7, -- "h": 8, +@@ -47,23 +43,17 @@ + "f": 6, + "g": 7, + "h": 8, - }["a"] -+ "NOT_YET_IMPLEMENTED_STRING": 1, -+ "NOT_YET_IMPLEMENTED_STRING": 2, -+ "NOT_YET_IMPLEMENTED_STRING": 3, -+ "NOT_YET_IMPLEMENTED_STRING": 4, -+ "NOT_YET_IMPLEMENTED_STRING": 5, -+ "NOT_YET_IMPLEMENTED_STRING": 6, -+ "NOT_YET_IMPLEMENTED_STRING": 7, -+ "NOT_YET_IMPLEMENTED_STRING": 8, + }[ -+ "NOT_YET_IMPLEMENTED_STRING" ++ "a" + ] ): pass @@ -147,8 +113,7 @@ some_module.some_function( -def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> ( - Set["xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"] -): -+def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set["NOT_YET_IMPLEMENTED_STRING"]: - json = { +- json = { - "k": { - "k2": { - "k3": [ @@ -156,13 +121,15 @@ some_module.some_function( - ] - } - } -+ "NOT_YET_IMPLEMENTED_STRING": { -+ "NOT_YET_IMPLEMENTED_STRING": {"NOT_YET_IMPLEMENTED_STRING": [1]}, -+ }, - } +- } ++def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[ ++ "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" ++]: ++ json = {"k": {"k2": {"k3": [1]}}} -@@ -80,35 +72,16 @@ + # The type annotation shouldn't get a trailing comma since that would change its type. +@@ -80,35 +70,16 @@ pass @@ -211,7 +178,7 @@ def f( a, ): d = { - "NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING", + "key": "value", } tup = (1,) @@ -221,8 +188,8 @@ def f2( b, ): d = { - "NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING": "NOT_YET_IMPLEMENTED_STRING", + "key": "value", + "key2": "value2", } tup = ( 1, @@ -236,35 +203,33 @@ def f( NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) x = { - "NOT_YET_IMPLEMENTED_STRING": 1, - "NOT_YET_IMPLEMENTED_STRING": 2, + "a": 1, + "b": 2, }[ - "NOT_YET_IMPLEMENTED_STRING" + "a" ] if ( a == { - "NOT_YET_IMPLEMENTED_STRING": 1, - "NOT_YET_IMPLEMENTED_STRING": 2, - "NOT_YET_IMPLEMENTED_STRING": 3, - "NOT_YET_IMPLEMENTED_STRING": 4, - "NOT_YET_IMPLEMENTED_STRING": 5, - "NOT_YET_IMPLEMENTED_STRING": 6, - "NOT_YET_IMPLEMENTED_STRING": 7, - "NOT_YET_IMPLEMENTED_STRING": 8, + "a": 1, + "b": 2, + "c": 3, + "d": 4, + "e": 5, + "f": 6, + "g": 7, + "h": 8, }[ - "NOT_YET_IMPLEMENTED_STRING" + "a" ] ): pass -def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set["NOT_YET_IMPLEMENTED_STRING"]: - json = { - "NOT_YET_IMPLEMENTED_STRING": { - "NOT_YET_IMPLEMENTED_STRING": {"NOT_YET_IMPLEMENTED_STRING": [1]}, - }, - } +def xxxxxxxxxxxxxxxxxxxxxxxxxxxx() -> Set[ + "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" +]: + json = {"k": {"k2": {"k3": [1]}}} # The type annotation shouldn't get a trailing comma since that would change its type. diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__import_spacing_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__import_spacing_py.snap index df1dfc81f6..30c49898e4 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__import_spacing_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__import_spacing_py.snap @@ -62,9 +62,7 @@ __all__ = ( ```diff --- Black +++ Ruff -@@ -1,54 +1,32 @@ --"""The asyncio package, tracking PEP 3156.""" -+"NOT_YET_IMPLEMENTED_STRING" +@@ -2,53 +2,31 @@ # flake8: noqa @@ -142,7 +140,7 @@ __all__ = ( ## Ruff Output ```py -"NOT_YET_IMPLEMENTED_STRING" +"""The asyncio package, tracking PEP 3156.""" # flake8: noqa diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__power_op_spacing_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__power_op_spacing_py.snap index 867b4314cd..693a6f7001 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__power_op_spacing_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__power_op_spacing_py.snap @@ -83,10 +83,9 @@ return np.divide( -b = 5 ** f() +b = 5 ** NOT_IMPLEMENTED_call() c = -(5**2) --d = 5 ** f["hi"] + d = 5 ** f["hi"] -e = lazy(lambda **kwargs: 5) -f = f() ** 5 -+d = 5 ** f["NOT_YET_IMPLEMENTED_STRING"] +e = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +f = NOT_IMPLEMENTED_call() ** 5 g = a.b**c.d @@ -114,10 +113,9 @@ return np.divide( -b = 5.0 ** f() +b = 5.0 ** NOT_IMPLEMENTED_call() c = -(5.0**2.0) --d = 5.0 ** f["hi"] + d = 5.0 ** f["hi"] -e = lazy(lambda **kwargs: 5) -f = f() ** 5.0 -+d = 5.0 ** f["NOT_YET_IMPLEMENTED_STRING"] +e = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) +f = NOT_IMPLEMENTED_call() ** 5.0 g = a.b**c.d @@ -177,7 +175,7 @@ def function_dont_replace_spaces(): a = 5**~4 b = 5 ** NOT_IMPLEMENTED_call() c = -(5**2) -d = 5 ** f["NOT_YET_IMPLEMENTED_STRING"] +d = 5 ** f["hi"] e = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) f = NOT_IMPLEMENTED_call() ** 5 g = a.b**c.d @@ -196,7 +194,7 @@ r = x**y a = 5.0**~4.0 b = 5.0 ** NOT_IMPLEMENTED_call() c = -(5.0**2.0) -d = 5.0 ** f["NOT_YET_IMPLEMENTED_STRING"] +d = 5.0 ** f["hi"] e = NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) f = NOT_IMPLEMENTED_call() ** 5.0 g = a.b**c.d diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__remove_parens_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__remove_parens_py.snap index edf95a4f94..c9d1141cbf 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__remove_parens_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__remove_parens_py.snap @@ -68,7 +68,7 @@ def example8(): ```diff --- Black +++ Ruff -@@ -1,24 +1,16 @@ +@@ -1,20 +1,12 @@ x = 1 x = 1.2 @@ -91,11 +91,6 @@ def example8(): def example(): -- return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" -+ return "NOT_YET_IMPLEMENTED_STRING" - - - def example1(): @@ -30,15 +22,11 @@ @@ -103,7 +98,7 @@ def example8(): - return ( - "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" - ) -+ return "NOT_YET_IMPLEMENTED_STRING" ++ return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" def example3(): @@ -169,7 +164,7 @@ async def show_status(): def example(): - return "NOT_YET_IMPLEMENTED_STRING" + return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" def example1(): @@ -181,7 +176,7 @@ def example1point5(): def example2(): - return "NOT_YET_IMPLEMENTED_STRING" + return "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" def example3(): diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__string_prefixes_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__string_prefixes_py.snap index 9298adaab4..1af332dee3 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__string_prefixes_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__string_prefixes_py.snap @@ -33,19 +33,16 @@ def docstring_multiline(): ```diff --- Black +++ Ruff -@@ -1,20 +1,36 @@ +@@ -1,13 +1,31 @@ #!/usr/bin/env python3 --name = "Łukasz" + name = "Łukasz" -(f"hello {name}", f"hello {name}") -(b"", b"") --("", "") --(r"", R"") -+name = "NOT_YET_IMPLEMENTED_STRING" +(NOT_YET_IMPLEMENTED_ExprJoinedStr, NOT_YET_IMPLEMENTED_ExprJoinedStr) +(b"NOT_YET_IMPLEMENTED_BYTE_STRING", b"NOT_YET_IMPLEMENTED_BYTE_STRING") -+("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING") -+("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING") + ("", "") + (r"", R"") -(rf"", rf"", Rf"", Rf"", rf"", rf"", Rf"", Rf"") -(rb"", rb"", Rb"", Rb"", rb"", rb"", Rb"", Rb"") @@ -72,15 +69,6 @@ def docstring_multiline(): def docstring_singleline(): -- R"""2020 was one hell of a year. The good news is that we were able to""" -+ "NOT_YET_IMPLEMENTED_STRING" - - - def docstring_multiline(): -- R""" -- clear out all of the issues opened in that time :p -- """ -+ "NOT_YET_IMPLEMENTED_STRING" ``` ## Ruff Output @@ -88,11 +76,11 @@ def docstring_multiline(): ```py #!/usr/bin/env python3 -name = "NOT_YET_IMPLEMENTED_STRING" +name = "Łukasz" (NOT_YET_IMPLEMENTED_ExprJoinedStr, NOT_YET_IMPLEMENTED_ExprJoinedStr) (b"NOT_YET_IMPLEMENTED_BYTE_STRING", b"NOT_YET_IMPLEMENTED_BYTE_STRING") -("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING") -("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING") +("", "") +(r"", R"") ( NOT_YET_IMPLEMENTED_ExprJoinedStr, @@ -117,11 +105,13 @@ name = "NOT_YET_IMPLEMENTED_STRING" def docstring_singleline(): - "NOT_YET_IMPLEMENTED_STRING" + R"""2020 was one hell of a year. The good news is that we were able to""" def docstring_multiline(): - "NOT_YET_IMPLEMENTED_STRING" + R""" + clear out all of the issues opened in that time :p + """ ``` ## Black Output diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens1_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens1_py.snap index f331e7a484..70f66ad05c 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens1_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens1_py.snap @@ -70,7 +70,7 @@ class A: - self.min_length, - ) % {"min_length": self.min_length} + return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) % { -+ "NOT_YET_IMPLEMENTED_STRING": self.min_length, ++ "min_length": self.min_length, + } @@ -112,7 +112,7 @@ if x: class X: def get_help_text(self): return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) % { - "NOT_YET_IMPLEMENTED_STRING": self.min_length, + "min_length": self.min_length, } diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens2_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens2_py.snap index 3186661eb0..122f1f4cfb 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens2_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens2_py.snap @@ -23,7 +23,7 @@ if (e123456.get_tk_patchlevel() >= (8, 6, 0, 'final') or - 8, -) <= get_tk_patchlevel() < (8, 6): +if ( -+ NOT_IMPLEMENTED_call() >= (8, 6, 0, "NOT_YET_IMPLEMENTED_STRING") ++ NOT_IMPLEMENTED_call() >= (8, 6, 0, "final") + or (8, 5, 8) <= NOT_IMPLEMENTED_call() < (8, 6) +): pass @@ -33,7 +33,7 @@ if (e123456.get_tk_patchlevel() >= (8, 6, 0, 'final') or ```py if ( - NOT_IMPLEMENTED_call() >= (8, 6, 0, "NOT_YET_IMPLEMENTED_STRING") + NOT_IMPLEMENTED_call() >= (8, 6, 0, "final") or (8, 5, 8) <= NOT_IMPLEMENTED_call() < (8, 6) ): pass diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens3_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens3_py.snap index 4108c2434f..106c7c2554 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens3_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_comma_optional_parens3_py.snap @@ -31,8 +31,8 @@ if True: - "qweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqweasdzxcqwe", - ) % {"reported_username": reported_username, "report_reason": report_reason} + return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) % { -+ "NOT_YET_IMPLEMENTED_STRING": reported_username, -+ "NOT_YET_IMPLEMENTED_STRING": report_reason, ++ "reported_username": reported_username, ++ "report_reason": report_reason, + } ``` @@ -43,8 +43,8 @@ if True: if True: if True: return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) % { - "NOT_YET_IMPLEMENTED_STRING": reported_username, - "NOT_YET_IMPLEMENTED_STRING": report_reason, + "reported_username": reported_username, + "report_reason": report_reason, } ``` diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_commas_in_leading_parts_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_commas_in_leading_parts_py.snap index 3ef4708db1..b6cdaf967b 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_commas_in_leading_parts_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__black_test__trailing_commas_in_leading_parts_py.snap @@ -46,7 +46,7 @@ assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx( ```diff --- Black +++ Ruff -@@ -1,50 +1,30 @@ +@@ -1,50 +1,26 @@ -zero( - one, -).two( @@ -86,11 +86,7 @@ assert xxxxxxxxx.xxxxxxxxx.xxxxxxxxx( - }, - api_key=api_key, - )["extensions"]["sdk"]["token"] -+ return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)["NOT_YET_IMPLEMENTED_STRING"][ -+ "NOT_YET_IMPLEMENTED_STRING" -+ ][ -+ "NOT_YET_IMPLEMENTED_STRING" -+ ] ++ return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)["extensions"]["sdk"]["token"] # Edge case where a bug in a working-in-progress version of @@ -130,11 +126,7 @@ NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg) # Example from https://github.com/psf/black/issues/3229 def refresh_token(self, device_family, refresh_token, api_key): - return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)["NOT_YET_IMPLEMENTED_STRING"][ - "NOT_YET_IMPLEMENTED_STRING" - ][ - "NOT_YET_IMPLEMENTED_STRING" - ] + return NOT_IMPLEMENTED_call(NOT_IMPLEMENTED_arg)["extensions"]["sdk"]["token"] # Edge case where a bug in a working-in-progress version of diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__slice_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__slice_py.snap index 4fa305f243..80370410e7 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__slice_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__slice_py.snap @@ -93,13 +93,13 @@ e210 = "e"[a() : 1 :] ## Output ```py # Handle comments both when lower and upper exist and when they don't -a1 = "NOT_YET_IMPLEMENTED_STRING"[ +a1 = "a"[ # a 1 # b : # c 2 # d ] -a2 = "NOT_YET_IMPLEMENTED_STRING"[ +a2 = "a"[ # a # b : # c @@ -107,7 +107,7 @@ a2 = "NOT_YET_IMPLEMENTED_STRING"[ ] # Check all places where comments can exist -b1 = "NOT_YET_IMPLEMENTED_STRING"[ # a +b1 = "b"[ # a # b 1 # c # d @@ -122,33 +122,33 @@ b1 = "NOT_YET_IMPLEMENTED_STRING"[ # a ] # Handle the spacing from the colon correctly with upper leading comments -c1 = "NOT_YET_IMPLEMENTED_STRING"[ +c1 = "c"[ 1: # e # f 2 ] -c2 = "NOT_YET_IMPLEMENTED_STRING"[ +c2 = "c"[ 1: # e 2 ] -c3 = "NOT_YET_IMPLEMENTED_STRING"[ +c3 = "c"[ 1: # f 2 ] -c4 = "NOT_YET_IMPLEMENTED_STRING"[ +c4 = "c"[ 1: # f 2 ] # End of line comments -d1 = "NOT_YET_IMPLEMENTED_STRING"[ # comment +d1 = "d"[ # comment : ] -d2 = "NOT_YET_IMPLEMENTED_STRING"[ # comment +d2 = "d"[ # comment 1: ] -d3 = "NOT_YET_IMPLEMENTED_STRING"[ +d3 = "d"[ 1 # comment : ] @@ -159,19 +159,19 @@ def a(): ... -e00 = "NOT_YET_IMPLEMENTED_STRING"[:] -e01 = "NOT_YET_IMPLEMENTED_STRING"[:1] -e02 = "NOT_YET_IMPLEMENTED_STRING"[ : NOT_IMPLEMENTED_call()] -e10 = "NOT_YET_IMPLEMENTED_STRING"[1:] -e11 = "NOT_YET_IMPLEMENTED_STRING"[1:1] -e12 = "NOT_YET_IMPLEMENTED_STRING"[1 : NOT_IMPLEMENTED_call()] -e20 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() :] -e21 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() : 1] -e22 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() : NOT_IMPLEMENTED_call()] -e200 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() : :] -e201 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() :: 1] -e202 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() :: NOT_IMPLEMENTED_call()] -e210 = "NOT_YET_IMPLEMENTED_STRING"[NOT_IMPLEMENTED_call() : 1 :] +e00 = "e"[:] +e01 = "e"[:1] +e02 = "e"[ : NOT_IMPLEMENTED_call()] +e10 = "e"[1:] +e11 = "e"[1:1] +e12 = "e"[1 : NOT_IMPLEMENTED_call()] +e20 = "e"[NOT_IMPLEMENTED_call() :] +e21 = "e"[NOT_IMPLEMENTED_call() : 1] +e22 = "e"[NOT_IMPLEMENTED_call() : NOT_IMPLEMENTED_call()] +e200 = "e"[NOT_IMPLEMENTED_call() : :] +e201 = "e"[NOT_IMPLEMENTED_call() :: 1] +e202 = "e"[NOT_IMPLEMENTED_call() :: NOT_IMPLEMENTED_call()] +e210 = "e"[NOT_IMPLEMENTED_call() : 1 :] ``` diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__string_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__string_py.snap new file mode 100644 index 0000000000..d57de901e1 --- /dev/null +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__string_py.snap @@ -0,0 +1,119 @@ +--- +source: crates/ruff_python_formatter/src/lib.rs +expression: snapshot +--- +## Input +```py +"' test" +'" test' + +"\" test" +'\' test' + +# Prefer single quotes for string with more double quotes +"' \" \" '' \" \" '" + +# Prefer double quotes for string with more single quotes +'\' " " \'\' " " \'' + +# Prefer double quotes for string with equal amount of single and double quotes +'" \' " " \'\'' +"' \" '' \" \" '" + +"\\' \"\"" +'\\\' ""' + + +u"Test" +U"Test" + +r"Test" +R"Test" + +'This string will not include \ +backslashes or newline characters.' + +if True: + 'This string will not include \ + backslashes or newline characters.' + +"""Multiline +String \" +""" + +'''Multiline +String \' +''' + +'''Multiline +String "" +''' + +'''Multiline +String """ +''' + +'''Multiline +String \"\"\" +''' +``` + + + +## Output +```py +"' test" +'" test' + +'" test' +"' test" + +# Prefer single quotes for string with more double quotes +"' \" \" '' \" \" '" + +# Prefer double quotes for string with more single quotes +"' \" \" '' \" \" '" + +# Prefer double quotes for string with equal amount of single and double quotes +"\" ' \" \" ''" +"' \" '' \" \" '" + +'\\\' ""' +'\\\' ""' + + +"Test" +"Test" + +r"Test" +R"Test" + +"This string will not include \ +backslashes or newline characters." + +if True: + "This string will not include \ + backslashes or newline characters." + +"""Multiline +String \" +""" + +"""Multiline +String \' +""" + +"""Multiline +String "" +""" + +'''Multiline +String """ +''' + +"""Multiline +String \"\"\" +""" +``` + + diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__tuple_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__tuple_py.snap index 70dab6420a..cce6cccafc 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__tuple_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__expression__tuple_py.snap @@ -77,98 +77,88 @@ a4 = ((1, 2), 3) # Wrapping parentheses checks b1 = ( - ("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING"), - ( - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - ), - ("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING"), - ("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING"), + ("Michael", "Ende"), + ("Der", "satanarchäolügenialkohöllische", "Wunschpunsch"), + ("Beelzebub", "Irrwitzer"), + ("Tyrannja", "Vamperl"), ) b2 = ( - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", + "akjdshflkjahdslkfjlasfdahjlfds", + "ljklsadhflakfdajflahfdlajfhafldkjalfj", + "ljklsadhflakfdajflahfdlajfhafldkjalf2", ) b3 = ( - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", + "The", + "Night", + "of", + "Wishes:", + "Or", + "the", + "Satanarchaeolidealcohellish", + "Notion", + "Potion", ) # Nested wrapping parentheses check c1 = ( - ("NOT_YET_IMPLEMENTED_STRING"), + ("cicero"), ( - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - ), - ( - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", - "NOT_YET_IMPLEMENTED_STRING", + "Qui", + "autem,", + "si", + "maxime", + "hoc", + "placeat,", + "moderatius", + "tamen", + "id", + "uolunt", + "fieri,", + "difficilem", + "quandam", + "temperantiam", + "postulant", + "in", + "eo,", + "quod", + "semel", + "admissum", + "coerceri", + "reprimique", + "non", + "potest,", + "ut", + "propemodum", + "iustioribus", + "utamur", + "illis,", + "qui", + "omnino", + "auocent", + "a", + "philosophia,", + "quam", + "his,", + "qui", + "rebus", + "infinitis", + "modum", + "constituant", + "in", + "reque", + "eo", + "meliore,", + "quo", + "maior", + "sit,", + "mediocritatem", + "desiderent.", ), + ("de", "finibus", "bonorum", "et", "malorum"), ) # Deeply nested parentheses -d1 = ((("NOT_YET_IMPLEMENTED_STRING",),),) +d1 = ((("3D",),),) d2 = ( ( ( @@ -197,7 +187,7 @@ d2 = ( ( ( ( - "NOT_YET_IMPLEMENTED_STRING", + "¯\_(ツ)_/¯", ), ), ), @@ -234,7 +224,10 @@ e2 = ( 2, ) e3 = (1,) -e4 = ("NOT_YET_IMPLEMENTED_STRING", "NOT_YET_IMPLEMENTED_STRING") +e4 = ( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor", + "incididunt", +) # Empty tuples and comments f1 = ( @@ -260,8 +253,14 @@ g2 = ( # Ensure the correct number of parentheses h1 = (1, 2) -h2 = (1, "NOT_YET_IMPLEMENTED_STRING") -h3 = 1, "NOT_YET_IMPLEMENTED_STRING" +h2 = ( + 1, + "qweiurpoiqwurepqiurpqirpuqoiwrupqoirupqoirupqoiurpqiorupwqiourpqurpqurpqurpqurpqurpqurüqurqpuriq", +) +h3 = ( + 1, + "qweiurpoiqwurepqiurpqirpuqoiwrupqoirupqoirupqoiurpqiorupwqiourpqurpqurpqurpqurpqurpqurüqurqpuriq", +) ``` diff --git a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__statement__if_py.snap b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__statement__if_py.snap index 8bd96653d9..a7e33556d9 100644 --- a/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__statement__if_py.snap +++ b/crates/ruff_python_formatter/src/snapshots/ruff_python_formatter__tests__ruff_test__statement__if_py.snap @@ -115,23 +115,23 @@ else: # instead of the else. # Originally found in https://github.com/python/cpython/blob/ab3823a97bdeefb0266b3c8d493f7f6223ce3686/Lib/dataclasses.py#L539 -if "NOT_YET_IMPLEMENTED_STRING": +if "if 1": pass -elif "NOT_YET_IMPLEMENTED_STRING": +elif "elif 1": pass # Don't drop this comment 1 x = 1 -if "NOT_YET_IMPLEMENTED_STRING": +if "if 2": pass -elif "NOT_YET_IMPLEMENTED_STRING": +elif "elif 2": pass else: pass # Don't drop this comment 2 x = 2 -if "NOT_YET_IMPLEMENTED_STRING": +if "if 3": pass else: pass