From 7a13f9644dbb4bad2d7230eb6a1f70667502c333 Mon Sep 17 00:00:00 2001 From: Glyphack Date: Thu, 1 Feb 2024 19:39:39 +0100 Subject: [PATCH] Keep trailing new line in module docstring --- .../src/other/string_literal.rs | 6 +- .../src/string/docstring.rs | 10 +- ...tibility@cases__module_docstring_2.py.snap | 134 ------------------ .../tests/snapshots/format@preview.py.snap | 16 +-- .../format@stub_files__suite.pyi.snap | 13 +- 5 files changed, 23 insertions(+), 156 deletions(-) delete mode 100644 crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__module_docstring_2.py.snap diff --git a/crates/ruff_python_formatter/src/other/string_literal.rs b/crates/ruff_python_formatter/src/other/string_literal.rs index 3071f370986927..7a1ad7d4664b56 100644 --- a/crates/ruff_python_formatter/src/other/string_literal.rs +++ b/crates/ruff_python_formatter/src/other/string_literal.rs @@ -66,7 +66,11 @@ impl Format> for FormatStringLiteral<'_> { ); if self.layout.is_docstring() { - docstring::format(&normalized, f) + let is_module = matches!( + f.context().node_level(), + crate::context::NodeLevel::TopLevel(_) + ); + docstring::format(&normalized, f, is_module) } else { normalized.fmt(f) } diff --git a/crates/ruff_python_formatter/src/string/docstring.rs b/crates/ruff_python_formatter/src/string/docstring.rs index c6669c776818db..0627c695693bdf 100644 --- a/crates/ruff_python_formatter/src/string/docstring.rs +++ b/crates/ruff_python_formatter/src/string/docstring.rs @@ -102,7 +102,11 @@ use super::{NormalizedString, QuoteChar}; /// line c /// """ /// ``` -pub(crate) fn format(normalized: &NormalizedString, f: &mut PyFormatter) -> FormatResult<()> { +pub(crate) fn format( + normalized: &NormalizedString, + f: &mut PyFormatter, + is_module: bool, +) -> FormatResult<()> { let docstring = &normalized.text; // Black doesn't change the indentation of docstrings that contain an escaped newline @@ -205,6 +209,10 @@ pub(crate) fn format(normalized: &NormalizedString, f: &mut PyFormatter) -> Form space().fmt(f)?; } + if is_module && trim_end.ends_with('\n') { + hard_line_break().fmt(f)?; + } + write!(f, [source_position(normalized.end()), normalized.quotes]) } diff --git a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__module_docstring_2.py.snap b/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__module_docstring_2.py.snap deleted file mode 100644 index db9b152a3d8c8e..00000000000000 --- a/crates/ruff_python_formatter/tests/snapshots/black_compatibility@cases__module_docstring_2.py.snap +++ /dev/null @@ -1,134 +0,0 @@ ---- -source: crates/ruff_python_formatter/tests/fixtures.rs -input_file: crates/ruff_python_formatter/resources/test/fixtures/black/cases/module_docstring_2.py ---- -## Input - -```python -"""I am a very helpful module docstring. - -With trailing spaces: -Lorem ipsum dolor sit amet, consectetur adipiscing elit, -sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. -Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris -nisi ut aliquip ex ea commodo consequat. -Duis aute irure dolor in reprehenderit in voluptate -velit esse cillum dolore eu fugiat nulla pariatur. -Excepteur sint occaecat cupidatat non proident, -sunt in culpa qui officia deserunt mollit anim id est laborum. -""" - - - - -a = 1 - - -"""Look at me I'm a docstring... - -............................................................ -............................................................ -............................................................ -............................................................ -............................................................ -............................................................ -............................................................ -........................................................NOT! -""" - - - - -b = 2 -``` - -## Black Differences - -```diff ---- Black -+++ Ruff -@@ -9,8 +9,7 @@ - Duis aute irure dolor in reprehenderit in voluptate - velit esse cillum dolore eu fugiat nulla pariatur. - Excepteur sint occaecat cupidatat non proident, --sunt in culpa qui officia deserunt mollit anim id est laborum. --""" -+sunt in culpa qui officia deserunt mollit anim id est laborum.""" - - a = 1 - -``` - -## Ruff Output - -```python -"""I am a very helpful module docstring. - -With trailing spaces: -Lorem ipsum dolor sit amet, consectetur adipiscing elit, -sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. -Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris -nisi ut aliquip ex ea commodo consequat. -Duis aute irure dolor in reprehenderit in voluptate -velit esse cillum dolore eu fugiat nulla pariatur. -Excepteur sint occaecat cupidatat non proident, -sunt in culpa qui officia deserunt mollit anim id est laborum.""" - -a = 1 - - -"""Look at me I'm a docstring... - -............................................................ -............................................................ -............................................................ -............................................................ -............................................................ -............................................................ -............................................................ -........................................................NOT! -""" - - -b = 2 -``` - -## Black Output - -```python -"""I am a very helpful module docstring. - -With trailing spaces: -Lorem ipsum dolor sit amet, consectetur adipiscing elit, -sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. -Ut enim ad minim veniam, -quis nostrud exercitation ullamco laboris -nisi ut aliquip ex ea commodo consequat. -Duis aute irure dolor in reprehenderit in voluptate -velit esse cillum dolore eu fugiat nulla pariatur. -Excepteur sint occaecat cupidatat non proident, -sunt in culpa qui officia deserunt mollit anim id est laborum. -""" - -a = 1 - - -"""Look at me I'm a docstring... - -............................................................ -............................................................ -............................................................ -............................................................ -............................................................ -............................................................ -............................................................ -........................................................NOT! -""" - - -b = 2 -``` - - diff --git a/crates/ruff_python_formatter/tests/snapshots/format@preview.py.snap b/crates/ruff_python_formatter/tests/snapshots/format@preview.py.snap index 1e88e30d7fc92c..0998ee42e422d0 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@preview.py.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@preview.py.snap @@ -189,13 +189,10 @@ def f(): ```diff --- Stable +++ Preview -@@ -13,15 +13,14 @@ - def callback(event ): - print('Python:Click') +@@ -15,13 +15,13 @@ -- button.on_event(ButtonClick, callback) --""" -+ button.on_event(ButtonClick, callback)""" + button.on_event(ButtonClick, callback) + """ + first_stmt_after_module_level_docstring = 1 @@ -208,7 +205,7 @@ def f(): def raw_docstring(): -@@ -41,23 +40,22 @@ +@@ -41,23 +41,22 @@ class RemoveNewlineBeforeClassDocstring: @@ -241,7 +238,7 @@ def f(): aaaaaaaaaaaaaaaaaaaaaaaaaaaaaa[bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb] = ( cccccccc.ccccccccccccc(d).cccccccc + e -@@ -71,9 +69,9 @@ +@@ -71,9 +70,9 @@ + eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee ) @@ -291,7 +288,8 @@ A code black to format def callback(event ): print('Python:Click') - button.on_event(ButtonClick, callback)""" + button.on_event(ButtonClick, callback) +""" first_stmt_after_module_level_docstring = 1 diff --git a/crates/ruff_python_formatter/tests/snapshots/format@stub_files__suite.pyi.snap b/crates/ruff_python_formatter/tests/snapshots/format@stub_files__suite.pyi.snap index aca672904758d5..cea732f045fe3c 100644 --- a/crates/ruff_python_formatter/tests/snapshots/format@stub_files__suite.pyi.snap +++ b/crates/ruff_python_formatter/tests/snapshots/format@stub_files__suite.pyi.snap @@ -313,16 +313,7 @@ class ComplexStatements: ```diff --- Stable +++ Preview -@@ -1,7 +1,6 @@ - """Tests for empty line rules in stub files, mostly inspired by typeshed. - The rules are a list of nested exceptions. See also --https://github.com/psf/black/blob/c160e4b7ce30c661ac4f2dfa5038becf1b8c5c33/src/black/lines.py#L576-L744 --""" -+https://github.com/psf/black/blob/c160e4b7ce30c661ac4f2dfa5038becf1b8c5c33/src/black/lines.py#L576-L744""" - - import sys - from typing import Self, TypeAlias, final -@@ -110,6 +109,7 @@ +@@ -110,6 +110,7 @@ class InnerClass5: def a(self): ... @@ -330,7 +321,7 @@ class ComplexStatements: field1 = 1 class InnerClass6: -@@ -119,6 +119,7 @@ +@@ -119,6 +120,7 @@ class InnerClass7: def a(self): ...