Skip to content

Commit d74ea36

Browse files
committed
fix "env use python" to use Python in PATH
This should use the Python, which is in the PATH, not the latest Python.
1 parent 36e1c63 commit d74ea36

File tree

4 files changed

+58
-14
lines changed

4 files changed

+58
-14
lines changed

src/poetry/utils/env/python/manager.py

+2-12
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from __future__ import annotations
22

3-
import contextlib
43
import os
54
import sys
65

@@ -229,13 +228,6 @@ def get_active_python(cls) -> Python | None:
229228

230229
return None
231230

232-
@classmethod
233-
def from_executable(cls, path: Path | str) -> Python:
234-
try:
235-
return cls(python=findpython.PythonVersion(executable=Path(path)))
236-
except (FileNotFoundError, NotADirectoryError, ValueError):
237-
raise ValueError(f"{path} is not a valid Python executable")
238-
239231
@classmethod
240232
def get_system_python(cls) -> Python:
241233
"""
@@ -252,10 +244,8 @@ def get_system_python(cls) -> Python:
252244

253245
@classmethod
254246
def get_by_name(cls, python_name: str) -> Python | None:
255-
if Path(python_name).exists():
256-
with contextlib.suppress(ValueError):
257-
# if it is a path try assuming it is an executable
258-
return cls.from_executable(python_name)
247+
if python := ShutilWhichPythonProvider.find_python_by_name(python_name):
248+
return cls(python=python)
259249

260250
if python := findpython.find(python_name):
261251
return cls(python=python)

src/poetry/utils/env/python/providers.py

+8-2
Original file line numberDiff line numberDiff line change
@@ -28,10 +28,16 @@ def create(cls) -> Self | None:
2828
return cls()
2929

3030
def find_pythons(self) -> Iterable[findpython.PythonVersion]:
31-
if path := shutil.which("python"):
32-
return [findpython.PythonVersion(executable=Path(path))]
31+
if python := self.find_python_by_name("python"):
32+
return [python]
3333
return []
3434

35+
@classmethod
36+
def find_python_by_name(cls, name: str) -> findpython.PythonVersion | None:
37+
if path := shutil.which(name):
38+
return findpython.PythonVersion(executable=Path(path))
39+
return None
40+
3541

3642
@dataclasses.dataclass
3743
class PoetryPythonPathProvider(PathProvider): # type: ignore[misc]

tests/utils/env/python/test_manager.py

+37
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from __future__ import annotations
22

33
import platform
4+
import sys
45

56
from typing import TYPE_CHECKING
67

@@ -95,3 +96,39 @@ def find_downloadable_versions_include_incompatible() -> None:
9596
assert len(
9697
list(Python.find_downloadable_versions(include_incompatible=True))
9798
) > len(list(Python.find_downloadable_versions()))
99+
100+
101+
@pytest.mark.parametrize(
102+
("name", "expected_minor"),
103+
[
104+
("3.9", 9),
105+
("3.10", 10),
106+
("3.11", None),
107+
],
108+
)
109+
def test_get_by_name_version(
110+
mocked_python_register: MockedPythonRegister, name: str, expected_minor: int | None
111+
) -> None:
112+
mocked_python_register("3.9.1", implementation="CPython", parent="a")
113+
mocked_python_register("3.10.3", implementation="CPython", parent="b")
114+
115+
python = Python.get_by_name(name)
116+
if expected_minor is None:
117+
assert python is None
118+
else:
119+
assert python is not None
120+
assert python.minor == expected_minor
121+
122+
123+
def test_get_by_name_python(without_mocked_findpython: None) -> None:
124+
python = Python.get_by_name("python")
125+
assert python is not None
126+
assert python.version.major == 3
127+
assert python.version.minor == sys.version_info.minor
128+
129+
130+
def test_get_by_name_path(without_mocked_findpython: None) -> None:
131+
python = Python.get_by_name(sys.executable)
132+
assert python is not None
133+
assert python.version.major == 3
134+
assert python.version.minor == sys.version_info.minor

tests/utils/env/python/test_python_providers.py

+11
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,27 @@
11
from __future__ import annotations
22

3+
import sys
4+
35
from typing import TYPE_CHECKING
46

57
from poetry.core.constraints.version import Version
68

79
from poetry.utils.env.python.providers import PoetryPythonPathProvider
10+
from poetry.utils.env.python.providers import ShutilWhichPythonProvider
811

912

1013
if TYPE_CHECKING:
1114
from tests.types import MockedPoetryPythonRegister
1215

1316

17+
def test_shutil_which_python_provider() -> None:
18+
provider = ShutilWhichPythonProvider.create()
19+
assert provider
20+
pythons = list(provider.find_pythons())
21+
assert len(pythons) == 1
22+
assert pythons[0].minor == sys.version_info.minor
23+
24+
1425
def test_poetry_python_path_provider_no_pythons() -> None:
1526
provider = PoetryPythonPathProvider.create()
1627
assert provider

0 commit comments

Comments
 (0)