diff --git a/mesonpy/_editable.py b/mesonpy/_editable.py index 02067cd4..0c0eeccc 100644 --- a/mesonpy/_editable.py +++ b/mesonpy/_editable.py @@ -340,11 +340,28 @@ def _rebuild(self) -> Node: if self._work_to_do(env): build_command = ' '.join(self._build_cmd) print(f'meson-python: building {self._name}: {build_command}', flush=True) - subprocess.run(self._build_cmd, cwd=self._build_path, env=env, check=True) + subprocess.run( + self._build_cmd, + cwd=self._build_path, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + env=env, + check=True, + ) else: - subprocess.run(self._build_cmd, cwd=self._build_path, env=env, stdout=subprocess.DEVNULL, check=True) + subprocess.run( + self._build_cmd, + cwd=self._build_path, + env=env, + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT, + check=True, + ) except subprocess.CalledProcessError as exc: - raise ImportError(f're-building the {self._name} meson-python editable wheel package failed') from exc + output = exc.output.decode(errors='replace') if exc.output is not None else 'No error details available' + raise ImportError( + f're-building the {self._name} meson-python editable wheel package failed with: \n{output}' + ) from exc install_plan_path = os.path.join(self._build_path, 'meson-info', 'intro-install_plan.json') with open(install_plan_path, 'r', encoding='utf8') as f: diff --git a/tests/test_editable.py b/tests/test_editable.py index cd69f008..c9f76397 100644 --- a/tests/test_editable.py +++ b/tests/test_editable.py @@ -336,9 +336,52 @@ def test_editable_rebuild_error(package_purelib_and_platlib, tmp_path, verbose): # Import module and trigger rebuild: the build fails and ImportErrror is raised stdout = io.StringIO() with redirect_stdout(stdout): - with pytest.raises(ImportError, match='re-building the purelib-and-platlib '): + with pytest.raises( + ImportError, match=r're-building the purelib-and-platlib (?s:.)*error: expected identifier' + ): import plat # noqa: F401 - assert not verbose or stdout.getvalue().startswith('meson-python: building ') + if verbose: + assert stdout.getvalue().startswith('meson-python: building ') + else: + assert not stdout.getvalue() + + finally: + del sys.meta_path[0] + sys.modules.pop('pure', None) + path.write_text(code) + + +@pytest.mark.parametrize('verbose', [False, True], ids=('', 'verbose')) +def test_editable_meson_file_rebuild_error(package_purelib_and_platlib, tmp_path, verbose): + with mesonpy._project({'builddir': os.fspath(tmp_path)}) as project: + finder = _editable.MesonpyMetaFinder( + project._metadata.name, + {'plat', 'pure'}, + os.fspath(tmp_path), + project._build_command, + verbose=verbose, + ) + path = package_purelib_and_platlib / 'meson.build' + code = path.read_text() + + try: + # Install editable hooks + sys.meta_path.insert(0, finder) + + # Insert invalid code in the meson build file + path.write_text('