Skip to content

Commit

Permalink
Deprecate conflicting D203 and D213 pydocstyle rules
Browse files Browse the repository at this point in the history
  • Loading branch information
charliermarsh committed Jan 28, 2023
1 parent fd56414 commit e7c4fa7
Show file tree
Hide file tree
Showing 12 changed files with 7 additions and 655 deletions.
7 changes: 1 addition & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -315,10 +315,7 @@ prefix, followed by three digits (e.g., `F401`). The prefix indicates that "sour
rules is determined by the `select` and `ignore` options, which support both the full code (e.g.,
`F401`) and the prefix (e.g., `F`).

As a special-case, Ruff also supports the `ALL` code, which enables all rules. Note that some of the
`pydocstyle` rules conflict (e.g., `D203` and `D211`) as they represent alternative docstring
formats. Enabling `ALL` without further configuration may result in suboptimal behavior, especially
for the `pydocstyle` plugin.
As a special-case, Ruff also supports the `ALL` code, which enables all rules.

If you're wondering how to configure Ruff, here are some **recommended guidelines**:

Expand Down Expand Up @@ -652,7 +649,6 @@ For more, see [pydocstyle](https://pypi.org/project/pydocstyle/) on PyPI.
| D200 | fits-on-one-line | One-line docstring should fit on one line | 🛠 |
| D201 | no-blank-line-before-function | No blank lines allowed before function docstring (found {num_lines}) | 🛠 |
| D202 | no-blank-line-after-function | No blank lines allowed after function docstring (found {num_lines}) | 🛠 |
| D203 | one-blank-line-before-class | 1 blank line required before class docstring | 🛠 |
| D204 | one-blank-line-after-class | 1 blank line required after class docstring | 🛠 |
| D205 | blank-line-after-summary | 1 blank line required between summary line and description | 🛠 |
| D206 | indent-with-spaces | Docstring should be indented with spaces, not tabs | |
Expand All @@ -662,7 +658,6 @@ For more, see [pydocstyle](https://pypi.org/project/pydocstyle/) on PyPI.
| D210 | no-surrounding-whitespace | No whitespaces allowed surrounding docstring text | 🛠 |
| D211 | no-blank-line-before-class | No blank lines allowed before class docstring | 🛠 |
| D212 | multi-line-summary-first-line | Multi-line docstring summary should start at the first line | 🛠 |
| D213 | multi-line-summary-second-line | Multi-line docstring summary should start at the second line | 🛠 |
| D214 | section-not-over-indented | Section is over-indented ("{name}") | 🛠 |
| D215 | section-underline-not-over-indented | Section underline is over-indented ("{name}") | 🛠 |
| D300 | uses-triple-quotes | Use """triple double quotes""" | |
Expand Down
2 changes: 0 additions & 2 deletions ruff.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1344,7 +1344,6 @@
"D200",
"D201",
"D202",
"D203",
"D204",
"D205",
"D206",
Expand All @@ -1355,7 +1354,6 @@
"D210",
"D211",
"D212",
"D213",
"D214",
"D215",
"D3",
Expand Down
12 changes: 1 addition & 11 deletions src/checkers/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4821,7 +4821,6 @@ impl<'a> Checker<'a> {
.rules
.enabled(&Rule::NoBlankLineBeforeFunction)
|| self.settings.rules.enabled(&Rule::NoBlankLineAfterFunction)
|| self.settings.rules.enabled(&Rule::OneBlankLineBeforeClass)
|| self.settings.rules.enabled(&Rule::OneBlankLineAfterClass)
|| self.settings.rules.enabled(&Rule::BlankLineAfterSummary)
|| self.settings.rules.enabled(&Rule::IndentWithSpaces)
Expand All @@ -4837,10 +4836,6 @@ impl<'a> Checker<'a> {
.settings
.rules
.enabled(&Rule::MultiLineSummaryFirstLine)
|| self
.settings
.rules
.enabled(&Rule::MultiLineSummarySecondLine)
|| self.settings.rules.enabled(&Rule::SectionNotOverIndented)
|| self
.settings
Expand Down Expand Up @@ -4953,8 +4948,7 @@ impl<'a> Checker<'a> {
{
pydocstyle::rules::blank_before_after_function(self, &docstring);
}
if self.settings.rules.enabled(&Rule::OneBlankLineBeforeClass)
|| self.settings.rules.enabled(&Rule::OneBlankLineAfterClass)
if self.settings.rules.enabled(&Rule::OneBlankLineAfterClass)
|| self.settings.rules.enabled(&Rule::NoBlankLineBeforeClass)
{
pydocstyle::rules::blank_before_after_class(self, &docstring);
Expand Down Expand Up @@ -4982,10 +4976,6 @@ impl<'a> Checker<'a> {
.settings
.rules
.enabled(&Rule::MultiLineSummaryFirstLine)
|| self
.settings
.rules
.enabled(&Rule::MultiLineSummarySecondLine)
{
pydocstyle::rules::multi_line_summary_start(self, &docstring);
}
Expand Down
18 changes: 0 additions & 18 deletions src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,6 @@ ruff_macros::define_rule_mapping!(
D200 => violations::FitsOnOneLine,
D201 => violations::NoBlankLineBeforeFunction,
D202 => violations::NoBlankLineAfterFunction,
D203 => violations::OneBlankLineBeforeClass,
D204 => violations::OneBlankLineAfterClass,
D205 => violations::BlankLineAfterSummary,
D206 => violations::IndentWithSpaces,
Expand All @@ -278,7 +277,6 @@ ruff_macros::define_rule_mapping!(
D210 => violations::NoSurroundingWhitespace,
D211 => violations::NoBlankLineBeforeClass,
D212 => violations::MultiLineSummaryFirstLine,
D213 => violations::MultiLineSummarySecondLine,
D214 => violations::SectionNotOverIndented,
D215 => violations::SectionUnderlineNotOverIndented,
D300 => violations::UsesTripleQuotes,
Expand Down Expand Up @@ -734,22 +732,6 @@ impl Diagnostic {
}
}

/// Pairs of checks that shouldn't be enabled together.
pub const INCOMPATIBLE_CODES: &[(Rule, Rule, &str)] = &[
(
Rule::OneBlankLineBeforeClass,
Rule::NoBlankLineBeforeClass,
"`one-blank-line-before-class` (D203) and `no-blank-line-before-class` (D211) are \
incompatible. Consider ignoring `one-blank-line-before-class`.",
),
(
Rule::MultiLineSummaryFirstLine,
Rule::MultiLineSummarySecondLine,
"`multi-line-summary-first-line` (D212) and `multi-line-summary-second-line` (D213) are \
incompatible. Consider ignoring one.",
),
];

#[cfg(test)]
mod tests {
use strum::IntoEnumIterator;
Expand Down
2 changes: 0 additions & 2 deletions src/rules/pydocstyle/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ mod tests {
#[test_case(Rule::FitsOnOneLine, Path::new("D.py"); "D200")]
#[test_case(Rule::NoBlankLineBeforeFunction, Path::new("D.py"); "D201")]
#[test_case(Rule::NoBlankLineAfterFunction, Path::new("D.py"); "D202")]
#[test_case(Rule::OneBlankLineBeforeClass, Path::new("D.py"); "D203")]
#[test_case(Rule::OneBlankLineAfterClass, Path::new("D.py"); "D204")]
#[test_case(Rule::BlankLineAfterSummary, Path::new("D.py"); "D205")]
#[test_case(Rule::IndentWithSpaces, Path::new("D.py"); "D206")]
Expand All @@ -37,7 +36,6 @@ mod tests {
#[test_case(Rule::NoSurroundingWhitespace, Path::new("D.py"); "D210")]
#[test_case(Rule::NoBlankLineBeforeClass, Path::new("D.py"); "D211")]
#[test_case(Rule::MultiLineSummaryFirstLine, Path::new("D.py"); "D212")]
#[test_case(Rule::MultiLineSummarySecondLine, Path::new("D.py"); "D213")]
#[test_case(Rule::SectionNotOverIndented, Path::new("sections.py"); "D214")]
#[test_case(Rule::SectionUnderlineNotOverIndented, Path::new("sections.py"); "D215")]
#[test_case(Rule::UsesTripleQuotes, Path::new("D.py"); "D300")]
Expand Down
29 changes: 2 additions & 27 deletions src/rules/pydocstyle/rules/blank_before_after_class.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::registry::{Diagnostic, Rule};
use crate::rules::pydocstyle::rules::regexes::COMMENT_REGEX;
use crate::violations;

/// D203, D204, D211
/// D204, D211
pub fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) {
let (DefinitionKind::Class(parent) | DefinitionKind::NestedClass(parent)) = &docstring.kind else {
return;
Expand All @@ -16,11 +16,7 @@ pub fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) {
if checker
.settings
.rules
.enabled(&Rule::OneBlankLineBeforeClass)
|| checker
.settings
.rules
.enabled(&Rule::NoBlankLineBeforeClass)
.enabled(&Rule::NoBlankLineBeforeClass)
{
let (before, ..) = checker.locator.partition_source_code_at(
&Range::from_located(parent),
Expand Down Expand Up @@ -53,27 +49,6 @@ pub fn blank_before_after_class(checker: &mut Checker, docstring: &Docstring) {
checker.diagnostics.push(diagnostic);
}
}
if checker
.settings
.rules
.enabled(&Rule::OneBlankLineBeforeClass)
{
if blank_lines_before != 1 {
let mut diagnostic = Diagnostic::new(
violations::OneBlankLineBeforeClass(blank_lines_before),
Range::from_located(docstring.expr),
);
if checker.patch(diagnostic.kind.rule()) {
// Insert one blank line before the class.
diagnostic.amend(Fix::replacement(
checker.stylist.line_ending().to_string(),
Location::new(docstring.expr.location.row() - blank_lines_before, 0),
Location::new(docstring.expr.location.row(), 0),
));
}
checker.diagnostics.push(diagnostic);
}
}
}

if checker
Expand Down
63 changes: 2 additions & 61 deletions src/rules/pydocstyle/rules/multi_line_summary_start.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,13 @@ use crate::ast::types::Range;
use crate::ast::whitespace::LinesWithTrailingNewline;
use crate::checkers::ast::Checker;
use crate::docstrings::constants;
use crate::docstrings::definition::{DefinitionKind, Docstring};
use crate::docstrings::definition::Docstring;
use crate::fix::Fix;
use crate::message::Location;
use crate::registry::{Diagnostic, Rule};
use crate::rules::pydocstyle::helpers::leading_quote;
use crate::violations;

/// D212, D213
/// D212
pub fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstring) {
let contents = docstring.contents;
let body = docstring.body;
Expand Down Expand Up @@ -51,63 +50,5 @@ pub fn multi_line_summary_start(checker: &mut Checker, docstring: &Docstring) {
}
checker.diagnostics.push(diagnostic);
}
} else {
if checker
.settings
.rules
.enabled(&Rule::MultiLineSummarySecondLine)
{
let mut diagnostic = Diagnostic::new(
violations::MultiLineSummarySecondLine,
Range::from_located(docstring.expr),
);
if checker.patch(diagnostic.kind.rule()) {
let mut indentation = String::from(docstring.indentation);
let mut fixable = true;
if !indentation.chars().all(char::is_whitespace) {
fixable = false;

// If the docstring isn't on its own line, look at the parent indentation, and
// add the default indentation to get the "right" level.
if let DefinitionKind::Class(parent)
| DefinitionKind::NestedClass(parent)
| DefinitionKind::Function(parent)
| DefinitionKind::NestedFunction(parent)
| DefinitionKind::Method(parent) = &docstring.kind
{
let parent_indentation =
checker.locator.slice_source_code_range(&Range::new(
Location::new(parent.location.row(), 0),
Location::new(parent.location.row(), parent.location.column()),
));
if parent_indentation.chars().all(char::is_whitespace) {
indentation.clear();
indentation.push_str(parent_indentation);
indentation.push_str(checker.stylist.indentation());
fixable = true;
}
};
}

if fixable {
let location = docstring.expr.location;
let prefix = leading_quote(contents).unwrap();
// Use replacement instead of insert to trim possible whitespace between leading
// quote and text.
let repl = format!(
"{}{}{}",
checker.stylist.line_ending().as_str(),
indentation,
first_line.strip_prefix(prefix).unwrap().trim_start()
);
diagnostic.amend(Fix::replacement(
repl,
Location::new(location.row(), location.column() + prefix.len()),
Location::new(location.row(), location.column() + first_line.len()),
));
}
}
checker.diagnostics.push(diagnostic);
}
}
}
6 changes: 0 additions & 6 deletions src/rules/pydocstyle/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,7 @@ impl Convention {
pub fn rules_to_be_ignored(self) -> &'static [Rule] {
match self {
Convention::Google => &[
Rule::OneBlankLineBeforeClass,
Rule::OneBlankLineAfterClass,
Rule::MultiLineSummarySecondLine,
Rule::SectionUnderlineNotOverIndented,
Rule::EndsInPeriod,
Rule::NoThisPrefix,
Expand All @@ -35,19 +33,15 @@ impl Convention {
],
Convention::Numpy => &[
Rule::PublicInit,
Rule::OneBlankLineBeforeClass,
Rule::MultiLineSummaryFirstLine,
Rule::MultiLineSummarySecondLine,
Rule::NoSignature,
Rule::BlankLineAfterLastSection,
Rule::EndsInPunctuation,
Rule::SectionNameEndsInColon,
Rule::DocumentAllArguments,
],
Convention::Pep257 => &[
Rule::OneBlankLineBeforeClass,
Rule::MultiLineSummaryFirstLine,
Rule::MultiLineSummarySecondLine,
Rule::SectionNotOverIndented,
Rule::SectionUnderlineNotOverIndented,
Rule::NoThisPrefix,
Expand Down

This file was deleted.

Loading

0 comments on commit e7c4fa7

Please sign in to comment.