From 89e36ee2e7fc0fc98f6bf5432b77a8558dee2658 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikko=20Lepp=C3=A4nen?= Date: Thu, 8 Feb 2024 14:37:46 +0200 Subject: [PATCH 1/5] [pydocstyle-D405] Allow using parameters as a sub-section header --- .../test/fixtures/pydocstyle/sections.py | 31 ++ crates/ruff_linter/src/docstrings/sections.rs | 17 +- ...__pydocstyle__tests__D214_sections.py.snap | 23 -- ...__pydocstyle__tests__D406_sections.py.snap | 52 ++-- ...__pydocstyle__tests__D407_sections.py.snap | 285 ++++++------------ ...__pydocstyle__tests__D410_sections.py.snap | 33 -- ...__pydocstyle__tests__D411_sections.py.snap | 33 -- ...ules__pydocstyle__tests__D413_D413.py.snap | 12 +- ...__pydocstyle__tests__D413_sections.py.snap | 149 +++++---- ...__pydocstyle__tests__D414_sections.py.snap | 33 -- ...__pydocstyle__tests__D417_sections.py.snap | 40 +-- 11 files changed, 270 insertions(+), 438 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py b/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py index 4a50617d26be7..6ba5380e6c01b 100644 --- a/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py +++ b/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py @@ -428,6 +428,25 @@ def test_method(self, test, another_test, z, _, x=1, y=2, _private_arg=1): # no """ + def test_method_should_be_correctly_capitalized(self, parameters: list[str], attributes: dict[str, str]): # noqa: D213 + """Test parameters and attributes sections are capitalized correctly. + + Parameters + ---------- + parameters: + A list of string parameters + attributes: + A dictionary of string attributes + + Attributes + ---------- + attributes: + A dictionary of string attributes + parameters: + A list of string parameters + + """ + @expect("D417: Missing argument descriptions in the docstring " "(argument(s) test, y, z are missing descriptions in " "'test_missing_args' docstring)", arg_count=5) @@ -488,6 +507,18 @@ def test_mixing_numpy_and_google(danger): # noqa: D213 """ + @staticmethod + def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], value: int): # noqa: D213 + """Test that lower case sub-section header is valid even if it has the same name as section kind. + + Parameters: + ---------- + parameters: + A list of string parameters + value: + Some value + """ + class TestIncorrectIndent: # noqa: D203 """Test class.""" diff --git a/crates/ruff_linter/src/docstrings/sections.rs b/crates/ruff_linter/src/docstrings/sections.rs index 1ef49ea614604..923655f7b312e 100644 --- a/crates/ruff_linter/src/docstrings/sections.rs +++ b/crates/ruff_linter/src/docstrings/sections.rs @@ -459,15 +459,30 @@ fn is_docstring_section( // args: The arguments to the function. // """ // ``` + // or if the style uses Numpy convention and argument name is the same as the section name and argument type is not specified: + // ```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 { + let verbatim = &line[TextRange::at(indent_size, section_name_size)]; if previous_section.indent_size < indent_size { - let verbatim = &line[TextRange::at(indent_size, section_name_size)]; if section_kind.as_str() != verbatim { return false; } } + // sub-section header should be lower case + if verbatim.chars().next().map(char::is_lowercase).is_some() { + return false; + } } true diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D214_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D214_sections.py.snap index 3fd044b8d8514..3fb4608144b21 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D214_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D214_sections.py.snap @@ -27,27 +27,4 @@ sections.py:144:5: D214 [*] Section is over-indented ("Returns") 148 148 | A value of some sort. 149 149 | -sections.py:558:5: D214 [*] Section is over-indented ("Returns") - | -557 | def titlecase_sub_section_header(): -558 | """Below, `Returns:` should be considered a section header. - | _____^ -559 | | -560 | | Args: -561 | | Here's a note. -562 | | -563 | | Returns: -564 | | """ - | |_______^ D214 - | - = help: Remove over-indentation from "Returns" - -ℹ Safe fix -560 560 | Args: -561 561 | Here's a note. -562 562 | -563 |- Returns: - 563 |+ Returns: -564 564 | """ - diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D406_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D406_sections.py.snap index d996d6fe54aa4..06cf52bc5ca73 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D406_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D406_sections.py.snap @@ -27,38 +27,32 @@ sections.py:30:5: D406 [*] Section name should end with a newline ("Returns") 34 34 | A value of some sort. 35 35 | -sections.py:216:5: D406 [*] Section name should end with a newline ("Raises") +sections.py:512:9: D406 [*] Section name should end with a newline ("Parameters") | -214 | @expect("D407: Missing dashed underline after section ('Raises')") -215 | def multiple_sections(): # noqa: D416 -216 | """Toggle the gizmo. - | _____^ -217 | | -218 | | Short summary -219 | | ------------- -220 | | -221 | | This is the function's description, which will also specify what it -222 | | returns. -223 | | -224 | | Returns -225 | | ------ -226 | | Many many wonderful things. -227 | | Raises: -228 | | My attention. -229 | | -230 | | """ - | |_______^ D406 +510 | @staticmethod +511 | def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], value: int): # noqa: D213 +512 | """Test that lower case sub-section header is valid even if it has the same name as section kind. + | _________^ +513 | | +514 | | Parameters: +515 | | ---------- +516 | | parameters: +517 | | A list of string parameters +518 | | value: +519 | | Some value +520 | | """ + | |___________^ D406 | - = help: Add newline after "Raises" + = help: Add newline after "Parameters" ℹ Safe fix -224 224 | Returns -225 225 | ------ -226 226 | Many many wonderful things. -227 |- Raises: - 227 |+ Raises -228 228 | My attention. -229 229 | -230 230 | """ +511 511 | def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], value: int): # noqa: D213 +512 512 | """Test that lower case sub-section header is valid even if it has the same name as section kind. +513 513 | +514 |- Parameters: + 514 |+ Parameters +515 515 | ---------- +516 516 | parameters: +517 517 | A list of string parameters diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap index 53e527de24b33..77489464537fe 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap @@ -71,39 +71,6 @@ sections.py:65:5: D407 [*] Missing dashed underline after section ("Returns") 69 70 | 70 71 | @expect(_D213) -sections.py:216:5: D407 [*] Missing dashed underline after section ("Raises") - | -214 | @expect("D407: Missing dashed underline after section ('Raises')") -215 | def multiple_sections(): # noqa: D416 -216 | """Toggle the gizmo. - | _____^ -217 | | -218 | | Short summary -219 | | ------------- -220 | | -221 | | This is the function's description, which will also specify what it -222 | | returns. -223 | | -224 | | Returns -225 | | ------ -226 | | Many many wonderful things. -227 | | Raises: -228 | | My attention. -229 | | -230 | | """ - | |_______^ D407 - | - = help: Add dashed line under "Raises" - -ℹ Safe fix -225 225 | ------ -226 226 | Many many wonderful things. -227 227 | Raises: - 228 |+ ------ -228 229 | My attention. -229 230 | -230 231 | """ - sections.py:261:5: D407 [*] Missing dashed underline after section ("Args") | 259 | @expect("D414: Section has no content ('Returns')") @@ -133,64 +100,6 @@ sections.py:261:5: D407 [*] Missing dashed underline after section ("Args") 265 266 | 266 267 | Returns: -sections.py:261:5: D407 [*] Missing dashed underline after section ("Returns") - | -259 | @expect("D414: Section has no content ('Returns')") -260 | def valid_google_style_section(): # noqa: D406, D407 -261 | """Toggle the gizmo. - | _____^ -262 | | -263 | | Args: -264 | | note: A random string. -265 | | -266 | | Returns: -267 | | -268 | | Raises: -269 | | RandomError: A random error that occurs randomly. -270 | | -271 | | """ - | |_______^ D407 - | - = help: Add dashed line under "Returns" - -ℹ Safe fix -264 264 | note: A random string. -265 265 | -266 266 | Returns: - 267 |+ ------- -267 268 | -268 269 | Raises: -269 270 | RandomError: A random error that occurs randomly. - -sections.py:261:5: D407 [*] Missing dashed underline after section ("Raises") - | -259 | @expect("D414: Section has no content ('Returns')") -260 | def valid_google_style_section(): # noqa: D406, D407 -261 | """Toggle the gizmo. - | _____^ -262 | | -263 | | Args: -264 | | note: A random string. -265 | | -266 | | Returns: -267 | | -268 | | Raises: -269 | | RandomError: A random error that occurs randomly. -270 | | -271 | | """ - | |_______^ D407 - | - = help: Add dashed line under "Raises" - -ℹ Safe fix -266 266 | Returns: -267 267 | -268 268 | Raises: - 269 |+ ------ -269 270 | RandomError: A random error that occurs randomly. -270 271 | -271 272 | """ - sections.py:278:5: D407 [*] Missing dashed underline after section ("Args") | 276 | "('Args:', not 'Args')") @@ -427,145 +336,123 @@ sections.py:380:9: D407 [*] Missing dashed underline after section ("Args") 384 385 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. 385 386 | Etiam at tellus a tellus faucibus maximus. Curabitur tellus -sections.py:499:9: D407 [*] Missing dashed underline after section ("Args") +sections.py:530:9: D407 [*] Missing dashed underline after section ("Args") | -497 | "'test_incorrect_indent' docstring)", arg_count=3) -498 | def test_incorrect_indent(self, x=1, y=2): # noqa: D207, D213, D407 -499 | """Reproducing issue #437. +528 | "'test_incorrect_indent' docstring)", arg_count=3) +529 | def test_incorrect_indent(self, x=1, y=2): # noqa: D207, D213, D407 +530 | """Reproducing issue #437. | _________^ -500 | | -501 | | Testing this incorrectly indented docstring. -502 | | -503 | | Args: -504 | | x: Test argument. -505 | | -506 | | """ +531 | | +532 | | Testing this incorrectly indented docstring. +533 | | +534 | | Args: +535 | | x: Test argument. +536 | | +537 | | """ | |___________^ D407 | = help: Add dashed line under "Args" ℹ Safe fix -501 501 | Testing this incorrectly indented docstring. -502 502 | -503 503 | Args: - 504 |+ ---- -504 505 | x: Test argument. -505 506 | -506 507 | """ - -sections.py:519:5: D407 [*] Missing dashed underline after section ("Parameters") - | -518 | def replace_equals_with_dash(): -519 | """Equal length equals should be replaced with dashes. +532 532 | Testing this incorrectly indented docstring. +533 533 | +534 534 | Args: + 535 |+ ---- +535 536 | x: Test argument. +536 537 | +537 538 | """ + +sections.py:550:5: D407 [*] Missing dashed underline after section ("Parameters") + | +549 | def replace_equals_with_dash(): +550 | """Equal length equals should be replaced with dashes. | _____^ -520 | | -521 | | Parameters -522 | | ========== -523 | | """ +551 | | +552 | | Parameters +553 | | ========== +554 | | """ | |_______^ D407 | = help: Add dashed line under "Parameters" ℹ Safe fix -519 519 | """Equal length equals should be replaced with dashes. -520 520 | -521 521 | Parameters -522 |- ========== - 522 |+ ---------- -523 523 | """ -524 524 | -525 525 | - -sections.py:527:5: D407 [*] Missing dashed underline after section ("Parameters") - | -526 | def replace_equals_with_dash2(): -527 | """Here, the length of equals is not the same. +550 550 | """Equal length equals should be replaced with dashes. +551 551 | +552 552 | Parameters +553 |- ========== + 553 |+ ---------- +554 554 | """ +555 555 | +556 556 | + +sections.py:558:5: D407 [*] Missing dashed underline after section ("Parameters") + | +557 | def replace_equals_with_dash2(): +558 | """Here, the length of equals is not the same. | _____^ -528 | | -529 | | Parameters -530 | | =========== -531 | | """ +559 | | +560 | | Parameters +561 | | =========== +562 | | """ | |_______^ D407 | = help: Add dashed line under "Parameters" ℹ Safe fix -527 527 | """Here, the length of equals is not the same. -528 528 | -529 529 | Parameters - 530 |+ ---------- -530 531 | =========== -531 532 | """ -532 533 | - -sections.py:548:5: D407 [*] Missing dashed underline after section ("Args") - | -547 | def lowercase_sub_section_header(): -548 | """Below, `returns:` should _not_ be considered a section header. - | _____^ -549 | | -550 | | Args: -551 | | Here's a note. -552 | | -553 | | returns: -554 | | """ - | |_______^ D407 - | - = help: Add dashed line under "Args" +558 558 | """Here, the length of equals is not the same. +559 559 | +560 560 | Parameters + 561 |+ ---------- +561 562 | =========== +562 563 | """ +563 564 | -ℹ Safe fix -548 548 | """Below, `returns:` should _not_ be considered a section header. -549 549 | -550 550 | Args: - 551 |+ ---- -551 552 | Here's a note. -552 553 | -553 554 | returns: - -sections.py:558:5: D407 [*] Missing dashed underline after section ("Args") +sections.py:579:5: D407 [*] Missing dashed underline after section ("Args") | -557 | def titlecase_sub_section_header(): -558 | """Below, `Returns:` should be considered a section header. +578 | def lowercase_sub_section_header(): +579 | """Below, `returns:` should _not_ be considered a section header. | _____^ -559 | | -560 | | Args: -561 | | Here's a note. -562 | | -563 | | Returns: -564 | | """ +580 | | +581 | | Args: +582 | | Here's a note. +583 | | +584 | | returns: +585 | | """ | |_______^ D407 | = help: Add dashed line under "Args" ℹ Safe fix -558 558 | """Below, `Returns:` should be considered a section header. -559 559 | -560 560 | Args: - 561 |+ ---- -561 562 | Here's a note. -562 563 | -563 564 | Returns: - -sections.py:558:5: D407 [*] Missing dashed underline after section ("Returns") - | -557 | def titlecase_sub_section_header(): -558 | """Below, `Returns:` should be considered a section header. +579 579 | """Below, `returns:` should _not_ be considered a section header. +580 580 | +581 581 | Args: + 582 |+ ---- +582 583 | Here's a note. +583 584 | +584 585 | returns: + +sections.py:589:5: D407 [*] Missing dashed underline after section ("Args") + | +588 | def titlecase_sub_section_header(): +589 | """Below, `Returns:` should be considered a section header. | _____^ -559 | | -560 | | Args: -561 | | Here's a note. -562 | | -563 | | Returns: -564 | | """ +590 | | +591 | | Args: +592 | | Here's a note. +593 | | +594 | | Returns: +595 | | """ | |_______^ D407 | - = help: Add dashed line under "Returns" + = help: Add dashed line under "Args" ℹ Safe fix -561 561 | Here's a note. -562 562 | -563 563 | Returns: - 564 |+ ------- -564 565 | """ +589 589 | """Below, `Returns:` should be considered a section header. +590 590 | +591 591 | Args: + 592 |+ ---- +592 593 | Here's a note. +593 594 | +594 595 | Returns: diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D410_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D410_sections.py.snap index 00d15acee3dfc..cde27ad469856 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D410_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D410_sections.py.snap @@ -31,37 +31,4 @@ sections.py:76:5: D410 [*] Missing blank line after section ("Returns") 81 82 | ------ 82 83 | -sections.py:216:5: D410 [*] Missing blank line after section ("Returns") - | -214 | @expect("D407: Missing dashed underline after section ('Raises')") -215 | def multiple_sections(): # noqa: D416 -216 | """Toggle the gizmo. - | _____^ -217 | | -218 | | Short summary -219 | | ------------- -220 | | -221 | | This is the function's description, which will also specify what it -222 | | returns. -223 | | -224 | | Returns -225 | | ------ -226 | | Many many wonderful things. -227 | | Raises: -228 | | My attention. -229 | | -230 | | """ - | |_______^ D410 - | - = help: Add blank line after "Returns" - -ℹ Safe fix -224 224 | Returns -225 225 | ------ -226 226 | Many many wonderful things. - 227 |+ -227 228 | Raises: -228 229 | My attention. -229 230 | - diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D411_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D411_sections.py.snap index f93054611928b..0ce8c968ded72 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D411_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D411_sections.py.snap @@ -57,37 +57,4 @@ sections.py:131:5: D411 [*] Missing blank line before section ("Returns") 135 136 | ------- 136 137 | A value of some sort. -sections.py:216:5: D411 [*] Missing blank line before section ("Raises") - | -214 | @expect("D407: Missing dashed underline after section ('Raises')") -215 | def multiple_sections(): # noqa: D416 -216 | """Toggle the gizmo. - | _____^ -217 | | -218 | | Short summary -219 | | ------------- -220 | | -221 | | This is the function's description, which will also specify what it -222 | | returns. -223 | | -224 | | Returns -225 | | ------ -226 | | Many many wonderful things. -227 | | Raises: -228 | | My attention. -229 | | -230 | | """ - | |_______^ D411 - | - = help: Add blank line before "Raises" - -ℹ Safe fix -224 224 | Returns -225 225 | ------ -226 226 | Many many wonderful things. - 227 |+ -227 228 | Raises: -228 229 | My attention. -229 230 | - diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_D413.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_D413.py.snap index eda7d334cfaad..dee6268920af2 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_D413.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_D413.py.snap @@ -1,7 +1,7 @@ --- source: crates/ruff_linter/src/rules/pydocstyle/mod.rs --- -D413.py:1:1: D413 [*] Missing blank line after last section ("Returns") +D413.py:1:1: D413 [*] Missing blank line after last section ("Args") | 1 | / """Do something. 2 | | @@ -14,7 +14,7 @@ D413.py:1:1: D413 [*] Missing blank line after last section ("Returns") 9 | | """ | |___^ D413 | - = help: Add blank line after "Returns" + = help: Add blank line after "Args" ℹ Safe fix 6 6 | @@ -26,7 +26,7 @@ D413.py:1:1: D413 [*] Missing blank line after last section ("Returns") 10 12 | 11 13 | -D413.py:13:5: D413 [*] Missing blank line after last section ("Returns") +D413.py:13:5: D413 [*] Missing blank line after last section ("Args") | 12 | def func(): 13 | """Do something. @@ -41,7 +41,7 @@ D413.py:13:5: D413 [*] Missing blank line after last section ("Returns") 21 | | """ | |_______^ D413 | - = help: Add blank line after "Returns" + = help: Add blank line after "Args" ℹ Safe fix 18 18 | @@ -52,7 +52,7 @@ D413.py:13:5: D413 [*] Missing blank line after last section ("Returns") 22 23 | 23 24 | -D413.py:52:5: D413 [*] Missing blank line after last section ("Returns") +D413.py:52:5: D413 [*] Missing blank line after last section ("Args") | 51 | def func(): 52 | """Do something. @@ -66,7 +66,7 @@ D413.py:52:5: D413 [*] Missing blank line after last section ("Returns") 59 | | the value""" | |____________________^ D413 | - = help: Add blank line after "Returns" + = help: Add blank line after "Args" ℹ Safe fix 56 56 | with a hanging indent diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap index f2bf6474708dc..d9bbae68c3b18 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap @@ -72,94 +72,121 @@ sections.py:170:5: D413 [*] Missing blank line after last section ("Returns") 175 176 | 176 177 | -sections.py:519:5: D413 [*] Missing blank line after last section ("Parameters") +sections.py:512:9: D413 [*] Missing blank line after last section ("Parameters") | -518 | def replace_equals_with_dash(): -519 | """Equal length equals should be replaced with dashes. +510 | @staticmethod +511 | def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], value: int): # noqa: D213 +512 | """Test that lower case sub-section header is valid even if it has the same name as section kind. + | _________^ +513 | | +514 | | Parameters: +515 | | ---------- +516 | | parameters: +517 | | A list of string parameters +518 | | value: +519 | | Some value +520 | | """ + | |___________^ D413 + | + = help: Add blank line after "Parameters" + +ℹ Safe fix +517 517 | A list of string parameters +518 518 | value: +519 519 | Some value + 520 |+ +520 521 | """ +521 522 | +522 523 | + +sections.py:550:5: D413 [*] Missing blank line after last section ("Parameters") + | +549 | def replace_equals_with_dash(): +550 | """Equal length equals should be replaced with dashes. | _____^ -520 | | -521 | | Parameters -522 | | ========== -523 | | """ +551 | | +552 | | Parameters +553 | | ========== +554 | | """ | |_______^ D413 | = help: Add blank line after "Parameters" ℹ Safe fix -520 520 | -521 521 | Parameters -522 522 | ========== - 523 |+ -523 524 | """ -524 525 | -525 526 | - -sections.py:527:5: D413 [*] Missing blank line after last section ("Parameters") +551 551 | +552 552 | Parameters +553 553 | ========== + 554 |+ +554 555 | """ +555 556 | +556 557 | + +sections.py:558:5: D413 [*] Missing blank line after last section ("Parameters") | -526 | def replace_equals_with_dash2(): -527 | """Here, the length of equals is not the same. +557 | def replace_equals_with_dash2(): +558 | """Here, the length of equals is not the same. | _____^ -528 | | -529 | | Parameters -530 | | =========== -531 | | """ +559 | | +560 | | Parameters +561 | | =========== +562 | | """ | |_______^ D413 | = help: Add blank line after "Parameters" ℹ Safe fix -528 528 | -529 529 | Parameters -530 530 | =========== - 531 |+ -531 532 | """ -532 533 | -533 534 | - -sections.py:548:5: D413 [*] Missing blank line after last section ("Args") +559 559 | +560 560 | Parameters +561 561 | =========== + 562 |+ +562 563 | """ +563 564 | +564 565 | + +sections.py:579:5: D413 [*] Missing blank line after last section ("Args") | -547 | def lowercase_sub_section_header(): -548 | """Below, `returns:` should _not_ be considered a section header. +578 | def lowercase_sub_section_header(): +579 | """Below, `returns:` should _not_ be considered a section header. | _____^ -549 | | -550 | | Args: -551 | | Here's a note. -552 | | -553 | | returns: -554 | | """ +580 | | +581 | | Args: +582 | | Here's a note. +583 | | +584 | | returns: +585 | | """ | |_______^ D413 | = help: Add blank line after "Args" ℹ Safe fix -551 551 | Here's a note. -552 552 | -553 553 | returns: - 554 |+ -554 555 | """ -555 556 | -556 557 | +582 582 | Here's a note. +583 583 | +584 584 | returns: + 585 |+ +585 586 | """ +586 587 | +587 588 | -sections.py:558:5: D413 [*] Missing blank line after last section ("Returns") +sections.py:589:5: D413 [*] Missing blank line after last section ("Args") | -557 | def titlecase_sub_section_header(): -558 | """Below, `Returns:` should be considered a section header. +588 | def titlecase_sub_section_header(): +589 | """Below, `Returns:` should be considered a section header. | _____^ -559 | | -560 | | Args: -561 | | Here's a note. -562 | | -563 | | Returns: -564 | | """ +590 | | +591 | | Args: +592 | | Here's a note. +593 | | +594 | | Returns: +595 | | """ | |_______^ D413 | - = help: Add blank line after "Returns" + = help: Add blank line after "Args" ℹ Safe fix -561 561 | Here's a note. -562 562 | -563 563 | Returns: - 564 |+ -564 565 | """ +592 592 | Here's a note. +593 593 | +594 594 | Returns: + 595 |+ +595 596 | """ diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D414_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D414_sections.py.snap index 9566fd691a6d4..11e9d33971937 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D414_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D414_sections.py.snap @@ -78,37 +78,4 @@ sections.py:170:5: D414 Section has no content ("Returns") | |_______^ D414 | -sections.py:261:5: D414 Section has no content ("Returns") - | -259 | @expect("D414: Section has no content ('Returns')") -260 | def valid_google_style_section(): # noqa: D406, D407 -261 | """Toggle the gizmo. - | _____^ -262 | | -263 | | Args: -264 | | note: A random string. -265 | | -266 | | Returns: -267 | | -268 | | Raises: -269 | | RandomError: A random error that occurs randomly. -270 | | -271 | | """ - | |_______^ D414 - | - -sections.py:558:5: D414 Section has no content ("Returns") - | -557 | def titlecase_sub_section_header(): -558 | """Below, `Returns:` should be considered a section header. - | _____^ -559 | | -560 | | Args: -561 | | Here's a note. -562 | | -563 | | Returns: -564 | | """ - | |_______^ D414 - | - diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D417_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D417_sections.py.snap index 1ea30245856fa..2d276f575ac90 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D417_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D417_sections.py.snap @@ -64,40 +64,40 @@ sections.py:398:5: D417 Missing argument description in the docstring for `test_ 399 | """Toggle the gizmo. | -sections.py:434:9: D417 Missing argument descriptions in the docstring for `test_missing_args`: `test`, `y`, `z` +sections.py:453:9: D417 Missing argument descriptions in the docstring for `test_missing_args`: `test`, `y`, `z` | -432 | "(argument(s) test, y, z are missing descriptions in " -433 | "'test_missing_args' docstring)", arg_count=5) -434 | def test_missing_args(self, test, x, y, z=3, t=1, _private=0): # noqa: D213, D407 +451 | "(argument(s) test, y, z are missing descriptions in " +452 | "'test_missing_args' docstring)", arg_count=5) +453 | def test_missing_args(self, test, x, y, z=3, t=1, _private=0): # noqa: D213, D407 | ^^^^^^^^^^^^^^^^^ D417 -435 | """Test a valid args section. +454 | """Test a valid args section. | -sections.py:449:9: D417 Missing argument descriptions in the docstring for `test_missing_args_class_method`: `test`, `y`, `z` +sections.py:468:9: D417 Missing argument descriptions in the docstring for `test_missing_args_class_method`: `test`, `y`, `z` | -447 | "(argument(s) test, y, z are missing descriptions in " -448 | "'test_missing_args_class_method' docstring)", arg_count=4) -449 | def test_missing_args_class_method(cls, test, x, y, z=3): # noqa: D213, D407 +466 | "(argument(s) test, y, z are missing descriptions in " +467 | "'test_missing_args_class_method' docstring)", arg_count=4) +468 | def test_missing_args_class_method(cls, test, x, y, z=3): # noqa: D213, D407 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D417 -450 | """Test a valid args section. +469 | """Test a valid args section. | -sections.py:468:9: D417 Missing argument descriptions in the docstring for `test_missing_args_static_method`: `a`, `z` +sections.py:487:9: D417 Missing argument descriptions in the docstring for `test_missing_args_static_method`: `a`, `z` | -466 | "(argument(s) a, z are missing descriptions in " -467 | "'test_missing_args_static_method' docstring)", arg_count=3) -468 | def test_missing_args_static_method(a, x, y, z=3, t=1): # noqa: D213, D407 +485 | "(argument(s) a, z are missing descriptions in " +486 | "'test_missing_args_static_method' docstring)", arg_count=3) +487 | def test_missing_args_static_method(a, x, y, z=3, t=1): # noqa: D213, D407 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D417 -469 | """Test a valid args section. +488 | """Test a valid args section. | -sections.py:498:9: D417 Missing argument description in the docstring for `test_incorrect_indent`: `y` +sections.py:529:9: D417 Missing argument description in the docstring for `test_incorrect_indent`: `y` | -496 | "(argument(s) y are missing descriptions in " -497 | "'test_incorrect_indent' docstring)", arg_count=3) -498 | def test_incorrect_indent(self, x=1, y=2): # noqa: D207, D213, D407 +527 | "(argument(s) y are missing descriptions in " +528 | "'test_incorrect_indent' docstring)", arg_count=3) +529 | def test_incorrect_indent(self, x=1, y=2): # noqa: D207, D213, D407 | ^^^^^^^^^^^^^^^^^^^^^ D417 -499 | """Reproducing issue #437. +530 | """Reproducing issue #437. | From 247539b6f0f18f171e07e99dc3c4a799cb5cad63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mikko=20Lepp=C3=A4nen?= Date: Thu, 8 Feb 2024 15:40:53 +0200 Subject: [PATCH 2/5] minor test case change: using Other Parameters instead of Attributes --- .../test/fixtures/pydocstyle/sections.py | 8 ++-- ...__pydocstyle__tests__D409_sections.py.snap | 37 +++++++++++++++++++ 2 files changed, 41 insertions(+), 4 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py b/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py index 6ba5380e6c01b..e7524901b7f6f 100644 --- a/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py +++ b/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py @@ -428,19 +428,19 @@ def test_method(self, test, another_test, z, _, x=1, y=2, _private_arg=1): # no """ - def test_method_should_be_correctly_capitalized(self, parameters: list[str], attributes: dict[str, str]): # noqa: D213 + def test_method_should_be_correctly_capitalized(self, 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 - attributes: + other_parameters: A dictionary of string attributes - Attributes + Other Parameters ---------- - attributes: + other_parameters: A dictionary of string attributes parameters: A list of string parameters diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D409_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D409_sections.py.snap index ce559c70a0dc2..e600d19fb5104 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D409_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D409_sections.py.snap @@ -61,4 +61,41 @@ sections.py:216:5: D409 [*] Section underline should match the length of its nam 227 227 | Raises: 228 228 | My attention. +sections.py:432:9: D409 [*] Section underline should match the length of its name ("Other Parameters") + | +431 | def test_method_should_be_correctly_capitalized(self, parameters: list[str], other_parameters: dict[str, str]): # noqa: D213 +432 | """Test parameters and attributes sections are capitalized correctly. + | _________^ +433 | | +434 | | Parameters +435 | | ---------- +436 | | parameters: +437 | | A list of string parameters +438 | | other_parameters: +439 | | A dictionary of string attributes +440 | | +441 | | Other Parameters +442 | | ---------- +443 | | other_parameters: +444 | | A dictionary of string attributes +445 | | parameters: +446 | | A list of string parameters +447 | | +448 | | """ + | |___________^ D409 +449 | +450 | @expect("D417: Missing argument descriptions in the docstring " + | + = help: Adjust underline length to match "Other Parameters" + +ℹ Safe fix +439 439 | A dictionary of string attributes +440 440 | +441 441 | Other Parameters +442 |- ---------- + 442 |+ ---------------- +443 443 | other_parameters: +444 444 | A dictionary of string attributes +445 445 | parameters: + From c53fdb0a76cc9727e7ce8c93573967486bb37d66 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 8 Feb 2024 16:05:42 -0500 Subject: [PATCH 3/5] Fix condition --- crates/ruff_linter/src/docstrings/sections.rs | 8 +- ...__pydocstyle__tests__D214_sections.py.snap | 23 ++++ ...__pydocstyle__tests__D406_sections.py.snap | 34 ++++++ ...__pydocstyle__tests__D407_sections.py.snap | 113 ++++++++++++++++++ ...__pydocstyle__tests__D410_sections.py.snap | 33 +++++ ...__pydocstyle__tests__D411_sections.py.snap | 33 +++++ ...ules__pydocstyle__tests__D413_D413.py.snap | 12 +- ...__pydocstyle__tests__D413_sections.py.snap | 4 +- ...__pydocstyle__tests__D414_sections.py.snap | 33 +++++ 9 files changed, 279 insertions(+), 14 deletions(-) diff --git a/crates/ruff_linter/src/docstrings/sections.rs b/crates/ruff_linter/src/docstrings/sections.rs index 923655f7b312e..c98d1d5e22483 100644 --- a/crates/ruff_linter/src/docstrings/sections.rs +++ b/crates/ruff_linter/src/docstrings/sections.rs @@ -459,7 +459,7 @@ fn is_docstring_section( // args: The arguments to the function. // """ // ``` - // or if the style uses Numpy convention and argument name is the same as the section name and argument type is not specified: + // Or `parameters` in: // ```python // def func(parameters: tuple[int]): // """Toggle the gizmo. @@ -474,15 +474,11 @@ fn is_docstring_section( // continue to treat it as a section header. if let Some(previous_section) = previous_section { let verbatim = &line[TextRange::at(indent_size, section_name_size)]; - if previous_section.indent_size < indent_size { + if previous_section.kind == section_kind || previous_section.indent_size < indent_size { if section_kind.as_str() != verbatim { return false; } } - // sub-section header should be lower case - if verbatim.chars().next().map(char::is_lowercase).is_some() { - return false; - } } true diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D214_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D214_sections.py.snap index 3fb4608144b21..4b52c795bfbc1 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D214_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D214_sections.py.snap @@ -27,4 +27,27 @@ sections.py:144:5: D214 [*] Section is over-indented ("Returns") 148 148 | A value of some sort. 149 149 | +sections.py:589:5: D214 [*] Section is over-indented ("Returns") + | +588 | def titlecase_sub_section_header(): +589 | """Below, `Returns:` should be considered a section header. + | _____^ +590 | | +591 | | Args: +592 | | Here's a note. +593 | | +594 | | Returns: +595 | | """ + | |_______^ D214 + | + = help: Remove over-indentation from "Returns" + +ℹ Safe fix +591 591 | Args: +592 592 | Here's a note. +593 593 | +594 |- Returns: + 594 |+ Returns: +595 595 | """ + diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D406_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D406_sections.py.snap index 06cf52bc5ca73..4afd15c144991 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D406_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D406_sections.py.snap @@ -27,6 +27,40 @@ sections.py:30:5: D406 [*] Section name should end with a newline ("Returns") 34 34 | A value of some sort. 35 35 | +sections.py:216:5: D406 [*] Section name should end with a newline ("Raises") + | +214 | @expect("D407: Missing dashed underline after section ('Raises')") +215 | def multiple_sections(): # noqa: D416 +216 | """Toggle the gizmo. + | _____^ +217 | | +218 | | Short summary +219 | | ------------- +220 | | +221 | | This is the function's description, which will also specify what it +222 | | returns. +223 | | +224 | | Returns +225 | | ------ +226 | | Many many wonderful things. +227 | | Raises: +228 | | My attention. +229 | | +230 | | """ + | |_______^ D406 + | + = help: Add newline after "Raises" + +ℹ Safe fix +224 224 | Returns +225 225 | ------ +226 226 | Many many wonderful things. +227 |- Raises: + 227 |+ Raises +228 228 | My attention. +229 229 | +230 230 | """ + sections.py:512:9: D406 [*] Section name should end with a newline ("Parameters") | 510 | @staticmethod diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap index 77489464537fe..916cb0110c874 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap @@ -71,6 +71,39 @@ sections.py:65:5: D407 [*] Missing dashed underline after section ("Returns") 69 70 | 70 71 | @expect(_D213) +sections.py:216:5: D407 [*] Missing dashed underline after section ("Raises") + | +214 | @expect("D407: Missing dashed underline after section ('Raises')") +215 | def multiple_sections(): # noqa: D416 +216 | """Toggle the gizmo. + | _____^ +217 | | +218 | | Short summary +219 | | ------------- +220 | | +221 | | This is the function's description, which will also specify what it +222 | | returns. +223 | | +224 | | Returns +225 | | ------ +226 | | Many many wonderful things. +227 | | Raises: +228 | | My attention. +229 | | +230 | | """ + | |_______^ D407 + | + = help: Add dashed line under "Raises" + +ℹ Safe fix +225 225 | ------ +226 226 | Many many wonderful things. +227 227 | Raises: + 228 |+ ------ +228 229 | My attention. +229 230 | +230 231 | """ + sections.py:261:5: D407 [*] Missing dashed underline after section ("Args") | 259 | @expect("D414: Section has no content ('Returns')") @@ -100,6 +133,64 @@ sections.py:261:5: D407 [*] Missing dashed underline after section ("Args") 265 266 | 266 267 | Returns: +sections.py:261:5: D407 [*] Missing dashed underline after section ("Returns") + | +259 | @expect("D414: Section has no content ('Returns')") +260 | def valid_google_style_section(): # noqa: D406, D407 +261 | """Toggle the gizmo. + | _____^ +262 | | +263 | | Args: +264 | | note: A random string. +265 | | +266 | | Returns: +267 | | +268 | | Raises: +269 | | RandomError: A random error that occurs randomly. +270 | | +271 | | """ + | |_______^ D407 + | + = help: Add dashed line under "Returns" + +ℹ Safe fix +264 264 | note: A random string. +265 265 | +266 266 | Returns: + 267 |+ ------- +267 268 | +268 269 | Raises: +269 270 | RandomError: A random error that occurs randomly. + +sections.py:261:5: D407 [*] Missing dashed underline after section ("Raises") + | +259 | @expect("D414: Section has no content ('Returns')") +260 | def valid_google_style_section(): # noqa: D406, D407 +261 | """Toggle the gizmo. + | _____^ +262 | | +263 | | Args: +264 | | note: A random string. +265 | | +266 | | Returns: +267 | | +268 | | Raises: +269 | | RandomError: A random error that occurs randomly. +270 | | +271 | | """ + | |_______^ D407 + | + = help: Add dashed line under "Raises" + +ℹ Safe fix +266 266 | Returns: +267 267 | +268 268 | Raises: + 269 |+ ------ +269 270 | RandomError: A random error that occurs randomly. +270 271 | +271 272 | """ + sections.py:278:5: D407 [*] Missing dashed underline after section ("Args") | 276 | "('Args:', not 'Args')") @@ -455,4 +546,26 @@ sections.py:589:5: D407 [*] Missing dashed underline after section ("Args") 593 594 | 594 595 | Returns: +sections.py:589:5: D407 [*] Missing dashed underline after section ("Returns") + | +588 | def titlecase_sub_section_header(): +589 | """Below, `Returns:` should be considered a section header. + | _____^ +590 | | +591 | | Args: +592 | | Here's a note. +593 | | +594 | | Returns: +595 | | """ + | |_______^ D407 + | + = help: Add dashed line under "Returns" + +ℹ Safe fix +592 592 | Here's a note. +593 593 | +594 594 | Returns: + 595 |+ ------- +595 596 | """ + diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D410_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D410_sections.py.snap index cde27ad469856..00d15acee3dfc 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D410_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D410_sections.py.snap @@ -31,4 +31,37 @@ sections.py:76:5: D410 [*] Missing blank line after section ("Returns") 81 82 | ------ 82 83 | +sections.py:216:5: D410 [*] Missing blank line after section ("Returns") + | +214 | @expect("D407: Missing dashed underline after section ('Raises')") +215 | def multiple_sections(): # noqa: D416 +216 | """Toggle the gizmo. + | _____^ +217 | | +218 | | Short summary +219 | | ------------- +220 | | +221 | | This is the function's description, which will also specify what it +222 | | returns. +223 | | +224 | | Returns +225 | | ------ +226 | | Many many wonderful things. +227 | | Raises: +228 | | My attention. +229 | | +230 | | """ + | |_______^ D410 + | + = help: Add blank line after "Returns" + +ℹ Safe fix +224 224 | Returns +225 225 | ------ +226 226 | Many many wonderful things. + 227 |+ +227 228 | Raises: +228 229 | My attention. +229 230 | + diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D411_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D411_sections.py.snap index 0ce8c968ded72..f93054611928b 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D411_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D411_sections.py.snap @@ -57,4 +57,37 @@ sections.py:131:5: D411 [*] Missing blank line before section ("Returns") 135 136 | ------- 136 137 | A value of some sort. +sections.py:216:5: D411 [*] Missing blank line before section ("Raises") + | +214 | @expect("D407: Missing dashed underline after section ('Raises')") +215 | def multiple_sections(): # noqa: D416 +216 | """Toggle the gizmo. + | _____^ +217 | | +218 | | Short summary +219 | | ------------- +220 | | +221 | | This is the function's description, which will also specify what it +222 | | returns. +223 | | +224 | | Returns +225 | | ------ +226 | | Many many wonderful things. +227 | | Raises: +228 | | My attention. +229 | | +230 | | """ + | |_______^ D411 + | + = help: Add blank line before "Raises" + +ℹ Safe fix +224 224 | Returns +225 225 | ------ +226 226 | Many many wonderful things. + 227 |+ +227 228 | Raises: +228 229 | My attention. +229 230 | + diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_D413.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_D413.py.snap index dee6268920af2..eda7d334cfaad 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_D413.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_D413.py.snap @@ -1,7 +1,7 @@ --- source: crates/ruff_linter/src/rules/pydocstyle/mod.rs --- -D413.py:1:1: D413 [*] Missing blank line after last section ("Args") +D413.py:1:1: D413 [*] Missing blank line after last section ("Returns") | 1 | / """Do something. 2 | | @@ -14,7 +14,7 @@ D413.py:1:1: D413 [*] Missing blank line after last section ("Args") 9 | | """ | |___^ D413 | - = help: Add blank line after "Args" + = help: Add blank line after "Returns" ℹ Safe fix 6 6 | @@ -26,7 +26,7 @@ D413.py:1:1: D413 [*] Missing blank line after last section ("Args") 10 12 | 11 13 | -D413.py:13:5: D413 [*] Missing blank line after last section ("Args") +D413.py:13:5: D413 [*] Missing blank line after last section ("Returns") | 12 | def func(): 13 | """Do something. @@ -41,7 +41,7 @@ D413.py:13:5: D413 [*] Missing blank line after last section ("Args") 21 | | """ | |_______^ D413 | - = help: Add blank line after "Args" + = help: Add blank line after "Returns" ℹ Safe fix 18 18 | @@ -52,7 +52,7 @@ D413.py:13:5: D413 [*] Missing blank line after last section ("Args") 22 23 | 23 24 | -D413.py:52:5: D413 [*] Missing blank line after last section ("Args") +D413.py:52:5: D413 [*] Missing blank line after last section ("Returns") | 51 | def func(): 52 | """Do something. @@ -66,7 +66,7 @@ D413.py:52:5: D413 [*] Missing blank line after last section ("Args") 59 | | the value""" | |____________________^ D413 | - = help: Add blank line after "Args" + = help: Add blank line after "Returns" ℹ Safe fix 56 56 | with a hanging indent diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap index d9bbae68c3b18..c8ccf0edec949 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap @@ -167,7 +167,7 @@ sections.py:579:5: D413 [*] Missing blank line after last section ("Args") 586 587 | 587 588 | -sections.py:589:5: D413 [*] Missing blank line after last section ("Args") +sections.py:589:5: D413 [*] Missing blank line after last section ("Returns") | 588 | def titlecase_sub_section_header(): 589 | """Below, `Returns:` should be considered a section header. @@ -180,7 +180,7 @@ sections.py:589:5: D413 [*] Missing blank line after last section ("Args") 595 | | """ | |_______^ D413 | - = help: Add blank line after "Args" + = help: Add blank line after "Returns" ℹ Safe fix 592 592 | Here's a note. diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D414_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D414_sections.py.snap index 11e9d33971937..171167289c3de 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D414_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D414_sections.py.snap @@ -78,4 +78,37 @@ sections.py:170:5: D414 Section has no content ("Returns") | |_______^ D414 | +sections.py:261:5: D414 Section has no content ("Returns") + | +259 | @expect("D414: Section has no content ('Returns')") +260 | def valid_google_style_section(): # noqa: D406, D407 +261 | """Toggle the gizmo. + | _____^ +262 | | +263 | | Args: +264 | | note: A random string. +265 | | +266 | | Returns: +267 | | +268 | | Raises: +269 | | RandomError: A random error that occurs randomly. +270 | | +271 | | """ + | |_______^ D414 + | + +sections.py:589:5: D414 Section has no content ("Returns") + | +588 | def titlecase_sub_section_header(): +589 | """Below, `Returns:` should be considered a section header. + | _____^ +590 | | +591 | | Args: +592 | | Here's a note. +593 | | +594 | | Returns: +595 | | """ + | |_______^ D414 + | + From 960a60fb4d1802bcede305e042b00917158b655e Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 8 Feb 2024 16:11:34 -0500 Subject: [PATCH 4/5] Move new sections to the end --- .../test/fixtures/pydocstyle/sections.py | 63 +++--- ...__pydocstyle__tests__D214_sections.py.snap | 32 +-- ...__pydocstyle__tests__D406_sections.py.snap | 43 ++-- ...__pydocstyle__tests__D407_sections.py.snap | 208 +++++++++--------- ...__pydocstyle__tests__D409_sections.py.snap | 60 +++-- ...__pydocstyle__tests__D413_sections.py.snap | 171 +++++++------- ...__pydocstyle__tests__D414_sections.py.snap | 18 +- ...__pydocstyle__tests__D417_sections.py.snap | 40 ++-- 8 files changed, 318 insertions(+), 317 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py b/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py index e7524901b7f6f..9d3c7946b4bb9 100644 --- a/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py +++ b/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py @@ -428,25 +428,6 @@ def test_method(self, test, another_test, z, _, x=1, y=2, _private_arg=1): # no """ - def test_method_should_be_correctly_capitalized(self, 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 - - """ - @expect("D417: Missing argument descriptions in the docstring " "(argument(s) test, y, z are missing descriptions in " "'test_missing_args' docstring)", arg_count=5) @@ -507,18 +488,6 @@ def test_mixing_numpy_and_google(danger): # noqa: D213 """ - @staticmethod - def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], value: int): # noqa: D213 - """Test that lower case sub-section header is valid even if it has the same name as section kind. - - Parameters: - ---------- - parameters: - A list of string parameters - value: - Some value - """ - class TestIncorrectIndent: # noqa: D203 """Test class.""" @@ -593,3 +562,35 @@ 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 + """ diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D214_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D214_sections.py.snap index 4b52c795bfbc1..d8ce888327b5c 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D214_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D214_sections.py.snap @@ -27,27 +27,29 @@ sections.py:144:5: D214 [*] Section is over-indented ("Returns") 148 148 | A value of some sort. 149 149 | -sections.py:589:5: D214 [*] Section is over-indented ("Returns") +sections.py:558:5: D214 [*] Section is over-indented ("Returns") | -588 | def titlecase_sub_section_header(): -589 | """Below, `Returns:` should be considered a section header. +557 | def titlecase_sub_section_header(): +558 | """Below, `Returns:` should be considered a section header. | _____^ -590 | | -591 | | Args: -592 | | Here's a note. -593 | | -594 | | Returns: -595 | | """ +559 | | +560 | | Args: +561 | | Here's a note. +562 | | +563 | | Returns: +564 | | """ | |_______^ D214 | = help: Remove over-indentation from "Returns" ℹ Safe fix -591 591 | Args: -592 592 | Here's a note. -593 593 | -594 |- Returns: - 594 |+ Returns: -595 595 | """ +560 560 | Args: +561 561 | Here's a note. +562 562 | +563 |- Returns: + 563 |+ Returns: +564 564 | """ +565 565 | +566 566 | diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D406_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D406_sections.py.snap index 4afd15c144991..14530459e76bd 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D406_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D406_sections.py.snap @@ -61,32 +61,31 @@ sections.py:216:5: D406 [*] Section name should end with a newline ("Raises") 229 229 | 230 230 | """ -sections.py:512:9: D406 [*] Section name should end with a newline ("Parameters") +sections.py:588:5: D406 [*] Section name should end with a newline ("Parameters") | -510 | @staticmethod -511 | def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], value: int): # noqa: D213 -512 | """Test that lower case sub-section header is valid even if it has the same name as section kind. - | _________^ -513 | | -514 | | Parameters: -515 | | ---------- -516 | | parameters: -517 | | A list of string parameters -518 | | value: -519 | | Some value -520 | | """ - | |___________^ D406 +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 -511 511 | def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], value: int): # noqa: D213 -512 512 | """Test that lower case sub-section header is valid even if it has the same name as section kind. -513 513 | -514 |- Parameters: - 514 |+ Parameters -515 515 | ---------- -516 516 | parameters: -517 517 | A list of string parameters +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 diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap index 916cb0110c874..e35fef3a80703 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap @@ -427,145 +427,147 @@ sections.py:380:9: D407 [*] Missing dashed underline after section ("Args") 384 385 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. 385 386 | Etiam at tellus a tellus faucibus maximus. Curabitur tellus -sections.py:530:9: D407 [*] Missing dashed underline after section ("Args") +sections.py:499:9: D407 [*] Missing dashed underline after section ("Args") | -528 | "'test_incorrect_indent' docstring)", arg_count=3) -529 | def test_incorrect_indent(self, x=1, y=2): # noqa: D207, D213, D407 -530 | """Reproducing issue #437. +497 | "'test_incorrect_indent' docstring)", arg_count=3) +498 | def test_incorrect_indent(self, x=1, y=2): # noqa: D207, D213, D407 +499 | """Reproducing issue #437. | _________^ -531 | | -532 | | Testing this incorrectly indented docstring. -533 | | -534 | | Args: -535 | | x: Test argument. -536 | | -537 | | """ +500 | | +501 | | Testing this incorrectly indented docstring. +502 | | +503 | | Args: +504 | | x: Test argument. +505 | | +506 | | """ | |___________^ D407 | = help: Add dashed line under "Args" ℹ Safe fix -532 532 | Testing this incorrectly indented docstring. -533 533 | -534 534 | Args: - 535 |+ ---- -535 536 | x: Test argument. -536 537 | -537 538 | """ - -sections.py:550:5: D407 [*] Missing dashed underline after section ("Parameters") - | -549 | def replace_equals_with_dash(): -550 | """Equal length equals should be replaced with dashes. +501 501 | Testing this incorrectly indented docstring. +502 502 | +503 503 | Args: + 504 |+ ---- +504 505 | x: Test argument. +505 506 | +506 507 | """ + +sections.py:519:5: D407 [*] Missing dashed underline after section ("Parameters") + | +518 | def replace_equals_with_dash(): +519 | """Equal length equals should be replaced with dashes. | _____^ -551 | | -552 | | Parameters -553 | | ========== -554 | | """ +520 | | +521 | | Parameters +522 | | ========== +523 | | """ | |_______^ D407 | = help: Add dashed line under "Parameters" ℹ Safe fix -550 550 | """Equal length equals should be replaced with dashes. -551 551 | -552 552 | Parameters -553 |- ========== - 553 |+ ---------- -554 554 | """ -555 555 | -556 556 | - -sections.py:558:5: D407 [*] Missing dashed underline after section ("Parameters") - | -557 | def replace_equals_with_dash2(): -558 | """Here, the length of equals is not the same. +519 519 | """Equal length equals should be replaced with dashes. +520 520 | +521 521 | Parameters +522 |- ========== + 522 |+ ---------- +523 523 | """ +524 524 | +525 525 | + +sections.py:527:5: D407 [*] Missing dashed underline after section ("Parameters") + | +526 | def replace_equals_with_dash2(): +527 | """Here, the length of equals is not the same. | _____^ -559 | | -560 | | Parameters -561 | | =========== -562 | | """ +528 | | +529 | | Parameters +530 | | =========== +531 | | """ | |_______^ D407 | = help: Add dashed line under "Parameters" ℹ Safe fix -558 558 | """Here, the length of equals is not the same. -559 559 | -560 560 | Parameters - 561 |+ ---------- -561 562 | =========== -562 563 | """ -563 564 | - -sections.py:579:5: D407 [*] Missing dashed underline after section ("Args") - | -578 | def lowercase_sub_section_header(): -579 | """Below, `returns:` should _not_ be considered a section header. +527 527 | """Here, the length of equals is not the same. +528 528 | +529 529 | Parameters + 530 |+ ---------- +530 531 | =========== +531 532 | """ +532 533 | + +sections.py:548:5: D407 [*] Missing dashed underline after section ("Args") + | +547 | def lowercase_sub_section_header(): +548 | """Below, `returns:` should _not_ be considered a section header. | _____^ -580 | | -581 | | Args: -582 | | Here's a note. -583 | | -584 | | returns: -585 | | """ +549 | | +550 | | Args: +551 | | Here's a note. +552 | | +553 | | returns: +554 | | """ | |_______^ D407 | = help: Add dashed line under "Args" ℹ Safe fix -579 579 | """Below, `returns:` should _not_ be considered a section header. -580 580 | -581 581 | Args: - 582 |+ ---- -582 583 | Here's a note. -583 584 | -584 585 | returns: - -sections.py:589:5: D407 [*] Missing dashed underline after section ("Args") - | -588 | def titlecase_sub_section_header(): -589 | """Below, `Returns:` should be considered a section header. +548 548 | """Below, `returns:` should _not_ be considered a section header. +549 549 | +550 550 | Args: + 551 |+ ---- +551 552 | Here's a note. +552 553 | +553 554 | returns: + +sections.py:558:5: D407 [*] Missing dashed underline after section ("Args") + | +557 | def titlecase_sub_section_header(): +558 | """Below, `Returns:` should be considered a section header. | _____^ -590 | | -591 | | Args: -592 | | Here's a note. -593 | | -594 | | Returns: -595 | | """ +559 | | +560 | | Args: +561 | | Here's a note. +562 | | +563 | | Returns: +564 | | """ | |_______^ D407 | = help: Add dashed line under "Args" ℹ Safe fix -589 589 | """Below, `Returns:` should be considered a section header. -590 590 | -591 591 | Args: - 592 |+ ---- -592 593 | Here's a note. -593 594 | -594 595 | Returns: - -sections.py:589:5: D407 [*] Missing dashed underline after section ("Returns") - | -588 | def titlecase_sub_section_header(): -589 | """Below, `Returns:` should be considered a section header. +558 558 | """Below, `Returns:` should be considered a section header. +559 559 | +560 560 | Args: + 561 |+ ---- +561 562 | Here's a note. +562 563 | +563 564 | Returns: + +sections.py:558:5: D407 [*] Missing dashed underline after section ("Returns") + | +557 | def titlecase_sub_section_header(): +558 | """Below, `Returns:` should be considered a section header. | _____^ -590 | | -591 | | Args: -592 | | Here's a note. -593 | | -594 | | Returns: -595 | | """ +559 | | +560 | | Args: +561 | | Here's a note. +562 | | +563 | | Returns: +564 | | """ | |_______^ D407 | = help: Add dashed line under "Returns" ℹ Safe fix -592 592 | Here's a note. -593 593 | -594 594 | Returns: - 595 |+ ------- -595 596 | """ +561 561 | Here's a note. +562 562 | +563 563 | Returns: + 564 |+ ------- +564 565 | """ +565 566 | +566 567 | diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D409_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D409_sections.py.snap index e600d19fb5104..881b5a0f0f099 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D409_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D409_sections.py.snap @@ -61,41 +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:432:9: D409 [*] Section underline should match the length of its name ("Other Parameters") +sections.py:568:5: D409 [*] Section underline should match the length of its name ("Other Parameters") | -431 | def test_method_should_be_correctly_capitalized(self, parameters: list[str], other_parameters: dict[str, str]): # noqa: D213 -432 | """Test parameters and attributes sections are capitalized correctly. - | _________^ -433 | | -434 | | Parameters -435 | | ---------- -436 | | parameters: -437 | | A list of string parameters -438 | | other_parameters: -439 | | A dictionary of string attributes -440 | | -441 | | Other Parameters -442 | | ---------- -443 | | other_parameters: -444 | | A dictionary of string attributes -445 | | parameters: -446 | | A list of string parameters -447 | | -448 | | """ - | |___________^ D409 -449 | -450 | @expect("D417: Missing argument descriptions in the docstring " +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 -439 439 | A dictionary of string attributes -440 440 | -441 441 | Other Parameters -442 |- ---------- - 442 |+ ---------------- -443 443 | other_parameters: -444 444 | A dictionary of string attributes -445 445 | parameters: +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: diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap index c8ccf0edec949..ee2f7fba886d7 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap @@ -72,121 +72,120 @@ sections.py:170:5: D413 [*] Missing blank line after last section ("Returns") 175 176 | 176 177 | -sections.py:512:9: D413 [*] Missing blank line after last section ("Parameters") +sections.py:519:5: D413 [*] Missing blank line after last section ("Parameters") | -510 | @staticmethod -511 | def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], value: int): # noqa: D213 -512 | """Test that lower case sub-section header is valid even if it has the same name as section kind. - | _________^ -513 | | -514 | | Parameters: -515 | | ---------- -516 | | parameters: -517 | | A list of string parameters -518 | | value: -519 | | Some value -520 | | """ - | |___________^ D413 +518 | def replace_equals_with_dash(): +519 | """Equal length equals should be replaced with dashes. + | _____^ +520 | | +521 | | Parameters +522 | | ========== +523 | | """ + | |_______^ D413 | = help: Add blank line after "Parameters" ℹ Safe fix -517 517 | A list of string parameters -518 518 | value: -519 519 | Some value - 520 |+ -520 521 | """ -521 522 | -522 523 | - -sections.py:550:5: D413 [*] Missing blank line after last section ("Parameters") +520 520 | +521 521 | Parameters +522 522 | ========== + 523 |+ +523 524 | """ +524 525 | +525 526 | + +sections.py:527:5: D413 [*] Missing blank line after last section ("Parameters") | -549 | def replace_equals_with_dash(): -550 | """Equal length equals should be replaced with dashes. +526 | def replace_equals_with_dash2(): +527 | """Here, the length of equals is not the same. | _____^ -551 | | -552 | | Parameters -553 | | ========== -554 | | """ +528 | | +529 | | Parameters +530 | | =========== +531 | | """ | |_______^ D413 | = help: Add blank line after "Parameters" ℹ Safe fix -551 551 | -552 552 | Parameters -553 553 | ========== - 554 |+ -554 555 | """ -555 556 | -556 557 | - -sections.py:558:5: D413 [*] Missing blank line after last section ("Parameters") +528 528 | +529 529 | Parameters +530 530 | =========== + 531 |+ +531 532 | """ +532 533 | +533 534 | + +sections.py:548:5: D413 [*] Missing blank line after last section ("Args") | -557 | def replace_equals_with_dash2(): -558 | """Here, the length of equals is not the same. +547 | def lowercase_sub_section_header(): +548 | """Below, `returns:` should _not_ be considered a section header. | _____^ -559 | | -560 | | Parameters -561 | | =========== -562 | | """ +549 | | +550 | | Args: +551 | | Here's a note. +552 | | +553 | | returns: +554 | | """ | |_______^ D413 | - = help: Add blank line after "Parameters" + = help: Add blank line after "Args" ℹ Safe fix -559 559 | -560 560 | Parameters -561 561 | =========== - 562 |+ -562 563 | """ -563 564 | -564 565 | - -sections.py:579:5: D413 [*] Missing blank line after last section ("Args") +551 551 | Here's a note. +552 552 | +553 553 | returns: + 554 |+ +554 555 | """ +555 556 | +556 557 | + +sections.py:558:5: D413 [*] Missing blank line after last section ("Returns") | -578 | def lowercase_sub_section_header(): -579 | """Below, `returns:` should _not_ be considered a section header. +557 | def titlecase_sub_section_header(): +558 | """Below, `Returns:` should be considered a section header. | _____^ -580 | | -581 | | Args: -582 | | Here's a note. -583 | | -584 | | returns: -585 | | """ +559 | | +560 | | Args: +561 | | Here's a note. +562 | | +563 | | Returns: +564 | | """ | |_______^ D413 | - = help: Add blank line after "Args" + = help: Add blank line after "Returns" ℹ Safe fix -582 582 | Here's a note. -583 583 | -584 584 | returns: - 585 |+ -585 586 | """ -586 587 | -587 588 | - -sections.py:589:5: D413 [*] Missing blank line after last section ("Returns") +561 561 | Here's a note. +562 562 | +563 563 | Returns: + 564 |+ +564 565 | """ +565 566 | +566 567 | + +sections.py:588:5: D413 [*] Missing blank line after last section ("Parameters") | -588 | def titlecase_sub_section_header(): -589 | """Below, `Returns:` should be considered a section header. +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. | _____^ -590 | | -591 | | Args: -592 | | Here's a note. -593 | | -594 | | Returns: -595 | | """ +589 | | +590 | | Parameters: +591 | | ---------- +592 | | parameters: +593 | | A list of string parameters +594 | | value: +595 | | Some value +596 | | """ | |_______^ D413 | - = help: Add blank line after "Returns" + = help: Add blank line after "Parameters" ℹ Safe fix -592 592 | Here's a note. -593 593 | -594 594 | Returns: - 595 |+ -595 596 | """ +593 593 | A list of string parameters +594 594 | value: +595 595 | Some value + 596 |+ +596 597 | """ diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D414_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D414_sections.py.snap index 171167289c3de..9566fd691a6d4 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D414_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D414_sections.py.snap @@ -97,17 +97,17 @@ sections.py:261:5: D414 Section has no content ("Returns") | |_______^ D414 | -sections.py:589:5: D414 Section has no content ("Returns") +sections.py:558:5: D414 Section has no content ("Returns") | -588 | def titlecase_sub_section_header(): -589 | """Below, `Returns:` should be considered a section header. +557 | def titlecase_sub_section_header(): +558 | """Below, `Returns:` should be considered a section header. | _____^ -590 | | -591 | | Args: -592 | | Here's a note. -593 | | -594 | | Returns: -595 | | """ +559 | | +560 | | Args: +561 | | Here's a note. +562 | | +563 | | Returns: +564 | | """ | |_______^ D414 | diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D417_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D417_sections.py.snap index 2d276f575ac90..1ea30245856fa 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D417_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D417_sections.py.snap @@ -64,40 +64,40 @@ sections.py:398:5: D417 Missing argument description in the docstring for `test_ 399 | """Toggle the gizmo. | -sections.py:453:9: D417 Missing argument descriptions in the docstring for `test_missing_args`: `test`, `y`, `z` +sections.py:434:9: D417 Missing argument descriptions in the docstring for `test_missing_args`: `test`, `y`, `z` | -451 | "(argument(s) test, y, z are missing descriptions in " -452 | "'test_missing_args' docstring)", arg_count=5) -453 | def test_missing_args(self, test, x, y, z=3, t=1, _private=0): # noqa: D213, D407 +432 | "(argument(s) test, y, z are missing descriptions in " +433 | "'test_missing_args' docstring)", arg_count=5) +434 | def test_missing_args(self, test, x, y, z=3, t=1, _private=0): # noqa: D213, D407 | ^^^^^^^^^^^^^^^^^ D417 -454 | """Test a valid args section. +435 | """Test a valid args section. | -sections.py:468:9: D417 Missing argument descriptions in the docstring for `test_missing_args_class_method`: `test`, `y`, `z` +sections.py:449:9: D417 Missing argument descriptions in the docstring for `test_missing_args_class_method`: `test`, `y`, `z` | -466 | "(argument(s) test, y, z are missing descriptions in " -467 | "'test_missing_args_class_method' docstring)", arg_count=4) -468 | def test_missing_args_class_method(cls, test, x, y, z=3): # noqa: D213, D407 +447 | "(argument(s) test, y, z are missing descriptions in " +448 | "'test_missing_args_class_method' docstring)", arg_count=4) +449 | def test_missing_args_class_method(cls, test, x, y, z=3): # noqa: D213, D407 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D417 -469 | """Test a valid args section. +450 | """Test a valid args section. | -sections.py:487:9: D417 Missing argument descriptions in the docstring for `test_missing_args_static_method`: `a`, `z` +sections.py:468:9: D417 Missing argument descriptions in the docstring for `test_missing_args_static_method`: `a`, `z` | -485 | "(argument(s) a, z are missing descriptions in " -486 | "'test_missing_args_static_method' docstring)", arg_count=3) -487 | def test_missing_args_static_method(a, x, y, z=3, t=1): # noqa: D213, D407 +466 | "(argument(s) a, z are missing descriptions in " +467 | "'test_missing_args_static_method' docstring)", arg_count=3) +468 | def test_missing_args_static_method(a, x, y, z=3, t=1): # noqa: D213, D407 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ D417 -488 | """Test a valid args section. +469 | """Test a valid args section. | -sections.py:529:9: D417 Missing argument description in the docstring for `test_incorrect_indent`: `y` +sections.py:498:9: D417 Missing argument description in the docstring for `test_incorrect_indent`: `y` | -527 | "(argument(s) y are missing descriptions in " -528 | "'test_incorrect_indent' docstring)", arg_count=3) -529 | def test_incorrect_indent(self, x=1, y=2): # noqa: D207, D213, D407 +496 | "(argument(s) y are missing descriptions in " +497 | "'test_incorrect_indent' docstring)", arg_count=3) +498 | def test_incorrect_indent(self, x=1, y=2): # noqa: D207, D213, D407 | ^^^^^^^^^^^^^^^^^^^^^ D417 -530 | """Reproducing issue #437. +499 | """Reproducing issue #437. | From d0dda316c72f6fa44cbfb8b2f0466c4d65c6e594 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Thu, 8 Feb 2024 16:40:59 -0500 Subject: [PATCH 5/5] Respect other kinds --- .../test/fixtures/pydocstyle/sections.py | 11 +++ crates/ruff_linter/src/docstrings/sections.rs | 68 +++++++++++++++++-- ...__pydocstyle__tests__D407_sections.py.snap | 25 +++++++ ...__pydocstyle__tests__D413_sections.py.snap | 2 + 4 files changed, 101 insertions(+), 5 deletions(-) diff --git a/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py b/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py index 9d3c7946b4bb9..ab0b02132b265 100644 --- a/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py +++ b/crates/ruff_linter/resources/test/fixtures/pydocstyle/sections.py @@ -594,3 +594,14 @@ def test_lowercase_sub_section_header_should_be_valid(parameters: list[str], val 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 + + """ diff --git a/crates/ruff_linter/src/docstrings/sections.rs b/crates/ruff_linter/src/docstrings/sections.rs index c98d1d5e22483..713bf3a596219 100644 --- a/crates/ruff_linter/src/docstrings/sections.rs +++ b/crates/ruff_linter/src/docstrings/sections.rs @@ -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: + /// + /// For Google, see: + 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> { @@ -472,11 +500,41 @@ fn is_docstring_section( // ``` // 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 { - let verbatim = &line[TextRange::at(indent_size, section_name_size)]; - if previous_section.kind == section_kind || previous_section.indent_size < indent_size { - if section_kind.as_str() != verbatim { - return false; + if section_kind.has_subsections() { + if let Some(previous_section) = previous_section { + let verbatim = &line[TextRange::at(indent_size, section_name_size)]; + + // 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; + } } } } diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap index e35fef3a80703..95efe19803e69 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D407_sections.py.snap @@ -570,4 +570,29 @@ sections.py:558:5: D407 [*] Missing dashed underline after section ("Returns") 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 + diff --git a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap index ee2f7fba886d7..0d1bcec87a0bc 100644 --- a/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap +++ b/crates/ruff_linter/src/rules/pydocstyle/snapshots/ruff_linter__rules__pydocstyle__tests__D413_sections.py.snap @@ -187,5 +187,7 @@ sections.py:588:5: D413 [*] Missing blank line after last section ("Parameters") 595 595 | Some value 596 |+ 596 597 | """ +597 598 | +598 599 |