File: test_cpython3_win.py

package info (click to toggle)
python-virtualenv 20.38.0%2Bds-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 1,216 kB
  • sloc: python: 12,110; sh: 177; ansic: 61; csh: 53; makefile: 8
file content (151 lines) | stat: -rw-r--r-- 6,515 bytes parent folder | download
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"