mirror of
https://github.com/astral-sh/ruff.git
synced 2025-10-03 07:04:53 +00:00
[pydocstyle
] Skip leading whitespace for D403
(#14963)
This PR introduces three changes to `D403`, which has to do with capitalizing the first word in a docstring. 1. The diagnostic and fix now skip leading whitespace when determining what counts as "the first word". 2. The name has been changed to `first-word-uncapitalized` from `first-line-capitalized`, for both clarity and compliance with our rule naming policy. 3. The diagnostic message and documentation has been modified slightly to reflect this. Closes #14890
This commit is contained in:
parent
a623d8f7c4
commit
6a5eff6017
6 changed files with 60 additions and 17 deletions
|
@ -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?
|
||||
"""
|
||||
|
|
|
@ -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,
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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"))]
|
||||
|
|
|
@ -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
|
||||
|
@ -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
|
||||
)
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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(),
|
||||
},
|
||||
|
@ -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);
|
||||
|
|
|
@ -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"""
|
||||
|
@ -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."""
|
||||
|
@ -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`
|
||||
|
||||
|
@ -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…
Add table
Add a link
Reference in a new issue