diff --git a/CHANGELOG.md b/CHANGELOG.md index dc19dd2..2af3dcc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,9 @@ The format follows [Keep a Changelog](https://keepachangelog.com/), versions fol ### Fixed - The shared workflow waits 60 s per download and retries ten times, so a slow PyPI response no longer fails a job. +- `ratchet` refuses a package directory that does not exist. Guessed from the name + (napalm-hpe-aruba-procurve ships `napalm_procurve`), it measured nothing and wrote an + empty baseline without a word. - `security` audited the runner's own pip instead of the package: pip-audit now checks a venv holding only the package and its dependencies. diff --git a/napalm_standard/cli.py b/napalm_standard/cli.py index 802560f..f4c2331 100644 --- a/napalm_standard/cli.py +++ b/napalm_standard/cli.py @@ -40,7 +40,11 @@ def _check(args: argparse.Namespace) -> int: def _ratchet(args: argparse.Namespace) -> int: - code, text = ratchet.run(args.path, _repo(args.path).package, write=args.write) + try: + code, text = ratchet.run(args.path, _repo(args.path).package, write=args.write) + except FileNotFoundError as exc: + print(exc, file=sys.stderr) + return 2 print(text) return code diff --git a/napalm_standard/ratchet.py b/napalm_standard/ratchet.py index 226e740..28b2871 100644 --- a/napalm_standard/ratchet.py +++ b/napalm_standard/ratchet.py @@ -152,6 +152,10 @@ def _lines(source: str) -> int: def measure(repo: pathlib.Path, package: str) -> dict[str, Any]: """Today's excesses, keyed the way the baseline stores them.""" + if not (repo / package).is_dir(): + raise FileNotFoundError( + f"no package directory {package}/ to measure; name it in [tool.napalm-standard] package" + ) function_lines: dict[str, int] = {} function_complexity: dict[str, int] = {} python_file_lines: dict[str, int] = {} diff --git a/tests/test_cli.py b/tests/test_cli.py index a335d21..3327411 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -135,3 +135,12 @@ def test_package_prints_the_import_package( ) -> None: assert cli.main(["package", str(make_repo())]) == 0 assert capsys.readouterr().out == "napalm_example\n" + + +def test_ratchet_names_the_missing_package( + make_repo: RepoFactory, capsys: pytest.CaptureFixture[str] +) -> None: + repo = make_repo({"napalm_example/__init__.py": None, "napalm_example/py.typed": None}) + + assert cli.main(["ratchet", "--write", str(repo)]) == 2 + assert "[tool.napalm-standard] package" in capsys.readouterr().err diff --git a/tests/test_ratchet.py b/tests/test_ratchet.py index 33db9bb..fec3427 100644 --- a/tests/test_ratchet.py +++ b/tests/test_ratchet.py @@ -308,3 +308,15 @@ def test_check_fails_on_a_problem_and_on_a_stale_entry(tmp_path: pathlib.Path) - assert code == 1 assert "pkg/mod.py::long = 62 (new)" in text assert "stale: function_lines: pkg/mod.py::old" in text + + +def test_a_package_that_does_not_exist_is_an_error_not_an_empty_baseline( + tmp_path: pathlib.Path, +) -> None: + """procurve's import package is napalm_procurve: guessed from the name, the + ratchet measured nothing and wrote an empty baseline without a word.""" + repo = _repo(tmp_path, LONG) + + with pytest.raises(FileNotFoundError, match="napalm_missing"): + qr.run(repo, "napalm_missing", write=True) + assert not (repo / qr.BASELINE).exists()