Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editable install: do not show any output in verbose mode when there is no work to do #579

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
6bc67f6
ENH: do not show any output in editable verbose mode when there is no…
lesteve Feb 22, 2024
b73ad7e
Reuse same code as in meson and add origin in comment
lesteve Feb 22, 2024
f7b3c00
Add test
lesteve Feb 23, 2024
779205f
Tweak output and test
lesteve Feb 23, 2024
804f434
Fix test on OSX
lesteve Feb 23, 2024
875eeb5
Simple quotes
lesteve Feb 23, 2024
78a5ea9
More simple quotes
lesteve Feb 23, 2024
69c0523
Only check first two lines of output
lesteve Feb 23, 2024
ab97efa
Tweak message and adapt test
lesteve Feb 23, 2024
0ae0795
Touching the file is enough to trigger compilation
lesteve Feb 23, 2024
4b67b30
Naive Windows attempt
lesteve Feb 23, 2024
d1eb4d0
Skip test on Alpine
lesteve Feb 23, 2024
e88169b
Skip test on Alpine
lesteve Feb 23, 2024
8cb12d7
Check exit code in dry-run command
lesteve Feb 23, 2024
e2177e3
Tackle comments
lesteve Feb 29, 2024
c4a60d4
Merge branch 'main' of https://github.com/mesonbuild/meson-python int…
lesteve Feb 29, 2024
2721e88
Touching the file is enough
lesteve Mar 4, 2024
89df78e
Check platform rather than first command argument
lesteve Mar 4, 2024
a6e336f
Merge branch 'main' of https://github.com/mesonbuild/meson-python int…
lesteve Mar 4, 2024
8f025a6
Debug CI
lesteve Mar 4, 2024
1e310d5
Debug CI
lesteve Mar 4, 2024
00680d0
Add test with verbose=True in main process
lesteve Mar 5, 2024
bc2f63c
Do not override existing ninja-args arguments on Windows
lesteve Mar 5, 2024
70e32ac
Fix mypy
lesteve Mar 5, 2024
674f813
Fix Windows
lesteve Mar 5, 2024
1557f58
Remove debug code
lesteve Mar 5, 2024
ee8048e
Tweak module unloading in case of import error
lesteve Mar 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 27 additions & 5 deletions mesonpy/_editable.py
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,26 @@
tree = self._rebuild()
return find_spec(fullname, tree)

def _work_to_do(self, env: dict[str, str]) -> bool:
# Code is adapted from:
# https://github.com/mesonbuild/meson/blob/a35d4d368a21f4b70afa3195da4d6292a649cb4c/mesonbuild/mtest.py#L1635-L1636
if sys.platform != 'win32':
dry_run_build_cmd = self._build_cmd + ['-n']
else:
# On Windows meson compile is used so to do a dry run you need to add --ninja-args=-n without ignoring
# existing --ninja-args in self._build_cmd
ninja_index_and_arg_list = [(i, arg) for i, arg in enumerate(self._build_cmd) if arg.startswith('--ninja-args=')]
if not ninja_index_and_arg_list:
dry_run_build_cmd = self._build_cmd + ['--ninja-args=-n']
else:
dry_run_build_cmd = self._build_cmd.copy()

Check warning on line 323 in mesonpy/_editable.py

View check run for this annotation

Codecov / codecov/patch

mesonpy/_editable.py#L323

Added line #L323 was not covered by tests
# Last --ninja-args overrides all the previous ones, so need to modify only the last one to add -n
last_ninja_index, last_ninja_args = ninja_index_and_arg_list[-1]
dry_run_build_cmd[last_ninja_index] = last_ninja_args + ',-n'

Check warning on line 326 in mesonpy/_editable.py

View check run for this annotation

Codecov / codecov/patch

mesonpy/_editable.py#L325-L326

Added lines #L325 - L326 were not covered by tests

p = subprocess.run(dry_run_build_cmd, cwd=self._build_path, env=env, capture_output=True, check=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 +337,14 @@
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
38 changes: 35 additions & 3 deletions tests/test_editable.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#
# SPDX-License-Identifier: MIT

import functools
import os
import pathlib
import pkgutil
Expand All @@ -13,7 +14,7 @@

from mesonpy import _editable

from .test_wheel import EXT_SUFFIX
from .test_wheel import EXT_SUFFIX, tag


def test_walk(package_complex):
Expand Down Expand Up @@ -61,12 +62,17 @@ def test_collect(package_complex):
assert tree['complex']['more']['__init__.py'] == os.path.join(root, 'complex', 'more', '__init__.py')


def test_mesonpy_meta_finder(package_complex, tmp_path):
@pytest.mark.parametrize(
'make_finder',
[_editable.MesonpyMetaFinder, functools.partial(_editable.MesonpyMetaFinder, verbose=True)]
)
def test_mesonpy_meta_finder(package_complex, tmp_path, make_finder):
# build a package in a temporary directory
mesonpy.Project(package_complex, tmp_path)

# point the meta finder to the build directory
finder = _editable.MesonpyMetaFinder({'complex'}, os.fspath(tmp_path), ['ninja'])
build_cmd = ['meson', 'compile'] if sys.platform == 'win32' else ['ninja']
finder = make_finder({'complex'}, os.fspath(tmp_path), build_cmd)

# check repr
assert repr(finder) == f'MesonpyMetaFinder({str(tmp_path)!r})'
Expand Down Expand Up @@ -99,6 +105,9 @@ def test_mesonpy_meta_finder(package_complex, tmp_path):
finally:
# remove finder from the meta path
del sys.meta_path[0]
# unload complex module and all its submodules to be able to run parametrized tests without side-effects
for module in ['complex', 'complex.test', 'complex.namespace', 'complex.namespace.foo']:
sys.modules.pop(module, None)


def test_mesonpy_traversable():
Expand Down Expand Up @@ -194,6 +203,29 @@ def test_editble_reentrant(venv, editable_imports_itself_during_build):
path.write_text(code)


@pytest.mark.skipif(tag.platform.startswith('musllinux'), reason='ninja -n segfaults on Alpine container')
def test_editable_verbose(venv, editable_complex, monkeypatch):
monkeypatch.setenv(_editable.VERBOSE, '1')
venv.pip('install', os.fspath(editable_complex))

# First import to make sure that the project is built
venv.python('-c', 'import complex')

# Second import should have no output since the project has already been built
assert venv.python('-c', 'import complex').strip() == ''

# Touch the pyx and make sure that the building info is seen
complex_package_dir = venv.python(
'-c', 'import os; import complex; print(os.path.dirname(complex.__file__))').strip()
cython_path = pathlib.Path(complex_package_dir).parent / 'test.pyx'
cython_path.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') == ''


def test_editable_pkgutils_walk_packages(package_complex, tmp_path):
# build a package in a temporary directory
mesonpy.Project(package_complex, tmp_path)
Expand Down
Loading