def test_check_docstring_parameters(): try: import numpydoc # noqa except ImportError: raise SkipTest("numpydoc is required to test the docstrings") incorrect = check_docstring_parameters(f_ok) assert incorrect == [] incorrect = check_docstring_parameters(f_ok, ignore=['b']) assert incorrect == [] incorrect = check_docstring_parameters(f_missing, ignore=['b']) assert incorrect == [] assert_raise_message(RuntimeError, 'Unknown section Results', check_docstring_parameters, f_bad_sections) assert_raise_message(RuntimeError, 'Unknown section Parameter', check_docstring_parameters, Klass.f_bad_sections) incorrect = check_docstring_parameters(f_check_param_definition) assert (incorrect == [ "sklearn.utils.tests.test_testing.f_check_param_definition There " "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')", ]) messages = [ [ "In function: sklearn.utils.tests.test_testing.f_bad_order", "There's a parameter name mismatch in function docstring w.r.t." " function signature, at index 0 diff: 'b' != 'a'", "Full diff:", "- ['b', 'a']", "+ ['a', 'b']" ], [ "In function: " + "sklearn.utils.tests.test_testing.f_too_many_param_docstring", "Parameters in function docstring have more items w.r.t. function" " signature, first extra item: c", "Full diff:", "- ['a', 'b']", "+ ['a', 'b', 'c']", "? +++++" ], [ "In function: sklearn.utils.tests.test_testing.f_missing", "Parameters in function docstring have less items w.r.t. function" " signature, first missing item: b", "Full diff:", "- ['a', 'b']", "+ ['a']" ], [ "In function: sklearn.utils.tests.test_testing.Klass.f_missing", "Parameters in function docstring have less items w.r.t. function" " signature, first missing item: X", "Full diff:", "- ['X', 'y']", "+ []" ], [ "In function: " + "sklearn.utils.tests.test_testing.MockMetaEstimator.predict", "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: " + "sklearn.utils.tests.test_testing.MockMetaEstimator." + "predict_proba", "Parameters in function docstring have less items w.r.t. function" " signature, first missing item: X", "Full diff:", "- ['X']", "+ []" ], [ "In function: " + "sklearn.utils.tests.test_testing.MockMetaEstimator.score", "Parameters in function docstring have less items w.r.t. function" " signature, first missing item: X", "Full diff:", "- ['X']", "+ []" ], [ "In function: " + "sklearn.utils.tests.test_testing.MockMetaEstimator.fit", "Parameters in function docstring have less items w.r.t. function" " signature, first missing item: X", "Full diff:", "- ['X', 'y']", "+ []" ], ] mock_meta = MockMetaEstimator(delegate=MockEst()) for msg, f in zip(messages, [ f_bad_order, f_too_many_param_docstring, f_missing, Klass.f_missing, mock_meta.predict, mock_meta.predict_proba, mock_meta.score, mock_meta.fit ]): incorrect = check_docstring_parameters(f) assert msg == incorrect, ('\n"%s"\n not in \n"%s"' % (msg, incorrect))
def test_docstring_parameters(): # Test module docstring formatting # Skip test if numpydoc is not found pytest.importorskip( "numpydoc", reason="numpydoc is required to test the docstrings" ) # XXX unreached code as of v0.22 from numpydoc import docscrape incorrect = [] for name in PUBLIC_MODULES: if name.endswith(".conftest"): # pytest tooling, not part of the scikit-learn API continue if name == "sklearn.utils.fixes": # We cannot always control these docstrings continue with warnings.catch_warnings(record=True): module = importlib.import_module(name) classes = inspect.getmembers(module, inspect.isclass) # Exclude non-scikit-learn classes classes = [cls for cls in classes if cls[1].__module__.startswith("sklearn")] for cname, cls in classes: this_incorrect = [] if cname in _DOCSTRING_IGNORES or cname.startswith("_"): continue if inspect.isabstract(cls): continue with warnings.catch_warnings(record=True) as w: cdoc = docscrape.ClassDoc(cls) if len(w): raise RuntimeError( "Error for __init__ of %s in %s:\n%s" % (cls, name, w[0]) ) cls_init = getattr(cls, "__init__", None) if _is_deprecated(cls_init): continue elif cls_init is not None: this_incorrect += check_docstring_parameters(cls.__init__, cdoc) for method_name in cdoc.methods: method = getattr(cls, method_name) if _is_deprecated(method): continue param_ignore = None # Now skip docstring test for y when y is None # by default for API reason if method_name in _METHODS_IGNORE_NONE_Y: sig = signature(method) if "y" in sig.parameters and sig.parameters["y"].default is None: param_ignore = ["y"] # ignore y for fit and score result = check_docstring_parameters(method, ignore=param_ignore) this_incorrect += result incorrect += this_incorrect functions = inspect.getmembers(module, inspect.isfunction) # Exclude imported functions functions = [fn for fn in functions if fn[1].__module__ == name] for fname, func in functions: # Don't test private methods / functions if fname.startswith("_"): continue if fname == "configuration" and name.endswith("setup"): continue name_ = _get_func_name(func) if not any(d in name_ for d in _DOCSTRING_IGNORES) and not _is_deprecated( func ): incorrect += check_docstring_parameters(func) msg = "\n".join(incorrect) if len(incorrect) > 0: raise AssertionError("Docstring Error:\n" + msg)
def test_check_docstring_parameters(mock_meta): pytest.importorskip( "numpydoc", reason="numpydoc is required to test the docstrings", minversion="1.2.0", ) incorrect = check_docstring_parameters(f_ok) assert incorrect == [] incorrect = check_docstring_parameters(f_ok, ignore=["b"]) assert incorrect == [] incorrect = check_docstring_parameters(f_missing, ignore=["b"]) assert incorrect == [] with pytest.raises(RuntimeError, match="Unknown section Results"): check_docstring_parameters(f_bad_sections) with pytest.raises(RuntimeError, match="Unknown section Parameter"): check_docstring_parameters(Klass.f_bad_sections) incorrect = check_docstring_parameters(f_check_param_definition) mock_meta_name = mock_meta.__class__.__name__ assert incorrect == [ "sklearn.utils.tests.test_testing.f_check_param_definition There " "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 There " "was no space between the param name and colon ('d:int')", ] messages = [ [ "In function: sklearn.utils.tests.test_testing.f_bad_order", "There's a parameter name mismatch in function docstring w.r.t." " function signature, at index 0 diff: 'b' != 'a'", "Full diff:", "- ['b', 'a']", "+ ['a', 'b']", ], [ "In function: " + "sklearn.utils.tests.test_testing.f_too_many_param_docstring", "Parameters in function docstring have more items w.r.t. function" " signature, first extra item: c", "Full diff:", "- ['a', 'b']", "+ ['a', 'b', 'c']", "? +++++", ], [ "In function: sklearn.utils.tests.test_testing.f_missing", "Parameters in function docstring have less items w.r.t. function" " signature, first missing item: b", "Full diff:", "- ['a', 'b']", "+ ['a']", ], [ "In function: sklearn.utils.tests.test_testing.Klass.f_missing", "Parameters in function docstring have less items w.r.t. function" " signature, first missing item: X", "Full diff:", "- ['X', 'y']", "+ []", ], [ "In function: " + f"sklearn.utils.tests.test_testing.{mock_meta_name}.predict", "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}." + "predict_proba", "potentially wrong underline length... ", "Parameters ", "--------- in ", ], [ "In function: " + f"sklearn.utils.tests.test_testing.{mock_meta_name}.score", "potentially wrong underline length... ", "Parameters ", "--------- in ", ], [ "In function: " + f"sklearn.utils.tests.test_testing.{mock_meta_name}.fit", "Parameters in function docstring have less items w.r.t. function" " signature, first missing item: X", "Full diff:", "- ['X', 'y']", "+ []", ], ] for msg, f in zip( messages, [ f_bad_order, f_too_many_param_docstring, f_missing, Klass.f_missing, mock_meta.predict, mock_meta.predict_proba, mock_meta.score, mock_meta.fit, ], ): incorrect = check_docstring_parameters(f) assert msg == incorrect, '\n"%s"\n not in \n"%s"' % (msg, incorrect)