Skip to content

Lint

lint

Ruff diagnostic filtering + availability probing for batch_edit's lint step.

batch_edit runs ruff --fix over the files it touched and reports the diagnostics ruff could not auto-fix. This module holds the helper that strips ruff's summary noise from that output so only real diagnostic lines remain, plus the availability probe that decides whether the lint step runs at all.

Availability is probed per target root by shelling uv run ruff --version with cwd=root — this detects an env-local ruff even when no global ruff is on PATH. Results are memoized per resolved root so repeated edits against the same project do not re-spawn the probe, while a different root re-probes.

filter_ruff_lines(stdout)

Keep real diagnostic lines, dropping ruff summary noise.

Source code in packages/axm-edit/src/axm_edit/services/lint.py
Python
def filter_ruff_lines(stdout: str) -> list[str]:
    """Keep real diagnostic lines, dropping ruff summary noise."""
    return [
        line
        for line in stdout.strip().splitlines()
        if line.strip() and not line.startswith(_RUFF_NOISE_PREFIXES)
    ]

ruff_available(root)

Return whether ruff can run inside root's environment.

Under a contract, probes the declared interpreter without installing or caching by root. Otherwise probes uv run ruff --version. Treats ruff as available iff the subprocess returns 0. A missing uv/ruff binary (FileNotFoundError) or any OS-level failure counts as absent (a clean skip), never as a crash. The verdict is memoized on the resolved absolute root; a distinct root re-probes.

Source code in packages/axm-edit/src/axm_edit/services/lint.py
Python
def ruff_available(root: Path) -> bool:
    """Return whether ruff can run inside *root*'s environment.

    Under a contract, probes the declared interpreter without installing or
    caching by root. Otherwise probes ``uv run ruff --version``. Treats ruff as
    available iff the subprocess returns 0. A missing ``uv``/ruff binary
    (``FileNotFoundError``) or any OS-level failure counts as *absent* (a
    clean skip), never as a crash. The verdict is memoized on the resolved
    absolute root; a distinct root re-probes.
    """
    resolved = Path(root).resolve()
    declared = session_dependency_environment(root)
    cached = _RUFF_AVAILABLE_CACHE.get(resolved) if declared is None else None
    if cached is not None:
        return cached

    try:
        result = run_ruff(root, ["--version"])
        available = result.returncode == 0
        if declared is not None:
            detail = (result.stderr or result.stdout).strip()[-2000:]
            _RUFF_PROBE_FAILURE.set(f"exit {result.returncode}: {detail}")
    except (FileNotFoundError, OSError, subprocess.TimeoutExpired) as exc:
        _RUFF_PROBE_FAILURE.set(str(exc)[-2000:])
        available = False

    if declared is None:
        _RUFF_AVAILABLE_CACHE[resolved] = available
    return available

ruff_failure(root)

Report the failed declared probe without implying a completed lint check.

Source code in packages/axm-edit/src/axm_edit/services/lint.py
Python
def ruff_failure(root: Path) -> str:
    """Report the failed declared probe without implying a completed lint check."""
    declared = session_dependency_environment(root)
    if declared is None:
        return "ruff not found, lint skipped"
    return (
        f"ruff unavailable in declared runtime {declared.interpreter}: "
        f"{_RUFF_PROBE_FAILURE.get()}; lint skipped"
    )

run_ruff(root, args)

Run one bounded lint step without changing a declared environment.

Source code in packages/axm-edit/src/axm_edit/services/lint.py
Python
def run_ruff(root: Path, args: list[str]) -> subprocess.CompletedProcess[str]:
    """Run one bounded lint step without changing a declared environment."""
    command, env = _ruff_command(root, args)
    if env is not None:
        return subprocess.run(
            command,
            cwd=root,
            capture_output=True,
            text=True,
            timeout=30,
            env=env,
        )
    return subprocess.run(
        command,
        cwd=root,
        capture_output=True,
        text=True,
        timeout=30,
    )