Skip to content

Commit

Permalink
tests: adapt tests for new env interface
Browse files Browse the repository at this point in the history
  • Loading branch information
layday committed Oct 24, 2021
1 parent 9044321 commit 4db81a3
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 66 deletions.
87 changes: 40 additions & 47 deletions tests/test_env.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
# SPDX-License-Identifier: MIT
import collections
import logging
import os
import platform
Expand All @@ -21,30 +20,29 @@
@pytest.mark.isolated
def test_isolation():
subprocess.check_call([sys.executable, '-c', 'import build.env'])
with build.env.IsolatedEnvBuilder() as env:
with build.env.IsolatedEnvManager() as env:
with pytest.raises(subprocess.CalledProcessError):
debug = 'import sys; import os; print(os.linesep.join(sys.path));'
subprocess.check_call([env.executable, '-c', f'{debug} import build.env'])
subprocess.check_call([env.python_executable, '-c', f'{debug} import build.env'])


@pytest.mark.isolated
def test_isolated_environment_install(mocker):
with build.env.IsolatedEnvBuilder() as env:
mocker.patch('build.env._subprocess')
with build.env.IsolatedEnvManager() as env:
mocker.patch('build.env._DefaultIsolatedEnv.run_isolated')

env.install([])
build.env._subprocess.assert_not_called()
env.install_packages([])
build.env._DefaultIsolatedEnv.run_isolated.assert_not_called()

env.install(['some', 'requirements'])
build.env._subprocess.assert_called()
args = build.env._subprocess.call_args[0][0][:-1]
env.install_packages(['some', 'requirements'])
build.env._DefaultIsolatedEnv.run_isolated.assert_called()
args = build.env._DefaultIsolatedEnv.run_isolated.call_args[0][0][:-1]
assert args == [
env.executable,
'-Im',
env.python_executable,
'-m',
'pip',
'install',
'--use-pep517',
'--no-warn-script-location',
'-r',
]

Expand All @@ -53,7 +51,7 @@ def test_isolated_environment_install(mocker):
@pytest.mark.skipif(sys.platform != 'darwin', reason='workaround for Apple Python')
def test_can_get_venv_paths_with_conflicting_default_scheme(mocker):
get_scheme_names = mocker.patch('sysconfig.get_scheme_names', return_value=('osx_framework_library',))
with build.env.IsolatedEnvBuilder():
with build.env.IsolatedEnvManager():
pass
assert get_scheme_names.call_count == 1

Expand All @@ -68,7 +66,7 @@ def _get_paths(vars): # noqa

get_paths = mocker.patch('sysconfig.get_paths', side_effect=_get_paths)
with pytest.raises(RuntimeError, match='Virtual environment creation failed, executable .* missing'):
with build.env.IsolatedEnvBuilder():
with build.env.IsolatedEnvManager():
pass
assert get_paths.call_count == 1

Expand Down Expand Up @@ -98,55 +96,50 @@ def install(self, requirements):


def test_isolated_env_log(mocker, caplog, package_test_flit):
mocker.patch('build.env._subprocess')
mocker.patch('build.env._DefaultIsolatedEnv.run_isolated')
caplog.set_level(logging.DEBUG)

builder = build.env.IsolatedEnvBuilder()
builder = build.env.IsolatedEnvManager()
builder.log('something')
with builder as env:
env.install(['something'])
env.install_packages(['something'])

assert [(record.levelname, record.message) for record in caplog.records] == [
('INFO', 'something'),
('INFO', 'Creating venv isolated environment...'),
('INFO', 'Installing packages in isolated environment... (something)'),
('INFO', 'Creating isolated environment (venv)...'),
('INFO', 'Updating pip...'),
('INFO', 'Uninstalling setuptools...'),
('INFO', 'Installing build dependencies... (something)'),
]
if sys.version_info >= (3, 8): # stacklevel
assert [(record.lineno) for record in caplog.records] == [105, 102, 193]
assert [(record.lineno) for record in caplog.records] == [103, 209, 216, 218, 239]


@pytest.mark.isolated
def test_default_pip_is_never_too_old():
with build.env.IsolatedEnvBuilder() as env:
with build.env.IsolatedEnvManager() as env:
version = subprocess.check_output(
[env.executable, '-c', 'import pip; print(pip.__version__)'], universal_newlines=True
[env.python_executable, '-c', 'import pip; print(pip.__version__)'], universal_newlines=True
).strip()
assert Version(version) >= Version('19.1')


@pytest.mark.isolated
@pytest.mark.parametrize('pip_version', ['20.2.0', '20.3.0', '21.0.0', '21.0.1'])
@pytest.mark.parametrize('arch', ['x86_64', 'arm64'])
def test_pip_needs_upgrade_mac_os_11(mocker, pip_version, arch):
SimpleNamespace = collections.namedtuple('SimpleNamespace', 'version')

