Skip to content

Commit

Permalink
ENH: no output in editable verbose mode when there is no work to do
Browse files Browse the repository at this point in the history
  • Loading branch information
lesteve authored and dnicolodi committed Mar 5, 2024
1 parent 2daa991 commit 6997ffb
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 5 deletions.
28 changes: 23 additions & 5 deletions mesonpy/_editable.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from __future__ import annotations

import ast
import functools
import importlib.abc
import importlib.machinery
Expand Down Expand Up @@ -308,6 +309,21 @@ def find_spec(
tree = self._rebuild()
return find_spec(fullname, tree)

def _work_to_do(self, env: dict[str, str]) -> bool:
if sys.platform == 'win32':
# On Windows the build command is 'meson compile' eventually with a --ninja-args= option.
if self._build_cmd[-1].startswith('--ninja-args='):
ninja_args = ast.literal_eval(self._build_cmd[-1].split('=', 1)[1]) + ['-n']
dry_run_build_cmd = self._build_cmd[:-1] + [f'--ninja-args={ninja_args!r}']

Check warning on line 317 in mesonpy/_editable.py

View check run for this annotation

Codecov / codecov/patch

mesonpy/_editable.py#L315-L317

Added lines #L315 - L317 were not covered by tests
else:
dry_run_build_cmd = self._build_cmd + ['--ninja-args=-n']

Check warning on line 319 in mesonpy/_editable.py

View check run for this annotation

Codecov / codecov/patch

mesonpy/_editable.py#L319

Added line #L319 was not covered by tests
else:
dry_run_build_cmd = self._build_cmd + ['-n']
# Check adapted from
# https://github.com/mesonbuild/meson/blob/a35d4d368a21f4b70afa3195da4d6292a649cb4c/mesonbuild/mtest.py#L1635-L1636
p = subprocess.run(dry_run_build_cmd, cwd=self._build_path, env=env, capture_output=True)
return b'ninja: no work to do.' not in p.stdout and b'samu: nothing to do' not in p.stdout

@functools.lru_cache(maxsize=1)
def _rebuild(self) -> Node:
# skip editable wheel lookup during rebuild: during the build
Expand All @@ -317,12 +333,14 @@ def _rebuild(self) -> Node:
env[MARKER] = os.pathsep.join((env.get(MARKER, ''), self._build_path))

if self._verbose or bool(env.get(VERBOSE, '')):
print('+ ' + ' '.join(self._build_cmd))
stdout = None
# We want to show some output only if there is some work to do
if self._work_to_do(env):
module_names = ' '.join(sorted(self._top_level_modules))
build_command = ' '.join(self._build_cmd)
print(f'meson-python: building {module_names} with {build_command!r}', flush=True)
subprocess.run(self._build_cmd, cwd=self._build_path, env=env)
else:
stdout = subprocess.DEVNULL

subprocess.run(self._build_cmd, cwd=self._build_path, env=env, stdout=stdout, check=True)
subprocess.run(self._build_cmd, cwd=self._build_path, env=env, stdout=subprocess.DEVNULL)

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:
Expand Down
31 changes: 31 additions & 0 deletions tests/test_editable.py
Original file line number Diff line number Diff line change
Expand Up @@ -237,3 +237,34 @@ def test_custom_target_install_dir(package_custom_target_dir, tmp_path):
import package.generated.two # noqa: F401
finally:
del sys.meta_path[0]


@pytest.mark.parametrize('verbose', [False, True], ids=('', 'verbose'))
@pytest.mark.parametrize('args', [[], ['-j1']], ids=('', '-Ccompile-args=-j1'))
def test_editable_rebuild(package_purelib_and_platlib, tmp_path, verbose, args):
with mesonpy._project({'builddir': os.fspath(tmp_path), 'compile-args': args}) as project:
finder = _editable.MesonpyMetaFinder({'plat', 'pure'}, os.fspath(tmp_path), project._build_command, verbose=verbose)
try:
# Install editable hooks
sys.meta_path.insert(0, finder)
# Import module and trigger rebuild
import plat # noqa: F401
finally:
del sys.meta_path[0]
sys.modules.pop('plat', None)


def test_editable_verbose(venv, package_complex, editable_complex, monkeypatch):
monkeypatch.setenv('MESONPY_EDITABLE_VERBOSE', '1')
venv.pip('install', os.fspath(editable_complex))

# Importint the module should not result in any output since the project has already been built
assert venv.python('-c', 'import complex').strip() == ''

# Touch a compiled source file and make sure that the build info is output on import
package_complex.joinpath('test.pyx').touch()
output = venv.python('-c', 'import complex').strip()
assert output.startswith('meson-python: building complex with')

# Another import without file changes should not show any output
assert venv.python('-c', 'import complex') == ''

0 comments on commit 6997ffb

Please sign in to comment.