Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 10 additions & 15 deletions .github/actions/generate-coverage/scripts/detect.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ def _forced_rust(selected_manifest: Path | None) -> tuple[Lang, Path | None]:
return Lang.RUST, selected_manifest


def _forced_python(selected_manifest: Path | None) -> tuple[Lang, Path | None]:
def _forced_python() -> tuple[Lang, Path | None]:
"""Resolve ``language=python``; requires a syncable ``[project]`` table."""
if not _has_python_project():
_fail(
Expand Down Expand Up @@ -148,25 +148,20 @@ def _forced_mixed(selected_manifest: Path | None) -> tuple[Lang, Path | None]:
return Lang.MIXED, selected_manifest


# Explicit (non-``auto``) language modes dispatch to a single-responsibility
# resolver that validates the mode's prerequisites.
_FORCED_RESOLVERS: dict[
LangMode, typ.Callable[[Path | None], tuple[Lang, Path | None]]
] = {
LangMode.RUST: _forced_rust,
LangMode.PYTHON: _forced_python,
LangMode.MIXED: _forced_mixed,
}


def get_lang(
cargo_manifest: str = "", mode: LangMode = LangMode.AUTO
) -> tuple[Lang, Path | None]:
"""Detect project language and selected Cargo manifest (if any)."""
selected_manifest = _resolve_cargo_manifest(cargo_manifest)
if mode is LangMode.AUTO:
return _auto_lang(selected_manifest)
return _FORCED_RESOLVERS[mode](selected_manifest)
match mode:
case LangMode.AUTO:
return _auto_lang(selected_manifest)
case LangMode.RUST:
return _forced_rust(selected_manifest)
case LangMode.PYTHON:
return _forced_python()
case LangMode.MIXED:
return _forced_mixed(selected_manifest)


def _parse_lang_mode(raw: str) -> LangMode:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,15 +208,6 @@ def _resolve_nextest_binary() -> Path | None:
return candidate if candidate.is_file() else None


def _find_nextest_binary() -> Path:
"""Resolve the installed cargo-nextest executable or fail clearly."""
resolved = _resolve_nextest_binary()
if resolved is not None:
return resolved
typer.echo("cargo-nextest not found after installation", err=True)
raise typer.Exit(1)


class _ArchiveTooLargeError(Exception):
"""Raised when a downloaded archive exceeds ``_MAX_ARCHIVE_BYTES``."""

Expand Down
3 changes: 0 additions & 3 deletions .github/actions/generate-coverage/scripts/resolve_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,6 @@

from plumbum import local

#: The step's own marker for where a run's interpreter came from, logged so a
#: run shows which rule chose it.
SOURCES: tuple[str, ...] = ("input", "UV_PYTHON", ".python-version", "PATH")
VERSION_PROBE = "import sys; print('%d.%d' % sys.version_info[:2])"
MAJOR_MINOR = re.compile(r"\d+\.\d+")

Expand Down
18 changes: 2 additions & 16 deletions .github/actions/generate-coverage/scripts/run_python.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,7 +358,8 @@ def _parse_pytest_workers(raw: str | None) -> str:
"""Parse and validate the pytest-workers value; raise ValueError on bad input.

This function is pure: it performs no I/O and has no side-effects.
Callers that need CLI error handling should use _normalize_pytest_workers.
Callers that need CLI error handling should convert ``ValueError`` into
their preferred command-line diagnostic.
"""
if raw is None:
return ""
Expand All @@ -382,21 +383,6 @@ def _parse_pytest_workers(raw: str | None) -> str:
raise ValueError(message)


def _normalize_pytest_workers(raw: str | None) -> str:
"""Validate and normalize the pytest-workers value, exiting on invalid input.

Delegates pure validation to _parse_pytest_workers. Any ValueError
raised there is converted into a CLI error message on stderr and
typer.Exit with code 2 — making this function's side-effects explicit
by design.
"""
try:
return _parse_pytest_workers(raw)
except ValueError as exc:
typer.echo(str(exc), err=True)
raise typer.Exit(2) from exc


def _coverage_args(
fmt: str,
out: Path,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -189,52 +189,6 @@ def test_expected_sha_for_unsupported_platform(
assert "Unsupported platform for cargo-nextest" in capsys.readouterr().err


def test_find_nextest_binary_prefers_path(
tmp_path: Path,
install_nextest_module: ModuleType,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Binary lookup prefers PATH via shutil.which."""
binary = tmp_path / "cargo-nextest"
binary.write_bytes(b"payload")
monkeypatch.setattr(install_nextest_module.shutil, "which", lambda _: str(binary))
assert install_nextest_module._find_nextest_binary() == binary


def test_find_nextest_binary_falls_back_to_home(
tmp_path: Path,
install_nextest_module: ModuleType,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Binary lookup falls back to ~/.cargo/bin when PATH is empty."""
monkeypatch.delenv("CARGO_HOME", raising=False)
monkeypatch.setattr(install_nextest_module.shutil, "which", lambda _: None)
monkeypatch.setattr(install_nextest_module.Path, "home", lambda: tmp_path)
cargo_bin = tmp_path / ".cargo" / "bin"
cargo_bin.mkdir(parents=True, exist_ok=True)
binary = cargo_bin / "cargo-nextest"
binary.write_bytes(b"payload")
assert install_nextest_module._find_nextest_binary() == binary


def test_find_nextest_binary_missing_exits(
tmp_path: Path,
install_nextest_module: ModuleType,
monkeypatch: pytest.MonkeyPatch,
capsys: pytest.CaptureFixture[str],
) -> None:
"""Missing cargo-nextest after install raises a Typer exit."""
monkeypatch.delenv("CARGO_HOME", raising=False)
monkeypatch.setattr(install_nextest_module.shutil, "which", lambda _: None)
monkeypatch.setattr(install_nextest_module.Path, "home", lambda: tmp_path)

with pytest.raises(install_nextest_module.typer.Exit) as excinfo:
install_nextest_module._find_nextest_binary()

assert _exit_code(excinfo.value) == 1
assert "cargo-nextest not found after installation" in capsys.readouterr().err


def test_resolve_nextest_binary_returns_none_when_missing(
tmp_path: Path,
install_nextest_module: ModuleType,
Expand Down
33 changes: 0 additions & 33 deletions .github/actions/generate-coverage/tests/test_scripts.py
Original file line number Diff line number Diff line change
Expand Up @@ -2426,39 +2426,6 @@ def test_coverage_cmd_for_fmt_threads_workers_through(
assert parts[-2:] == ["-n", "2"]


@pytest.mark.parametrize(
("raw", "expected"),
[
(None, ""),
("", ""),
(" ", ""),
("auto", "auto"),
("AUTO", "auto"),
(" logical ", "logical"),
("4", "4"),
("1", "1"),
],
)
def test_normalize_pytest_workers_accepts_valid_values(
run_python_module: ModuleType,
raw: str | None,
expected: str,
) -> None:
"""Valid worker values normalize to the lowercase/stripped form."""
assert run_python_module._normalize_pytest_workers(raw) == expected


@pytest.mark.parametrize("raw", ["banana", "-1", "4.0", "auto2", "two", "0"])
def test_normalize_pytest_workers_rejects_invalid_values(
run_python_module: ModuleType,
raw: str,
) -> None:
"""Junk worker values exit with the configuration-error code."""
with pytest.raises(run_python_module.typer.Exit) as excinfo:
run_python_module._normalize_pytest_workers(raw)
assert _exit_code(excinfo.value) == 2


@pytest.mark.parametrize(
("raw", "expected"),
[
Expand Down
27 changes: 27 additions & 0 deletions .github/actions/install-makeutil/action.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
name: Install Makefile parser
description: Install the pinned Makeutil parser used by the Python contract suite

inputs:
makeutil-revision:
description: Immutable Makeutil Git revision to install
required: true
makeutil-toolchain:
description: Rust nightly toolchain used to build Makeutil
required: true

runs:
using: composite
steps:
- name: Install Makefile parser
shell: bash
env:
MAKEUTIL_REVISION: ${{ inputs.makeutil-revision }}
MAKEUTIL_TOOLCHAIN: ${{ inputs.makeutil-toolchain }}
run: |
rustup toolchain install "${MAKEUTIL_TOOLCHAIN}" --profile minimal
RUSTFLAGS="-Zpolonius=next" cargo +"${MAKEUTIL_TOOLCHAIN}" install \
--git https://github.com/leynos/makeutil \
--rev "${MAKEUTIL_REVISION}" \
--locked \
--force \
makeutil
35 changes: 0 additions & 35 deletions .github/actions/rust-build-release/src/runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -262,38 +262,3 @@ def runtime_available(name: str, *, cwd: str | Path | None = None) -> bool:
return False

return True


def detect_host_target(
*,
default: str = DEFAULT_HOST_TARGET,
rustc_path: str | Path | None = None,
) -> str:
"""Return the active Rust host triple, defaulting to *default* when unknown."""
candidate = rustc_path or shutil.which("rustc")
if candidate is None:
return default
try:
exec_path = ensure_allowed_executable(candidate, ("rustc", "rustc.exe"))
except UnexpectedExecutableError:
return default
try:
result = run_validated(
exec_path,
["-vV"],
allowed_names=("rustc", "rustc.exe"),
timeout=PROBE_TIMEOUT,
method="run",
)
except (ProcessExecutionError, ProcessTimedOut, OSError):
return default

triple = next(
(
line.partition(":")[2].strip()
for line in (result.stdout or "").splitlines()
if line.startswith("host:")
),
"",
)
return triple or default
114 changes: 0 additions & 114 deletions .github/actions/rust-build-release/tests/test_runtime.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,59 +225,6 @@ def test_podman_security_timeout_treated_as_unavailable(
), "podman security timeout warning missing"


def test_detect_host_target_returns_default_when_rustc_missing(
runtime_module: ModuleType, module_harness: HarnessFactory
) -> None:
"""Falls back to the default triple when rustc is unavailable."""
harness = module_harness(runtime_module)
harness.patch_shutil_which(lambda name: None)
assert runtime_module.detect_host_target() == runtime_module.DEFAULT_HOST_TARGET


def test_detect_host_target_parses_rustc_output(
runtime_module: ModuleType, module_harness: HarnessFactory
) -> None:
"""Parses the host triple from rustc version output."""
harness = module_harness(runtime_module)
harness.patch_shutil_which(
lambda name: "/usr/bin/rustc" if name == "rustc" else None
)
harness.patch_attr("ensure_allowed_executable", lambda path, allowed: path)

def fake_run(
executable: str,
args: list[str],
*,
allowed_names: tuple[str, ...],
capture_output: bool = False,
check: bool = False,
text: bool = False,
**_: object,
) -> RunOutput:
_ = (allowed_names, capture_output, check, text)
return _run_result(stdout="host: custom-triple\n")

harness.monkeypatch.setattr(runtime_module, "run_validated", fake_run)
assert runtime_module.detect_host_target() == "custom-triple"


def test_detect_host_target_returns_default_on_timeout(
runtime_module: ModuleType, module_harness: HarnessFactory
) -> None:
"""Falls back to the default triple when rustc probing times out."""
harness = module_harness(runtime_module)
harness.patch_shutil_which(
lambda name: "/usr/bin/rustc" if name == "rustc" else None
)
harness.patch_attr("ensure_allowed_executable", lambda path, allowed: path)
_patch_run_validated_timeout(runtime_module, harness)

assert (
runtime_module.detect_host_target(default="fallback-triple")
== "fallback-triple"
)


def test_platform_default_host_target_windows(
runtime_module: ModuleType, module_harness: HarnessFactory
) -> None:
Expand All @@ -300,67 +247,6 @@ def test_platform_default_host_target_darwin_arm(
assert runtime_module._platform_default_host_target() == "aarch64-apple-darwin"


def test_detect_host_target_passes_timeout_to_run_validated(
runtime_module: ModuleType, module_harness: HarnessFactory
) -> None:
"""Ensures rustc probing is bounded via the timeout parameter."""
harness = module_harness(runtime_module)
harness.patch_shutil_which(
lambda name: "/usr/bin/rustc" if name == "rustc" else None
)
harness.patch_attr("ensure_allowed_executable", lambda path, allowed: path)

call_kwargs: dict[str, object] = {}

def fake_run(
executable: str,
args: list[str],
*,
allowed_names: tuple[str, ...],
**kwargs: object,
) -> RunOutput:
_ = (executable, args)
call_kwargs.update(kwargs)
call_kwargs["allowed_names"] = allowed_names
return _run_result(stdout="host: bounded\n")

harness.monkeypatch.setattr(runtime_module, "run_validated", fake_run)

assert runtime_module.detect_host_target() == "bounded"
assert call_kwargs.get("timeout") == runtime_module.PROBE_TIMEOUT
assert call_kwargs.get("allowed_names") == ("rustc", "rustc.exe")


def test_probe_timeout_env_override(
runtime_module: ModuleType,
module_harness: HarnessFactory,
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""Respect RUNTIME_PROBE_TIMEOUT when importing the module."""
monkeypatch.setenv("RUNTIME_PROBE_TIMEOUT", "2")
module = _reload_runtime_module(runtime_module, "rbr_runtime_reloaded")
harness = module_harness(module)

harness.patch_shutil_which(lambda name: "/usr/bin/rustc")
harness.patch_attr("ensure_allowed_executable", lambda path, allowed: path)

captured: dict[str, object] = {}

def fake_run(
executable: str,
args: list[str],
*,
allowed_names: tuple[str, ...],
**kwargs: object,
) -> RunOutput:
captured.update(kwargs)
return _run_result(stdout="host: x86_64-unknown-linux-gnu\n")

harness.monkeypatch.setattr(module, "run_validated", fake_run)
module.detect_host_target()
assert captured.get("timeout") == 2


@pytest.mark.parametrize(
("machine", "expected"),
[
Expand Down
Loading
Loading