diff --git a/crates/ruff/resources/test/fixtures/pydocstyle/D.py b/crates/ruff/resources/test/fixtures/pydocstyle/D.py index 0bedca5f1d..d8d9bf5d05 100644 --- a/crates/ruff/resources/test/fixtures/pydocstyle/D.py +++ b/crates/ruff/resources/test/fixtures/pydocstyle/D.py @@ -658,3 +658,8 @@ class CommentAfterDocstring: "After this docstring there's a comment." # priorities=1 def sort_services(self): pass + + +def newline_after_closing_quote(self): + "We enforce a newline after the closing quote for a multi-line docstring \ + but continuations shouldn't be considered multi-line" diff --git a/crates/ruff/src/docstrings/mod.rs b/crates/ruff/src/docstrings/mod.rs index 4ed8e9baaa..aea8b14faa 100644 --- a/crates/ruff/src/docstrings/mod.rs +++ b/crates/ruff/src/docstrings/mod.rs @@ -30,6 +30,11 @@ impl<'a> Docstring<'a> { pub(crate) fn leading_quote(&self) -> &'a str { &self.contents[TextRange::up_to(self.body_range.start())] } + + pub(crate) fn triple_quoted(&self) -> bool { + let leading_quote = self.leading_quote(); + leading_quote.ends_with("\"\"\"") || leading_quote.ends_with("'''") + } } impl Ranged for Docstring<'_> { diff --git a/crates/ruff/src/rules/pydocstyle/rules/blank_after_summary.rs b/crates/ruff/src/rules/pydocstyle/rules/blank_after_summary.rs index 05acc242c9..1672ad8a23 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/blank_after_summary.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/blank_after_summary.rs @@ -70,6 +70,10 @@ impl Violation for BlankLineAfterSummary { pub(crate) fn blank_after_summary(checker: &mut Checker, docstring: &Docstring) { let body = docstring.body(); + if !docstring.triple_quoted() { + return; + } + let mut lines_count: usize = 1; let mut blanks_count = 0; for line in body.trim().universal_newlines().skip(1) { diff --git a/crates/ruff/src/rules/pydocstyle/rules/newline_after_last_paragraph.rs b/crates/ruff/src/rules/pydocstyle/rules/newline_after_last_paragraph.rs index 09ce6d84e9..55b5c20153 100644 --- a/crates/ruff/src/rules/pydocstyle/rules/newline_after_last_paragraph.rs +++ b/crates/ruff/src/rules/pydocstyle/rules/newline_after_last_paragraph.rs @@ -63,6 +63,10 @@ pub(crate) fn newline_after_last_paragraph(checker: &mut Checker, docstring: &Do let contents = docstring.contents; let body = docstring.body(); + if !docstring.triple_quoted() { + return; + } + let mut line_count = 0; for line in NewlineWithTrailingNewline::from(body.as_str()) { if !line.trim().is_empty() { diff --git a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D204_D.py.snap b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D204_D.py.snap index 3d0d0384e9..a2db13ef2a 100644 --- a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D204_D.py.snap +++ b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D204_D.py.snap @@ -97,5 +97,6 @@ D.py:658:5: D204 [*] 1 blank line required after class docstring 659 |+ 659 660 | def sort_services(self): 660 661 | pass +661 662 | diff --git a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D300_D.py.snap b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D300_D.py.snap index 33ff3d12f9..502ad6d435 100644 --- a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D300_D.py.snap +++ b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D300_D.py.snap @@ -77,4 +77,13 @@ D.py:658:5: D300 Use triple double quotes `"""` 660 | pass | +D.py:664:5: D300 Use triple double quotes `"""` + | +663 | def newline_after_closing_quote(self): +664 | "We enforce a newline after the closing quote for a multi-line docstring \ + | _____^ +665 | | but continuations shouldn't be considered multi-line" + | |_________________________________________________________^ D300 + | + diff --git a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D400_D.py.snap b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D400_D.py.snap index 45481187d8..6c9ba058cb 100644 --- a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D400_D.py.snap +++ b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D400_D.py.snap @@ -310,4 +310,21 @@ D.py:641:18: D400 [*] First line should end with a period 643 643 | 644 644 | def single_line_docstring_with_an_escaped_backslash(): +D.py:664:5: D400 [*] First line should end with a period + | +663 | def newline_after_closing_quote(self): +664 | "We enforce a newline after the closing quote for a multi-line docstring \ + | _____^ +665 | | but continuations shouldn't be considered multi-line" + | |_________________________________________________________^ D400 + | + = help: Add period + +ℹ Suggested fix +662 662 | +663 663 | def newline_after_closing_quote(self): +664 664 | "We enforce a newline after the closing quote for a multi-line docstring \ +665 |- but continuations shouldn't be considered multi-line" + 665 |+ but continuations shouldn't be considered multi-line." + diff --git a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D415_D.py.snap b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D415_D.py.snap index a5630beb76..0c3aa113e7 100644 --- a/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D415_D.py.snap +++ b/crates/ruff/src/rules/pydocstyle/snapshots/ruff__rules__pydocstyle__tests__D415_D.py.snap @@ -292,4 +292,21 @@ D.py:641:18: D415 [*] First line should end with a period, question mark, or exc 643 643 | 644 644 | def single_line_docstring_with_an_escaped_backslash(): +D.py:664:5: D415 [*] First line should end with a period, question mark, or exclamation point + | +663 | def newline_after_closing_quote(self): +664 | "We enforce a newline after the closing quote for a multi-line docstring \ + | _____^ +665 | | but continuations shouldn't be considered multi-line" + | |_________________________________________________________^ D415 + | + = help: Add closing punctuation + +ℹ Suggested fix +662 662 | +663 663 | def newline_after_closing_quote(self): +664 664 | "We enforce a newline after the closing quote for a multi-line docstring \ +665 |- but continuations shouldn't be considered multi-line" + 665 |+ but continuations shouldn't be considered multi-line." +