From 960c266ef848271b81d90475c6787f1ff7e55bfb Mon Sep 17 00:00:00 2001 From: dcbr <15089458+dcbr@users.noreply.github.com> Date: Mon, 25 Oct 2021 17:14:47 +0200 Subject: [PATCH 1/4] Fix invalid "PR01" error when parameter is specified in "Other Parameters" section. --- numpydoc/tests/test_validate.py | 28 ++++++++++++++++++++++++++++ numpydoc/validate.py | 3 ++- 2 files changed, 30 insertions(+), 1 deletion(-) diff --git a/numpydoc/tests/test_validate.py b/numpydoc/tests/test_validate.py index 704a25ef..47b39c57 100644 --- a/numpydoc/tests/test_validate.py +++ b/numpydoc/tests/test_validate.py @@ -410,6 +410,33 @@ def multiple_variables_on_one_line(self, matrix, a, b, i, j): """ pass + def other_parameters(self, param1, param2): + """ + Ensure "Other Parameters" are recognized. + + The second parameter is used infrequently, so it is put in the + "Other Parameters" section. + + Parameters + ---------- + param1 : bool + Description of commonly used parameter. + + Other Parameters + ---------------- + param2 : str + Description of infrequently used parameter. + + See Also + -------- + related : Something related. + + Examples + -------- + >>> result = 1 + 1 + """ + pass + class BadGenericDocStrings: """Everything here has a bad docstring @@ -1039,6 +1066,7 @@ def test_good_class(self, capsys): "no_returns", "empty_returns", "multiple_variables_on_one_line", + "other_parameters", ], ) def test_good_functions(self, capsys, func): diff --git a/numpydoc/validate.py b/numpydoc/validate.py index b33ea780..0001e83a 100644 --- a/numpydoc/validate.py +++ b/numpydoc/validate.py @@ -9,6 +9,7 @@ import collections import importlib import inspect +import itertools import pydoc import re import textwrap @@ -263,7 +264,7 @@ def extended_summary(self): @property def doc_parameters(self): parameters = collections.OrderedDict() - for names, type_, desc in self.doc["Parameters"]: + for names, type_, desc in itertools.chain(self.doc["Parameters"], self.doc["Other Parameters"]): for name in names.split(", "): parameters[name] = (type_, desc) return parameters From e8c58e54b95a9431e598ba7bf311bff24f238562 Mon Sep 17 00:00:00 2001 From: dcbr <15089458+dcbr@users.noreply.github.com> Date: Tue, 2 Nov 2021 08:58:00 +0100 Subject: [PATCH 2/4] Fix 'foo' docstring in doc/example.py --- doc/example.py | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/doc/example.py b/doc/example.py index b3ba6869..f2a1dc4f 100644 --- a/doc/example.py +++ b/doc/example.py @@ -35,7 +35,7 @@ # numpy module itself, unabbreviated. -def foo(var1, var2, *args, long_var_name='hi', **kwargs): +def foo(var1, var2, *args, long_var_name='hi', only_seldom_used_keyword=0, **kwargs): r"""Summarize the function in one line. Several sentences providing an extended description. Refer to @@ -70,10 +70,9 @@ def foo(var1, var2, *args, long_var_name='hi', **kwargs): Other Parameters ---------------- - only_seldom_used_keywords : type - Explanation. - common_parameters_listed_above : type - Explanation. + only_seldom_used_keyword : int, optional + Infrequently used parameters can be described under this optional + section to prevent cluttering the Parameters section. Raises ------ From 120b84c90ecf9ebc33adaed306c97e133671ad93 Mon Sep 17 00:00:00 2001 From: dcbr <15089458+dcbr@users.noreply.github.com> Date: Tue, 2 Nov 2021 11:56:31 +0100 Subject: [PATCH 3/4] Change "PR03" (wrong parameters order) validation test --- numpydoc/validate.py | 49 +++++++++++++++++++++++++++++++------------- 1 file changed, 35 insertions(+), 14 deletions(-) diff --git a/numpydoc/validate.py b/numpydoc/validate.py index 2b512dfd..39424fd3 100644 --- a/numpydoc/validate.py +++ b/numpydoc/validate.py @@ -9,7 +9,6 @@ import collections import importlib import inspect -import itertools import pydoc import re import textwrap @@ -262,14 +261,26 @@ def extended_summary(self): return " ".join(self.doc["Summary"]) return " ".join(self.doc["Extended Summary"]) - @property - def doc_parameters(self): + def _doc_parameters(self, sections): parameters = collections.OrderedDict() - for names, type_, desc in itertools.chain(self.doc["Parameters"], self.doc["Other Parameters"]): - for name in names.split(", "): - parameters[name] = (type_, desc) + for section in sections: + for names, type_, desc in self.doc[section]: + for name in names.split(", "): + parameters[name] = (type_, desc) return parameters + @property + def doc_parameters(self): + return self._doc_parameters(["Parameters"]) + + @property + def doc_other_parameters(self): + return self._doc_parameters(["Other Parameters"]) + + @property + def doc_all_parameters(self): + return self._doc_parameters(["Parameters", "Other Parameters"]) + @property def signature_parameters(self): def add_stars(param_name, info): @@ -308,22 +319,32 @@ def add_stars(param_name, info): def parameter_mismatches(self): errs = [] signature_params = self.signature_parameters - doc_params = tuple(self.doc_parameters) - missing = set(signature_params) - set(doc_params) + all_params = tuple(self.doc_all_parameters) + missing = set(signature_params) - set(all_params) if missing: errs.append(error("PR01", missing_params=str(missing))) - extra = set(doc_params) - set(signature_params) + extra = set(all_params) - set(signature_params) if extra: errs.append(error("PR02", unknown_params=str(extra))) + order_match = True + params, other_params = tuple(self.doc_parameters.keys()), tuple(self.doc_other_parameters.keys()) + i_p, i_o = 0, 0 + for param in signature_params: + if i_p < len(params) and param == params[i_p]: + i_p += 1 + elif i_o < len(other_params) and param == other_params[i_o]: + i_o += 1 + else: + order_match = False + break if ( not missing and not extra - and signature_params != doc_params - and not (not signature_params and not doc_params) + and not order_match ): errs.append( error( - "PR03", actual_params=signature_params, documented_params=doc_params + "PR03", actual_params=signature_params, documented_params="{}, {}".format(params, other_params) ) ) @@ -334,7 +355,7 @@ def directives_without_two_colons(self): return DIRECTIVE_PATTERN.findall(self.raw_doc) def parameter_type(self, param): - return self.doc_parameters[param][0] + return self.doc_all_parameters[param][0] @property def see_also(self): @@ -543,7 +564,7 @@ def validate(obj_name): # PR03: Wrong parameters order errs += doc.parameter_mismatches - for param, kind_desc in doc.doc_parameters.items(): + for param, kind_desc in doc.doc_all_parameters.items(): if not param.startswith("*"): # Check can ignore var / kwargs if not doc.parameter_type(param): if ":" in param: From e9dbb3d83d28557422bfa5bba1580b73dce70036 Mon Sep 17 00:00:00 2001 From: dcbr <15089458+dcbr@users.noreply.github.com> Date: Fri, 5 Nov 2021 18:10:32 +0100 Subject: [PATCH 4/4] Revert "PR03" changes. --- doc/example.py | 7 +++++-- numpydoc/validate.py | 16 +++------------- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/doc/example.py b/doc/example.py index f2a1dc4f..43defc5b 100644 --- a/doc/example.py +++ b/doc/example.py @@ -55,8 +55,6 @@ def foo(var1, var2, *args, long_var_name='hi', only_seldom_used_keyword=0, **kwa Other arguments. long_var_name : {'hi', 'ho'}, optional Choices in brackets, default first when optional. - **kwargs : dict - Keyword arguments. Returns ------- @@ -73,6 +71,11 @@ def foo(var1, var2, *args, long_var_name='hi', only_seldom_used_keyword=0, **kwa only_seldom_used_keyword : int, optional Infrequently used parameters can be described under this optional section to prevent cluttering the Parameters section. + **kwargs : dict + Other infrequently used keyword arguments. Note that all keyword + arguments appearing after the first parameter specified under the + Other Parameters section, should also be described under this + section. Raises ------ diff --git a/numpydoc/validate.py b/numpydoc/validate.py index 39424fd3..91aca6b1 100644 --- a/numpydoc/validate.py +++ b/numpydoc/validate.py @@ -326,25 +326,15 @@ def parameter_mismatches(self): extra = set(all_params) - set(signature_params) if extra: errs.append(error("PR02", unknown_params=str(extra))) - order_match = True - params, other_params = tuple(self.doc_parameters.keys()), tuple(self.doc_other_parameters.keys()) - i_p, i_o = 0, 0 - for param in signature_params: - if i_p < len(params) and param == params[i_p]: - i_p += 1 - elif i_o < len(other_params) and param == other_params[i_o]: - i_o += 1 - else: - order_match = False - break if ( not missing and not extra - and not order_match + and signature_params != all_params + and not (not signature_params and not all_params) ): errs.append( error( - "PR03", actual_params=signature_params, documented_params="{}, {}".format(params, other_params) + "PR03", actual_params=signature_params, documented_params=all_params ) )