summaryrefslogtreecommitdiffstats
path: root/tests/test_integration.py
diff options
context:
space:
mode:
Diffstat (limited to 'tests/test_integration.py')
-rw-r--r--tests/test_integration.py136
1 files changed, 136 insertions, 0 deletions
diff --git a/tests/test_integration.py b/tests/test_integration.py
new file mode 100644
index 0000000..bc2f4ff
--- /dev/null
+++ b/tests/test_integration.py
@@ -0,0 +1,136 @@
+# SPDX-License-Identifier: MIT
+
+import os
+import os.path
+import platform
+import re
+import shutil
+import subprocess
+import sys
+import tarfile
+import urllib.request
+
+import filelock
+import pytest
+
+import build.__main__
+
+
+IS_WINDOWS = sys.platform.startswith('win')
+IS_PYPY3 = platform.python_implementation() == 'PyPy'
+
+
+INTEGRATION_SOURCES = {
+ 'dateutil': ('dateutil/dateutil', '2.8.1'),
+ 'pip': ('pypa/pip', '20.2.1'),
+ 'Solaar': ('pwr-Solaar/Solaar', '1.0.3'),
+ 'flit': ('takluyver/flit', '2.3.0'),
+}
+
+_SDIST = re.compile('.*.tar.gz')
+_WHEEL = re.compile('.*.whl')
+ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
+
+
+def get_project(name, tmp_path):
+ dest = tmp_path / name
+ if name == 'build':
+ # our own project is available in-source, just ignore development files
+
+ def _ignore_folder(base, filenames):
+ ignore = [n for n in filenames if n in excl or any(n.endswith(i) for i in ('_cache', '.egg-info', '.pyc'))]
+ if os.path.basename == ROOT and 'build' in filenames: # ignore build only at root (our module is build too)
+ ignore.append('build')
+ return ignore
+
+ excl = '.tox', 'dist', '.git', '__pycache__', '.integration-sources', '.github', 'tests', 'docs'
+ shutil.copytree(ROOT, str(dest), ignore=_ignore_folder)
+ return dest
+
+ # for other projects download from github and cache it
+ tar_store = os.path.join(ROOT, '.integration-sources')
+ try:
+ os.makedirs(tar_store)
+ except OSError: # python 2 has no exist_ok, and checking with exists is not parallel safe
+ pass # just ignore, if the creation failed we will have another failure soon that will notify the user
+
+ github_org_repo, version = INTEGRATION_SOURCES[name]
+ tar_filename = f'{name}-{version}.tar.gz'
+ tarball = os.path.join(tar_store, tar_filename)
+ with filelock.FileLock(os.path.join(tar_store, f'{tar_filename}.lock')):
+ if not os.path.exists(tarball):
+ url = f'https://github.com/{github_org_repo}/archive/{version}.tar.gz'
+ with urllib.request.urlopen(url) as request, open(tarball, 'wb') as file_handler:
+ shutil.copyfileobj(request, file_handler)
+ with tarfile.open(tarball, 'r:gz') as tar_handler:
+ tar_handler.extractall(str(dest))
+ return dest / f'{name}-{version}'
+
+
+@pytest.mark.parametrize(
+ 'call',
+ [
+ None, # via code
+ [sys.executable, '-m', 'build'], # module
+ ['pyproject-build'], # entrypoint
+ ],
+ ids=['code', 'module', 'entrypoint'],
+)
+@pytest.mark.parametrize(
+ 'args',
+ [[], ['-x', '--no-isolation']],
+ ids=['isolated', 'no_isolation'],
+)
+@pytest.mark.parametrize(
+ 'project',
+ [
+ 'build',
+ 'pip',
+ 'dateutil',
+ 'Solaar',
+ 'flit',
+ ],
+)
+@pytest.mark.isolated
+def test_build(monkeypatch, project, args, call, tmp_path):
+ if project == 'flit' and '--no-isolation' in args:
+ pytest.xfail("can't build flit without isolation due to missing dependencies")
+ if project == 'Solaar' and IS_WINDOWS and IS_PYPY3:
+ pytest.xfail('Solaar fails building wheels via sdists on Windows on PyPy 3')
+
+ monkeypatch.chdir(tmp_path)
+ monkeypatch.setenv('SETUPTOOLS_SCM_PRETEND_VERSION', '0+dummy') # for the projects that use setuptools_scm
+
+ if call and call[0] == 'pyproject-build':
+ exe_name = f"pyproject-build{'.exe' if sys.platform.startswith('win') else ''}"
+ exe = os.path.join(os.path.dirname(sys.executable), exe_name)
+ if os.path.exists(exe):
+ call[0] = exe
+ else:
+ pytest.skip('Running via PYTHONPATH, so the pyproject-build entrypoint is not available')
+ path = get_project(project, tmp_path)
+ pkgs = tmp_path / 'pkgs'
+ args = [str(path), '-o', str(pkgs)] + args
+
+ if call is None:
+ build.__main__.main(args)
+ else:
+ subprocess.check_call(call + args)
+
+ pkg_names = os.listdir(str(pkgs))
+ assert list(filter(_SDIST.match, pkg_names))
+ assert list(filter(_WHEEL.match, pkg_names))
+
+
+def test_isolation(tmp_dir, package_test_flit, mocker):
+ try:
+ import flit_core # noqa: F401
+ except ModuleNotFoundError:
+ pass
+ else:
+ pytest.xfail('flit_core is available -- we want it missing!') # pragma: no cover
+
+ mocker.patch('build.__main__._error')
+
+ build.__main__.main([package_test_flit, '-o', tmp_dir, '--no-isolation'])
+ build.__main__._error.assert_called_with("Backend 'flit_core.buildapi' is not available.")