|
1 | 1 | from __future__ import annotations |
2 | 2 |
|
3 | 3 | import os |
| 4 | +import subprocess |
4 | 5 |
|
5 | 6 | from contextlib import contextmanager |
6 | 7 | from contextlib import redirect_stdout |
7 | 8 | from io import StringIO |
8 | 9 | from typing import TYPE_CHECKING |
9 | 10 |
|
| 11 | +from build import BuildBackendException |
10 | 12 | from build.env import IsolatedEnv as BaseIsolatedEnv |
11 | 13 |
|
| 14 | +from poetry.utils._compat import decode |
12 | 15 | from poetry.utils.env import Env |
13 | 16 | from poetry.utils.env import EnvManager |
14 | 17 | from poetry.utils.env import ephemeral_environment |
|
28 | 31 | class IsolatedBuildBaseError(Exception): ... |
29 | 32 |
|
30 | 33 |
|
31 | | -class IsolatedBuildError(IsolatedBuildBaseError): ... |
| 34 | +class IsolatedBuildBackendError(IsolatedBuildBaseError): |
| 35 | + def __init__(self, source: Path, exception: BuildBackendException) -> None: |
| 36 | + super().__init__() |
| 37 | + self.source = source |
| 38 | + self.exception = exception |
| 39 | + |
| 40 | + def generate_message( |
| 41 | + self, source_string: str | None = None, build_command: str | None = None |
| 42 | + ) -> str: |
| 43 | + e = self.exception.exception |
| 44 | + source_string = source_string or self.source.as_posix() |
| 45 | + build_command = ( |
| 46 | + build_command |
| 47 | + or f'pip wheel --no-cache-dir --use-pep517 "{self.source.as_posix()}"' |
| 48 | + ) |
| 49 | + |
| 50 | + reasons = ["PEP517 build of a dependency failed", str(self.exception)] |
| 51 | + |
| 52 | + if isinstance(e, subprocess.CalledProcessError): |
| 53 | + inner_traceback = decode(e.output).strip() |
| 54 | + inner_reason = "\n | ".join( |
| 55 | + ["", str(e), "", *inner_traceback.split("\n")] |
| 56 | + ).lstrip("\n") |
| 57 | + reasons.append(f"<warning>{inner_reason}</warning>") |
| 58 | + |
| 59 | + reasons.append( |
| 60 | + "<info>" |
| 61 | + "<options=bold>Note:</> This error originates from the build backend, and is likely not a " |
| 62 | + f"problem with poetry but one of the following issues with {source_string}\n\n" |
| 63 | + " - not supporting PEP 517 builds\n" |
| 64 | + " - not specifying PEP 517 build requirements correctly\n" |
| 65 | + " - the build requirements are incompatible with your operating system or Python versions\n" |
| 66 | + " - the build requirements are missing system dependencies (eg: compilers, libraries, headers).\n\n" |
| 67 | + f"You can verify this by running <c1>{build_command}</c1>." |
| 68 | + "</info>" |
| 69 | + ) |
| 70 | + |
| 71 | + return "\n\n".join(reasons) |
| 72 | + |
| 73 | + def __str__(self) -> str: |
| 74 | + return self.generate_message() |
32 | 75 |
|
33 | 76 |
|
34 | 77 | class IsolatedBuildInstallError(IsolatedBuildBaseError): |
@@ -140,18 +183,20 @@ def isolated_builder( |
140 | 183 | ) as venv: |
141 | 184 | env = IsolatedEnv(venv, pool) |
142 | 185 | stdout = StringIO() |
| 186 | + try: |
| 187 | + builder = ProjectBuilder.from_isolated_env( |
| 188 | + env, source, runner=quiet_subprocess_runner |
| 189 | + ) |
143 | 190 |
|
144 | | - builder = ProjectBuilder.from_isolated_env( |
145 | | - env, source, runner=quiet_subprocess_runner |
146 | | - ) |
147 | | - |
148 | | - with redirect_stdout(stdout): |
149 | | - env.install(builder.build_system_requires) |
| 191 | + with redirect_stdout(stdout): |
| 192 | + env.install(builder.build_system_requires) |
150 | 193 |
|
151 | | - # we repeat the build system requirements to avoid poetry installer from removing them |
152 | | - env.install( |
153 | | - builder.build_system_requires |
154 | | - | builder.get_requires_for_build(distribution) |
155 | | - ) |
| 194 | + # we repeat the build system requirements to avoid poetry installer from removing them |
| 195 | + env.install( |
| 196 | + builder.build_system_requires |
| 197 | + | builder.get_requires_for_build(distribution) |
| 198 | + ) |
156 | 199 |
|
157 | | - yield builder |
| 200 | + yield builder |
| 201 | + except BuildBackendException as e: |
| 202 | + raise IsolatedBuildBackendError(source, e) from None |
0 commit comments