From 5aacb118ce4fe3683c5b1f7440ad0a4a01a0148e Mon Sep 17 00:00:00 2001 From: "Thomas J. Fan" Date: Mon, 24 Jan 2022 15:01:48 -0500 Subject: [PATCH 1/7] MAINT Adjust tests for numpydoc 1.2 --- sklearn/_min_dependencies.py | 2 +- sklearn/utils/tests/test_testing.py | 39 +++++++++++------------------ 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/sklearn/_min_dependencies.py b/sklearn/_min_dependencies.py index 911914de1bdff..9015338627f7a 100644 --- a/sklearn/_min_dependencies.py +++ b/sklearn/_min_dependencies.py @@ -45,7 +45,7 @@ "pyamg": ("4.0.0", "tests"), "sphinx": ("4.0.1", "docs"), "sphinx-gallery": ("0.7.0", "docs"), - "numpydoc": ("1.0.0", "docs"), + "numpydoc": ("1.2.0", "docs, tests"), "Pillow": ("7.1.2", "docs"), "sphinx-prompt": ("1.3.0", "docs"), "sphinxext-opengraph": ("0.4.2", "docs"), diff --git a/sklearn/utils/tests/test_testing.py b/sklearn/utils/tests/test_testing.py index a3a42aeb4c83f..d6d4972f10e01 100644 --- a/sklearn/utils/tests/test_testing.py +++ b/sklearn/utils/tests/test_testing.py @@ -370,7 +370,7 @@ def f_check_param_definition(a, b, c, d, e): b: Parameter b c : - Parameter c + This is parsed correctly in numpydoc 1.2 d:int Parameter d e @@ -387,7 +387,7 @@ def f_bad_sections(self, X, y): """Function f Parameter - ---------- + --------- a : int Parameter a b : float @@ -446,20 +446,14 @@ def score(self, X): """This is available only if delegate has score. Parameters - --------- + ---------- y : ndarray Parameter y """ @available_if(lambda self: hasattr(self.delegate, "predict_proba")) def predict_proba(self, X): - """This is available only if delegate has predict_proba. - - Parameters - --------- - X : ndarray - Parameter X - """ + """This is available only if delegate has predict_proba.""" return X @deprecated("Testing deprecated function with wrong params") @@ -495,20 +489,14 @@ def score(self, X): """This is available only if delegate has score. Parameters - --------- + ---------- y : ndarray Parameter y """ @if_delegate_has_method(delegate="delegate") def predict_proba(self, X): - """This is available only if delegate has predict_proba. - - Parameters - --------- - X : ndarray - Parameter X - """ + """This is available only if delegate has predict_proba.""" return X @deprecated("Testing deprecated function with wrong params") @@ -525,7 +513,9 @@ def fit(self, X, y): ) def test_check_docstring_parameters(mock_meta): pytest.importorskip( - "numpydoc", reason="numpydoc is required to test the docstrings" + "numpydoc", + reason="numpydoc is required to test the docstrings", + minversion="1.2.0", ) incorrect = check_docstring_parameters(f_ok) @@ -546,8 +536,6 @@ def test_check_docstring_parameters(mock_meta): "was no space between the param name and colon ('a: int')", "sklearn.utils.tests.test_testing.f_check_param_definition There " "was no space between the param name and colon ('b:')", - "sklearn.utils.tests.test_testing.f_check_param_definition " - "Parameter 'c :' has an empty type spec. Remove the colon", "sklearn.utils.tests.test_testing.f_check_param_definition There " "was no space between the param name and colon ('d:int')", ] @@ -611,11 +599,13 @@ def test_check_docstring_parameters(mock_meta): [ "In function: " + f"sklearn.utils.tests.test_testing.{mock_meta_name}.score", - "Parameters in function docstring have less items w.r.t. function" - " signature, first missing item: X", + "There's a parameter name mismatch in function docstring w.r.t. function" + " signature, at index 0 diff: 'X' != 'y'", "Full diff:", "- ['X']", - "+ []", + "? ^", + "+ ['y']", + "? ^", ], [ "In function: " + f"sklearn.utils.tests.test_testing.{mock_meta_name}.fit", @@ -641,6 +631,7 @@ def test_check_docstring_parameters(mock_meta): ], ): incorrect = check_docstring_parameters(f) + print(incorrect) assert msg == incorrect, '\n"%s"\n not in \n"%s"' % (msg, incorrect) From 1b0115c669bac4831084148941bee87614c6a7e6 Mon Sep 17 00:00:00 2001 From: "Thomas J. Fan" Date: Mon, 24 Jan 2022 15:07:51 -0500 Subject: [PATCH 2/7] CLN Remove print --- sklearn/utils/tests/test_testing.py | 1 - 1 file changed, 1 deletion(-) diff --git a/sklearn/utils/tests/test_testing.py b/sklearn/utils/tests/test_testing.py index d6d4972f10e01..77818f78c9b05 100644 --- a/sklearn/utils/tests/test_testing.py +++ b/sklearn/utils/tests/test_testing.py @@ -631,7 +631,6 @@ def test_check_docstring_parameters(mock_meta): ], ): incorrect = check_docstring_parameters(f) - print(incorrect) assert msg == incorrect, '\n"%s"\n not in \n"%s"' % (msg, incorrect) From 03badc9f40fd6a6c28b81090c572e0aa1dca4e53 Mon Sep 17 00:00:00 2001 From: "Thomas J. Fan" Date: Mon, 24 Jan 2022 15:34:00 -0500 Subject: [PATCH 3/7] CLN Better error for underline length --- sklearn/utils/_testing.py | 14 +++++++++++--- sklearn/utils/tests/test_testing.py | 28 ++++++++++++++++++++-------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/sklearn/utils/_testing.py b/sklearn/utils/_testing.py index 1724063be2f43..4191338f7d080 100644 --- a/sklearn/utils/_testing.py +++ b/sklearn/utils/_testing.py @@ -655,14 +655,22 @@ def check_docstring_parameters(func, doc=None, ignore=None): # Analyze function's docstring if doc is None: - with warnings.catch_warnings(record=True) as w: + records = [] + with warnings.catch_warnings(record=True): + warnings.simplefilter("error", UserWarning) try: doc = docscrape.FunctionDoc(func) + except UserWarning as exp: + if "potentially wrong underline length" in str(exp): + message = str(exp).split("\n")[:4] + incorrect += [f"In function: {func_name}"] + message + return incorrect + records.append(str(exp)) except Exception as exp: incorrect += [func_name + " parsing error: " + str(exp)] return incorrect - if len(w): - raise RuntimeError("Error for %s:\n%s" % (func_name, w[0])) + if len(records): + raise RuntimeError("Error for %s:\n%s" % (func_name, records[0])) param_docs = [] for name, type_definition, param_doc in doc["Parameters"]: diff --git a/sklearn/utils/tests/test_testing.py b/sklearn/utils/tests/test_testing.py index 77818f78c9b05..d52216a6cd87b 100644 --- a/sklearn/utils/tests/test_testing.py +++ b/sklearn/utils/tests/test_testing.py @@ -453,7 +453,13 @@ def score(self, X): @available_if(lambda self: hasattr(self.delegate, "predict_proba")) def predict_proba(self, X): - """This is available only if delegate has predict_proba.""" + """This is available only if delegate has predict_proba. + + Parameters + --------- + X : ndarray + Parameter X + """ return X @deprecated("Testing deprecated function with wrong params") @@ -496,7 +502,13 @@ def score(self, X): @if_delegate_has_method(delegate="delegate") def predict_proba(self, X): - """This is available only if delegate has predict_proba.""" + """This is available only if delegate has predict_proba. + + Parameters + --------- + X : ndarray + Parameter X + """ return X @deprecated("Testing deprecated function with wrong params") @@ -590,11 +602,10 @@ def test_check_docstring_parameters(mock_meta): "In function: " + f"sklearn.utils.tests.test_testing.{mock_meta_name}." + "predict_proba", - "Parameters in function docstring have less items w.r.t. function" - " signature, first missing item: X", - "Full diff:", - "- ['X']", - "+ []", + "potentially wrong underline length... ", + "Parameters ", + "--------- in ", + "This is available only if delegate has predict_proba.", ], [ "In function: " @@ -627,10 +638,11 @@ def test_check_docstring_parameters(mock_meta): mock_meta.predict, mock_meta.predict_proba, mock_meta.score, - mock_meta.fit, + # mock_meta.fit, ], ): incorrect = check_docstring_parameters(f) + print(incorrect) assert msg == incorrect, '\n"%s"\n not in \n"%s"' % (msg, incorrect) From 9a9fa0cb0e57b2e9448d919d4b07be0c659c4d75 Mon Sep 17 00:00:00 2001 From: "Thomas J. Fan" Date: Mon, 24 Jan 2022 22:44:24 -0500 Subject: [PATCH 4/7] CLN Remove pin --- build_tools/circle/build_test_arm.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build_tools/circle/build_test_arm.sh b/build_tools/circle/build_test_arm.sh index 5ea185eed726c..67beaae5dba31 100755 --- a/build_tools/circle/build_test_arm.sh +++ b/build_tools/circle/build_test_arm.sh @@ -60,7 +60,7 @@ fi if [[ "$TEST_DOCSTRINGS" == "true" ]]; then # numpydoc requires sphinx mamba install --verbose -y sphinx - mamba install --verbose -y "numpydoc<1.2" + mamba install --verbose -y numpydoc fi python --version From a342efbba2d8e0d4c2193d7ea1c03518d7a029f7 Mon Sep 17 00:00:00 2001 From: "Thomas J. Fan" Date: Tue, 25 Jan 2022 09:55:19 -0500 Subject: [PATCH 5/7] CLN Address comments --- build_tools/azure/install.sh | 2 -- sklearn/utils/tests/test_testing.py | 3 +-- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/build_tools/azure/install.sh b/build_tools/azure/install.sh index 4bff104b072b7..8fd9b0b9cc67f 100755 --- a/build_tools/azure/install.sh +++ b/build_tools/azure/install.sh @@ -147,8 +147,6 @@ fi if [[ "$TEST_DOCSTRINGS" == "true" ]]; then # numpydoc requires sphinx python -m pip install sphinx - # TODO: update the docstring checks to be compatible with new - # numpydoc versions python -m pip install numpydoc fi diff --git a/sklearn/utils/tests/test_testing.py b/sklearn/utils/tests/test_testing.py index d52216a6cd87b..83840d920354c 100644 --- a/sklearn/utils/tests/test_testing.py +++ b/sklearn/utils/tests/test_testing.py @@ -638,11 +638,10 @@ def test_check_docstring_parameters(mock_meta): mock_meta.predict, mock_meta.predict_proba, mock_meta.score, - # mock_meta.fit, + mock_meta.fit, ], ): incorrect = check_docstring_parameters(f) - print(incorrect) assert msg == incorrect, '\n"%s"\n not in \n"%s"' % (msg, incorrect) From bc2d157b532bfb4da843cc3379804ce6c0c91874 Mon Sep 17 00:00:00 2001 From: "Thomas J. Fan" Date: Tue, 25 Jan 2022 11:58:28 -0500 Subject: [PATCH 6/7] Update sklearn/utils/_testing.py Co-authored-by: Julien Jerphanion --- sklearn/utils/_testing.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sklearn/utils/_testing.py b/sklearn/utils/_testing.py index 4191338f7d080..f972e725956f2 100644 --- a/sklearn/utils/_testing.py +++ b/sklearn/utils/_testing.py @@ -662,6 +662,9 @@ def check_docstring_parameters(func, doc=None, ignore=None): doc = docscrape.FunctionDoc(func) except UserWarning as exp: if "potentially wrong underline length" in str(exp): + # Catch warning raised as of numpydoc 1.2 when + # the underline length for a section of a docstring + # is not consistent. message = str(exp).split("\n")[:4] incorrect += [f"In function: {func_name}"] + message return incorrect From 772f80c9566e6c6d865a1c19545fb72e93c8a145 Mon Sep 17 00:00:00 2001 From: "Thomas J. Fan" Date: Thu, 27 Jan 2022 12:00:40 -0500 Subject: [PATCH 7/7] TST Update test for new error message --- sklearn/utils/_testing.py | 2 +- sklearn/utils/tests/test_testing.py | 15 +++++---------- 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/sklearn/utils/_testing.py b/sklearn/utils/_testing.py index f972e725956f2..7b57549e5886c 100644 --- a/sklearn/utils/_testing.py +++ b/sklearn/utils/_testing.py @@ -665,7 +665,7 @@ def check_docstring_parameters(func, doc=None, ignore=None): # Catch warning raised as of numpydoc 1.2 when # the underline length for a section of a docstring # is not consistent. - message = str(exp).split("\n")[:4] + message = str(exp).split("\n")[:3] incorrect += [f"In function: {func_name}"] + message return incorrect records.append(str(exp)) diff --git a/sklearn/utils/tests/test_testing.py b/sklearn/utils/tests/test_testing.py index 83840d920354c..ea4831fb02400 100644 --- a/sklearn/utils/tests/test_testing.py +++ b/sklearn/utils/tests/test_testing.py @@ -446,7 +446,7 @@ def score(self, X): """This is available only if delegate has score. Parameters - ---------- + --------- y : ndarray Parameter y """ @@ -495,7 +495,7 @@ def score(self, X): """This is available only if delegate has score. Parameters - ---------- + --------- y : ndarray Parameter y """ @@ -605,18 +605,13 @@ def test_check_docstring_parameters(mock_meta): "potentially wrong underline length... ", "Parameters ", "--------- in ", - "This is available only if delegate has predict_proba.", ], [ "In function: " + f"sklearn.utils.tests.test_testing.{mock_meta_name}.score", - "There's a parameter name mismatch in function docstring w.r.t. function" - " signature, at index 0 diff: 'X' != 'y'", - "Full diff:", - "- ['X']", - "? ^", - "+ ['y']", - "? ^", + "potentially wrong underline length... ", + "Parameters ", + "--------- in ", ], [ "In function: " + f"sklearn.utils.tests.test_testing.{mock_meta_name}.fit",