|
13 | 13 | from collections.abc import Iterator |
14 | 14 |
|
15 | 15 | PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.9 3.10 3.11 3.12 3.13 3.14").split() |
| 16 | +PYTHON_DEV = "3.14" |
16 | 17 |
|
17 | 18 | _commands = [] |
18 | 19 |
|
@@ -49,12 +50,21 @@ def _uv_install(venv: Path) -> None: |
49 | 50 | def _run(version: str, cmd: str, *args: str, **kwargs: Any) -> None: |
50 | 51 | kwargs = {"check": True, **kwargs} |
51 | 52 | uv_run = ["uv", "run", "--no-sync"] |
52 | | - if version == "default": |
53 | | - with _environ(UV_PROJECT_ENVIRONMENT=".venv"): |
54 | | - subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510 |
55 | | - else: |
56 | | - with _environ(UV_PROJECT_ENVIRONMENT=f".venvs/{version}", MULTIRUN="1"): |
57 | | - subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510 |
| 53 | + try: |
| 54 | + if version == "default": |
| 55 | + with _environ(UV_PROJECT_ENVIRONMENT=".venv"): |
| 56 | + subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510 |
| 57 | + else: |
| 58 | + with _environ(UV_PROJECT_ENVIRONMENT=f".venvs/{version}", MULTIRUN="1"): |
| 59 | + subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510 |
| 60 | + except subprocess.CalledProcessError as process: |
| 61 | + raise _RunError( |
| 62 | + returncode=process.returncode, |
| 63 | + python_version=version, |
| 64 | + cmd=process.cmd, |
| 65 | + output=process.output, |
| 66 | + stderr=process.stderr, |
| 67 | + ) from process |
58 | 68 |
|
59 | 69 |
|
60 | 70 | def _command(name: str) -> Callable[[Callable[..., None]], Callable[..., None]]: |
@@ -148,6 +158,12 @@ def setup() -> None: |
148 | 158 | _uv_install(venv_path) |
149 | 159 |
|
150 | 160 |
|
| 161 | +class _RunError(subprocess.CalledProcessError): |
| 162 | + def __init__(self, *args: Any, python_version: str, **kwargs: Any): |
| 163 | + super().__init__(*args, **kwargs) |
| 164 | + self.python_version = python_version |
| 165 | + |
| 166 | + |
151 | 167 | @_command("run") |
152 | 168 | def run(cmd: str, *args: str, **kwargs: Any) -> None: |
153 | 169 | """Run a command in the default virtual environment. |
@@ -328,7 +344,14 @@ def main(args: list[str]) -> int: |
328 | 344 | if __name__ == "__main__": |
329 | 345 | try: |
330 | 346 | sys.exit(main(sys.argv[1:])) |
331 | | - except subprocess.CalledProcessError as process: |
| 347 | + except _RunError as process: |
332 | 348 | if process.output: |
333 | 349 | print(process.output, file=sys.stderr) |
334 | | - sys.exit(process.returncode) |
| 350 | + if (code := process.returncode) == 139: # noqa: PLR2004 |
| 351 | + print( |
| 352 | + f"✗ (python{process.python_version}) '{' '.join(process.cmd)}' failed with return code {code} (segfault)", |
| 353 | + file=sys.stderr, |
| 354 | + ) |
| 355 | + if process.python_version == PYTHON_DEV: |
| 356 | + code = 0 |
| 357 | + sys.exit(code) |
0 commit comments