diff --git a/api/libs/pyrefly_diagnostics.py b/api/libs/pyrefly_diagnostics.py index 4d9df650991..08e51fbb1b2 100644 --- a/api/libs/pyrefly_diagnostics.py +++ b/api/libs/pyrefly_diagnostics.py @@ -2,9 +2,10 @@ from __future__ import annotations +import argparse import sys -_DIAGNOSTIC_PREFIXES = ("ERROR ", "WARNING ") +_DIAGNOSTIC_PREFIXES = ("ERROR ", "WARN ", "WARNING ") _LOCATION_PREFIX = "-->" @@ -13,7 +14,7 @@ def extract_diagnostics(raw_output: str) -> str: The full pyrefly output includes code excerpts and carets, which create noisy diffs. This helper keeps only: - - diagnostic headline lines (``ERROR ...`` / ``WARNING ...``) + - diagnostic headline lines (``ERROR ...`` / ``WARN ...`` / ``WARNING ...``) - the following location line (``--> path:line:column``), when present """ @@ -36,11 +37,28 @@ def extract_diagnostics(raw_output: str) -> str: return "\n".join(diagnostics) + "\n" +def render_diagnostics(raw_output: str, exit_code: int) -> str: + """Render concise diagnostics and fall back to raw output on unmatched failures.""" + + diagnostics = extract_diagnostics(raw_output) + if diagnostics: + return diagnostics + + if exit_code != 0: + return raw_output + + return "" + + def main() -> int: """Read pyrefly output from stdin and print normalized diagnostics.""" + parser = argparse.ArgumentParser() + parser.add_argument("--status", type=int, default=0) + args = parser.parse_args() + raw_output = sys.stdin.read() - sys.stdout.write(extract_diagnostics(raw_output)) + sys.stdout.write(render_diagnostics(raw_output, exit_code=args.status)) return 0 diff --git a/api/tests/unit_tests/libs/test_pyrefly_diagnostics.py b/api/tests/unit_tests/libs/test_pyrefly_diagnostics.py index 704daa8fb46..523c975e3ef 100644 --- a/api/tests/unit_tests/libs/test_pyrefly_diagnostics.py +++ b/api/tests/unit_tests/libs/test_pyrefly_diagnostics.py @@ -1,4 +1,4 @@ -from libs.pyrefly_diagnostics import extract_diagnostics +from libs.pyrefly_diagnostics import extract_diagnostics, render_diagnostics def test_extract_diagnostics_keeps_only_summary_and_location_lines() -> None: @@ -40,6 +40,37 @@ def test_extract_diagnostics_handles_error_without_location_line() -> None: assert diagnostics == "ERROR unexpected pyrefly output format [bad-format]\n" +def test_extract_diagnostics_keeps_warn_headlines_and_location_lines() -> None: + # Arrange + raw_output = """INFO Checking project configured at `/tmp/project/pyrefly.toml` +WARN Skipping include pattern `/tmp/project/tests` because it is matched by `project-excludes`. + --> tests/test_containers_integration_tests/pyrefly.toml:3:1 +""" + + # Act + diagnostics = extract_diagnostics(raw_output) + + # Assert + assert diagnostics == ( + "WARN Skipping include pattern `/tmp/project/tests` because it is matched by `project-excludes`.\n" + " --> tests/test_containers_integration_tests/pyrefly.toml:3:1\n" + ) + + +def test_render_diagnostics_falls_back_to_raw_output_for_nonzero_exit_without_matches() -> None: + # Arrange + raw_output = ( + "INFO Checking project configured at `/tmp/project/pyrefly.toml`\n" + "No Python files matched pattern `/tmp/project/tests/test_containers_integration_tests`\n" + ) + + # Act + diagnostics = render_diagnostics(raw_output, exit_code=1) + + # Assert + assert diagnostics == raw_output + + def test_extract_diagnostics_returns_empty_for_non_error_output() -> None: # Arrange raw_output = "INFO Checking project configured at `/tmp/project/pyrefly.toml`\n" diff --git a/dev/pyrefly-check-local b/dev/pyrefly-check-local index 2c2be12455f..01c58f7ad68 100755 --- a/dev/pyrefly-check-local +++ b/dev/pyrefly-check-local @@ -44,7 +44,7 @@ run_pyrefly() { local pyrefly_status=$? set -e - uv run --directory api python libs/pyrefly_diagnostics.py < "$tmp_output" + uv run --directory api python libs/pyrefly_diagnostics.py --status "$pyrefly_status" < "$tmp_output" rm -f "$tmp_output" return "$pyrefly_status" }