From 29abec9556b0559f0b24e2bbf78c7a5e48edd0df Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Thu, 23 May 2024 20:11:25 -0700 Subject: [PATCH 1/6] Make `numpydoc lint --ignore ...` parsing more robust Before, the only way to specify ignores is as: numpydoc lint filename --ignore EX01 SA01 and multiple invocations of the ignore flag overwrote one another. Instead, ignored checks are now specified as: numpydoc lint --ignore=EX01,SA01 filename The comma can also be whitespace: numpydoc lint --ignore="EX01 SA01" filename Multiple ignore flags work correctly: numpydoc lint --ignore EX01 --ignore SA01 filename --- numpydoc/cli.py | 11 +++++++++-- numpydoc/tests/test_main.py | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/numpydoc/cli.py b/numpydoc/cli.py index ef8cff2c..37a9ab6b 100644 --- a/numpydoc/cli.py +++ b/numpydoc/cli.py @@ -2,6 +2,7 @@ import argparse import ast +import re from collections.abc import Sequence from pathlib import Path from typing import List, Union @@ -100,8 +101,6 @@ def _parse_config(s): ) lint_parser.add_argument( "--ignore", - type=str, - nargs="*", help=( f"""Check codes to ignore.{ ' Currently ignoring the following from ' @@ -110,6 +109,7 @@ def _parse_config(s): if ignored_checks else '' }""" ), + action="append", ) lint_parser.set_defaults(func=validate_docstrings.run_hook) @@ -122,6 +122,13 @@ def main(argv: Union[Sequence[str], None] = None) -> int: args = vars(ap.parse_args(argv)) + # Parse --ignored=SA01,EX01 + ignored_checks = [] + if args.get("ignore", None) is not None: + for checks in args["ignore"]: + ignored_checks += re.split("\\W+", checks) + args["ignore"] = ignored_checks + try: func = args.pop("func") return func(**args) diff --git a/numpydoc/tests/test_main.py b/numpydoc/tests/test_main.py index 12c06840..7d26737a 100644 --- a/numpydoc/tests/test_main.py +++ b/numpydoc/tests/test_main.py @@ -117,7 +117,7 @@ def test_validate_perfect_docstring(): assert exit_status == 0 -@pytest.mark.parametrize("args", [[], ["--ignore", "ES01", "SA01", "EX01"]]) +@pytest.mark.parametrize("args", [[], ["--ignore", "ES01,SA01,EX01"]]) def test_lint(capsys, args): argv = ["lint", "numpydoc/__main__.py"] + args if args: From 30de5265b9f97fd1d68db9030c19b93f11fa8373 Mon Sep 17 00:00:00 2001 From: Ross Barnowski Date: Wed, 19 Jun 2024 04:37:58 -0700 Subject: [PATCH 2/6] Update numpydoc/tests/test_main.py Co-authored-by: Stefanie Molin <24376333+stefmolin@users.noreply.github.com> --- numpydoc/tests/test_main.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/numpydoc/tests/test_main.py b/numpydoc/tests/test_main.py index 7d26737a..f42e3964 100644 --- a/numpydoc/tests/test_main.py +++ b/numpydoc/tests/test_main.py @@ -117,7 +117,10 @@ def test_validate_perfect_docstring(): assert exit_status == 0 -@pytest.mark.parametrize("args", [[], ["--ignore", "ES01,SA01,EX01"]]) +@pytest.mark.parametrize( + "args", + [[], ["--ignore", "ES01,SA01,EX01"], ["--ignore", "ES01", "--ignore", "SA01 EX01"]], +) def test_lint(capsys, args): argv = ["lint", "numpydoc/__main__.py"] + args if args: From 8c65282b4c89a207bfdea91fe67ad23460e212b8 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Fri, 22 May 2026 23:23:12 +0000 Subject: [PATCH 3/6] Address review: update test cases and --ignore help text --- numpydoc/cli.py | 5 ++++- numpydoc/tests/test_main.py | 21 +++++---------------- 2 files changed, 9 insertions(+), 17 deletions(-) diff --git a/numpydoc/cli.py b/numpydoc/cli.py index b47faf5c..d72b7e0c 100644 --- a/numpydoc/cli.py +++ b/numpydoc/cli.py @@ -102,7 +102,10 @@ def _parse_config(s): lint_parser.add_argument( "--ignore", help=( - f"""Check codes to ignore.{ + "Check codes to ignore. Can be specified multiple times; each value\n" + "may contain multiple comma or space separated codes\n" + "(e.g., --ignore ES01,SA01 or --ignore ES01 --ignore 'SA01 EX01')." + f"""{ " Currently ignoring the following from " f"{Path(project_root_from_cwd) / config_file}: {ignored_checks_text}" "Values provided here will be in addition to the above, unless an alternate config is provided." diff --git a/numpydoc/tests/test_main.py b/numpydoc/tests/test_main.py index f42e3964..4bf630f1 100644 --- a/numpydoc/tests/test_main.py +++ b/numpydoc/tests/test_main.py @@ -1,4 +1,4 @@ -import inspect +import importlib.resources import io import sys @@ -119,27 +119,16 @@ def test_validate_perfect_docstring(): @pytest.mark.parametrize( "args", - [[], ["--ignore", "ES01,SA01,EX01"], ["--ignore", "ES01", "--ignore", "SA01 EX01"]], + [[], ["--ignore", "SS03,ES01"], ["--ignore", "SS03", "--ignore", "ES01 SA01"]], ) def test_lint(capsys, args): - argv = ["lint", "numpydoc/__main__.py"] + args + fpath = str(importlib.resources.files(numpydoc).joinpath("__main__.py")) + argv = ["lint", fpath] + args if args: expected = "" expected_status = 0 else: - expected = inspect.cleandoc( - """ - +------------------------+----------+---------+----------------------------+ - | file | item | check | description | - +========================+==========+=========+============================+ - | numpydoc/__main__.py:1 | __main__ | ES01 | No extended summary found | - +------------------------+----------+---------+----------------------------+ - | numpydoc/__main__.py:1 | __main__ | SA01 | See Also section not found | - +------------------------+----------+---------+----------------------------+ - | numpydoc/__main__.py:1 | __main__ | EX01 | No examples section found | - +------------------------+----------+---------+----------------------------+ - """ - ) + expected = f"{fpath}:1: SS03 Summary does not end with a period" expected_status = 1 return_status = numpydoc.cli.main(argv) From 3236347c37e07a10c7e9ca70c9c2cf257a1135c9 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Fri, 22 May 2026 23:49:23 +0000 Subject: [PATCH 4/6] test: use tmp_path instead of __main__.py in test_lint --- numpydoc/tests/test_main.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/numpydoc/tests/test_main.py b/numpydoc/tests/test_main.py index 4bf630f1..9aadbc58 100644 --- a/numpydoc/tests/test_main.py +++ b/numpydoc/tests/test_main.py @@ -1,4 +1,3 @@ -import importlib.resources import io import sys @@ -121,14 +120,15 @@ def test_validate_perfect_docstring(): "args", [[], ["--ignore", "SS03,ES01"], ["--ignore", "SS03", "--ignore", "ES01 SA01"]], ) -def test_lint(capsys, args): - fpath = str(importlib.resources.files(numpydoc).joinpath("__main__.py")) - argv = ["lint", fpath] + args +def test_lint(capsys, tmp_path, args): + f = tmp_path / "example.py" + f.write_text('"""Summary without period"""\n') + argv = ["lint", str(f)] + args if args: expected = "" expected_status = 0 else: - expected = f"{fpath}:1: SS03 Summary does not end with a period" + expected = f"{f}:1: SS03 Summary does not end with a period" expected_status = 1 return_status = numpydoc.cli.main(argv) From c790eeb5b4434f64dceaba54baa3cfd24dc7b6ea Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Fri, 22 May 2026 23:54:34 +0000 Subject: [PATCH 5/6] fix: restore proper docstring in __main__.py --- numpydoc/__main__.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/numpydoc/__main__.py b/numpydoc/__main__.py index 8cd0943e..c3fb1ec5 100644 --- a/numpydoc/__main__.py +++ b/numpydoc/__main__.py @@ -1,6 +1,6 @@ """ -Implementing `python -m numpydoc` functionality -""" # '.' omitted at end of docstring for testing purposes! +Implements ``python -m numpydoc`` functionality. +""" from .cli import main From bb087e8dbd868ac97a6bc193fc2713030ca24d98 Mon Sep 17 00:00:00 2001 From: Stefan van der Walt Date: Sat, 23 May 2026 00:12:54 +0000 Subject: [PATCH 6/6] Test space-separated code path --- numpydoc/tests/test_main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/numpydoc/tests/test_main.py b/numpydoc/tests/test_main.py index 9aadbc58..c2dc9be8 100644 --- a/numpydoc/tests/test_main.py +++ b/numpydoc/tests/test_main.py @@ -118,7 +118,7 @@ def test_validate_perfect_docstring(): @pytest.mark.parametrize( "args", - [[], ["--ignore", "SS03,ES01"], ["--ignore", "SS03", "--ignore", "ES01 SA01"]], + [[], ["--ignore", "SS03,ES01"], ["--ignore", "ES01", "--ignore", "SA01 SS03"]], ) def test_lint(capsys, tmp_path, args): f = tmp_path / "example.py"