Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[pydocstyle] Skip leading whitespace for D403 #14963

Merged
merged 10 commits into from
Dec 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions crates/ruff_linter/resources/test/fixtures/pydocstyle/D403.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,13 @@ def single_word():

def single_word_no_dot():
"""singleword"""

def first_word_lots_of_whitespace():
"""



here is the start of my docstring!

What do you think?
"""
4 changes: 2 additions & 2 deletions crates/ruff_linter/src/checkers/ast/analyze/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ pub(crate) fn definitions(checker: &mut Checker) {
Rule::EndsInPeriod,
Rule::EndsInPunctuation,
Rule::EscapeSequenceInDocstring,
Rule::FirstLineCapitalized,
Rule::FirstWordUncapitalized,
Rule::FitsOnOneLine,
Rule::IndentWithSpaces,
Rule::MultiLineSummaryFirstLine,
Expand Down Expand Up @@ -277,7 +277,7 @@ pub(crate) fn definitions(checker: &mut Checker) {
if checker.enabled(Rule::NoSignature) {
pydocstyle::rules::no_signature(checker, &docstring);
}
if checker.enabled(Rule::FirstLineCapitalized) {
if checker.enabled(Rule::FirstWordUncapitalized) {
pydocstyle::rules::capitalized(checker, &docstring);
}
if checker.enabled(Rule::DocstringStartsWithThis) {
Expand Down
2 changes: 1 addition & 1 deletion crates/ruff_linter/src/codes.rs
Original file line number Diff line number Diff line change
Expand Up @@ -566,7 +566,7 @@ pub fn code_to_rule(linter: Linter, code: &str) -> Option<(RuleGroup, Rule)> {
(Pydocstyle, "400") => (RuleGroup::Stable, rules::pydocstyle::rules::EndsInPeriod),
(Pydocstyle, "401") => (RuleGroup::Stable, rules::pydocstyle::rules::NonImperativeMood),
(Pydocstyle, "402") => (RuleGroup::Stable, rules::pydocstyle::rules::NoSignature),
(Pydocstyle, "403") => (RuleGroup::Stable, rules::pydocstyle::rules::FirstLineCapitalized),
(Pydocstyle, "403") => (RuleGroup::Stable, rules::pydocstyle::rules::FirstWordUncapitalized),
(Pydocstyle, "404") => (RuleGroup::Stable, rules::pydocstyle::rules::DocstringStartsWithThis),
(Pydocstyle, "405") => (RuleGroup::Stable, rules::pydocstyle::rules::CapitalizeSectionName),
(Pydocstyle, "406") => (RuleGroup::Stable, rules::pydocstyle::rules::NewLineAfterSectionName),
Expand Down
4 changes: 2 additions & 2 deletions crates/ruff_linter/src/rules/pydocstyle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@ mod tests {
#[test_case(Rule::EndsInPeriod, Path::new("D400_415.py"))]
#[test_case(Rule::EndsInPunctuation, Path::new("D.py"))]
#[test_case(Rule::EndsInPunctuation, Path::new("D400_415.py"))]
#[test_case(Rule::FirstLineCapitalized, Path::new("D.py"))]
#[test_case(Rule::FirstLineCapitalized, Path::new("D403.py"))]
#[test_case(Rule::FirstWordUncapitalized, Path::new("D.py"))]
#[test_case(Rule::FirstWordUncapitalized, Path::new("D403.py"))]
#[test_case(Rule::FitsOnOneLine, Path::new("D.py"))]
#[test_case(Rule::IndentWithSpaces, Path::new("D.py"))]
#[test_case(Rule::UndocumentedMagicMethod, Path::new("D.py"))]
Expand Down
19 changes: 11 additions & 8 deletions crates/ruff_linter/src/rules/pydocstyle/rules/capitalized.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ use crate::docstrings::Docstring;
/// Checks for docstrings that do not start with a capital letter.
///
/// ## Why is this bad?
/// The first character in a docstring should be capitalized for, grammatical
/// correctness and consistency.
/// The first non-whitespace character in a docstring should be
/// capitalized for grammatical correctness and consistency.
///
/// ## Example
/// ```python
Expand All @@ -30,16 +30,16 @@ use crate::docstrings::Docstring;
/// - [NumPy Style Guide](https://numpydoc.readthedocs.io/en/latest/format.html)
/// - [Google Python Style Guide - Docstrings](https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings)
#[derive(ViolationMetadata)]
pub(crate) struct FirstLineCapitalized {
pub(crate) struct FirstWordUncapitalized {
first_word: String,
capitalized_word: String,
}

impl AlwaysFixableViolation for FirstLineCapitalized {
impl AlwaysFixableViolation for FirstWordUncapitalized {
#[derive_message_formats]
fn message(&self) -> String {
format!(
"First word of the first line should be capitalized: `{}` -> `{}`",
"First word of the docstring should be capitalized: `{}` -> `{}`",
self.first_word, self.capitalized_word
)
}
Expand All @@ -59,7 +59,8 @@ pub(crate) fn capitalized(checker: &mut Checker, docstring: &Docstring) {
}

let body = docstring.body();
let first_word = body.split_once(' ').map_or_else(
let trim_start_body = body.trim_start();
let first_word = trim_start_body.split_once(' ').map_or_else(
|| {
// If the docstring is a single word, trim the punctuation marks because
// it makes the ASCII test below fail.
Expand Down Expand Up @@ -91,8 +92,10 @@ pub(crate) fn capitalized(checker: &mut Checker, docstring: &Docstring) {

let capitalized_word = uppercase_first_char.to_string() + first_word_chars.as_str();

let leading_whitespace_len = body.text_len() - trim_start_body.text_len();

let mut diagnostic = Diagnostic::new(
FirstLineCapitalized {
FirstWordUncapitalized {
first_word: first_word.to_string(),
capitalized_word: capitalized_word.to_string(),
},
Expand All @@ -101,7 +104,7 @@ pub(crate) fn capitalized(checker: &mut Checker, docstring: &Docstring) {

diagnostic.set_fix(Fix::safe_edit(Edit::range_replacement(
capitalized_word,
TextRange::at(body.start(), first_word.text_len()),
TextRange::at(body.start() + leading_whitespace_len, first_word.text_len()),
)));

checker.diagnostics.push(diagnostic);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
---
source: crates/ruff_linter/src/rules/pydocstyle/mod.rs
snapshot_kind: text
---
D403.py:2:5: D403 [*] First word of the first line should be capitalized: `this` -> `This`
D403.py:2:5: D403 [*] First word of the docstring should be capitalized: `this` -> `This`
|
1 | def bad_function():
2 | """this docstring is not capitalized"""
Expand All @@ -20,7 +19,7 @@ D403.py:2:5: D403 [*] First word of the first line should be capitalized: `this`
4 4 | def good_function():
5 5 | """This docstring is capitalized."""

D403.py:30:5: D403 [*] First word of the first line should be capitalized: `singleword` -> `Singleword`
D403.py:30:5: D403 [*] First word of the docstring should be capitalized: `singleword` -> `Singleword`
|
29 | def single_word():
30 | """singleword."""
Expand All @@ -40,11 +39,13 @@ D403.py:30:5: D403 [*] First word of the first line should be capitalized: `sing
32 32 | def single_word_no_dot():
33 33 | """singleword"""

D403.py:33:5: D403 [*] First word of the first line should be capitalized: `singleword` -> `Singleword`
D403.py:33:5: D403 [*] First word of the docstring should be capitalized: `singleword` -> `Singleword`
|
32 | def single_word_no_dot():
33 | """singleword"""
| ^^^^^^^^^^^^^^^^ D403
34 |
35 | def first_word_lots_of_whitespace():
|
= help: Capitalize `singleword` to `Singleword`

Expand All @@ -54,3 +55,32 @@ D403.py:33:5: D403 [*] First word of the first line should be capitalized: `sing
32 32 | def single_word_no_dot():
33 |- """singleword"""
33 |+ """Singleword"""
34 34 |
35 35 | def first_word_lots_of_whitespace():
36 36 | """

D403.py:36:5: D403 [*] First word of the docstring should be capitalized: `here` -> `Here`
|
35 | def first_word_lots_of_whitespace():
36 | """
| _____^
37 | |
38 | |
39 | |
40 | | here is the start of my docstring!
41 | |
42 | | What do you think?
43 | | """
| |_______^ D403
|
= help: Capitalize `here` to `Here`

ℹ Safe fix
37 37 |
38 38 |
39 39 |
40 |- here is the start of my docstring!
40 |+ Here is the start of my docstring!
41 41 |
42 42 | What do you think?
43 43 | """
Loading