Skip to content

Commit

Permalink
Ignore single quote docstrings with newline escape
Browse files Browse the repository at this point in the history
**Summary** Ignore the edge case whether a single quoted string is multiple lines through an
escape, previously emitting invalid code. Single quote docstrings are
flagged by D300.
```python
"\
"
```

Fixes #7139

**Test Plan** New `D` fixture.
  • Loading branch information
konstin committed Sep 5, 2023
1 parent e02d76f commit 12b786a
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 4 deletions.
5 changes: 5 additions & 0 deletions crates/ruff/resources/test/fixtures/pydocstyle/D.py
Original file line number Diff line number Diff line change
Expand Up @@ -639,3 +639,8 @@ def starts_with_space_then_this():
class SameLine: """This is a docstring on the same line"""

def same_line(): """This is a docstring on the same line"""


def single_line_docstring_with_an_escaped_backslash():
"\
"
16 changes: 12 additions & 4 deletions crates/ruff/src/rules/pydocstyle/rules/ends_with_period.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,13 +90,21 @@ pub(crate) fn ends_with_period(checker: &mut Checker, docstring: &Docstring) {
let line = lines.nth(index).unwrap();
let trimmed = line.trim_end();

if trimmed.ends_with("\\") {
// Ignore the edge case whether a single quoted string is multiple lines through an
// escape (https://github.com/astral-sh/ruff/issues/7139). Single quote docstrings are
// flagged by D300.
// ```python
// "\
// "
// ```
return;
}

if !trimmed.ends_with('.') {
let mut diagnostic = Diagnostic::new(EndsInPeriod, docstring.range());
// Best-effort autofix: avoid adding a period after other punctuation marks.
if checker.patch(diagnostic.kind.rule())
&& !trimmed.ends_with(':')
&& !trimmed.ends_with(';')
{
if checker.patch(diagnostic.kind.rule()) && !trimmed.ends_with([':', ';']) {
diagnostic.set_fix(Fix::suggested(Edit::insertion(
".".to_string(),
line.start() + trimmed.text_len(),
Expand Down
11 changes: 11 additions & 0 deletions crates/ruff/src/rules/pydocstyle/rules/ends_with_punctuation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,17 @@ pub(crate) fn ends_with_punctuation(checker: &mut Checker, docstring: &Docstring
let line = lines.next().unwrap();
let trimmed = line.trim_end();

if trimmed.ends_with("\\") {
// Ignore the edge case whether a single quoted string is multiple lines through an
// escape (https://github.com/astral-sh/ruff/issues/7139). Single quote docstrings are
// flagged by D300.
// ```python
// "\
// "
// ```
return;
}

if !trimmed.ends_with(['.', '!', '?']) {
let mut diagnostic = Diagnostic::new(EndsInPunctuation, docstring.range());
// Best-effort autofix: avoid adding a period after other punctuation marks.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,15 @@ pub(crate) fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstr
}
checker.diagnostics.push(diagnostic);
}
} else if first_line.as_str().ends_with("\\") {
// Ignore the edge case whether a single quoted string is multiple lines through an
// escape (https://github.com/astral-sh/ruff/issues/7139). Single quote docstrings are
// flagged by D300.
// ```python
// "\
// "
// ```
return;
} else {
if checker.enabled(Rule::MultiLineSummarySecondLine) {
let mut diagnostic = Diagnostic::new(MultiLineSummarySecondLine, docstring.range());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,14 @@ D.py:624:5: D200 One-line docstring should fit on one line
|
= help: Reformat to one line

D.py:645:5: D200 One-line docstring should fit on one line
|
644 | def single_line_docstring_with_an_escaped_backslash():
645 | "\
| _____^
646 | | "
| |_____^ D200
|
= help: Reformat to one line


Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,13 @@ D.py:328:5: D300 Use triple double quotes `"""`
| ^^^^^^^^^^^^ D300
|

D.py:645:5: D300 Use triple double quotes `"""`
|
644 | def single_line_docstring_with_an_escaped_backslash():
645 | "\
| _____^
646 | | "
| |_____^ D300
|


Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ D.py:639:17: D400 [*] First line should end with a period
639 |+class SameLine: """This is a docstring on the same line."""
640 640 |
641 641 | def same_line(): """This is a docstring on the same line"""
642 642 |

D.py:641:18: D400 [*] First line should end with a period
|
Expand All @@ -305,5 +306,8 @@ D.py:641:18: D400 [*] First line should end with a period
640 640 |
641 |-def same_line(): """This is a docstring on the same line"""
641 |+def same_line(): """This is a docstring on the same line."""
642 642 |
643 643 |
644 644 | def single_line_docstring_with_an_escaped_backslash():


Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,7 @@ D.py:639:17: D415 [*] First line should end with a period, question mark, or exc
639 |+class SameLine: """This is a docstring on the same line."""
640 640 |
641 641 | def same_line(): """This is a docstring on the same line"""
642 642 |

D.py:641:18: D415 [*] First line should end with a period, question mark, or exclamation point
|
Expand All @@ -287,5 +288,8 @@ D.py:641:18: D415 [*] First line should end with a period, question mark, or exc
640 640 |
641 |-def same_line(): """This is a docstring on the same line"""
641 |+def same_line(): """This is a docstring on the same line."""
642 642 |
643 643 |
644 644 | def single_line_docstring_with_an_escaped_backslash():


0 comments on commit 12b786a

Please sign in to comment.