Skip to content

Commit 0059471

Browse files
lestevednicolodi
authored andcommitted
ENH: no output in editable verbose mode when there is no work to do
1 parent 2daa991 commit 0059471

File tree

2 files changed

+61
-5
lines changed

2 files changed

+61
-5
lines changed

mesonpy/_editable.py

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
from __future__ import annotations
88

9+
import ast
910
import functools
1011
import importlib.abc
1112
import importlib.machinery
@@ -308,6 +309,21 @@ def find_spec(
308309
tree = self._rebuild()
309310
return find_spec(fullname, tree)
310311

312+
def _work_to_do(self, env: dict[str, str]) -> bool:
313+
if sys.platform == 'win32':
314+
# On Windows the build command is 'meson compile' eventually with a --ninja-args= option.
315+
if self._build_cmd[-1].startswith('--ninja-args='):
316+
ninja_args = ast.literal_eval(self._build_cmd[-1].split('=', 1)[1])
317+
dry_run_build_cmd = self._build_cmd[:-1] + [f'--ninja-args={ninja_args!r}']
318+
else:
319+
dry_run_build_cmd = self._build_cmd + ['--ninja-args=-n']
320+
else:
321+
dry_run_build_cmd = self._build_cmd + ['-n']
322+
# Check adapted from
323+
# https://github.com/mesonbuild/meson/blob/a35d4d368a21f4b70afa3195da4d6292a649cb4c/mesonbuild/mtest.py#L1635-L1636
324+
p = subprocess.run(dry_run_build_cmd, cwd=self._build_path, env=env, capture_output=True, check=True)
325+
return b'ninja: no work to do.' not in p.stdout and b'samu: nothing to do' not in p.stdout
326+
311327
@functools.lru_cache(maxsize=1)
312328
def _rebuild(self) -> Node:
313329
# skip editable wheel lookup during rebuild: during the build
@@ -317,12 +333,14 @@ def _rebuild(self) -> Node:
317333
env[MARKER] = os.pathsep.join((env.get(MARKER, ''), self._build_path))
318334

319335
if self._verbose or bool(env.get(VERBOSE, '')):
320-
print('+ ' + ' '.join(self._build_cmd))
321-
stdout = None
336+
# We want to show some output only if there is some work to do
337+
if self._work_to_do(env):
338+
module_names = ' '.join(sorted(self._top_level_modules))
339+
build_command = ' '.join(self._build_cmd)
340+
print(f'meson-python: building {module_names} with {build_command!r}', flush=True)
341+
subprocess.run(self._build_cmd, cwd=self._build_path, env=env)
322342
else:
323-
stdout = subprocess.DEVNULL
324-
325-
subprocess.run(self._build_cmd, cwd=self._build_path, env=env, stdout=stdout, check=True)
343+
subprocess.run(self._build_cmd, cwd=self._build_path, env=env, stdout=subprocess.DEVNULL)
326344

327345
install_plan_path = os.path.join(self._build_path, 'meson-info', 'intro-install_plan.json')
328346
with open(install_plan_path, 'r', encoding='utf8') as f:

tests/test_editable.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,9 @@ def test_mesonpy_meta_finder(package_complex, tmp_path):
9999
finally:
100100
# remove finder from the meta path
101101
del sys.meta_path[0]
102+
# unload complex module and all its submodules to be able to run parametrized tests without side-effects
103+
for module in ['complex', 'complex.test', 'complex.namespace', 'complex.namespace.foo']:
104+
sys.modules.pop(module, None)
102105

103106

104107
def test_mesonpy_traversable():
@@ -237,3 +240,38 @@ def test_custom_target_install_dir(package_custom_target_dir, tmp_path):
237240
import package.generated.two # noqa: F401
238241
finally:
239242
del sys.meta_path[0]
243+
244+
245+
@pytest.mark.parametrize('verbose', [False, True], ids=('', 'verbose'))
246+
@pytest.mark.parametrize('args', [[], ['-j0']], ids=('', '-Ccompile-args=-j0'))
247+
def test_editable_rebuild(package_simple, tmp_path, verbose, args):
248+
# Build a package in a temporary directory
249+
with mesonpy._project({'builddir': os.fspath(tmp_path), 'compile-args': args}) as project:
250+
finder = _editable.MesonpyMetaFinder({'simple'}, os.fspath(tmp_path), project._build_command, verbose=verbose)
251+
252+
try:
253+
# Install editable hooks
254+
sys.meta_path.insert(0, finder)
255+
256+
# Import module and trigger rebuild
257+
import simple # noqa: F401
258+
259+
finally:
260+
del sys.meta_path[0]
261+
sys.modules.pop('simple', None)
262+
263+
264+
def test_editable_verbose(venv, package_complex, editable_complex, monkeypatch):
265+
monkeypatch.setenv('MESONPY_EDITABLE_VERBOSE', '1')
266+
venv.pip('install', os.fspath(editable_complex))
267+
268+
# Importint the module should not result in any output since the project has already been built
269+
assert venv.python('-c', 'import complex').strip() == ''
270+
271+
# Touch a compiled source file and make sure that the build info is output on import
272+
package_complex.joinpath('test.pyx').touch()
273+
output = venv.python('-c', 'import complex').strip()
274+
assert output.startswith('meson-python: building complex with')
275+
276+
# Another import without file changes should not show any output
277+
assert venv.python('-c', 'import complex') == ''

0 commit comments

Comments
 (0)