|
14 | 14 | from collections.abc import Iterator |
15 | 15 |
|
16 | 16 |
|
17 | | -PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.9 3.10 3.11 3.12 3.13").split() |
| 17 | +PYTHON_VERSIONS = os.getenv("PYTHON_VERSIONS", "3.9 3.10 3.11 3.12 3.13 3.14").split() |
| 18 | +PYTHON_DEV = "3.14" |
18 | 19 |
|
19 | 20 |
|
20 | 21 | def shell(cmd: str, *, capture_output: bool = False, **kwargs: Any) -> str | None: |
@@ -67,16 +68,31 @@ def setup() -> None: |
67 | 68 | uv_install(venv_path) |
68 | 69 |
|
69 | 70 |
|
| 71 | +class _RunError(subprocess.CalledProcessError): |
| 72 | + def __init__(self, *args: Any, python_version: str, **kwargs: Any): |
| 73 | + super().__init__(*args, **kwargs) |
| 74 | + self.python_version = python_version |
| 75 | + |
| 76 | + |
70 | 77 | def run(version: str, cmd: str, *args: str, **kwargs: Any) -> None: |
71 | 78 | """Run a command in a virtual environment.""" |
72 | 79 | kwargs = {"check": True, **kwargs} |
73 | 80 | uv_run = ["uv", "run", "--no-sync"] |
74 | | - if version == "default": |
75 | | - with environ(UV_PROJECT_ENVIRONMENT=".venv"): |
76 | | - subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510 |
77 | | - else: |
78 | | - with environ(UV_PROJECT_ENVIRONMENT=f".venvs/{version}", MULTIRUN="1"): |
79 | | - subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510 |
| 81 | + try: |
| 82 | + if version == "default": |
| 83 | + with environ(UV_PROJECT_ENVIRONMENT=".venv"): |
| 84 | + subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510 |
| 85 | + else: |
| 86 | + with environ(UV_PROJECT_ENVIRONMENT=f".venvs/{version}", MULTIRUN="1"): |
| 87 | + subprocess.run([*uv_run, cmd, *args], **kwargs) # noqa: S603, PLW1510 |
| 88 | + except subprocess.CalledProcessError as process: |
| 89 | + raise _RunError( |
| 90 | + returncode=process.returncode, |
| 91 | + python_version=version, |
| 92 | + cmd=process.cmd, |
| 93 | + output=process.output, |
| 94 | + stderr=process.stderr, |
| 95 | + ) from process |
80 | 96 |
|
81 | 97 |
|
82 | 98 | def multirun(cmd: str, *args: str, **kwargs: Any) -> None: |
@@ -195,7 +211,14 @@ def main() -> int: |
195 | 211 | if __name__ == "__main__": |
196 | 212 | try: |
197 | 213 | sys.exit(main()) |
198 | | - except subprocess.CalledProcessError as process: |
| 214 | + except _RunError as process: |
199 | 215 | if process.output: |
200 | 216 | print(process.output, file=sys.stderr) |
201 | | - sys.exit(process.returncode) |
| 217 | + if (code := process.returncode) == 139: # noqa: PLR2004 |
| 218 | + print( |
| 219 | + f"✗ (python{process.python_version}) '{' '.join(process.cmd)}' failed with return code {code} (segfault)", |
| 220 | + file=sys.stderr, |
| 221 | + ) |
| 222 | + if process.python_version == PYTHON_DEV: |
| 223 | + code = 0 |
| 224 | + sys.exit(code) |
0 commit comments