mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-10 20:47:15 +01:00
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
64 lines
2.0 KiB
Python
64 lines
2.0 KiB
Python
"""Command line: `coverage-gaps REPORT [--json] [--max-files N] ...`."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import argparse
|
|
import sys
|
|
from collections.abc import Sequence
|
|
from pathlib import Path
|
|
|
|
from coverage_gaps.models import ReportError
|
|
from coverage_gaps.parsers import load_report
|
|
from coverage_gaps.render import select, to_json, to_markdown
|
|
|
|
EXIT_COVERED = 0
|
|
EXIT_GAPS = 1
|
|
EXIT_UNREADABLE = 2
|
|
|
|
|
|
def build_parser() -> argparse.ArgumentParser:
|
|
"""Argument parser (format is auto-detected from file content)."""
|
|
parser = argparse.ArgumentParser(
|
|
prog="coverage-gaps",
|
|
description="List uncovered lines/branches from lcov, Cobertura, JaCoCo "
|
|
"or coverage.py JSON reports. Exit 0 covered, 1 gaps, 2 unreadable.",
|
|
)
|
|
parser.add_argument("report", type=Path, help="coverage report file")
|
|
parser.add_argument("--json", action="store_true", help="emit JSON, not markdown")
|
|
parser.add_argument(
|
|
"--max-files",
|
|
type=int,
|
|
default=0,
|
|
metavar="N",
|
|
help="list only the N worst files (0 = all)",
|
|
)
|
|
parser.add_argument(
|
|
"--min-missed",
|
|
type=int,
|
|
default=1,
|
|
metavar="N",
|
|
help="skip files with fewer than N missed lines+branches",
|
|
)
|
|
parser.add_argument(
|
|
"--path-prefix",
|
|
default="",
|
|
metavar="PREFIX",
|
|
help="only files whose path starts with PREFIX",
|
|
)
|
|
return parser
|
|
|
|
|
|
def main(argv: Sequence[str] | None = None) -> int:
|
|
"""Run the tool and return the process exit code."""
|
|
args = build_parser().parse_args(argv)
|
|
try:
|
|
fmt, gaps = load_report(args.report)
|
|
except ReportError as exc:
|
|
print(f"coverage-gaps: {exc}", file=sys.stderr)
|
|
return EXIT_UNREADABLE
|
|
files = select(gaps, path_prefix=args.path_prefix, min_missed=args.min_missed)
|
|
shown = args.max_files if args.max_files > 0 else len(files)
|
|
render = to_json if args.json else to_markdown
|
|
sys.stdout.write(render(fmt, files, shown) + ("\n" if args.json else ""))
|
|
return EXIT_GAPS if files else EXIT_COVERED
|