summaryrefslogtreecommitdiff
path: root/setuptools/tests/integration
diff options
context:
space:
mode:
authorAnderson Bravalheri <andersonbravalheri@gmail.com>2021-11-13 16:33:23 +0000
committerAnderson Bravalheri <andersonbravalheri@gmail.com>2021-12-21 02:24:15 +0000
commit48361da818928e4ffe609878a93a65e9210082dd (patch)
treefb869585e39b9ae5527eb61cfabda2ac4269314d /setuptools/tests/integration
parent60dcba4c3b9f40f0dc9180bcf4f9954087ff9aad (diff)
downloadpython-setuptools-git-48361da818928e4ffe609878a93a65e9210082dd.tar.gz
Simulate pip's isolation using virtualenv
Diffstat (limited to 'setuptools/tests/integration')
-rw-r--r--setuptools/tests/integration/test_pip_install_sdist.py100
1 files changed, 49 insertions, 51 deletions
diff --git a/setuptools/tests/integration/test_pip_install_sdist.py b/setuptools/tests/integration/test_pip_install_sdist.py
index 7fbd8899..68f7f823 100644
--- a/setuptools/tests/integration/test_pip_install_sdist.py
+++ b/setuptools/tests/integration/test_pip_install_sdist.py
@@ -10,7 +10,6 @@ The number of tested packages is purposefully kept small, to minimise duration
and the associated maintenance cost (changes in the way these packages define
their build process may require changes in the tests).
"""
-import importlib
import json
import os
import subprocess
@@ -19,16 +18,17 @@ import tarfile
from enum import Enum
from glob import glob
from hashlib import md5
-from itertools import chain
from urllib.request import urlopen
from zipfile import ZipFile
import pytest
+import setuptools
from packaging.requirements import Requirement
pytestmark = pytest.mark.integration
+SETUPTOOLS_ROOT = os.path.dirname(next(iter(setuptools.__path__)))
LATEST, = list(Enum("v", "LATEST"))
"""Default version to be checked"""
@@ -55,6 +55,9 @@ EXAMPLES = [
("botocore", LATEST),
("kiwisolver", "1.3.2"), # build_ext, version pinned due to setup_requires
("brotli", LATEST), # not in the list but used by urllib3
+
+ # When adding packages to this list, make sure they expose a `__version__`
+ # attribute, or modify the tests bellow
]
@@ -66,11 +69,13 @@ EXTRA_BUILD_DEPS = {
}
+VIRTUALENV = (sys.executable, "-m", "virtualenv")
+
+
# By default, pip will try to build packages in isolation (PEP 517), which
# means it will download the previous stable version of setuptools.
# `pip` flags can avoid that (the version of setuptools under test
# should be the one to be used)
-PIP = (sys.executable, "-m", "pip")
SDIST_OPTIONS = (
"--ignore-installed",
"--no-build-isolation",
@@ -81,9 +86,14 @@ SDIST_OPTIONS = (
# dependencies. The test script will have to also handle that.
+@pytest.fixture
+def venv_python(tmp_path):
+ run_command([*VIRTUALENV, str(tmp_path / ".venv")])
+ return str(next(tmp_path.glob(".venv/*/python")))
+
+
@pytest.fixture(autouse=True)
-def _prepare(tmp_path, monkeypatch, request):
- (tmp_path / "lib").mkdir(exist_ok=True)
+def _prepare(tmp_path, venv_python, monkeypatch, request):
download_path = os.getenv("DOWNLOAD_PATH", str(tmp_path))
os.makedirs(download_path, exist_ok=True)
@@ -95,8 +105,9 @@ def _prepare(tmp_path, monkeypatch, request):
# it is necessary to debug the tests directly from the CI logs.
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print("Temporary directory:")
- for entry in chain(tmp_path.glob("*"), tmp_path.glob("lib/*")):
- print(entry)
+ map(print, tmp_path.glob("*"))
+ print("Virtual environment:")
+ run_command([venv_python, "-m", "pip", "freeze"])
request.addfinalizer(_debug_info)
@@ -104,57 +115,48 @@ ALREADY_LOADED = ("pytest", "mypy") # loaded by pytest/pytest-enabler
@pytest.mark.parametrize('package, version', EXAMPLES)
-def test_install_sdist(package, version, tmp_path, monkeypatch):
- lib = tmp_path / "lib"
+def test_install_sdist(package, version, tmp_path, venv_python):
+ venv_pip = (venv_python, "-m", "pip")
sdist = retrieve_sdist(package, version, tmp_path)
deps = build_deps(package, sdist)
if deps:
print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
print("Dependencies:", deps)
- pip_install(*deps, target=lib)
-
- pip_install(*SDIST_OPTIONS, sdist, target=lib)
+ run_command([*venv_pip, "install", *deps])
- if package in ALREADY_LOADED:
- # We cannot import packages already in use from a different location
- assert (lib / package).exists()
- return
+ # Use a virtualenv to simulate PEP 517 isolation
+ # but install setuptools to force the version under development
+ correct_setuptools = os.getenv("PROJECT_ROOT") or SETUPTOOLS_ROOT
+ assert os.path.exists(os.path.join(correct_setuptools, "pyproject.toml"))
+ run_command([*venv_pip, "install", "-Ie", correct_setuptools])
+ run_command([*venv_pip, "install", *SDIST_OPTIONS, sdist])
- # Make sure the package was installed correctly
- with monkeypatch.context() as m:
- m.syspath_prepend(str(lib)) # add installed packages to path
- pkg = importlib.import_module(package)
- if hasattr(pkg, '__version__'):
- print(pkg.__version__)
- for path in getattr(pkg, '__path__', []):
- assert os.path.abspath(path).startswith(os.path.abspath(tmp_path))
+ # Execute a simple script to make sure the package was installed correctly
+ script = f"import {package}; print(getattr({package}, '__version__', 0))"
+ run_command([venv_python, "-c", script])
# ---- Helper Functions ----
-def pip_install(*args, target):
- """Install packages in the ``target`` directory"""
- cmd = [*PIP, 'install', '--target', str(target), *args]
- env = {**os.environ, "PYTHONPATH": str(target)}
- # ^-- use libs installed in the target for build, but keep
- # compiling/build-related env variables
-
- try:
- subprocess.run(
- cmd,
- check=True,
- stdout=subprocess.PIPE,
- stderr=subprocess.PIPE,
- universal_newlines=True,
- env=env
- )
- except subprocess.CalledProcessError as ex:
- print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
- print("Command", repr(ex.cmd), "failed with code", ex.returncode)
- print(ex.stdout)
- print(ex.stderr)
- raise
+def run_command(cmd, env=None):
+ r = subprocess.run(
+ cmd,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ universal_newlines=True,
+ env={**os.environ, **(env or {})}
+ # ^-- allow overwriting instead of discarding the current env
+ )
+
+ out = r.stdout + "\n" + r.stderr
+ # pytest omits stdout/err by default, if the test fails they help debugging
+ print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")
+ print(f"Command: {cmd}\nreturn code: {r.returncode}\n\n{out}")
+
+ if r.returncode == 0:
+ return out
+ raise subprocess.CalledProcessError(r.returncode, cmd, r.stdout, r.stderr)
def retrieve_sdist(package, version, tmp_path):
@@ -212,10 +214,6 @@ def download(url, dest, md5_digest):
assert os.path.exists(dest)
-IN_TEST_VENV = ("setuptools", "wheel", "packaging")
-"""Don't re-install"""
-
-
def build_deps(package, sdist_file):
"""Find out what are the build dependencies for a package.
@@ -234,7 +232,7 @@ def build_deps(package, sdist_file):
deps += EXTRA_BUILD_DEPS.get(package, [])
# Remove setuptools from requirements (and deduplicate)
requirements = {Requirement(d).name: d for d in deps}
- return [v for k, v in requirements.items() if k not in IN_TEST_VENV]
+ return [v for k, v in requirements.items() if k != "setuptools"]
def _read_pyproject(archive):