_subprocess = mocker.patch('build.env._subprocess')
def test_pip_needs_upgrade_mac_os_11(mocker, arch):
_subprocess = mocker.patch('build.env._DefaultIsolatedEnv.run_isolated')
mocker.patch('platform.system', return_value='Darwin')
mocker.patch('platform.machine', return_value=arch)
mocker.patch('platform.mac_ver', return_value=('11.0', ('', '', ''), ''))
mocker.patch('build.env.metadata.distributions', return_value=(SimpleNamespace(version=pip_version),))

min_version = Version('20.3' if arch == 'x86_64' else '21.0.1')
with build.env.IsolatedEnvBuilder():
if Version(pip_version) < min_version:
print(_subprocess.call_args_list)
upgrade_call, uninstall_call = _subprocess.call_args_list
answer = 'pip>=20.3.0' if arch == 'x86_64' else 'pip>=21.0.1'
assert upgrade_call[0][0][1:] == ['-m', 'pip', 'install', answer]
assert uninstall_call[0][0][1:] == ['-m', 'pip', 'uninstall', 'setuptools', '-y']
else:
(uninstall_call,) = _subprocess.call_args_list
assert uninstall_call[0][0][1:] == ['-m', 'pip', 'uninstall', 'setuptools', '-y']
mocker.patch('platform.mac_ver', return_value=('11.0', ('', '', ''), arch))

# Cache must be cleared to rerun
build.env._get_min_pip_version.cache_clear()

with build.env.IsolatedEnvManager():
upgrade_call, uninstall_call = _subprocess.call_args_list
print(_subprocess.call_args_list)
answer = 'pip>=20.3' if arch == 'x86_64' else 'pip>=21.0.1'
assert upgrade_call[0][0][1:] == ['-m', 'pip', 'install', answer]
assert uninstall_call[0][0][1:] == ['-m', 'pip', 'uninstall', '-y', 'setuptools']


@pytest.mark.isolated
Expand All @@ -160,8 +153,8 @@ def test_venv_symlink(mocker, has_symlink):
mocker.patch('os.symlink', side_effect=OSError())

# Cache must be cleared to rerun
build.env._fs_supports_symlink.cache_clear()
supports_symlink = build.env._fs_supports_symlink()
build.env._fs_supports_symlink.cache_clear()
build.env._fs_supports_symlinks.cache_clear()
supports_symlinks = build.env._fs_supports_symlinks()
build.env._fs_supports_symlinks.cache_clear()

assert supports_symlink is has_symlink
assert supports_symlinks is has_symlink
45 changes: 27 additions & 18 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ def test_build_isolated(mocker, package_test_flit):
],
)
mocker.patch('build.__main__._error')
install = mocker.patch('build.env._IsolatedEnvVenvPip.install')
install = mocker.patch('build.env._DefaultIsolatedEnv.install_packages')

build.__main__.build_package(package_test_flit, '.', ['sdist'])

