fix(macos): make matching python3-config available in build/test venvs (#2922)
This commit is contained in:
+13
-1
@@ -152,6 +152,10 @@ def virtualenv(
|
||||
venv. Otherwise, pip is installed.
|
||||
"""
|
||||
|
||||
# the unresolved path, so e.g. the python.org framework bin directory is
|
||||
# used rather than the internal location of the real binary
|
||||
base_python_bin_dir = None if _IS_WIN else python.parent
|
||||
|
||||
# virtualenv may fail if this is a symlink.
|
||||
python = python.resolve()
|
||||
|
||||
@@ -189,7 +193,7 @@ def virtualenv(
|
||||
python,
|
||||
venv_path,
|
||||
)
|
||||
venv_env = activate_virtualenv(venv_path, env=env)
|
||||
venv_env = activate_virtualenv(venv_path, env=env, base_python_bin_dir=base_python_bin_dir)
|
||||
if not use_uv and pip_version == "embed":
|
||||
call(
|
||||
"python",
|
||||
@@ -208,11 +212,19 @@ def virtualenv(
|
||||
def activate_virtualenv(
|
||||
venv_path: Path,
|
||||
env: dict[str, str] | None = None,
|
||||
base_python_bin_dir: Path | None = None,
|
||||
) -> dict[str, str]:
|
||||
"""
|
||||
Return a copy of the environment with the virtualenv at `venv_path` activated.
|
||||
|
||||
If given, `base_python_bin_dir` is placed on PATH right after the venv, so
|
||||
that scripts installed alongside the base interpreter that aren't copied
|
||||
into the venv (such as python3-config, see #2021) resolve to the matching
|
||||
interpreter.
|
||||
"""
|
||||
paths = [str(venv_path), str(venv_path / "Scripts")] if _IS_WIN else [str(venv_path / "bin")]
|
||||
if base_python_bin_dir is not None:
|
||||
paths.append(str(base_python_bin_dir))
|
||||
venv_env = os.environ.copy() if env is None else env.copy()
|
||||
venv_env["PATH"] = os.pathsep.join([*paths, venv_env["PATH"]])
|
||||
venv_env["VIRTUAL_ENV"] = str(venv_path)
|
||||
|
||||
@@ -0,0 +1,60 @@
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
|
||||
import cibuildwheel.venv
|
||||
from cibuildwheel.venv import activate_virtualenv, find_uv, virtualenv
|
||||
|
||||
|
||||
def test_activate_virtualenv(tmp_path: Path) -> None:
|
||||
venv_path = tmp_path / "venv"
|
||||
env = activate_virtualenv(venv_path, env={"PATH": "/usr/bin"})
|
||||
paths = env["PATH"].split(os.pathsep)
|
||||
if sys.platform == "win32":
|
||||
assert paths[:2] == [str(venv_path), str(venv_path / "Scripts")]
|
||||
else:
|
||||
assert paths[0] == str(venv_path / "bin")
|
||||
assert paths[-1] == "/usr/bin"
|
||||
assert env["VIRTUAL_ENV"] == str(venv_path)
|
||||
|
||||
|
||||
def test_activate_virtualenv_base_python_bin_dir(tmp_path: Path) -> None:
|
||||
venv_path = tmp_path / "venv"
|
||||
base_bin = tmp_path / "base" / "bin"
|
||||
env = activate_virtualenv(venv_path, env={"PATH": "/usr/bin"}, base_python_bin_dir=base_bin)
|
||||
paths = env["PATH"].split(os.pathsep)
|
||||
# the base interpreter's bin dir comes right after the venv, so scripts
|
||||
# like python3-config resolve to the matching interpreter (see #2021)
|
||||
if sys.platform == "win32":
|
||||
assert paths[:3] == [str(venv_path), str(venv_path / "Scripts"), str(base_bin)]
|
||||
else:
|
||||
assert paths[:2] == [str(venv_path / "bin"), str(base_bin)]
|
||||
assert paths[-1] == "/usr/bin"
|
||||
|
||||
|
||||
@pytest.mark.skipif(sys.platform == "win32", reason="POSIX-only behavior")
|
||||
@pytest.mark.skipif(find_uv() is None, reason="requires uv")
|
||||
def test_virtualenv_puts_base_python_bin_dir_on_path(tmp_path: Path) -> None:
|
||||
version = "{}.{}".format(*sys.version_info[:2])
|
||||
venv_path = tmp_path / "venv"
|
||||
env = virtualenv(
|
||||
version, Path(sys.executable), venv_path, None, use_uv=True, env={"PATH": "/usr/bin"}
|
||||
)
|
||||
paths = env["PATH"].split(os.pathsep)
|
||||
assert paths == [str(venv_path / "bin"), str(Path(sys.executable).parent), "/usr/bin"]
|
||||
|
||||
|
||||
@pytest.mark.skipif(find_uv() is None, reason="requires uv")
|
||||
def test_virtualenv_no_base_python_bin_dir_on_windows(
|
||||
tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
) -> None:
|
||||
monkeypatch.setattr(cibuildwheel.venv, "_IS_WIN", True)
|
||||
version = "{}.{}".format(*sys.version_info[:2])
|
||||
venv_path = tmp_path / "venv"
|
||||
env = virtualenv(
|
||||
version, Path(sys.executable), venv_path, None, use_uv=True, env={"PATH": "/usr/bin"}
|
||||
)
|
||||
paths = env["PATH"].split(os.pathsep)
|
||||
assert str(Path(sys.executable).parent) not in paths
|
||||
Reference in New Issue
Block a user