From 09a119a20db08894a6dd18ddcd76f50ff099d4a6 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Fri, 16 May 2025 22:10:29 +0800 Subject: [PATCH 1/7] Print meson output in case of error during editable rebuild --- mesonpy/_editable.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mesonpy/_editable.py b/mesonpy/_editable.py index 02067cd43..f91738231 100644 --- a/mesonpy/_editable.py +++ b/mesonpy/_editable.py @@ -344,7 +344,9 @@ def _rebuild(self) -> Node: else: subprocess.run(self._build_cmd, cwd=self._build_path, env=env, stdout=subprocess.DEVNULL, 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 if exc.output is not None else exc.stdout + raise ImportError(f're-building the {self._name} meson-python editable wheel package failed with: \n{output.decode(errors="replace")}') 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: From 7b7330a0227cb122d7d89dae2f104fe209ce447e Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Mon, 26 May 2025 11:16:48 +0000 Subject: [PATCH 2/7] improve handling of no output --- mesonpy/_editable.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mesonpy/_editable.py b/mesonpy/_editable.py index f91738231..3c6fea933 100644 --- a/mesonpy/_editable.py +++ b/mesonpy/_editable.py @@ -344,8 +344,8 @@ def _rebuild(self) -> Node: else: subprocess.run(self._build_cmd, cwd=self._build_path, env=env, stdout=subprocess.DEVNULL, check=True) except subprocess.CalledProcessError as exc: - output = exc.output if exc.output is not None else exc.stdout - raise ImportError(f're-building the {self._name} meson-python editable wheel package failed with: \n{output.decode(errors="replace")}') 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') From 84b650b07e40384e57ab13e4020d43074d8c1a17 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Mon, 26 May 2025 11:20:15 +0000 Subject: [PATCH 3/7] Fix linter --- mesonpy/_editable.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/mesonpy/_editable.py b/mesonpy/_editable.py index 3c6fea933..ccfc87228 100644 --- a/mesonpy/_editable.py +++ b/mesonpy/_editable.py @@ -344,9 +344,10 @@ def _rebuild(self) -> Node: else: subprocess.run(self._build_cmd, cwd=self._build_path, env=env, stdout=subprocess.DEVNULL, check=True) except subprocess.CalledProcessError as 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 - + 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: From bce07877f3cfc4e34cc8f46311af9daf7671e92f Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Mon, 26 May 2025 11:24:41 +0000 Subject: [PATCH 4/7] fix linter part 2 --- mesonpy/_editable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mesonpy/_editable.py b/mesonpy/_editable.py index ccfc87228..c12f1779f 100644 --- a/mesonpy/_editable.py +++ b/mesonpy/_editable.py @@ -344,7 +344,7 @@ def _rebuild(self) -> Node: else: subprocess.run(self._build_cmd, cwd=self._build_path, env=env, stdout=subprocess.DEVNULL, check=True) except subprocess.CalledProcessError as exc: - output = exc.output.decode(errors='replace') if exc.output is not None else "No error details available" + 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 From 284ebff10267c666d03b113ba556563779288b25 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 27 May 2025 06:06:46 +0000 Subject: [PATCH 5/7] Add and adapt tests --- mesonpy/_editable.py | 18 ++++++++++++++++-- tests/test_editable.py | 41 +++++++++++++++++++++++++++++++++++++++-- 2 files changed, 55 insertions(+), 4 deletions(-) diff --git a/mesonpy/_editable.py b/mesonpy/_editable.py index c12f1779f..0c0eeccc7 100644 --- a/mesonpy/_editable.py +++ b/mesonpy/_editable.py @@ -340,9 +340,23 @@ 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: output = exc.output.decode(errors='replace') if exc.output is not None else 'No error details available' raise ImportError( diff --git a/tests/test_editable.py b/tests/test_editable.py index cd69f0089..c84415aea 100644 --- a/tests/test_editable.py +++ b/tests/test_editable.py @@ -336,9 +336,46 @@ 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('return') + + # Import module and trigger rebuild: the build fails and ImportErrror is raised + stdout = io.StringIO() + with redirect_stdout(stdout): + with pytest.raises(ImportError, match=r're-building the purelib-and-platlib (?s:.)*ERROR: Invalid source tree:'): + import plat # noqa: F401 + if verbose: + assert stdout.getvalue().startswith('meson-python: building ') + else: + assert not stdout.getvalue() finally: del sys.meta_path[0] From ba938be36125be3012e61321176325e839aef33f Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 27 May 2025 06:18:29 +0000 Subject: [PATCH 6/7] Fix linter --- tests/test_editable.py | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/tests/test_editable.py b/tests/test_editable.py index c84415aea..72405303b 100644 --- a/tests/test_editable.py +++ b/tests/test_editable.py @@ -336,7 +336,9 @@ 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=r're-building the purelib-and-platlib (?s:.)*error: expected identifier'): + with pytest.raises( + ImportError, match=r're-building the purelib-and-platlib (?s:.)*error: expected identifier' + ): import plat # noqa: F401 if verbose: assert stdout.getvalue().startswith('meson-python: building ') @@ -348,13 +350,15 @@ def test_editable_rebuild_error(package_purelib_and_platlib, tmp_path, verbose): 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, + project._metadata.name, + {'plat', 'pure'}, + os.fspath(tmp_path), + project._build_command, verbose=verbose, ) path = package_purelib_and_platlib / 'meson.build' @@ -370,7 +374,9 @@ def test_editable_meson_file_rebuild_error(package_purelib_and_platlib, tmp_path # Import module and trigger rebuild: the build fails and ImportErrror is raised stdout = io.StringIO() with redirect_stdout(stdout): - with pytest.raises(ImportError, match=r're-building the purelib-and-platlib (?s:.)*ERROR: Invalid source tree:'): + with pytest.raises( + ImportError, match=r're-building the purelib-and-platlib (?s:.)*ERROR: Invalid source tree:' + ): import plat # noqa: F401 if verbose: assert stdout.getvalue().startswith('meson-python: building ') From 8cfc7e68bc81db2f28c8c3a2a173b72a79288a83 Mon Sep 17 00:00:00 2001 From: Tobias Diez Date: Tue, 27 May 2025 06:20:43 +0000 Subject: [PATCH 7/7] Use really invalid meson code to trigger exception --- tests/test_editable.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_editable.py b/tests/test_editable.py index 72405303b..c9f763976 100644 --- a/tests/test_editable.py +++ b/tests/test_editable.py @@ -369,7 +369,7 @@ def test_editable_meson_file_rebuild_error(package_purelib_and_platlib, tmp_path sys.meta_path.insert(0, finder) # Insert invalid code in the meson build file - path.write_text('return') + path.write_text('