From 48cc14aec3fa45413935f22410ca73ed14596b1b Mon Sep 17 00:00:00 2001 From: Ashley Whetter Date: Tue, 12 Apr 2022 18:37:43 -0700 Subject: [PATCH] docparams extension considers type comments as type documentation. Closes #6287 --- doc/whatsnew/fragments/6287.bugfix | 3 + pylint/extensions/_check_docs_utils.py | 104 ++++++++++++++++++ pylint/extensions/docparams.py | 23 ++-- .../ext/docparams/missing_param_doc.py | 71 ++++++++++++ .../ext/docparams/missing_param_doc_py38.py | 53 +++++++++ .../ext/docparams/missing_param_doc_py38.rc | 11 ++ .../missing_param_doc_required_Google.py | 17 +++ .../missing_param_doc_required_Google.txt | 52 ++++----- .../missing_param_doc_required_Numpy.py | 22 ++++ .../missing_param_doc_required_Numpy.txt | 44 ++++---- .../missing_param_doc_required_Sphinx.py | 18 +++ .../missing_param_doc_required_Sphinx.txt | 80 +++++++------- 12 files changed, 397 insertions(+), 101 deletions(-) create mode 100644 doc/whatsnew/fragments/6287.bugfix create mode 100644 tests/functional/ext/docparams/missing_param_doc_py38.py create mode 100644 tests/functional/ext/docparams/missing_param_doc_py38.rc diff --git a/doc/whatsnew/fragments/6287.bugfix b/doc/whatsnew/fragments/6287.bugfix new file mode 100644 index 00000000000..d1d6ad7ec65 --- /dev/null +++ b/doc/whatsnew/fragments/6287.bugfix @@ -0,0 +1,3 @@ +docparams extension considers type comments as type documentation. + +Closes #6287 diff --git a/pylint/extensions/_check_docs_utils.py b/pylint/extensions/_check_docs_utils.py index dddc577d647..d49f4f6c1bf 100644 --- a/pylint/extensions/_check_docs_utils.py +++ b/pylint/extensions/_check_docs_utils.py @@ -6,7 +6,9 @@ from __future__ import annotations +import itertools import re +from collections.abc import Iterable import astroid from astroid import nodes @@ -159,6 +161,108 @@ def possible_exc_types(node: nodes.NodeNG) -> set[nodes.ClassDef]: return set() +def _is_ellipsis(node: nodes.NodeNG) -> bool: + return isinstance(node, nodes.Const) and node.value == Ellipsis + + +def _merge_annotations( + annotations: Iterable[nodes.NodeNG], comment_annotations: Iterable[nodes.NodeNG] +) -> Iterable[nodes.NodeNG | None]: + for ann, comment_ann in itertools.zip_longest(annotations, comment_annotations): + if ann and not _is_ellipsis(ann): + yield ann + elif comment_ann and not _is_ellipsis(comment_ann): + yield comment_ann + else: + yield None + + +def _annotations_list(args_node: nodes.Arguments) -> list[nodes.NodeNG]: + """Get a merged list of annotations. + + The annotations can come from: + + * Real type annotations. + * A type comment on the function. + * A type common on the individual argument. + + :param args_node: The node to get the annotations for. + :returns: The annotations. + """ + plain_annotations = args_node.annotations or () + func_comment_annotations = args_node.parent.type_comment_args or () + comment_annotations = args_node.type_comment_posonlyargs + comment_annotations += args_node.type_comment_args or [] + comment_annotations += args_node.type_comment_kwonlyargs + return list( + _merge_annotations( + plain_annotations, + _merge_annotations(func_comment_annotations, comment_annotations), + ) + ) + + +def args_with_annotation(args_node: nodes.Arguments) -> set[str]: + result = set() + annotations = _annotations_list(args_node) + annotation_offset = 0 + + if args_node.posonlyargs: + posonlyargs_annotations = args_node.posonlyargs_annotations + if not any(args_node.posonlyargs_annotations): + num_args = len(args_node.posonlyargs) + posonlyargs_annotations = annotations[ + annotation_offset : annotation_offset + num_args + ] + annotation_offset += num_args + + for arg, annotation in zip(args_node.posonlyargs, posonlyargs_annotations): + if annotation: + result.add(arg.name) + + if args_node.args: + num_args = len(args_node.args) + for arg, annotation in zip( + args_node.args, + annotations[annotation_offset : annotation_offset + num_args], + ): + if annotation: + result.add(arg.name) + + annotation_offset += num_args + + if args_node.vararg: + annotation = None + if args_node.varargannotation: + result.add(args_node.vararg) + elif len(annotations) > annotation_offset and annotations[annotation_offset]: + result.add(args_node.vararg) + annotation_offset += 1 + + if args_node.kwonlyargs: + kwonlyargs_annotations = args_node.kwonlyargs_annotations + if not any(args_node.kwonlyargs_annotations): + num_args = len(args_node.kwonlyargs) + kwonlyargs_annotations = annotations[ + annotation_offset : annotation_offset + num_args + ] + annotation_offset += num_args + + for arg, annotation in zip(args_node.kwonlyargs, kwonlyargs_annotations): + if annotation: + result.add(arg.name) + + if args_node.kwarg: + annotation = None + if args_node.kwargannotation: + result.add(args_node.kwarg) + elif len(annotations) > annotation_offset and annotations[annotation_offset]: + result.add(args_node.kwarg) + annotation_offset += 1 + + return result + + def docstringify( docstring: nodes.Const | None, default_type: str = "default" ) -> Docstring: diff --git a/pylint/extensions/docparams.py b/pylint/extensions/docparams.py index 6e173c39efe..11f597423e4 100644 --- a/pylint/extensions/docparams.py +++ b/pylint/extensions/docparams.py @@ -348,7 +348,7 @@ def visit_return(self, node: nodes.Return) -> None: if not (doc.has_returns() or (doc.has_property_returns() and is_property)): self.add_message("missing-return-doc", node=func_node, confidence=HIGH) - if func_node.returns: + if func_node.returns or func_node.type_comment_returns: return if not (doc.has_rtype() or (doc.has_property_type() and is_property)): @@ -379,7 +379,9 @@ def visit_yield(self, node: nodes.Yield | nodes.YieldFrom) -> None: if not doc_has_yields: self.add_message("missing-yield-doc", node=func_node, confidence=HIGH) - if not (doc_has_yields_type or func_node.returns): + if not ( + doc_has_yields_type or func_node.returns or func_node.type_comment_returns + ): self.add_message("missing-yield-type-doc", node=func_node, confidence=HIGH) visit_yieldfrom = visit_yield @@ -540,8 +542,9 @@ class constructor. # Collect the function arguments. expected_argument_names = {arg.name for arg in arguments_node.args} - expected_argument_names.update(arg.name for arg in arguments_node.kwonlyargs) - expected_argument_names.update(arg.name for arg in arguments_node.posonlyargs) + expected_argument_names.update( + a.name for a in arguments_node.posonlyargs + arguments_node.kwonlyargs + ) not_needed_type_in_docstring = self.not_needed_param_in_docstring.copy() expected_but_ignored_argument_names = set() @@ -564,7 +567,7 @@ class constructor. if not params_with_doc and not params_with_type and accept_no_param_doc: tolerate_missing_params = True - # This is before the update of param_with_type because this must check only + # This is before the update of params_with_type because this must check only # the type documented in a docstring, not the one using pep484 # See #4117 and #4593 self._compare_ignored_args( @@ -573,15 +576,7 @@ class constructor. expected_but_ignored_argument_names, warning_node, ) - for index, arg_name in enumerate(arguments_node.args): - if arguments_node.annotations[index]: - params_with_type.add(arg_name.name) - for index, arg_name in enumerate(arguments_node.kwonlyargs): - if arguments_node.kwonlyargs_annotations[index]: - params_with_type.add(arg_name.name) - for index, arg_name in enumerate(arguments_node.posonlyargs): - if arguments_node.posonlyargs_annotations[index]: - params_with_type.add(arg_name.name) + params_with_type |= utils.args_with_annotation(arguments_node) if not tolerate_missing_params: missing_param_doc = (expected_argument_names - params_with_doc) - ( diff --git a/tests/functional/ext/docparams/missing_param_doc.py b/tests/functional/ext/docparams/missing_param_doc.py index e72507a7859..3bb4c61657c 100644 --- a/tests/functional/ext/docparams/missing_param_doc.py +++ b/tests/functional/ext/docparams/missing_param_doc.py @@ -140,3 +140,74 @@ def foobar15(*args): Relevant parameters. """ print(args) + + +def foobar16(one: int, two: str, three: float) -> int: + """Description of the function + + Args: + one: A number. + two: Another number. + three: Yes another number. + + Returns: + The number one. + """ + print(one, two, three) + return 1 + + +def foobar17(one, two, three): + # type: (int, str, float) -> int + """Description of the function + + Args: + one: A number. + two: Another number. + three: Yes another number. + + Returns: + The number one. + """ + print(one, two, three) + return 1 + + +def foobar18( + one, # type: int + two, # type: str + three, # type: float +): + # type: (...) -> int + """Description of the function + + Args: + one: A number. + two: Another number. + three: Yes another number. + + Returns: + The number one. + """ + print(one, two, three) + return 1 + + +def foobar19( + one, # type: int + two, # type: str + **kwargs, # type: float +): + # type: (...) -> int + """Description of the function + + Args: + one: A number. + two: Another number. + kwargs: More numbers. + + Returns: + The number one. + """ + print(one, two, kwargs) + return 1 diff --git a/tests/functional/ext/docparams/missing_param_doc_py38.py b/tests/functional/ext/docparams/missing_param_doc_py38.py new file mode 100644 index 00000000000..b799cdd96d8 --- /dev/null +++ b/tests/functional/ext/docparams/missing_param_doc_py38.py @@ -0,0 +1,53 @@ +#pylint: disable= missing-module-docstring + +def foobar1(one: int, /, two: str, *, three: float) -> int: + """Description of the function + + Args: + one: A number. + two: Another number. + three: Yes another number. + + Returns: + The number one. + """ + print(one, two, three) + return 1 + + +def foobar2(one, /, two, * three): + # type: (int, str, float) -> int + """Description of the function + + Args: + one: A number. + two: Another number. + three: Yes another number. + + Returns: + The number one. + """ + print(one, two, three) + return 1 + + +def foobar3( + one, # type: int + /, + two, # type: str + *, + three, # type: float +): + # type: (...) -> int + """Description of the function + + Args: + one: A number. + two: Another number. + three: Yes another number. + + Returns: + The number one. + """ + print(one, two, three) + return 1 diff --git a/tests/functional/ext/docparams/missing_param_doc_py38.rc b/tests/functional/ext/docparams/missing_param_doc_py38.rc new file mode 100644 index 00000000000..9e58d2f8c70 --- /dev/null +++ b/tests/functional/ext/docparams/missing_param_doc_py38.rc @@ -0,0 +1,11 @@ +[MASTER] +load-plugins=pylint.extensions.docparams, + +[testoptions] +min_pyver=3.8 + +[PARAMETER_DOCUMENTATION] +accept-no-param-doc=no +accept-no-raise-doc=no +accept-no-return-doc=no +accept-no-yields-doc=no diff --git a/tests/functional/ext/docparams/parameter/missing_param_doc_required_Google.py b/tests/functional/ext/docparams/parameter/missing_param_doc_required_Google.py index 9178415813f..0fd82307fb3 100644 --- a/tests/functional/ext/docparams/parameter/missing_param_doc_required_Google.py +++ b/tests/functional/ext/docparams/parameter/missing_param_doc_required_Google.py @@ -4,11 +4,14 @@ Styleguide: https://google.github.io/styleguide/pyguide.html#doc-function-args """ + # pylint: disable=invalid-name, unused-argument, undefined-variable # pylint: disable=line-too-long, too-few-public-methods, missing-class-docstring # pylint: disable=missing-function-docstring, function-redefined, inconsistent-return-statements # pylint: disable=dangerous-default-value, too-many-arguments +from __future__ import annotations + def test_multi_line_parameters(param: int) -> None: """Checks that multi line parameters lists are checked correctly @@ -326,6 +329,20 @@ def test_finds_kwargs_without_type_google(named_arg, **kwargs): return named_arg +def test_finds_kwargs_without_type_google(named_arg, **kwargs: dict[str, str]): + """The docstring + + Args: + named_arg (object): Returned + **kwargs: Keyword arguments + + Returns: + object or None: Maybe named_arg + """ + if kwargs: + return named_arg + + def test_finds_kwargs_without_asterisk_google(named_arg, **kwargs): """The docstring diff --git a/tests/functional/ext/docparams/parameter/missing_param_doc_required_Google.txt b/tests/functional/ext/docparams/parameter/missing_param_doc_required_Google.txt index 33a479d11d6..9689b147c4c 100644 --- a/tests/functional/ext/docparams/parameter/missing_param_doc_required_Google.txt +++ b/tests/functional/ext/docparams/parameter/missing_param_doc_required_Google.txt @@ -1,26 +1,26 @@ -missing-param-doc:24:0:24:48:test_missing_func_params_in_google_docstring:"""y"" missing in parameter documentation":HIGH -missing-type-doc:24:0:24:48:test_missing_func_params_in_google_docstring:"""x, y"" missing in parameter type documentation":HIGH -missing-type-doc:80:0:80:73:test_missing_func_params_with_partial_annotations_in_google_docstring:"""x"" missing in parameter type documentation":HIGH -differing-param-doc:131:0:131:65:test_func_params_and_wrong_keyword_params_in_google_docstring:"""these"" differing in parameter documentation":HIGH -differing-type-doc:131:0:131:65:test_func_params_and_wrong_keyword_params_in_google_docstring:"""these"" differing in parameter type documentation":HIGH -missing-param-doc:131:0:131:65:test_func_params_and_wrong_keyword_params_in_google_docstring:"""that"" missing in parameter documentation":HIGH -missing-type-doc:131:0:131:65:test_func_params_and_wrong_keyword_params_in_google_docstring:"""that"" missing in parameter type documentation":HIGH -missing-param-doc:148:4:148:54:Foo.test_missing_method_params_in_google_docstring:"""y"" missing in parameter documentation":HIGH -missing-type-doc:148:4:148:54:Foo.test_missing_method_params_in_google_docstring:"""x, y"" missing in parameter type documentation":HIGH -differing-param-doc:179:0:179:58:test_wrong_name_of_func_params_in_google_docstring_one:"""xarg1, zarg1"" differing in parameter documentation":HIGH -differing-type-doc:179:0:179:58:test_wrong_name_of_func_params_in_google_docstring_one:"""xarg1, zarg1"" differing in parameter type documentation":HIGH -missing-param-doc:179:0:179:58:test_wrong_name_of_func_params_in_google_docstring_one:"""xarg, zarg"" missing in parameter documentation":HIGH -missing-type-doc:179:0:179:58:test_wrong_name_of_func_params_in_google_docstring_one:"""xarg, zarg"" missing in parameter type documentation":HIGH -differing-param-doc:194:0:194:58:test_wrong_name_of_func_params_in_google_docstring_two:"""yarg1"" differing in parameter documentation":HIGH -differing-type-doc:194:0:194:58:test_wrong_name_of_func_params_in_google_docstring_two:"""yarg1"" differing in parameter type documentation":HIGH -missing-param-doc:221:0:221:14:ClassFoo:"""x"" missing in parameter documentation":HIGH -missing-type-doc:221:0:221:14:ClassFoo:"""x, y"" missing in parameter type documentation":HIGH -missing-param-doc:239:4:239:16:ClassFoo.__init__:"""x"" missing in parameter documentation":HIGH -missing-type-doc:239:4:239:16:ClassFoo.__init__:"""x, y"" missing in parameter type documentation":HIGH -missing-param-doc:251:0:251:14:ClassFoo:"""x"" missing in parameter documentation":HIGH -missing-type-doc:251:0:251:14:ClassFoo:"""x, y"" missing in parameter type documentation":HIGH -multiple-constructor-doc:251:0:251:14:ClassFoo:"""ClassFoo"" has constructor parameters documented in class and __init__":HIGH -missing-param-doc:265:4:265:16:ClassFoo.__init__:"""x"" missing in parameter documentation":HIGH -missing-type-doc:265:4:265:16:ClassFoo.__init__:"""x, y"" missing in parameter type documentation":HIGH -missing-param-doc:275:0:275:34:test_warns_missing_args_google:"""*args"" missing in parameter documentation":HIGH -missing-param-doc:288:0:288:36:test_warns_missing_kwargs_google:"""**kwargs"" missing in parameter documentation":HIGH +missing-param-doc:27:0:27:48:test_missing_func_params_in_google_docstring:"""y"" missing in parameter documentation":HIGH +missing-type-doc:27:0:27:48:test_missing_func_params_in_google_docstring:"""x, y"" missing in parameter type documentation":HIGH +missing-type-doc:83:0:83:73:test_missing_func_params_with_partial_annotations_in_google_docstring:"""x"" missing in parameter type documentation":HIGH +differing-param-doc:134:0:134:65:test_func_params_and_wrong_keyword_params_in_google_docstring:"""these"" differing in parameter documentation":HIGH +differing-type-doc:134:0:134:65:test_func_params_and_wrong_keyword_params_in_google_docstring:"""these"" differing in parameter type documentation":HIGH +missing-param-doc:134:0:134:65:test_func_params_and_wrong_keyword_params_in_google_docstring:"""that"" missing in parameter documentation":HIGH +missing-type-doc:134:0:134:65:test_func_params_and_wrong_keyword_params_in_google_docstring:"""that"" missing in parameter type documentation":HIGH +missing-param-doc:151:4:151:54:Foo.test_missing_method_params_in_google_docstring:"""y"" missing in parameter documentation":HIGH +missing-type-doc:151:4:151:54:Foo.test_missing_method_params_in_google_docstring:"""x, y"" missing in parameter type documentation":HIGH +differing-param-doc:182:0:182:58:test_wrong_name_of_func_params_in_google_docstring_one:"""xarg1, zarg1"" differing in parameter documentation":HIGH +differing-type-doc:182:0:182:58:test_wrong_name_of_func_params_in_google_docstring_one:"""xarg1, zarg1"" differing in parameter type documentation":HIGH +missing-param-doc:182:0:182:58:test_wrong_name_of_func_params_in_google_docstring_one:"""xarg, zarg"" missing in parameter documentation":HIGH +missing-type-doc:182:0:182:58:test_wrong_name_of_func_params_in_google_docstring_one:"""xarg, zarg"" missing in parameter type documentation":HIGH +differing-param-doc:197:0:197:58:test_wrong_name_of_func_params_in_google_docstring_two:"""yarg1"" differing in parameter documentation":HIGH +differing-type-doc:197:0:197:58:test_wrong_name_of_func_params_in_google_docstring_two:"""yarg1"" differing in parameter type documentation":HIGH +missing-param-doc:224:0:224:14:ClassFoo:"""x"" missing in parameter documentation":HIGH +missing-type-doc:224:0:224:14:ClassFoo:"""x, y"" missing in parameter type documentation":HIGH +missing-param-doc:242:4:242:16:ClassFoo.__init__:"""x"" missing in parameter documentation":HIGH +missing-type-doc:242:4:242:16:ClassFoo.__init__:"""x, y"" missing in parameter type documentation":HIGH +missing-param-doc:254:0:254:14:ClassFoo:"""x"" missing in parameter documentation":HIGH +missing-type-doc:254:0:254:14:ClassFoo:"""x, y"" missing in parameter type documentation":HIGH +multiple-constructor-doc:254:0:254:14:ClassFoo:"""ClassFoo"" has constructor parameters documented in class and __init__":HIGH +missing-param-doc:268:4:268:16:ClassFoo.__init__:"""x"" missing in parameter documentation":HIGH +missing-type-doc:268:4:268:16:ClassFoo.__init__:"""x, y"" missing in parameter type documentation":HIGH +missing-param-doc:278:0:278:34:test_warns_missing_args_google:"""*args"" missing in parameter documentation":HIGH +missing-param-doc:291:0:291:36:test_warns_missing_kwargs_google:"""**kwargs"" missing in parameter documentation":HIGH diff --git a/tests/functional/ext/docparams/parameter/missing_param_doc_required_Numpy.py b/tests/functional/ext/docparams/parameter/missing_param_doc_required_Numpy.py index 794f4c2f6dd..83fa9700d36 100644 --- a/tests/functional/ext/docparams/parameter/missing_param_doc_required_Numpy.py +++ b/tests/functional/ext/docparams/parameter/missing_param_doc_required_Numpy.py @@ -1,10 +1,13 @@ """Tests for missing-param-doc and missing-type-doc for Numpy style docstrings with accept-no-param-doc = no """ + # pylint: disable=invalid-name, unused-argument, undefined-variable, too-many-arguments # pylint: disable=line-too-long, too-few-public-methods, missing-class-docstring # pylint: disable=missing-function-docstring, function-redefined, inconsistent-return-statements +from __future__ import annotations + def test_missing_func_params_in_numpy_docstring( # [missing-param-doc, missing-type-doc] x, y, z @@ -294,6 +297,25 @@ def test_finds_kwargs_without_type_numpy(named_arg, **kwargs): return named_arg +def test_finds_kwargs_with_type_numpy(named_arg, **kwargs: dict[str, str]): + """The docstring + + Args + ---- + named_arg : object + Returned + **kwargs : + Keyword arguments + + Returns + ------- + object or None + Maybe named_arg + """ + if kwargs: + return named_arg + + def test_finds_kwargs_without_asterisk_numpy(named_arg, **kwargs): """The docstring diff --git a/tests/functional/ext/docparams/parameter/missing_param_doc_required_Numpy.txt b/tests/functional/ext/docparams/parameter/missing_param_doc_required_Numpy.txt index a58b9c7cad3..b5ac61cd8b0 100644 --- a/tests/functional/ext/docparams/parameter/missing_param_doc_required_Numpy.txt +++ b/tests/functional/ext/docparams/parameter/missing_param_doc_required_Numpy.txt @@ -1,22 +1,22 @@ -missing-param-doc:9:0:9:47:test_missing_func_params_in_numpy_docstring:"""y"" missing in parameter documentation":HIGH -missing-type-doc:9:0:9:47:test_missing_func_params_in_numpy_docstring:"""x, y"" missing in parameter type documentation":HIGH -missing-param-doc:27:4:27:53:Foo.test_missing_method_params_in_numpy_docstring:"""y"" missing in parameter documentation":HIGH -missing-type-doc:27:4:27:53:Foo.test_missing_method_params_in_numpy_docstring:"""x, y"" missing in parameter type documentation":HIGH -differing-param-doc:66:0:66:53:test_wrong_name_of_func_params_in_numpy_docstring:"""xarg1, zarg1"" differing in parameter documentation":HIGH -differing-type-doc:66:0:66:53:test_wrong_name_of_func_params_in_numpy_docstring:"""xarg1, zarg1"" differing in parameter type documentation":HIGH -missing-param-doc:66:0:66:53:test_wrong_name_of_func_params_in_numpy_docstring:"""xarg, zarg"" missing in parameter documentation":HIGH -missing-type-doc:66:0:66:53:test_wrong_name_of_func_params_in_numpy_docstring:"""xarg, zarg"" missing in parameter type documentation":HIGH -differing-param-doc:85:0:85:57:test_wrong_name_of_func_params_in_numpy_docstring_two:"""yarg1"" differing in parameter documentation":HIGH -differing-type-doc:85:0:85:57:test_wrong_name_of_func_params_in_numpy_docstring_two:"""yarg1"" differing in parameter type documentation":HIGH -missing-param-doc:116:0:116:14:ClassFoo:"""x"" missing in parameter documentation":HIGH -missing-type-doc:116:0:116:14:ClassFoo:"""x, y"" missing in parameter type documentation":HIGH -missing-param-doc:156:4:156:16:ClassFoo.__init__:"""x"" missing in parameter documentation":HIGH -missing-type-doc:156:4:156:16:ClassFoo.__init__:"""x, y"" missing in parameter type documentation":HIGH -missing-param-doc:172:0:172:14:ClassFoo:"""x"" missing in parameter documentation":HIGH -missing-type-doc:172:0:172:14:ClassFoo:"""x, y"" missing in parameter type documentation":HIGH -multiple-constructor-doc:172:0:172:14:ClassFoo:"""ClassFoo"" has constructor parameters documented in class and __init__":HIGH -missing-param-doc:188:4:188:16:ClassFoo.__init__:"""x"" missing in parameter documentation":HIGH -missing-type-doc:188:4:188:16:ClassFoo.__init__:"""x, y"" missing in parameter type documentation":HIGH -missing-param-doc:200:0:200:33:test_warns_missing_args_numpy:"""*args"" missing in parameter documentation":HIGH -missing-param-doc:217:0:217:35:test_warns_missing_kwargs_numpy:"""**kwargs"" missing in parameter documentation":HIGH -missing-type-doc:234:0:234:38:test_finds_args_without_type_numpy:"""untyped_arg"" missing in parameter type documentation":HIGH +missing-param-doc:12:0:12:47:test_missing_func_params_in_numpy_docstring:"""y"" missing in parameter documentation":HIGH +missing-type-doc:12:0:12:47:test_missing_func_params_in_numpy_docstring:"""x, y"" missing in parameter type documentation":HIGH +missing-param-doc:30:4:30:53:Foo.test_missing_method_params_in_numpy_docstring:"""y"" missing in parameter documentation":HIGH +missing-type-doc:30:4:30:53:Foo.test_missing_method_params_in_numpy_docstring:"""x, y"" missing in parameter type documentation":HIGH +differing-param-doc:69:0:69:53:test_wrong_name_of_func_params_in_numpy_docstring:"""xarg1, zarg1"" differing in parameter documentation":HIGH +differing-type-doc:69:0:69:53:test_wrong_name_of_func_params_in_numpy_docstring:"""xarg1, zarg1"" differing in parameter type documentation":HIGH +missing-param-doc:69:0:69:53:test_wrong_name_of_func_params_in_numpy_docstring:"""xarg, zarg"" missing in parameter documentation":HIGH +missing-type-doc:69:0:69:53:test_wrong_name_of_func_params_in_numpy_docstring:"""xarg, zarg"" missing in parameter type documentation":HIGH +differing-param-doc:88:0:88:57:test_wrong_name_of_func_params_in_numpy_docstring_two:"""yarg1"" differing in parameter documentation":HIGH +differing-type-doc:88:0:88:57:test_wrong_name_of_func_params_in_numpy_docstring_two:"""yarg1"" differing in parameter type documentation":HIGH +missing-param-doc:119:0:119:14:ClassFoo:"""x"" missing in parameter documentation":HIGH +missing-type-doc:119:0:119:14:ClassFoo:"""x, y"" missing in parameter type documentation":HIGH +missing-param-doc:159:4:159:16:ClassFoo.__init__:"""x"" missing in parameter documentation":HIGH +missing-type-doc:159:4:159:16:ClassFoo.__init__:"""x, y"" missing in parameter type documentation":HIGH +missing-param-doc:175:0:175:14:ClassFoo:"""x"" missing in parameter documentation":HIGH +missing-type-doc:175:0:175:14:ClassFoo:"""x, y"" missing in parameter type documentation":HIGH +multiple-constructor-doc:175:0:175:14:ClassFoo:"""ClassFoo"" has constructor parameters documented in class and __init__":HIGH +missing-param-doc:191:4:191:16:ClassFoo.__init__:"""x"" missing in parameter documentation":HIGH +missing-type-doc:191:4:191:16:ClassFoo.__init__:"""x, y"" missing in parameter type documentation":HIGH +missing-param-doc:203:0:203:33:test_warns_missing_args_numpy:"""*args"" missing in parameter documentation":HIGH +missing-param-doc:220:0:220:35:test_warns_missing_kwargs_numpy:"""**kwargs"" missing in parameter documentation":HIGH +missing-type-doc:237:0:237:38:test_finds_args_without_type_numpy:"""untyped_arg"" missing in parameter type documentation":HIGH diff --git a/tests/functional/ext/docparams/parameter/missing_param_doc_required_Sphinx.py b/tests/functional/ext/docparams/parameter/missing_param_doc_required_Sphinx.py index 36f3aed1f3c..62406f7c76e 100644 --- a/tests/functional/ext/docparams/parameter/missing_param_doc_required_Sphinx.py +++ b/tests/functional/ext/docparams/parameter/missing_param_doc_required_Sphinx.py @@ -1,9 +1,12 @@ """Tests for missing-param-doc and missing-type-doc for Sphinx style docstrings with accept-no-param-doc = no""" + # pylint: disable=function-redefined, invalid-name, undefined-variable, missing-class-docstring # pylint: disable=unused-argument, too-few-public-methods, unnecessary-pass, line-too-long # pylint: disable=missing-function-docstring, disallowed-name +from __future__ import annotations + def test_missing_func_params_in_sphinx_docstring( # [missing-param-doc, missing-type-doc] x, y, z @@ -181,6 +184,21 @@ def test_warns_missing_kwargs_sphinx( # [missing-param-doc, inconsistent-return return named_arg +def test_warns_typed_kwargs_sphinx( # [missing-param-doc, inconsistent-return-statements] + named_arg, **kwargs: dict[str, str] +): + """The docstring + + :param named_arg: Returned + :type named_arg: object + + :returns: Maybe named_arg + :rtype: object or None + """ + if kwargs: + return named_arg + + def test_finds_args_without_type_sphinx( # [missing-param-doc, inconsistent-return-statements] named_arg, *args ): diff --git a/tests/functional/ext/docparams/parameter/missing_param_doc_required_Sphinx.txt b/tests/functional/ext/docparams/parameter/missing_param_doc_required_Sphinx.txt index b3819fff79c..0785d61b4fd 100644 --- a/tests/functional/ext/docparams/parameter/missing_param_doc_required_Sphinx.txt +++ b/tests/functional/ext/docparams/parameter/missing_param_doc_required_Sphinx.txt @@ -1,39 +1,41 @@ -missing-param-doc:8:0:8:48:test_missing_func_params_in_sphinx_docstring:"""y"" missing in parameter documentation":HIGH -missing-type-doc:8:0:8:48:test_missing_func_params_in_sphinx_docstring:"""x, y"" missing in parameter type documentation":HIGH -missing-param-doc:22:4:22:54:Foo.test_missing_method_params_in_sphinx_docstring:"""y"" missing in parameter documentation":HIGH -missing-type-doc:22:4:22:54:Foo.test_missing_method_params_in_sphinx_docstring:"""x, y"" missing in parameter type documentation":HIGH -differing-param-doc:55:0:55:54:test_wrong_name_of_func_params_in_sphinx_docstring:"""xarg1, zarg1"" differing in parameter documentation":HIGH -differing-type-doc:55:0:55:54:test_wrong_name_of_func_params_in_sphinx_docstring:"""yarg1, zarg1"" differing in parameter type documentation":HIGH -missing-param-doc:55:0:55:54:test_wrong_name_of_func_params_in_sphinx_docstring:"""xarg, zarg"" missing in parameter documentation":HIGH -missing-type-doc:55:0:55:54:test_wrong_name_of_func_params_in_sphinx_docstring:"""yarg, zarg"" missing in parameter type documentation":HIGH -differing-param-doc:72:0:72:58:test_wrong_name_of_func_params_in_sphinx_docstring_two:"""yarg1"" differing in parameter documentation":HIGH -differing-type-doc:72:0:72:58:test_wrong_name_of_func_params_in_sphinx_docstring_two:"""yarg1"" differing in parameter type documentation":HIGH -missing-param-doc:99:0:99:14:ClassFoo:"""x"" missing in parameter documentation":HIGH -missing-type-doc:99:0:99:14:ClassFoo:"""x, y"" missing in parameter type documentation":HIGH -missing-param-doc:116:4:116:16:ClassFoo.__init__:"""x"" missing in parameter documentation":HIGH -missing-type-doc:116:4:116:16:ClassFoo.__init__:"""x, y"" missing in parameter type documentation":HIGH -missing-param-doc:131:0:131:14:ClassFoo:"""x"" missing in parameter documentation":HIGH -missing-type-doc:131:0:131:14:ClassFoo:"""x, y"" missing in parameter type documentation":HIGH -multiple-constructor-doc:131:0:131:14:ClassFoo:"""ClassFoo"" has constructor parameters documented in class and __init__":HIGH -missing-param-doc:144:4:144:16:ClassFoo.__init__:"""x"" missing in parameter documentation":HIGH -missing-type-doc:144:4:144:16:ClassFoo.__init__:"""x, y"" missing in parameter type documentation":HIGH -inconsistent-return-statements:154:0:154:34:test_warns_missing_args_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED -missing-param-doc:154:0:154:34:test_warns_missing_args_sphinx:"""*args"" missing in parameter documentation":HIGH -inconsistent-return-statements:169:0:169:36:test_warns_missing_kwargs_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED -missing-param-doc:169:0:169:36:test_warns_missing_kwargs_sphinx:"""**kwargs"" missing in parameter documentation":HIGH -inconsistent-return-statements:184:0:184:39:test_finds_args_without_type_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED -missing-param-doc:184:0:184:39:test_finds_args_without_type_sphinx:"""*args"" missing in parameter documentation":HIGH -inconsistent-return-statements:201:0:201:41:test_finds_kwargs_without_type_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED -missing-param-doc:201:0:201:41:test_finds_kwargs_without_type_sphinx:"""**kwargs"" missing in parameter documentation":HIGH -inconsistent-return-statements:218:0:218:39:test_finds_args_without_type_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED -inconsistent-return-statements:237:0:237:41:test_finds_kwargs_without_type_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED -inconsistent-return-statements:256:0:256:39:test_finds_args_without_type_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED -inconsistent-return-statements:274:0:274:41:test_finds_kwargs_without_type_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED -missing-raises-doc:299:4:299:11:Foo.foo:"""AttributeError"" not documented as being raised":HIGH -unreachable:325:8:325:17:Foo.foo:Unreachable code:HIGH -missing-param-doc:328:4:328:11:Foo.foo:"""value"" missing in parameter documentation":HIGH -missing-raises-doc:328:4:328:11:Foo.foo:"""AttributeError"" not documented as being raised":HIGH -missing-type-doc:328:4:328:11:Foo.foo:"""value"" missing in parameter type documentation":HIGH -unreachable:364:8:364:17:Foo.foo:Unreachable code:HIGH -useless-param-doc:368:4:368:55:Foo.test_useless_docs_ignored_argument_names_sphinx:"""_, _ignored"" useless ignored parameter documentation":HIGH -useless-type-doc:368:4:368:55:Foo.test_useless_docs_ignored_argument_names_sphinx:"""_"" useless ignored parameter type documentation":HIGH +missing-param-doc:11:0:11:48:test_missing_func_params_in_sphinx_docstring:"""y"" missing in parameter documentation":HIGH +missing-type-doc:11:0:11:48:test_missing_func_params_in_sphinx_docstring:"""x, y"" missing in parameter type documentation":HIGH +missing-param-doc:25:4:25:54:Foo.test_missing_method_params_in_sphinx_docstring:"""y"" missing in parameter documentation":HIGH +missing-type-doc:25:4:25:54:Foo.test_missing_method_params_in_sphinx_docstring:"""x, y"" missing in parameter type documentation":HIGH +differing-param-doc:58:0:58:54:test_wrong_name_of_func_params_in_sphinx_docstring:"""xarg1, zarg1"" differing in parameter documentation":HIGH +differing-type-doc:58:0:58:54:test_wrong_name_of_func_params_in_sphinx_docstring:"""yarg1, zarg1"" differing in parameter type documentation":HIGH +missing-param-doc:58:0:58:54:test_wrong_name_of_func_params_in_sphinx_docstring:"""xarg, zarg"" missing in parameter documentation":HIGH +missing-type-doc:58:0:58:54:test_wrong_name_of_func_params_in_sphinx_docstring:"""yarg, zarg"" missing in parameter type documentation":HIGH +differing-param-doc:75:0:75:58:test_wrong_name_of_func_params_in_sphinx_docstring_two:"""yarg1"" differing in parameter documentation":HIGH +differing-type-doc:75:0:75:58:test_wrong_name_of_func_params_in_sphinx_docstring_two:"""yarg1"" differing in parameter type documentation":HIGH +missing-param-doc:102:0:102:14:ClassFoo:"""x"" missing in parameter documentation":HIGH +missing-type-doc:102:0:102:14:ClassFoo:"""x, y"" missing in parameter type documentation":HIGH +missing-param-doc:119:4:119:16:ClassFoo.__init__:"""x"" missing in parameter documentation":HIGH +missing-type-doc:119:4:119:16:ClassFoo.__init__:"""x, y"" missing in parameter type documentation":HIGH +missing-param-doc:134:0:134:14:ClassFoo:"""x"" missing in parameter documentation":HIGH +missing-type-doc:134:0:134:14:ClassFoo:"""x, y"" missing in parameter type documentation":HIGH +multiple-constructor-doc:134:0:134:14:ClassFoo:"""ClassFoo"" has constructor parameters documented in class and __init__":HIGH +missing-param-doc:147:4:147:16:ClassFoo.__init__:"""x"" missing in parameter documentation":HIGH +missing-type-doc:147:4:147:16:ClassFoo.__init__:"""x, y"" missing in parameter type documentation":HIGH +inconsistent-return-statements:157:0:157:34:test_warns_missing_args_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED +missing-param-doc:157:0:157:34:test_warns_missing_args_sphinx:"""*args"" missing in parameter documentation":HIGH +inconsistent-return-statements:172:0:172:36:test_warns_missing_kwargs_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED +missing-param-doc:172:0:172:36:test_warns_missing_kwargs_sphinx:"""**kwargs"" missing in parameter documentation":HIGH +inconsistent-return-statements:187:0:187:34:test_warns_typed_kwargs_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED +missing-param-doc:187:0:187:34:test_warns_typed_kwargs_sphinx:"""**kwargs"" missing in parameter documentation":HIGH +inconsistent-return-statements:202:0:202:39:test_finds_args_without_type_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED +missing-param-doc:202:0:202:39:test_finds_args_without_type_sphinx:"""*args"" missing in parameter documentation":HIGH +inconsistent-return-statements:219:0:219:41:test_finds_kwargs_without_type_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED +missing-param-doc:219:0:219:41:test_finds_kwargs_without_type_sphinx:"""**kwargs"" missing in parameter documentation":HIGH +inconsistent-return-statements:236:0:236:39:test_finds_args_without_type_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED +inconsistent-return-statements:255:0:255:41:test_finds_kwargs_without_type_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED +inconsistent-return-statements:274:0:274:39:test_finds_args_without_type_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED +inconsistent-return-statements:292:0:292:41:test_finds_kwargs_without_type_sphinx:Either all return statements in a function should return an expression, or none of them should.:UNDEFINED +missing-raises-doc:317:4:317:11:Foo.foo:"""AttributeError"" not documented as being raised":HIGH +unreachable:343:8:343:17:Foo.foo:Unreachable code:HIGH +missing-param-doc:346:4:346:11:Foo.foo:"""value"" missing in parameter documentation":HIGH +missing-raises-doc:346:4:346:11:Foo.foo:"""AttributeError"" not documented as being raised":HIGH +missing-type-doc:346:4:346:11:Foo.foo:"""value"" missing in parameter type documentation":HIGH +unreachable:382:8:382:17:Foo.foo:Unreachable code:HIGH +useless-param-doc:386:4:386:55:Foo.test_useless_docs_ignored_argument_names_sphinx:"""_, _ignored"" useless ignored parameter documentation":HIGH +useless-type-doc:386:4:386:55:Foo.test_useless_docs_ignored_argument_names_sphinx:"""_"" useless ignored parameter type documentation":HIGH