feat: Print FatalError messages using Logger (#2292)

* feat: Print FatalError messages using Logger

This makes them appear GHA annotations in CI logs, which makes them easier to spot. I've also added the "cibuildwheel: " prefix to those errors, I think it helps when viewing a log to know which tool is talking to you - it can be difficult to understand with build tools.

* Nicer error message on invalid architecture

* Fix some message formatting and test expectations
This commit is contained in:
Joe Rickerby
2025-03-01 10:47:44 +01:00
committed by GitHub
parent 708cf1d32b
commit 9e72cd9b54
6 changed files with 28 additions and 23 deletions
+4 -5
View File
@@ -68,7 +68,7 @@ def main() -> None:
if log.step_active: if log.step_active:
log.step_end_with_error(message) log.step_end_with_error(message)
else: else:
print(f"cibuildwheel: {message}", file=sys.stderr) log.error(message)
if global_options.print_traceback_on_error: if global_options.print_traceback_on_error:
traceback.print_exc(file=sys.stderr) traceback.print_exc(file=sys.stderr)
@@ -253,7 +253,7 @@ def _compute_platform_auto() -> PlatformName:
return "windows" return "windows"
else: else:
msg = ( msg = (
'cibuildwheel: Unable to detect platform from "sys.platform". cibuildwheel doesn\'t ' 'Unable to detect platform from "sys.platform". cibuildwheel doesn\'t '
"support building wheels for this platform. You might be able to build for a different " "support building wheels for this platform. You might be able to build for a different "
"platform using the --platform argument. Check --help output for more information." "platform using the --platform argument. Check --help output for more information."
) )
@@ -343,9 +343,8 @@ def print_new_wheels(msg: str, output_dir: Path) -> Generator[None, None, None]:
def build_in_directory(args: CommandLineArguments) -> None: def build_in_directory(args: CommandLineArguments) -> None:
platform: PlatformName = _compute_platform(args) platform: PlatformName = _compute_platform(args)
if platform == "pyodide" and sys.platform == "win32": if platform == "pyodide" and sys.platform == "win32":
msg = "cibuildwheel: Building for pyodide is not supported on Windows" msg = "Building for pyodide is not supported on Windows"
print(msg, file=sys.stderr) raise errors.ConfigurationError(msg)
sys.exit(2)
options = compute_options(platform=platform, command_line_arguments=args, env=os.environ) options = compute_options(platform=platform, command_line_arguments=args, env=os.environ)
+7 -1
View File
@@ -8,6 +8,8 @@ from collections.abc import Set
from enum import StrEnum, auto from enum import StrEnum, auto
from typing import Final, Literal from typing import Final, Literal
from cibuildwheel import errors
from .typing import PlatformName from .typing import PlatformName
PRETTY_NAMES: Final[dict[PlatformName, str]] = { PRETTY_NAMES: Final[dict[PlatformName, str]] = {
@@ -78,7 +80,11 @@ class Architecture(StrEnum):
elif arch_str == "auto32": elif arch_str == "auto32":
result |= Architecture.bitness_archs(platform=platform, bitness="32") result |= Architecture.bitness_archs(platform=platform, bitness="32")
else: else:
result.add(Architecture(arch_str)) try:
result.add(Architecture(arch_str))
except ValueError as e:
msg = f"Invalid architecture '{arch_str}'"
raise errors.ConfigurationError(msg) from e
return result return result
@staticmethod @staticmethod
+6 -6
View File
@@ -451,12 +451,12 @@ def build(options: Options, tmp_path: Path) -> None: # noqa: ARG001
except subprocess.CalledProcessError as error: except subprocess.CalledProcessError as error:
msg = unwrap( msg = unwrap(
f""" f"""
cibuildwheel: {build_step.container_engine.name} not found. An {build_step.container_engine.name} not found. An OCI exe like
OCI exe like Docker or Podman is required to run Linux builds. Docker or Podman is required to run Linux builds. If you're
If you're building on Travis CI, add `services: [docker]` to building on Travis CI, add `services: [docker]` to your
your .travis.yml. If you're building on Circle CI in Linux, .travis.yml. If you're building on Circle CI in Linux, add a
add a `setup_remote_docker` step to your .circleci/config.yml. `setup_remote_docker` step to your .circleci/config.yml. If
If you're building on Cirrus CI, use `docker_builder` task. you're building on Cirrus CI, use `docker_builder` task.
""" """
) )
raise errors.ConfigurationError(msg) from error raise errors.ConfigurationError(msg) from error
+6 -6
View File
@@ -159,24 +159,24 @@ class Logger:
def notice(self, message: str) -> None: def notice(self, message: str) -> None:
if self.fold_mode == "github": if self.fold_mode == "github":
print(f"::notice::{message}\n", file=sys.stderr) print(f"::notice::cibuildwheel: {message}\n", file=sys.stderr)
else: else:
c = self.colors c = self.colors
print(f"{c.bold}Note{c.end}: {message}\n", file=sys.stderr) print(f"cibuildwheel: {c.bold}note{c.end}: {message}\n", file=sys.stderr)
def warning(self, message: str) -> None: def warning(self, message: str) -> None:
if self.fold_mode == "github": if self.fold_mode == "github":
print(f"::warning::{message}\n", file=sys.stderr) print(f"::warning::cibuildwheel: {message}\n", file=sys.stderr)
else: else:
c = self.colors c = self.colors
print(f"{c.yellow}Warning{c.end}: {message}\n", file=sys.stderr) print(f"cibuildwheel: {c.yellow}warning{c.end}: {message}\n", file=sys.stderr)
def error(self, error: BaseException | str) -> None: def error(self, error: BaseException | str) -> None:
if self.fold_mode == "github": if self.fold_mode == "github":
print(f"::error::{error}\n", file=sys.stderr) print(f"::error::cibuildwheel: {error}\n", file=sys.stderr)
else: else:
c = self.colors c = self.colors
print(f"{c.bright_red}Error{c.end}: {error}\n", file=sys.stderr) print(f"cibuildwheel: {c.bright_red}error{c.end}: {error}\n", file=sys.stderr)
@property @property
def step_active(self) -> bool: def step_active(self) -> bool:
+2 -2
View File
@@ -265,7 +265,7 @@ def setup_python(
which_python = call("which", "python", env=env, capture_stdout=True).strip() which_python = call("which", "python", env=env, capture_stdout=True).strip()
print(which_python) print(which_python)
if which_python != str(venv_bin_path / "python"): if which_python != str(venv_bin_path / "python"):
msg = "cibuildwheel: python available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it." msg = "python available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it."
raise errors.FatalError(msg) raise errors.FatalError(msg)
call("python", "--version", env=env) call("python", "--version", env=env)
@@ -275,7 +275,7 @@ def setup_python(
which_pip = call("which", "pip", env=env, capture_stdout=True).strip() which_pip = call("which", "pip", env=env, capture_stdout=True).strip()
print(which_pip) print(which_pip)
if which_pip != str(venv_bin_path / "pip"): if which_pip != str(venv_bin_path / "pip"):
msg = "cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it." msg = "pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it."
raise errors.FatalError(msg) raise errors.FatalError(msg)
call("pip", "--version", env=env) call("pip", "--version", env=env)
+3 -3
View File
@@ -41,7 +41,7 @@ def test_unknown_platform_on_ci(monkeypatch, capsys):
assert exit.value.code == 2 assert exit.value.code == 2
_, err = capsys.readouterr() _, err = capsys.readouterr()
assert 'cibuildwheel: Unable to detect platform from "sys.platform"' in err assert 'Unable to detect platform from "sys.platform"' in err
def test_unknown_platform(monkeypatch, capsys): def test_unknown_platform(monkeypatch, capsys):
@@ -52,7 +52,7 @@ def test_unknown_platform(monkeypatch, capsys):
_, err = capsys.readouterr() _, err = capsys.readouterr()
assert exit.value.code == 2 assert exit.value.code == 2
assert "cibuildwheel: Unsupported platform: nonexistent" in err assert "Unsupported platform: nonexistent" in err
def test_platform_argument(platform, intercepted_build_args, monkeypatch): def test_platform_argument(platform, intercepted_build_args, monkeypatch):
@@ -276,4 +276,4 @@ def test_pyodide_on_windows(monkeypatch, capsys):
_, err = capsys.readouterr() _, err = capsys.readouterr()
assert exit.value.code == 2 assert exit.value.code == 2
assert "cibuildwheel: Building for pyodide is not supported on Windows" in err assert "Building for pyodide is not supported on Windows" in err