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-D405] Allow using parameters as a sub-section header #9894

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
43 changes: 43 additions & 0 deletions crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py
Original file line number Diff line number Diff line change
Expand Up @@ -562,3 +562,46 @@ def titlecase_sub_section_header():

Returns:
"""


def test_method_should_be_correctly_capitalized(parameters: list[str], other_parameters: dict[str, str]): # noqa: D213
"""Test parameters and attributes sections are capitalized correctly.

Parameters
----------
parameters:
A list of string parameters
other_parameters:
A dictionary of string attributes

Other Parameters
----------
other_parameters:
A dictionary of string attributes
parameters:
A list of string parameters

"""


def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], value: int): # noqa: D213
"""Test that lower case subsection header is valid even if it has the same name as section kind.

Parameters:
----------
parameters:
A list of string parameters
value:
Some value
"""


def test_lowercase_sub_section_header_different_kind(returns: int):
"""Test that lower case subsection header is valid even if it is of a different kind.

Parameters
-‐-----------------
returns:
some value

"""
77 changes: 73 additions & 4 deletions crates/ruff_linter/src/docstrings/sections.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,34 @@ impl SectionKind {
Self::Yields => "Yields",
}
}

/// Returns `true` if a section can contain subsections, as in:
/// ```python
/// Yields
/// ------
/// int
/// Description of the anonymous integer return value.
/// ```
///
/// For NumPy, see: <https://numpydoc.readthedocs.io/en/latest/format.html>
///
/// For Google, see: <https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings>
pub(crate) fn has_subsections(self) -> bool {
matches!(
self,
Self::Args
| Self::Arguments
| Self::OtherArgs
| Self::OtherParameters
| Self::OtherParams
| Self::Parameters
| Self::Raises
| Self::Returns
| Self::SeeAlso
| Self::Warns
| Self::Yields
)
}
}

pub(crate) struct SectionContexts<'a> {
Expand Down Expand Up @@ -459,13 +487,54 @@ fn is_docstring_section(
// args: The arguments to the function.
// """
// ```
// Or `parameters` in:
// ```python
// def func(parameters: tuple[int]):
// """Toggle the gizmo.
//
// Parameters:
// -----
// parameters:
// The arguments to the function.
// """
// ```
// However, if the header is an _exact_ match (like `Returns:`, as opposed to `returns:`), then
// continue to treat it as a section header.
if let Some(previous_section) = previous_section {
if previous_section.indent_size < indent_size {
if section_kind.has_subsections() {
if let Some(previous_section) = previous_section {
let verbatim = &line[TextRange::at(indent_size, section_name_size)];
if section_kind.as_str() != verbatim {
return false;

// If the section is more deeply indented, assume it's a subsection, as in:
// ```python
// def func(args: tuple[int]):
// """Toggle the gizmo.
//
// Args:
// args: The arguments to the function.
// """
// ```
if previous_section.indent_size < indent_size {
if section_kind.as_str() != verbatim {
return false;
}
}

// If the section isn't underlined, and isn't title-cased, assume it's a subsection,
// as in:
// ```python
// def func(parameters: tuple[int]):
// """Toggle the gizmo.
//
// Parameters:
// -----
// parameters:
// The arguments to the function.
// """
// ```
if !next_line_is_underline && verbatim.chars().next().is_some_and(char::is_lowercase) {
if section_kind.as_str() != verbatim {
return false;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,5 +49,7 @@ sections.py:558:5: D214 [*] Section is over-indented ("Returns")
563 |- Returns:
563 |+ Returns:
564 564 | """
565 565 |
566 566 |


Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,31 @@ sections.py:216:5: D406 [*] Section name should end with a newline ("Raises")
229 229 |
230 230 | """

sections.py:588:5: D406 [*] Section name should end with a newline ("Parameters")
|
587 | def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], value: int): # noqa: D213
588 | """Test that lower case subsection header is valid even if it has the same name as section kind.
| _____^
589 | |
590 | | Parameters:
591 | | ----------
592 | | parameters:
593 | | A list of string parameters
594 | | value:
595 | | Some value
596 | | """
| |_______^ D406
|
= help: Add newline after "Parameters"

ℹ Safe fix
587 587 | def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], value: int): # noqa: D213
588 588 | """Test that lower case subsection header is valid even if it has the same name as section kind.
589 589 |
590 |- Parameters:
590 |+ Parameters
591 591 | ----------
592 592 | parameters:
593 593 | A list of string parameters


Original file line number Diff line number Diff line change
Expand Up @@ -567,5 +567,32 @@ sections.py:558:5: D407 [*] Missing dashed underline after section ("Returns")
563 563 | Returns:
564 |+ -------
564 565 | """
565 566 |
566 567 |

sections.py:600:4: D407 [*] Missing dashed underline after section ("Parameters")
|
599 | def test_lowercase_sub_section_header_different_kind(returns: int):
600 | """Test that lower case subsection header is valid even if it is of a different kind.
| ____^
601 | |
602 | | Parameters
603 | | -‐-----------------
604 | | returns:
605 | | some value
606 | |
607 | | """
| |______^ D407
|
= help: Add dashed line under "Parameters"

ℹ Safe fix
600 600 | """Test that lower case subsection header is valid even if it is of a different kind.
601 601 |
602 602 | Parameters
603 |+ ----------
603 604 | -‐-----------------
604 605 | returns:
605 606 | some value


Original file line number Diff line number Diff line change
Expand Up @@ -61,4 +61,39 @@ sections.py:216:5: D409 [*] Section underline should match the length of its nam
227 227 | Raises:
228 228 | My attention.

sections.py:568:5: D409 [*] Section underline should match the length of its name ("Other Parameters")
|
567 | def test_method_should_be_correctly_capitalized(parameters: list[str], other_parameters: dict[str, str]): # noqa: D213
568 | """Test parameters and attributes sections are capitalized correctly.
| _____^
569 | |
570 | | Parameters
571 | | ----------
572 | | parameters:
573 | | A list of string parameters
574 | | other_parameters:
575 | | A dictionary of string attributes
576 | |
577 | | Other Parameters
578 | | ----------
579 | | other_parameters:
580 | | A dictionary of string attributes
581 | | parameters:
582 | | A list of string parameters
583 | |
584 | | """
| |_______^ D409
|
= help: Adjust underline length to match "Other Parameters"

ℹ Safe fix
575 575 | A dictionary of string attributes
576 576 |
577 577 | Other Parameters
578 |- ----------
578 |+ ----------------
579 579 | other_parameters:
580 580 | A dictionary of string attributes
581 581 | parameters:


Original file line number Diff line number Diff line change
Expand Up @@ -161,5 +161,33 @@ sections.py:558:5: D413 [*] Missing blank line after last section ("Returns")
563 563 | Returns:
564 |+
564 565 | """
565 566 |
566 567 |

sections.py:588:5: D413 [*] Missing blank line after last section ("Parameters")
|
587 | def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], value: int): # noqa: D213
588 | """Test that lower case subsection header is valid even if it has the same name as section kind.
| _____^
589 | |
590 | | Parameters:
591 | | ----------
592 | | parameters:
593 | | A list of string parameters
594 | | value:
595 | | Some value
596 | | """
| |_______^ D413
|
= help: Add blank line after "Parameters"

ℹ Safe fix
593 593 | A list of string parameters
594 594 | value:
595 595 | Some value
596 |+
596 597 | """
597 598 |
598 599 |


Loading