refactor: Use utils.call & utils.shell in macos.py & windows.py (#978)

This commit is contained in:
Matthieu Darbois
2022-01-05 02:59:24 +01:00
committed by GitHub
parent 73b7de0a75
commit 9e18cb8656
3 changed files with 196 additions and 206 deletions
+69 -108
View File
@@ -1,13 +1,12 @@
import os import os
import platform import platform
import re import re
import shlex
import shutil import shutil
import subprocess import subprocess
import sys import sys
import tempfile import tempfile
from pathlib import Path from pathlib import Path
from typing import Any, Dict, List, NamedTuple, Optional, Sequence, Set, Tuple, cast from typing import Any, Dict, List, NamedTuple, Sequence, Set, Tuple, cast
from .architecture import Architecture from .architecture import Architecture
from .environment import ParsedEnvironment from .environment import ParsedEnvironment
@@ -18,31 +17,18 @@ from .util import (
BuildFrontend, BuildFrontend,
BuildSelector, BuildSelector,
NonPlatformWheelError, NonPlatformWheelError,
call,
download, download,
get_build_verbosity_extra_flags, get_build_verbosity_extra_flags,
get_pip_version, get_pip_version,
install_certifi_script, install_certifi_script,
prepare_command, prepare_command,
read_python_configs, read_python_configs,
shell,
unwrap, unwrap,
) )
def call(
args: Sequence[PathOrStr],
env: Optional[Dict[str, str]] = None,
cwd: Optional[str] = None,
shell: bool = False,
) -> None:
# print the command executing for the logs
if shell:
print(f"+ {args}")
else:
print("+ " + " ".join(shlex.quote(str(a)) for a in args))
subprocess.run(args, env=env, cwd=cwd, shell=shell, check=True)
def get_macos_version() -> Tuple[int, int]: def get_macos_version() -> Tuple[int, int]:
""" """
Returns the macOS major/minor version, as a tuple, e.g. (10, 15) or (11, 0) Returns the macOS major/minor version, as a tuple, e.g. (10, 15) or (11, 0)
@@ -58,13 +44,7 @@ def get_macos_version() -> Tuple[int, int]:
def get_macos_sdks() -> List[str]: def get_macos_sdks() -> List[str]:
output = subprocess.run( output = call("xcodebuild", "-showsdks", capture_stdout=True)
["xcodebuild", "-showsdks"],
universal_newlines=True,
check=True,
stdout=subprocess.PIPE,
).stdout
return [m.group(1) for m in re.finditer(r"-sdk (macosx\S+)", output)] return [m.group(1) for m in re.finditer(r"-sdk (macosx\S+)", output)]
@@ -114,9 +94,7 @@ def make_symlinks(installation_bin_path: Path, python_executable: str, pip_execu
def install_cpython(version: str, url: str) -> Path: def install_cpython(version: str, url: str) -> Path:
installed_system_packages = subprocess.run( installed_system_packages = call("pkgutil", "--pkgs", capture_stdout=True).splitlines()
["pkgutil", "--pkgs"], universal_newlines=True, check=True, stdout=subprocess.PIPE
).stdout.splitlines()
# if this version of python isn't installed, get it from python.org and install # if this version of python isn't installed, get it from python.org and install
python_package_identifier = f"org.python.Python.PythonFramework-{version}" python_package_identifier = f"org.python.Python.PythonFramework-{version}"
@@ -127,10 +105,10 @@ def install_cpython(version: str, url: str) -> Path:
# download the pkg # download the pkg
download(url, Path("/tmp/Python.pkg")) download(url, Path("/tmp/Python.pkg"))
# install # install
call(["sudo", "installer", "-pkg", "/tmp/Python.pkg", "-target", "/"]) call("sudo", "installer", "-pkg", "/tmp/Python.pkg", "-target", "/")
env = os.environ.copy() env = os.environ.copy()
env["PIP_DISABLE_PIP_VERSION_CHECK"] = "1" env["PIP_DISABLE_PIP_VERSION_CHECK"] = "1"
call([str(installation_bin_path / python_executable), str(install_certifi_script)], env=env) call(str(installation_bin_path / python_executable), str(install_certifi_script), env=env)
pip_executable = "pip3" pip_executable = "pip3"
make_symlinks(installation_bin_path, python_executable, pip_executable) make_symlinks(installation_bin_path, python_executable, pip_executable)
@@ -147,7 +125,7 @@ def install_pypy(version: str, url: str) -> Path:
if not installation_path.exists(): if not installation_path.exists():
downloaded_tar_bz2 = Path("/tmp") / pypy_tar_bz2 downloaded_tar_bz2 = Path("/tmp") / pypy_tar_bz2
download(url, downloaded_tar_bz2) download(url, downloaded_tar_bz2)
call(["tar", "-C", "/tmp", "-xf", downloaded_tar_bz2]) call("tar", "-C", "/tmp", "-xf", downloaded_tar_bz2)
installation_bin_path = installation_path / "bin" installation_bin_path = installation_path / "bin"
python_executable = "pypy3" python_executable = "pypy3"
@@ -203,20 +181,18 @@ def setup_python(
requires_reinstall = not (installation_bin_path / "pip").exists() requires_reinstall = not (installation_bin_path / "pip").exists()
if requires_reinstall: if requires_reinstall:
# maybe pip isn't installed at all. ensurepip resolves that. # maybe pip isn't installed at all. ensurepip resolves that.
call(["python", "-m", "ensurepip"], env=env, cwd="/tmp") call("python", "-m", "ensurepip", env=env, cwd="/tmp")
# upgrade pip to the version matching our constraints # upgrade pip to the version matching our constraints
# if necessary, reinstall it to ensure that it's available on PATH as 'pip' # if necessary, reinstall it to ensure that it's available on PATH as 'pip'
call( call(
[ "python",
"python", "-m",
"-m", "pip",
"pip", "install",
"install", "--force-reinstall" if requires_reinstall else "--upgrade",
"--force-reinstall" if requires_reinstall else "--upgrade", "pip",
"pip", *dependency_constraint_flags,
*dependency_constraint_flags,
],
env=env, env=env,
cwd="/tmp", cwd="/tmp",
) )
@@ -226,11 +202,9 @@ def setup_python(
# check what pip version we're on # check what pip version we're on
assert (installation_bin_path / "pip").exists() assert (installation_bin_path / "pip").exists()
call(["which", "pip"], env=env) call("which", "pip", env=env)
call(["pip", "--version"], env=env) call("pip", "--version", env=env)
which_pip = subprocess.run( which_pip = call("which", "pip", env=env, capture_stdout=True).strip()
["which", "pip"], env=env, universal_newlines=True, check=True, stdout=subprocess.PIPE
).stdout.strip()
if which_pip != "/tmp/cibw_bin/pip": if which_pip != "/tmp/cibw_bin/pip":
print( print(
"cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it.", "cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it.",
@@ -239,11 +213,9 @@ def setup_python(
sys.exit(1) sys.exit(1)
# check what Python version we're on # check what Python version we're on
call(["which", "python"], env=env) call("which", "python", env=env)
call(["python", "--version"], env=env) call("python", "--version", env=env)
which_python = subprocess.run( which_python = call("which", "python", env=env, capture_stdout=True).strip()
["which", "python"], env=env, universal_newlines=True, check=True, stdout=subprocess.PIPE
).stdout.strip()
if which_python != "/tmp/cibw_bin/python": if which_python != "/tmp/cibw_bin/python":
print( print(
"cibuildwheel: python available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it.", "cibuildwheel: python available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it.",
@@ -298,27 +270,23 @@ def setup_python(
log.step("Installing build tools...") log.step("Installing build tools...")
if build_frontend == "pip": if build_frontend == "pip":
call( call(
[ "pip",
"pip", "install",
"install", "--upgrade",
"--upgrade", "setuptools",
"setuptools", "wheel",
"wheel", "delocate",
"delocate", *dependency_constraint_flags,
*dependency_constraint_flags,
],
env=env, env=env,
) )
elif build_frontend == "build": elif build_frontend == "build":
call( call(
[ "pip",
"pip", "install",
"install", "--upgrade",
"--upgrade", "delocate",
"delocate", "build[virtualenv]",
"build[virtualenv]", *dependency_constraint_flags,
*dependency_constraint_flags,
],
env=env, env=env,
) )
else: else:
@@ -347,7 +315,7 @@ def build(options: Options) -> None:
before_all_prepared = prepare_command( before_all_prepared = prepare_command(
before_all_options.before_all, project=".", package=before_all_options.package_dir before_all_options.before_all, project=".", package=before_all_options.package_dir
) )
call([before_all_prepared], shell=True, env=env) shell(before_all_prepared, env=env)
for config in python_configurations: for config in python_configurations:
build_options = options.build_options(config.identifier) build_options = options.build_options(config.identifier)
@@ -375,7 +343,7 @@ def build(options: Options) -> None:
before_build_prepared = prepare_command( before_build_prepared = prepare_command(
build_options.before_build, project=".", package=build_options.package_dir build_options.before_build, project=".", package=build_options.package_dir
) )
call(before_build_prepared, env=env, shell=True) shell(before_build_prepared, env=env)
log.step("Building wheel...") log.step("Building wheel...")
if built_wheel_dir.exists(): if built_wheel_dir.exists():
@@ -388,16 +356,14 @@ def build(options: Options) -> None:
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org # Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
# see https://github.com/pypa/cibuildwheel/pull/369 # see https://github.com/pypa/cibuildwheel/pull/369
call( call(
[ "python",
"python", "-m",
"-m", "pip",
"pip", "wheel",
"wheel", build_options.package_dir.resolve(),
build_options.package_dir.resolve(), f"--wheel-dir={built_wheel_dir}",
f"--wheel-dir={built_wheel_dir}", "--no-deps",
"--no-deps", *verbosity_flags,
*verbosity_flags,
],
env=env, env=env,
) )
elif build_options.build_frontend == "build": elif build_options.build_frontend == "build":
@@ -410,15 +376,13 @@ def build(options: Options) -> None:
build_env["PIP_CONSTRAINT"] = constraint_path.as_uri() build_env["PIP_CONSTRAINT"] = constraint_path.as_uri()
build_env["VIRTUALENV_PIP"] = get_pip_version(env) build_env["VIRTUALENV_PIP"] = get_pip_version(env)
call( call(
[ "python",
"python", "-m",
"-m", "build",
"build", build_options.package_dir,
build_options.package_dir, "--wheel",
"--wheel", f"--outdir={built_wheel_dir}",
f"--outdir={built_wheel_dir}", f"--config-setting={config_setting}",
f"--config-setting={config_setting}",
],
env=build_env, env=build_env,
) )
else: else:
@@ -449,7 +413,7 @@ def build(options: Options) -> None:
dest_dir=repaired_wheel_dir, dest_dir=repaired_wheel_dir,
delocate_archs=delocate_archs, delocate_archs=delocate_archs,
) )
call(repair_command_prepared, env=env, shell=True) shell(repair_command_prepared, env=env)
else: else:
shutil.move(str(built_wheel), repaired_wheel_dir) shutil.move(str(built_wheel), repaired_wheel_dir)
@@ -514,7 +478,7 @@ def build(options: Options) -> None:
# set up a virtual environment to install and test from, to make sure # set up a virtual environment to install and test from, to make sure
# there are no dependencies that were pulled in at build time. # there are no dependencies that were pulled in at build time.
call(["pip", "install", "virtualenv", *dependency_constraint_flags], env=env) call("pip", "install", "virtualenv", *dependency_constraint_flags, env=env)
venv_dir = Path(tempfile.mkdtemp()) venv_dir = Path(tempfile.mkdtemp())
arch_prefix = [] arch_prefix = []
@@ -528,18 +492,16 @@ def build(options: Options) -> None:
) )
# define a custom 'call' function that adds the arch prefix each time # define a custom 'call' function that adds the arch prefix each time
def call_with_arch(args: Sequence[PathOrStr], **kwargs: Any) -> None: def call_with_arch(*args: PathOrStr, **kwargs: Any) -> None:
if isinstance(args, str): call(*arch_prefix, *args, **kwargs)
args = " ".join(arch_prefix) + " " + args
else: def shell_with_arch(command: str, **kwargs: Any) -> None:
args = [*arch_prefix, *args] command = " ".join(arch_prefix) + " " + command
call(args, **kwargs) shell(command, **kwargs)
# Use --no-download to ensure determinism by using seed libraries # Use --no-download to ensure determinism by using seed libraries
# built into virtualenv # built into virtualenv
call_with_arch( call_with_arch("python", "-m", "virtualenv", "--no-download", venv_dir, env=env)
["python", "-m", "virtualenv", "--no-download", venv_dir], env=env
)
virtualenv_env = env.copy() virtualenv_env = env.copy()
virtualenv_env["PATH"] = os.pathsep.join( virtualenv_env["PATH"] = os.pathsep.join(
@@ -550,7 +512,7 @@ def build(options: Options) -> None:
) )
# check that we are using the Python from the virtual environment # check that we are using the Python from the virtual environment
call_with_arch(["which", "python"], env=virtualenv_env) call_with_arch("which", "python", env=virtualenv_env)
if build_options.before_test: if build_options.before_test:
before_test_prepared = prepare_command( before_test_prepared = prepare_command(
@@ -558,18 +520,20 @@ def build(options: Options) -> None:
project=".", project=".",
package=build_options.package_dir, package=build_options.package_dir,
) )
call_with_arch(before_test_prepared, env=virtualenv_env, shell=True) shell_with_arch(before_test_prepared, env=virtualenv_env)
# install the wheel # install the wheel
call_with_arch( call_with_arch(
["pip", "install", f"{repaired_wheel}{build_options.test_extras}"], "pip",
"install",
f"{repaired_wheel}{build_options.test_extras}",
env=virtualenv_env, env=virtualenv_env,
) )
# test the wheel # test the wheel
if build_options.test_requires: if build_options.test_requires:
call_with_arch( call_with_arch(
["pip", "install"] + build_options.test_requires, env=virtualenv_env "pip", "install", *build_options.test_requires, env=virtualenv_env
) )
# run the tests from $HOME, with an absolute path in the command # run the tests from $HOME, with an absolute path in the command
@@ -580,11 +544,8 @@ def build(options: Options) -> None:
project=Path(".").resolve(), project=Path(".").resolve(),
package=build_options.package_dir.resolve(), package=build_options.package_dir.resolve(),
) )
call_with_arch( shell_with_arch(
test_command_prepared, test_command_prepared, cwd=os.environ["HOME"], env=virtualenv_env
cwd=os.environ["HOME"],
env=virtualenv_env,
shell=True,
) )
# clean up # clean up
+69 -6
View File
@@ -3,6 +3,7 @@ import fnmatch
import itertools import itertools
import os import os
import re import re
import shlex
import ssl import ssl
import subprocess import subprocess
import sys import sys
@@ -12,7 +13,18 @@ import urllib.request
from enum import Enum from enum import Enum
from pathlib import Path from pathlib import Path
from time import sleep from time import sleep
from typing import Any, Dict, Iterable, Iterator, List, NamedTuple, Optional, TextIO from typing import (
Any,
Dict,
Iterable,
Iterator,
List,
NamedTuple,
Optional,
TextIO,
cast,
overload,
)
import bracex import bracex
import certifi import certifi
@@ -47,6 +59,60 @@ MUSLLINUX_ARCHS = (
"s390x", "s390x",
) )
IS_WIN = sys.platform.startswith("win")
@overload
def call(
*args: PathOrStr,
env: Optional[Dict[str, str]] = None,
cwd: Optional[PathOrStr] = None,
capture_stdout: Literal[False] = ...,
) -> None:
...
@overload
def call(
*args: PathOrStr,
env: Optional[Dict[str, str]] = None,
cwd: Optional[PathOrStr] = None,
capture_stdout: Literal[True],
) -> str:
...
def call(
*args: PathOrStr,
env: Optional[Dict[str, str]] = None,
cwd: Optional[PathOrStr] = None,
capture_stdout: bool = False,
) -> Optional[str]:
"""
Run subprocess.run, but print the commands first. Takes the commands as
*args. Uses shell=True on Windows due to a bug. Also converts to
Paths to strings, due to Windows behavior at least on older Pythons.
https://bugs.python.org/issue8557
"""
args_ = [str(arg) for arg in args]
# print the command executing for the logs
print("+ " + " ".join(shlex.quote(a) for a in args_))
kwargs: Dict[str, Any] = {}
if capture_stdout:
kwargs["universal_newlines"] = True
kwargs["stdout"] = subprocess.PIPE
result = subprocess.run(args_, check=True, shell=IS_WIN, env=env, cwd=cwd, **kwargs)
if not capture_stdout:
return None
return cast(str, result.stdout)
def shell(
command: str, env: Optional[Dict[str, str]] = None, cwd: Optional[PathOrStr] = None
) -> None:
print(f"+ {command}")
subprocess.run(command, env=env, cwd=cwd, shell=True, check=True)
def format_safe(template: str, **kwargs: Any) -> str: def format_safe(template: str, **kwargs: Any) -> str:
""" """
@@ -376,11 +442,8 @@ def print_new_wheels(msg: str, output_dir: Path) -> Iterator[None]:
def get_pip_version(env: Dict[str, str]) -> str: def get_pip_version(env: Dict[str, str]) -> str:
# we use shell=True here for windows, even though we don't need a shell due to a bug versions_output_text = call(
# https://bugs.python.org/issue8557 "python", "-m", "pip", "freeze", "--all", capture_stdout=True, env=env
shell = sys.platform.startswith("win")
versions_output_text = subprocess.check_output(
["python", "-m", "pip", "freeze", "--all"], universal_newlines=True, shell=shell, env=env
) )
(pip_version,) = ( (pip_version,) = (
version[5:] version[5:]
+58 -92
View File
@@ -18,32 +18,18 @@ from .util import (
BuildFrontend, BuildFrontend,
BuildSelector, BuildSelector,
NonPlatformWheelError, NonPlatformWheelError,
call,
download, download,
get_build_verbosity_extra_flags, get_build_verbosity_extra_flags,
get_pip_version, get_pip_version,
prepare_command, prepare_command,
read_python_configs, read_python_configs,
shell,
) )
CIBW_INSTALL_PATH = Path("C:\\cibw") CIBW_INSTALL_PATH = Path("C:\\cibw")
def call(
args: Sequence[PathOrStr], env: Optional[Dict[str, str]] = None, cwd: Optional[PathOrStr] = None
) -> None:
print("+ " + " ".join(str(a) for a in args))
# we use shell=True here, even though we don't need a shell due to a bug
# https://bugs.python.org/issue8557
subprocess.run([str(a) for a in args], env=env, cwd=cwd, shell=True, check=True)
def shell(
command: str, env: Optional[Dict[str, str]] = None, cwd: Optional[PathOrStr] = None
) -> None:
print(f"+ {command}")
subprocess.run(command, env=env, cwd=cwd, shell=True, check=True)
def get_nuget_args(version: str, arch: str) -> List[str]: def get_nuget_args(version: str, arch: str) -> List[str]:
platform_suffix = {"32": "x86", "64": "", "ARM64": "arm64"} platform_suffix = {"32": "x86", "64": "", "ARM64": "arm64"}
python_name = "python" + platform_suffix[arch] python_name = "python" + platform_suffix[arch]
@@ -94,7 +80,7 @@ def extract_zip(zip_src: Path, dest: Path) -> None:
def install_cpython(version: str, arch: str, nuget: Path) -> Path: def install_cpython(version: str, arch: str, nuget: Path) -> Path:
nuget_args = get_nuget_args(version, arch) nuget_args = get_nuget_args(version, arch)
installation_path = Path(nuget_args[-1]) / (nuget_args[0] + "." + version) / "tools" installation_path = Path(nuget_args[-1]) / (nuget_args[0] + "." + version) / "tools"
call([nuget, "install", *nuget_args]) call(nuget, "install", *nuget_args)
# "python3" is not included in the vanilla nuget package, # "python3" is not included in the vanilla nuget package,
# though it can be present if modified (like on Azure). # though it can be present if modified (like on Azure).
if not (installation_path / "python3.exe").exists(): if not (installation_path / "python3.exe").exists():
@@ -165,7 +151,7 @@ def setup_python(
if requires_reinstall: if requires_reinstall:
# maybe pip isn't installed at all. ensurepip resolves that. # maybe pip isn't installed at all. ensurepip resolves that.
call(["python", "-m", "ensurepip"], env=env, cwd=CIBW_INSTALL_PATH) call("python", "-m", "ensurepip", env=env, cwd=CIBW_INSTALL_PATH)
# pip older than 21.3 builds executables such as pip.exe for x64 platform. # pip older than 21.3 builds executables such as pip.exe for x64 platform.
# The first re-install of pip updates pip module but builds pip.exe using # The first re-install of pip updates pip module but builds pip.exe using
@@ -175,16 +161,14 @@ def setup_python(
# pip versions newer than 21.3. # pip versions newer than 21.3.
if python_configuration.arch == "ARM64" and Version(get_pip_version(env)) < Version("21.3"): if python_configuration.arch == "ARM64" and Version(get_pip_version(env)) < Version("21.3"):
call( call(
[ "python",
"python", "-m",
"-m", "pip",
"pip", "install",
"install", "--force-reinstall",
"--force-reinstall", "--upgrade",
"--upgrade", "pip",
"pip", *dependency_constraint_flags,
*dependency_constraint_flags,
],
env=env, env=env,
cwd=CIBW_INSTALL_PATH, cwd=CIBW_INSTALL_PATH,
) )
@@ -192,15 +176,13 @@ def setup_python(
# upgrade pip to the version matching our constraints # upgrade pip to the version matching our constraints
# if necessary, reinstall it to ensure that it's available on PATH as 'pip.exe' # if necessary, reinstall it to ensure that it's available on PATH as 'pip.exe'
call( call(
[ "python",
"python", "-m",
"-m", "pip",
"pip", "install",
"install", "--force-reinstall" if requires_reinstall else "--upgrade",
"--force-reinstall" if requires_reinstall else "--upgrade", "pip",
"pip", *dependency_constraint_flags,
*dependency_constraint_flags,
],
env=env, env=env,
cwd=CIBW_INSTALL_PATH, cwd=CIBW_INSTALL_PATH,
) )
@@ -209,20 +191,10 @@ def setup_python(
env = environment.as_dictionary(prev_environment=env) env = environment.as_dictionary(prev_environment=env)
# check what Python version we're on # check what Python version we're on
call(["where", "python"], env=env) call("where", "python", env=env)
call(["python", "--version"], env=env) call("python", "--version", env=env)
call(["python", "-c", "\"import struct; print(struct.calcsize('P') * 8)\""], env=env) call("python", "-c", "\"import struct; print(struct.calcsize('P') * 8)\"", env=env)
where_python = ( where_python = call("where", "python", env=env, capture_stdout=True).splitlines()[0].strip()
subprocess.run(
["where", "python"],
env=env,
universal_newlines=True,
check=True,
stdout=subprocess.PIPE,
)
.stdout.splitlines()[0]
.strip()
)
if where_python != str(installation_path / "python.exe"): if where_python != str(installation_path / "python.exe"):
print( print(
"cibuildwheel: python available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it.", "cibuildwheel: python available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert python above it.",
@@ -232,13 +204,7 @@ def setup_python(
# check what pip version we're on # check what pip version we're on
assert (installation_path / "Scripts" / "pip.exe").exists() assert (installation_path / "Scripts" / "pip.exe").exists()
where_pip = ( where_pip = call("where", "pip", env=env, capture_stdout=True).splitlines()[0].strip()
subprocess.run(
["where", "pip"], env=env, universal_newlines=True, check=True, stdout=subprocess.PIPE
)
.stdout.splitlines()[0]
.strip()
)
if where_pip.strip() != str(installation_path / "Scripts" / "pip.exe"): if where_pip.strip() != str(installation_path / "Scripts" / "pip.exe"):
print( print(
"cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it.", "cibuildwheel: pip available on PATH doesn't match our installed instance. If you have modified PATH, ensure that you don't overwrite cibuildwheel's entry or insert pip above it.",
@@ -246,23 +212,25 @@ def setup_python(
) )
sys.exit(1) sys.exit(1)
call(["pip", "--version"], env=env) call("pip", "--version", env=env)
if build_frontend == "pip": if build_frontend == "pip":
call( call(
[ "pip",
"pip", "install",
"install", "--upgrade",
"--upgrade", "setuptools",
"setuptools", "wheel",
"wheel", *dependency_constraint_flags,
*dependency_constraint_flags,
],
env=env, env=env,
) )
elif build_frontend == "build": elif build_frontend == "build":
call( call(
["pip", "install", "--upgrade", "build[virtualenv]", *dependency_constraint_flags], "pip",
"install",
"--upgrade",
"build[virtualenv]",
*dependency_constraint_flags,
env=env, env=env,
) )
else: else:
@@ -330,16 +298,14 @@ def build(options: Options) -> None:
# Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org # Path.resolve() is needed. Without it pip wheel may try to fetch package from pypi.org
# see https://github.com/pypa/cibuildwheel/pull/369 # see https://github.com/pypa/cibuildwheel/pull/369
call( call(
[ "python",
"python", "-m",
"-m", "pip",
"pip", "wheel",
"wheel", options.globals.package_dir.resolve(),
options.globals.package_dir.resolve(), f"--wheel-dir={built_wheel_dir}",
f"--wheel-dir={built_wheel_dir}", "--no-deps",
"--no-deps", *get_build_verbosity_extra_flags(build_options.build_verbosity),
*get_build_verbosity_extra_flags(build_options.build_verbosity),
],
env=env, env=env,
) )
elif build_options.build_frontend == "build": elif build_options.build_frontend == "build":
@@ -364,15 +330,13 @@ def build(options: Options) -> None:
build_env["PIP_CONSTRAINT"] = str(constraints_path) build_env["PIP_CONSTRAINT"] = str(constraints_path)
build_env["VIRTUALENV_PIP"] = get_pip_version(env) build_env["VIRTUALENV_PIP"] = get_pip_version(env)
call( call(
[ "python",
"python", "-m",
"-m", "build",
"build", build_options.package_dir,
build_options.package_dir, "--wheel",
"--wheel", f"--outdir={built_wheel_dir}",
f"--outdir={built_wheel_dir}", f"--config-setting={config_setting}",
f"--config-setting={config_setting}",
],
env=build_env, env=build_env,
) )
else: else:
@@ -403,12 +367,12 @@ def build(options: Options) -> None:
log.step("Testing wheel...") log.step("Testing wheel...")
# set up a virtual environment to install and test from, to make sure # set up a virtual environment to install and test from, to make sure
# there are no dependencies that were pulled in at build time. # there are no dependencies that were pulled in at build time.
call(["pip", "install", "virtualenv", *dependency_constraint_flags], env=env) call("pip", "install", "virtualenv", *dependency_constraint_flags, env=env)
venv_dir = Path(tempfile.mkdtemp()) venv_dir = Path(tempfile.mkdtemp())
# Use --no-download to ensure determinism by using seed libraries # Use --no-download to ensure determinism by using seed libraries
# built into virtualenv # built into virtualenv
call(["python", "-m", "virtualenv", "--no-download", venv_dir], env=env) call("python", "-m", "virtualenv", "--no-download", venv_dir, env=env)
virtualenv_env = env.copy() virtualenv_env = env.copy()
virtualenv_env["PATH"] = os.pathsep.join( virtualenv_env["PATH"] = os.pathsep.join(
@@ -419,7 +383,7 @@ def build(options: Options) -> None:
) )
# check that we are using the Python from the virtual environment # check that we are using the Python from the virtual environment
call(["where", "python"], env=virtualenv_env) call("where", "python", env=virtualenv_env)
if build_options.before_test: if build_options.before_test:
before_test_prepared = prepare_command( before_test_prepared = prepare_command(
@@ -431,13 +395,15 @@ def build(options: Options) -> None:
# install the wheel # install the wheel
call( call(
["pip", "install", str(repaired_wheel) + build_options.test_extras], "pip",
"install",
str(repaired_wheel) + build_options.test_extras,
env=virtualenv_env, env=virtualenv_env,
) )
# test the wheel # test the wheel
if build_options.test_requires: if build_options.test_requires:
call(["pip", "install"] + build_options.test_requires, env=virtualenv_env) call("pip", "install", *build_options.test_requires, env=virtualenv_env)
# run the tests from c:\, with an absolute path in the command # run the tests from c:\, with an absolute path in the command
# (this ensures that Python runs the tests against the installed wheel # (this ensures that Python runs the tests against the installed wheel