diff --git a/docs/docstrings.md b/docs/docstrings.md index a9078032..9c01be45 100644 --- a/docs/docstrings.md +++ b/docs/docstrings.md @@ -95,7 +95,8 @@ Option | Google | Numpy | Sphinx -------------------------- | ------ | ----- | ------ Ignore `__init__` summary | ✅ | ✅ | [❌][issue-ignore-init-summary-sphinx] Trim doctest flags | ✅ | ✅ | [❌][issue-trim-doctest-flags-sphinx] +Warn about unknown params | ✅ | ✅ | [❌][issue-warn-unknown-params-sphinx] [issue-ignore-init-summary-sphinx]: https://github.com/mkdocstrings/griffe/issues/45 [issue-trim-doctest-flags-sphinx]: https://github.com/mkdocstrings/griffe/issues/49 - +[issue-warn-unknown-params-sphinx]: https://github.com/mkdocstrings/griffe/issues/64 diff --git a/src/griffe/docstrings/numpy.py b/src/griffe/docstrings/numpy.py index 6a94a283..278bacc4 100644 --- a/src/griffe/docstrings/numpy.py +++ b/src/griffe/docstrings/numpy.py @@ -213,7 +213,11 @@ def _read_block(docstring: Docstring, offset: int) -> tuple[str, int]: # noqa: _RE_DOCTEST_FLAGS: Pattern = re.compile(r"(\s*#\s*doctest:.+)$") -def _read_parameters(docstring: Docstring, offset: int) -> tuple[list[DocstringParameter], int]: # noqa: WPS231 +def _read_parameters( # noqa: WPS231 + docstring: Docstring, + offset: int, + warn_unknown_params: bool = True, +) -> tuple[list[DocstringParameter], int]: parameters = [] annotation: str | Name | Expression | None @@ -257,6 +261,15 @@ def _read_parameters(docstring: Docstring, offset: int) -> tuple[list[DocstringP default = docstring.parent.parameters[name].default # type: ignore[union-attr] break + if warn_unknown_params and docstring.parent is not None: + for name in names: # noqa: WPS440 + if name not in docstring.parent.parameters: # type: ignore[attr-defined] + _warn( + docstring, + new_offset, + f"Parameter '{name}' does not appear in the parent signature", + ) + for name in names: # noqa: WPS440 parameters.append(DocstringParameter(name, value=default, annotation=annotation, description=description)) @@ -282,7 +295,7 @@ def _read_other_parameters_section( offset: int, **options: Any, ) -> tuple[DocstringSectionOtherParameters | None, int]: - parameters, new_offset = _read_parameters(docstring, offset) + parameters, new_offset = _read_parameters(docstring, offset, warn_unknown_params=False) if parameters: return DocstringSectionOtherParameters(parameters), new_offset diff --git a/tests/test_docstrings/test_google.py b/tests/test_docstrings/test_google.py index c376fee1..f3d16d54 100644 --- a/tests/test_docstrings/test_google.py +++ b/tests/test_docstrings/test_google.py @@ -702,8 +702,8 @@ def test_parameter_line_without_colon_keyword_only(parse_google): assert "Empty" in warnings[1] -def test_warn_about_extra_parameters(parse_google): - """Warn about extra parameters in "Parameters" sections. +def test_warn_about_unknown_parameters(parse_google): + """Warn about unknown parameters in "Parameters" sections. Parameters: parse_google: Fixture parser. @@ -714,7 +714,7 @@ def test_warn_about_extra_parameters(parse_google): y (int): Integer. """ - sections, warnings = parse_google( + _, warnings = parse_google( docstring, parent=Function( "func", @@ -728,8 +728,8 @@ def test_warn_about_extra_parameters(parse_google): assert "'x' does not appear in the parent signature" in warnings[0] -def test_never_warn_about_extra_other_parameters(parse_google): - """Never Warn about extra parameters in "Other parameters" sections. +def test_never_warn_about_unknown_other_parameters(parse_google): + """Never warn about unknown parameters in "Other parameters" sections. Parameters: parse_google: Fixture parser. diff --git a/tests/test_docstrings/test_numpy.py b/tests/test_docstrings/test_numpy.py index b51694ed..2f6a2bd9 100644 --- a/tests/test_docstrings/test_numpy.py +++ b/tests/test_docstrings/test_numpy.py @@ -527,6 +527,65 @@ def test_retrieve_attributes_annotation_from_parent(parse_numpy): assert attributes[1].annotation.source == "str" +# ============================================================================================= +# Parameters sections +def test_warn_about_unknown_parameters(parse_numpy): + """Warn about unknown parameters in "Parameters" sections. + + Parameters: + parse_numpy: Fixture parser. + """ + docstring = """ + Parameters + ---------- + x : int + Integer. + y : int + Integer. + """ + + _, warnings = parse_numpy( + docstring, + parent=Function( + "func", + parameters=Parameters( + Parameter("a"), + Parameter("y"), + ), + ), + ) + assert len(warnings) == 1 + assert "'x' does not appear in the parent signature" in warnings[0] + + +def test_never_warn_about_unknown_other_parameters(parse_numpy): + """Never warn about unknown parameters in "Other parameters" sections. + + Parameters: + parse_numpy: Fixture parser. + """ + docstring = """ + Other Parameters + ---------------- + x : int + Integer. + z : int + Integer. + """ + + _, warnings = parse_numpy( + docstring, + parent=Function( + "func", + parameters=Parameters( + Parameter("a"), + Parameter("y"), + ), + ), + ) + assert not warnings + + # ============================================================================================= # Yields sections @pytest.mark.parametrize( @@ -651,7 +710,7 @@ def test_ignore_init_summary(parse_numpy, docstring): Parameters: parse_numpy: Fixture parser. - docstring: The docstring to parse_google (parametrized). + docstring: The docstring to parse (parametrized). """ sections, _ = parse_numpy(docstring, parent=Function("__init__", parent=Class("C")), ignore_init_summary=True) for section in sections: