1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
|
# SPDX-FileCopyrightText: 2021 The meson-python developers
#
# SPDX-License-Identifier: MIT
import os
import re
import shutil
import subprocess
import sys
import textwrap
from typing import List
import packaging.requirements
import pytest
import mesonpy
@pytest.mark.parametrize('system_patchelf', ['patchelf', None], ids=['patchelf', 'nopatchelf'])
@pytest.mark.parametrize('ninja', [None, '1.8.1', '1.8.3'], ids=['noninja', 'oldninja', 'newninja'])
def test_get_requires_for_build_wheel(monkeypatch, package_pure, system_patchelf, ninja):
# the NINJA environment variable affects the ninja executable lookup and breaks the test
monkeypatch.delenv('NINJA', raising=False)
def which(prog: str) -> bool:
if prog == 'patchelf':
return system_patchelf
if prog == 'ninja':
return ninja and 'ninja'
if prog in ('ninja-build', 'samu'):
return None
# smoke check for the future if we add another usage
raise AssertionError(f'Called with {prog}, tests not expecting that usage')
subprocess_run = subprocess.run
def run(cmd: List[str], *args: object, **kwargs: object) -> subprocess.CompletedProcess:
if cmd == ['ninja', '--version']:
return subprocess.CompletedProcess(cmd, 0, f'{ninja}\n', '')
return subprocess_run(cmd, *args, **kwargs)
monkeypatch.setattr(shutil, 'which', which)
monkeypatch.setattr(subprocess, 'run', run)
expected = set()
if ninja is None or mesonpy._parse_version_string(ninja) < (1, 8, 2):
expected.add('ninja')
if system_patchelf is None and sys.platform.startswith('linux'):
expected.add('patchelf')
requirements = mesonpy.get_requires_for_build_wheel()
# Check that the requirement strings are in the correct format.
names = {packaging.requirements.Requirement(x).name for x in requirements}
assert names == expected
def test_invalid_config_settings(capsys, package_pure, tmp_path_session):
for method in mesonpy.build_sdist, mesonpy.build_wheel:
with pytest.raises(SystemExit):
method(tmp_path_session, {'invalid': ()})
out, err = capsys.readouterr()
assert 'Unknown option "invalid"' in out
def test_invalid_config_settings_suggest(capsys, package_pure, tmp_path_session):
for method in mesonpy.build_sdist, mesonpy.build_wheel:
with pytest.raises(SystemExit):
method(tmp_path_session, {'setup_args': ()})
out, err = capsys.readouterr()
assert 'Unknown option "setup_args". Did you mean "setup-args" or "dist-args"?' in out
def test_validate_config_settings_invalid():
with pytest.raises(mesonpy.ConfigError, match='Unknown option "invalid"'):
mesonpy._validate_config_settings({'invalid': ()})
def test_validate_config_settings_repeated():
with pytest.raises(mesonpy.ConfigError, match='Only one value for "builddir" can be specified'):
mesonpy._validate_config_settings({'builddir': ['one', 'two']})
def test_validate_config_settings_str():
config = mesonpy._validate_config_settings({'setup-args': '-Dfoo=true'})
assert config['setup-args'] == ['-Dfoo=true']
def test_validate_config_settings_list():
config = mesonpy._validate_config_settings({'setup-args': ['-Done=1', '-Dtwo=2']})
assert config['setup-args'] == ['-Done=1', '-Dtwo=2']
def test_validate_config_settings_tuple():
config = mesonpy._validate_config_settings({'setup-args': ('-Done=1', '-Dtwo=2')})
assert config['setup-args'] == ['-Done=1', '-Dtwo=2']
@pytest.mark.parametrize('meson', [None, 'meson'])
def test_get_meson_command(monkeypatch, meson):
# The MESON environment variable affects the meson executable lookup and breaks the test.
monkeypatch.delenv('MESON', raising=False)
assert mesonpy._get_meson_command(meson) == ['meson']
def test_get_meson_command_bad_path(monkeypatch):
# The MESON environment variable affects the meson executable lookup and breaks the test.
monkeypatch.delenv('MESON', raising=False)
with pytest.raises(mesonpy.ConfigError, match=re.escape('meson executable "bad" not found')):
mesonpy._get_meson_command('bad')
def test_get_meson_command_bad_python_path(monkeypatch):
# The MESON environment variable affects the meson executable lookup and breaks the test.
monkeypatch.delenv('MESON', raising=False)
with pytest.raises(mesonpy.ConfigError, match=re.escape('Could not find the specified meson: "bad-python-path.py"')):
mesonpy._get_meson_command('bad-python-path.py')
def test_get_meson_command_wrong_version(monkeypatch, tmp_path):
# The MESON environment variable affects the meson executable lookup and breaks the test.
monkeypatch.delenv('MESON', raising=False)
meson = tmp_path / 'meson.py'
meson.write_text(textwrap.dedent('''
print('0.0.1')
'''))
with pytest.raises(mesonpy.ConfigError, match=r'Could not find meson version [0-9\.]+ or newer, found 0\.0\.1\.'):
mesonpy._get_meson_command(os.fspath(meson))
def test_get_meson_command_error(monkeypatch, tmp_path):
# The MESON environment variable affects the meson executable lookup and breaks the test.
monkeypatch.delenv('MESON', raising=False)
meson = tmp_path / 'meson.py'
meson.write_text(textwrap.dedent('''
import sys
print('Just testing', file=sys.stderr)
sys.exit(1)
'''))
with pytest.raises(mesonpy.ConfigError, match=re.escape('Could not execute meson: Just testing')):
mesonpy._get_meson_command(os.fspath(meson))
|