Skip to content

[pydocstyle] Skip section detection inside RST directive bodies (D214, D405, D413)#23635

Open
bxff wants to merge 1 commit intoastral-sh:mainfrom
bxff:investigate/sphinx-docstring-reformat
Open

[pydocstyle] Skip section detection inside RST directive bodies (D214, D405, D413)#23635
bxff wants to merge 1 commit intoastral-sh:mainfrom
bxff:investigate/sphinx-docstring-reformat

Conversation

@bxff
Copy link
Copy Markdown
Contributor

@bxff bxff commented Feb 28, 2026

Summary

Fixes #23562.

Content inside reStructuredText directives (e.g., .. code-block:: yaml) was incorrectly identified as docstring section headers. For example, references: inside a code-block would trigger D405 (capitalization), D214 (over-indentation), and D413 (missing blank line).

The root cause is that the section parser in from_docstring (docstrings/sections.rs) iterates docstring lines and calls is_docstring_section with no awareness of RST directive blocks. The word references matches SectionKind::References, the suffix : passes the section name check, and the preceding blank line (required by RST after the directive declaration) satisfies the end-of-paragraph heuristic.

There is already existing RST awareness in blanks_and_section_underline (the is_sphinx check at lines 1593 and 1691), but that serves a different purpose — it preserves blank lines when a real section header like Example: has a .. code-block:: directive as its body content. This fix is complementary: it prevents content inside a directive body from being misidentified as section headers in the first place.

This adds RST directive body tracking to from_docstring. When a line starting with .. is detected (an RST directive), all subsequent lines indented deeper than the directive are skipped from section detection. Real sections after directives continue to be detected correctly.

Test Plan

Added sphinx_directive.py test fixture with cases for:

  • Module-level docstring with .. code-block:: yaml containing references: (the exact case from ruff incorrectly reformatting Sphinx docstrings #23562)
  • Function-level docstring with directive followed by real sections (Returns:)
  • Single-colon directive variant (.. code-block: yaml)
  • Nested directives (.. note:: containing .. code-block::)
  • Real section (Notes:) following a directive — verifies sections after directives are still detected

Registered test cases for D214, D405, and D413 against the new fixture. All 72 pydocstyle tests pass:

cargo test -p ruff_linter -- "pydocstyle::tests::rules"
test result: ok. 72 passed; 0 failed; 0 ignored

Also manually verified the original reproduction case no longer triggers D405/D214/D413 false positives.

…214`, `D405`, `D413`)

Closes astral-sh#23562

Content inside reStructuredText directives (e.g., `.. code-block:: yaml`) was incorrectly identified as docstring section headers. For example, `references:` inside a code-block would trigger D405 (capitalization), D214 (over-indentation), and D413 (missing blank line).

This adds RST directive body tracking to `from_docstring` in the section parser. When a line starting with `.. ` is detected, all subsequent lines indented deeper than the directive are skipped from section detection. Real sections after directives continue to be detected correctly.
@astral-sh-bot
Copy link
Copy Markdown

astral-sh-bot bot commented Feb 28, 2026

ruff-ecosystem results

Linter (stable)

✅ ecosystem check detected no linter changes.

Linter (preview)

✅ ecosystem check detected no linter changes.

@amyreese amyreese added bug Something isn't working rule Implementing or modifying a lint rule labels Mar 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working rule Implementing or modifying a lint rule

Projects

None yet

Development

Successfully merging this pull request may close these issues.

ruff incorrectly reformatting Sphinx docstrings

3 participants