Expand Down Expand Up @@ -168,7 +168,7 @@ def test_build_no_isolation_with_check_deps(mocker, package_test_flit, missing_d
@pytest.mark.isolated
def test_build_raises_build_exception(mocker, package_test_flit):
mocker.patch('build.ProjectBuilder.get_requires_for_build', side_effect=build.BuildException)
mocker.patch('build.env._IsolatedEnvVenvPip.install')
mocker.patch('build.env._DefaultIsolatedEnv.install_packages')

with pytest.raises(build.BuildException):
build.__main__.build_package(package_test_flit, '.', ['sdist'])
Expand All @@ -177,7 +177,7 @@ def test_build_raises_build_exception(mocker, package_test_flit):
@pytest.mark.isolated
def test_build_raises_build_backend_exception(mocker, package_test_flit):
mocker.patch('build.ProjectBuilder.get_requires_for_build', side_effect=build.BuildBackendException(Exception('a')))
mocker.patch('build.env._IsolatedEnvVenvPip.install')
mocker.patch('build.env._DefaultIsolatedEnv.install_packages')

msg = f"Backend operation failed: Exception('a'{',' if sys.version_info < (3, 7) else ''})"
with pytest.raises(build.BuildBackendException, match=re.escape(msg)):
Expand Down Expand Up @@ -218,15 +218,19 @@ def test_build_package_via_sdist_invalid_distribution(tmp_dir, package_test_setu
(
[],
[
'* Creating venv isolated environment...',
'* Installing packages in isolated environment... (setuptools >= 42.0.0, wheel >= 0.36.0)',
'* Creating isolated environment (venv)...',
'* Updating pip...',
'* Uninstalling setuptools...',
'* Installing build dependencies... (setuptools >= 42.0.0, wheel >= 0.36.0)',
'* Getting dependencies for sdist...',
'* Building sdist...',
'* Building wheel from sdist',
'* Creating venv isolated environment...',
'* Installing packages in isolated environment... (setuptools >= 42.0.0, wheel >= 0.36.0)',
'* Creating isolated environment (venv)...',
'* Updating pip...',
'* Uninstalling setuptools...',
'* Installing build dependencies... (setuptools >= 42.0.0, wheel >= 0.36.0)',
'* Getting dependencies for wheel...',
'* Installing packages in isolated environment... (wheel)',
'* Installing build dependencies... (wheel)',
'* Building wheel...',
'Successfully built test_setuptools-1.0.0.tar.gz and test_setuptools-1.0.0-py2.py3-none-any.whl',
],
Expand All @@ -245,10 +249,12 @@ def test_build_package_via_sdist_invalid_distribution(tmp_dir, package_test_setu
(
['--wheel'],
[
'* Creating venv isolated environment...',
'* Installing packages in isolated environment... (setuptools >= 42.0.0, wheel >= 0.36.0)',
'* Creating isolated environment (venv)...',
'* Updating pip...',
'* Uninstalling setuptools...',
'* Installing build dependencies... (setuptools >= 42.0.0, wheel >= 0.36.0)',
'* Getting dependencies for wheel...',
'* Installing packages in isolated environment... (wheel)',
'* Installing build dependencies... (wheel)',
'* Building wheel...',
'Successfully built test_setuptools-1.0.0-py2.py3-none-any.whl',
],
Expand Down Expand Up @@ -285,7 +291,7 @@ def test_build_package_via_sdist_invalid_distribution(tmp_dir, package_test_setu
'sdist-and-wheel-direct-no-isolation',
],
)
@pytest.mark.flaky(reruns=5)
# @pytest.mark.flaky(reruns=5)
def test_output(package_test_setuptools, tmp_dir, capsys, args, output):
build.__main__.main([package_test_setuptools, '-o', tmp_dir] + args)
stdout, stderr = capsys.readouterr()
Expand All @@ -307,8 +313,10 @@ def main_reload_styles():
False,
'ERROR ',
[
'* Creating venv isolated environment...',
'* Installing packages in isolated environment... (setuptools >= 42.0.0, this is invalid, wheel >= 0.36.0)',
'* Creating isolated environment (venv)...',
'* Updating pip...',
'* Uninstalling setuptools...',
'* Installing build dependencies... (setuptools >= 42.0.0, this is invalid, wheel >= 0.36.0)',
'',
'Traceback (most recent call last):',
],
Expand All @@ -317,9 +325,10 @@ def main_reload_styles():
True,
'\33[91mERROR\33[0m ',
[
'\33[1m* Creating venv isolated environment...\33[0m',
'\33[1m* Installing packages in isolated environment... '
'(setuptools >= 42.0.0, this is invalid, wheel >= 0.36.0)\33[0m',
'\33[1m* Creating isolated environment (venv)...\33[0m',
'\33[1m* Updating pip...\33[0m',
'\33[1m* Uninstalling setuptools...\33[0m',
'\33[1m* Installing build dependencies... ' '(setuptools >= 42.0.0, this is invalid, wheel >= 0.36.0)\33[0m',
'',
'\33[2mTraceback (most recent call last):',
],
Expand Down Expand Up @@ -354,7 +363,7 @@ def test_output_env_subprocess_error(
stdout, stderr = capsys.readouterr()
stdout, stderr = stdout.splitlines(), stderr.splitlines()

assert stdout[:4] == stdout_body
assert stdout[:6] == stdout_body
assert stdout[-1].startswith(stdout_error)

assert len(stderr) == 1
Expand Down
2 changes: 1 addition & 1 deletion tests/test_projectbuilder.py
Original file line number Diff line number Diff line change
Expand Up @@ -356,7 +356,7 @@ def test_build_not_dir_outdir(mocker, tmp_dir, package_test_flit):
def demo_pkg_inline(tmp_path_factory):
# builds a wheel without any dependencies and with a console script demo-pkg-inline
tmp_path = tmp_path_factory.mktemp('demo-pkg-inline')
builder = build.ProjectBuilder(srcdir=os.path.join(os.path.dirname(__file__), 'packages', 'inline'))
builder = build.ProjectBuilder(source_dir=os.path.join(os.path.dirname(__file__), 'packages', 'inline'))
out = tmp_path / 'dist'
builder.build('wheel', str(out))
return next(out.iterdir())
Expand Down

0 comments on commit 4db81a3

Please sign in to comment.