Skip to content

Commit cc4d315

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

File tree

2 files changed

+56
-5
lines changed

2 files changed

+56
-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]) + ['-n']
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)
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: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,3 +237,36 @@ def test_custom_target_install_dir(package_custom_target_dir, tmp_path):
237237
import package.generated.two # noqa: F401
238238
finally:
239239
del sys.meta_path[0]
240+
241+
242+
@pytest.mark.parametrize('verbose', [False, True], ids=('', 'verbose'))
243+
@pytest.mark.parametrize('args', [[], ['-j1']], ids=('', '-Ccompile-args=-j1'))
244+
def test_editable_rebuild(package_purelib_and_platlib, tmp_path, verbose, args):
245+
with mesonpy._project({'builddir': os.fspath(tmp_path), 'compile-args': args}) as project:
246+
finder = _editable.MesonpyMetaFinder({'plat', 'pure'}, os.fspath(tmp_path), project._build_command, verbose=verbose)
247+
try:
248+
# Install editable hooks
249+
sys.meta_path.insert(0, finder)
250+
# Import module and trigger rebuild. Importing any module in the
251+
# Python package triggers the build. Prefer to load the pure Python
252+
# one as Cygwin is not happy when reloading an extension module.
253+
import pure # noqa: F401
254+
finally:
255+
del sys.meta_path[0]
256+
sys.modules.pop('pure', None)
257+
258+
259+
def test_editable_verbose(venv, package_complex, editable_complex, monkeypatch):
260+
monkeypatch.setenv('MESONPY_EDITABLE_VERBOSE', '1')
261+
venv.pip('install', os.fspath(editable_complex))
262+
263+
# Importint the module should not result in any output since the project has already been built
264+
assert venv.python('-c', 'import complex').strip() == ''
265+
266+
# Touch a compiled source file and make sure that the build info is output on import
267+
package_complex.joinpath('test.pyx').touch()
268+
output = venv.python('-c', 'import complex').strip()
269+
assert output.startswith('meson-python: building complex with')
270+
271+
# Another import without file changes should not show any output
272+
assert venv.python('-c', 'import complex') == ''

0 commit comments

Comments
 (0)