Skip to content

Commit 0a739dd

Browse files
Add --accept-empty to avoid exit code 1 (#48)
* Draft * black * Flake & Typo * Make descriptions for `--accept-empty` in README/Click match Co-authored-by: Hunter McGushion <hunter@mcgushion.com>
1 parent 13c0d02 commit 0a739dd

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ docstr-coverage some_project/src
6161
- _--skip-file-doc, -f_ - Ignore module docstrings (at the top of files)
6262
- _--skip-private, -P_ - Ignore private functions (starting with a single underscore)
6363
- _--skip-class-def, -c_ - Ignore docstrings of class definitions
64+
- _--accept-empty, -a_ - Exit with code 0 if no Python files are found (default: exit code 1)
6465
- _--exclude=\<regex\>, -e \<regex\>_ - Filepath pattern to exclude from analysis
6566
- To exclude the contents of a virtual environment `env` and your `tests` directory, run:
6667
```docstr-coverage some_project/ -e ".*/(env|tests)"```
@@ -103,6 +104,7 @@ skip_init: True # Boolean
103104
skip_class_def: True # Boolean
104105
skip_private: True # Boolean
105106
follow_links: True # Boolean
107+
accept_empty: True # Boolean
106108
ignore_names_file: .*/test # regex
107109
fail_under: 90 # int
108110
percentage_only: True # Boolean

docstr_coverage/cli.py

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import platform
55
import re
66
import sys
7+
import warnings
78
from typing import List, Optional
89

910
import click
@@ -217,6 +218,12 @@ def _assert_valid_key_value(k, v):
217218
is_flag=True,
218219
help="Output only the overall coverage percentage as a float, silencing all other logging",
219220
)
221+
@click.option(
222+
"-a",
223+
"--accept-empty",
224+
is_flag=True,
225+
help="Exit with code 0 if no Python files are found (default: exit code 1)",
226+
)
220227
@click.help_option("-h", "--help")
221228
@click.argument(
222229
"paths",
@@ -279,7 +286,14 @@ def execute(paths, **kwargs):
279286
)
280287

281288
if len(all_paths) < 1:
282-
sys.exit("No Python files found")
289+
if kwargs["accept_empty"] is True:
290+
warnings.warn("No Python files found in specified paths. Processing aborted")
291+
sys.exit(0)
292+
else:
293+
sys.exit(
294+
"No Python files found "
295+
"(use `--accept-empty` to exit with code 0 if you expect this case)"
296+
)
283297

284298
# Parse ignore names file
285299
has_ignore_patterns_in_config = "ignore_patterns" in kwargs

tests/test_cli.py

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,3 +444,62 @@ def test_ignore_patterns_files(
444444
else:
445445
parse_ig_from_dict.assert_not_called()
446446
mock_parse_ig_f.assert_not_called()
447+
448+
449+
@pytest.mark.parametrize(
450+
["paths", "path_contains_py"],
451+
[
452+
pytest.param([SAMPLES_DIR], True, id="samples_dir_x1"),
453+
pytest.param([SAMPLES_A.documented], True, id="files_x1"),
454+
pytest.param([SAMPLES_A.empty, SAMPLES_A.partial], True, id="files_x2"),
455+
pytest.param([SAMPLES_A.dirpath, SAMPLES_B.dirpath], True, id="dirs_x2"),
456+
pytest.param(
457+
[SAMPLES_A.empty, SAMPLES_A.partial, SAMPLES_B.dirpath], True, id="files_x2+dir_x1"
458+
),
459+
pytest.param([os.path.join("sample_files", "subdir_a")], True, id="rel_dir_x1"),
460+
pytest.param(
461+
[os.path.join("config_files", "docstr_ignore.txt")], False, id="file_with_no_python"
462+
),
463+
pytest.param([os.path.join(CWD, "config_files")], False, id="folder_with_no_python"),
464+
],
465+
)
466+
@pytest.mark.parametrize(
467+
["accept_empty_flag", "accept_empty_value"],
468+
[
469+
pytest.param([], False, id="no_accept_empty"),
470+
pytest.param(["-a"], True, id="short_accept_empty"),
471+
pytest.param(["--accept-empty"], True, id="long_accept_empty"),
472+
],
473+
)
474+
@pytest.mark.usefixtures("cd_tests_dir_fixture")
475+
def test_accept_empty(
476+
paths: List[str],
477+
path_contains_py: bool,
478+
accept_empty_flag: List[str],
479+
accept_empty_value: bool,
480+
runner: CliRunner,
481+
):
482+
"""Test that the `--accept-empty`/`-a` flag leads to the correct exit codes
483+
484+
Parameters
485+
----------
486+
paths: List[str]
487+
Path arguments provided to CLI. These should be made absolute before they are passed to
488+
:func:`docstr_coverage.cli.collect_filepaths`
489+
path_contains_py: bool
490+
True iff the passed paths point (directly or indirectly via dir) to at least one .py file
491+
accept_empty_flag: List[str]
492+
Flag under test
493+
accept_empty_value: bool
494+
True iff the flag under test specifies to return exit code 0 if no .py file was found
495+
runner: CliRunner
496+
Click utility to invoke command line scripts"""
497+
498+
dont_fail_due_to_coverage = ["--fail-under=5"]
499+
500+
run_result = runner.invoke(execute, paths + accept_empty_flag + dont_fail_due_to_coverage)
501+
502+
if accept_empty_flag or path_contains_py:
503+
assert run_result.exit_code == 0
504+
else:
505+
assert run_result.exit_code == 1

0 commit comments

Comments
 (0)