1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
|
from __future__ import annotations
import pytest
from testing.helpers import contains_exe, contains_ref, has_src, is_exe
from testing.path import join as path
from virtualenv.create.via_global_ref.builtin.cpython.cpython3 import CPython3Windows
CPYTHON3_PATH = (
"virtualenv.create.via_global_ref.builtin.cpython.common.Path",
"virtualenv.create.via_global_ref.builtin.cpython.cpython3.Path",
)
@pytest.mark.parametrize("py_info_name", ["cpython3_win_embed"])
def test_2_exe_on_default_py_host(py_info, mock_files):
mock_files(CPYTHON3_PATH, [py_info.system_executable])
sources = tuple(CPython3Windows.sources(interpreter=py_info))
# Default Python exe.
assert contains_exe(sources, py_info.system_executable)
# Should always exist.
assert contains_exe(sources, path(py_info.prefix, "pythonw.exe"))
@pytest.mark.parametrize("py_info_name", ["cpython3_win_embed"])
def test_3_exe_on_not_default_py_host(py_info, mock_files):
# Not default python host.
py_info.system_executable = path(py_info.prefix, "python666.exe")
mock_files(CPYTHON3_PATH, [py_info.system_executable])
sources = tuple(CPython3Windows.sources(interpreter=py_info))
# Not default Python exe linked to both the default name and origin.
assert contains_exe(sources, py_info.system_executable, "python.exe")
assert contains_exe(sources, py_info.system_executable, "python666.exe")
# Should always exist.
assert contains_exe(sources, path(py_info.prefix, "pythonw.exe"))
@pytest.mark.parametrize("py_info_name", ["cpython3_win_embed"])
def test_only_shim(py_info, mock_files):
shim = path(py_info.system_stdlib, "venv\\scripts\\nt\\python.exe")
py_files = (
path(py_info.prefix, "libcrypto-1_1.dll"),
path(py_info.prefix, "libffi-7.dll"),
path(py_info.prefix, "_asyncio.pyd"),
path(py_info.prefix, "_bz2.pyd"),
)
mock_files(CPYTHON3_PATH, [shim, *py_files])
sources = tuple(CPython3Windows.sources(interpreter=py_info))
assert CPython3Windows.has_shim(interpreter=py_info)
assert contains_exe(sources, shim)
assert not contains_exe(sources, py_info.system_executable)
for file in py_files:
assert not contains_ref(sources, file)
@pytest.mark.parametrize("py_info_name", ["cpython3_win_embed"])
def test_exe_dll_pyd_without_shim(py_info, mock_files):
py_files = (
path(py_info.prefix, "libcrypto-1_1.dll"),
path(py_info.prefix, "libffi-7.dll"),
path(py_info.prefix, "_asyncio.pyd"),
path(py_info.prefix, "_bz2.pyd"),
)
mock_files(CPYTHON3_PATH, py_files)
sources = tuple(CPython3Windows.sources(interpreter=py_info))
assert not CPython3Windows.has_shim(interpreter=py_info)
assert contains_exe(sources, py_info.system_executable)
for file in py_files:
assert contains_ref(sources, file)
@pytest.mark.parametrize("py_info_name", ["cpython3_win_embed"])
def test_python_zip_if_exists_and_set_in_path(py_info, mock_files):
python_zip_name = f"python{py_info.version_nodot}.zip"
python_zip = path(py_info.prefix, python_zip_name)
mock_files(CPYTHON3_PATH, [python_zip])
sources = tuple(CPython3Windows.sources(interpreter=py_info))
assert python_zip in py_info.path
assert contains_ref(sources, python_zip)
@pytest.mark.parametrize("py_info_name", ["cpython3_win_embed"])
def test_no_python_zip_if_exists_and_not_set_in_path(py_info, mock_files):
python_zip_name = f"python{py_info.version_nodot}.zip"
python_zip = path(py_info.prefix, python_zip_name)
py_info.path.remove(python_zip)
mock_files(CPYTHON3_PATH, [python_zip])
sources = tuple(CPython3Windows.sources(interpreter=py_info))
assert python_zip not in py_info.path
assert not contains_ref(sources, python_zip)
@pytest.mark.parametrize("py_info_name", ["cpython3_win_embed"])
def test_no_python_zip_if_not_exists(py_info, mock_files):
python_zip_name = f"python{py_info.version_nodot}.zip"
python_zip = path(py_info.prefix, python_zip_name)
# No `python_zip`, just python.exe file.
mock_files(CPYTHON3_PATH, [py_info.system_executable])
sources = tuple(CPython3Windows.sources(interpreter=py_info))
assert python_zip in py_info.path
assert not contains_ref(sources, python_zip)
@pytest.mark.parametrize("py_info_name", ["cpython3_win_embed"])
def test_python3_exe_present(py_info, mock_files):
mock_files(CPYTHON3_PATH, [py_info.system_executable])
sources = tuple(CPython3Windows.sources(interpreter=py_info))
assert contains_exe(sources, py_info.system_executable, "python3.exe")
assert contains_exe(sources, py_info.system_executable, "python3")
@pytest.mark.parametrize("py_info_name", ["cpython3_win_free_threaded"])
def test_free_threaded_exe_naming(py_info, mock_files):
mock_files(CPYTHON3_PATH, [py_info.system_executable])
sources = tuple(CPython3Windows.sources(interpreter=py_info))
assert contains_exe(sources, py_info.system_executable, "python3.13t.exe")
pythonw_refs = [s for s in sources if is_exe(s) and has_src(path(py_info.prefix, "pythonw.exe"))(s)]
assert len(pythonw_refs) == 1
assert "pythonw3.13t.exe" in pythonw_refs[0].aliases
@pytest.mark.parametrize("py_info_name", ["cpython3_win_embed"])
def test_pywin32_dll_exclusion(py_info, mock_files):
"""Test that pywin32 DLLs are excluded from virtualenv creation."""
# Mock pywin32 DLLs that should be excluded
pywin32_dlls = (
path(py_info.prefix, "pywintypes39.dll"),
path(py_info.prefix, "pywintypes310.dll"),
path(py_info.prefix, "pythoncom39.dll"),
path(py_info.prefix, "pythoncom310.dll"),
)
# Mock regular DLLs that should be included
regular_dlls = (
path(py_info.prefix, "libcrypto-1_1.dll"),
path(py_info.prefix, "libffi-7.dll"),
)
# Only mock the DLL files (no shim) so dll_and_pyd() method will be called
all_files = [*pywin32_dlls, *regular_dlls]
mock_files(CPYTHON3_PATH, all_files)
sources = tuple(CPython3Windows.sources(interpreter=py_info))
# Make sure we're in the no-shim code path
assert not CPython3Windows.has_shim(interpreter=py_info)
# Verify pywin32 DLLs are excluded
for dll in pywin32_dlls:
assert not contains_ref(sources, dll), f"pywin32 DLL {dll} should be excluded"
# Verify regular DLLs are included
for dll in regular_dlls:
assert contains_ref(sources, dll), f"Regular DLL {dll} should be included"
|