Skip to content

Commit 1791aa4

Browse files
authored
fix "env use python" to use Python in PATH (#10187)
1 parent 36e1c63 commit 1791aa4

File tree

4 files changed

+60
-13
lines changed

4 files changed

+60
-13
lines changed

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

+4-11
Original file line numberDiff line numberDiff line change
@@ -229,13 +229,6 @@ def get_active_python(cls) -> Python | None:
229229

230230
return None
231231

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-
239232
@classmethod
240233
def get_system_python(cls) -> Python:
241234
"""
@@ -252,10 +245,10 @@ def get_system_python(cls) -> Python:
252245

253246
@classmethod
254247
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)
248+
# Ignore broken installations.
249+
with contextlib.suppress(ValueError):
250+
if python := ShutilWhichPythonProvider.find_python_by_name(python_name):
251+
return cls(python=python)
259252

260253
if python := findpython.find(python_name):
261254
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)