File: test_python_manager.py

package info (click to toggle)
poetry 2.3.2%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 10,636 kB
  • sloc: python: 56,035; sh: 128; makefile: 100; ansic: 49
file content (143 lines) | stat: -rw-r--r-- 4,768 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
from __future__ import annotations

import os
import sys
import textwrap

from pathlib import Path
from typing import TYPE_CHECKING

import findpython
import packaging.version
import pytest

from poetry.core.constraints.version import Version

from poetry.utils.env.python import Python


if TYPE_CHECKING:
    from unittest.mock import MagicMock

    from pytest_mock import MockerFixture

    from poetry.config.config import Config
    from tests.types import MockedPythonRegister
    from tests.types import ProjectFactory


@pytest.fixture(scope="session")
def python_version() -> Version:
    version = sys.version.split(" ", 1)[0]
    if version[-1] == "+":
        version = version[:-1]
    return Version.parse(version)


def test_python_get_version_on_the_fly() -> None:
    python = Python.get_system_python()

    assert python.version == Version.parse(
        ".".join([str(s) for s in sys.version_info[:3]])
    )
    assert python.patch_version == Version.parse(
        ".".join([str(s) for s in sys.version_info[:3]])
    )
    assert python.minor_version == Version.parse(
        ".".join([str(s) for s in sys.version_info[:2]])
    )


def test_python_get_system_python() -> None:
    python = Python.get_system_python()

    assert python.executable.resolve() == findpython.find().executable.resolve()
    assert python.version == Version.parse(
        ".".join(str(v) for v in sys.version_info[:3])
    )


def test_python_get_preferred_default(config: Config, python_version: Version) -> None:
    python = Python.get_preferred_python(config)

    assert python.executable.resolve() == Path(sys.executable).resolve()
    assert python.version == python_version


def test_get_preferred_python_use_poetry_python_disabled(
    config: Config, mocker: MockerFixture
) -> None:
    mocker.patch(
        "poetry.utils.env.python.Python.get_active_python",
        return_value=Python(
            python=findpython.PythonVersion(
                executable=Path("/usr/bin/python3.7"),
                _version=packaging.version.Version("3.7.1"),
                _interpreter=Path("/usr/bin/python3.7"),
            )
        ),
    )

    config.config["virtualenvs"]["use-poetry-python"] = False
    python = Python.get_preferred_python(config)

    assert python.executable.as_posix().startswith("/usr/bin/python")
    assert python.version == Version.parse("3.7.1")


def test_get_preferred_python_use_poetry_python_disabled_fallback(
    config: Config, with_no_active_python: MagicMock
) -> None:
    config.config["virtualenvs"]["use-poetry-python"] = False
    python = Python.get_preferred_python(config)

    assert with_no_active_python.call_count == 1
    assert python.executable.resolve() == Path(sys.executable).resolve()


def test_fallback_on_detect_active_python(with_no_active_python: MagicMock) -> None:
    active_python = Python.get_active_python()
    assert active_python is None
    assert with_no_active_python.call_count == 1


@pytest.mark.skipif(sys.platform != "win32", reason="Windows only")
def test_detect_active_python_with_bat(
    tmp_path: Path, without_mocked_findpython: None, python_version: Version
) -> None:
    """On Windows pyenv uses batch files for python management."""
    python_wrapper = tmp_path / "python.bat"

    with python_wrapper.open("w", encoding="locale") as f:
        f.write(
            textwrap.dedent(f"""
            @echo off
            SET PYTHON_EXE="{sys.executable}"
            %PYTHON_EXE% %*
        """)
        )
    os.environ["PATH"] = str(python_wrapper.parent) + os.pathsep + os.environ["PATH"]

    python = Python.get_active_python()
    assert python is not None

    # TODO: Asses if Poetry needs to discover real path in these cases as
    # this is not a symlink and won't be handled by findpython
    assert python.executable.as_posix() == Path(sys.executable).as_posix()
    assert python.version == python_version


def test_python_find_compatible(
    project_factory: ProjectFactory, mocked_python_register: MockedPythonRegister
) -> None:
    # Note: This test may fail on Windows systems using Python from the Microsoft Store,
    # as the executable is named `py.exe`, which is not currently recognized by
    # Python.get_compatible_python. This issue will be resolved in #2117.
    # However, this does not cause problems in our case because Poetry's own
    # Python interpreter is used before attempting to find another compatible version.
    fixture = Path(__file__).parent.parent / "fixtures" / "simple_project"
    poetry = project_factory("simple-project", source=fixture)
    mocked_python_register("3.12")
    python = Python.get_compatible_python(poetry)

    assert Version.from_parts(3, 4) <= python.version <= Version.from_parts(4, 0)