Skip to content

Commit

Permalink
Ensure the correct environment executables are used
Browse files Browse the repository at this point in the history
Co-authored-by: finswimmer <2164565+finswimmer@users.noreply.github.com>
  • Loading branch information
sdispater and finswimmer committed Aug 27, 2021
1 parent 2e259b0 commit af920c5
Show file tree
Hide file tree
Showing 4 changed files with 99 additions and 12 deletions.
16 changes: 13 additions & 3 deletions poetry/console/commands/env/info.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ def handle(self) -> Optional[int]:
self._display_complete_info(env)

def _display_complete_info(self, env: "Env") -> None:
from poetry.utils.env import GenericEnv

env_python_version = ".".join(str(s) for s in env.version_info[:3])
self.line("")
self.line("<b>Virtualenv</b>")
Expand All @@ -44,6 +46,9 @@ def _display_complete_info(self, env: "Env") -> None:
"<info>Path</info>: <comment>{}</>".format(
env.path if env.is_venv() else "NA"
),
"<info>Executable</info>: <comment>{}</>".format(
env.python if env.is_venv() else "NA"
),
]
if env.is_venv():
listing.append(
Expand All @@ -55,13 +60,18 @@ def _display_complete_info(self, env: "Env") -> None:

self.line("")

system_env = GenericEnv(env.base)
self.line("<b>System</b>")
self.line(
"\n".join(
[
"<info>Platform</info>: <comment>{}</>".format(env.platform),
"<info>OS</info>: <comment>{}</>".format(env.os),
"<info>Python</info>: <comment>{}</>".format(env.base),
"<info>Platform</info>: <comment>{}</>".format(env.platform),
"<info>OS</info>: <comment>{}</>".format(env.os),
"<info>Python</info>: <comment>{}</>".format(
".".join(str(v) for v in system_env.version_info[:3])
),
"<info>Path</info>: <comment>{}</>".format(system_env.path),
"<info>Executable</info>: <comment>{}</>".format(system_env.python),
]
)
)
40 changes: 35 additions & 5 deletions poetry/utils/env.py
Original file line number Diff line number Diff line change
Expand Up @@ -1061,6 +1061,30 @@ def __init__(self, path: Path, base: Optional[Path] = None) -> None:
self._path = path
self._bin_dir = self._path / bin_dir

try:
python_executables = sorted(
[
p.name
for p in self._bin_dir.glob("python*")
if re.match(r"python(?:\d+(?:\.\d+)?)?(?:\.exe)?$", p.name)
]
)
self._executable = python_executables[0].rstrip(".exe")
except IndexError:
self._executable = "python" + (".exe" if self._is_windows else "")

try:
pip_executables = sorted(
[
p.name
for p in self._bin_dir.glob("pip*")
if re.match(r"pip(?:\d+(?:\.\d+)?)?(?:\.exe)?$", p.name)
]
)
self._pip_executable = pip_executables[0].rstrip(".exe")
except IndexError:
self._pip_executable = "pip" + (".exe" if self._is_windows else "")

self._base = base or path

self._marker_env = None
Expand Down Expand Up @@ -1095,7 +1119,7 @@ def python(self) -> str:
"""
Path to current python executable
"""
return self._bin("python")
return self._bin(self._executable)

@property
def marker_env(self) -> Dict[str, Any]:
Expand All @@ -1121,7 +1145,7 @@ def pip(self) -> str:
Path to current pip executable
"""
# we do not use as_posix() here due to issues with windows pathlib2 implementation
path = self._bin("pip")
path = self._bin(self._pip_executable)
if not Path(path).exists():
return str(self.pip_embedded)
return path
Expand Down Expand Up @@ -1267,7 +1291,7 @@ def run_pip(self, *args: str, **kwargs: Any) -> Union[int, str]:
return self._run(cmd, **kwargs)

def run_python_script(self, content: str, **kwargs: Any) -> str:
return self.run("python", "-W", "ignore", "-", input_=content, **kwargs)
return self.run(self._executable, "-W", "ignore", "-", input_=content, **kwargs)

def _run(self, cmd: List[str], **kwargs: Any) -> Union[int, str]:
"""
Expand Down Expand Up @@ -1489,7 +1513,10 @@ def get_python_implementation(self) -> str:
def get_pip_command(self, embedded: bool = False) -> List[str]:
# We're in a virtualenv that is known to be sane,
# so assume that we have a functional pip
return [self._bin("python"), self.pip_embedded if embedded else self.pip]
return [
self._bin(self._executable),
self.pip_embedded if embedded else self.pip,
]

def get_supported_tags(self) -> List[Tag]:
file_path = Path(packaging.tags.__file__)
Expand Down Expand Up @@ -1607,7 +1634,10 @@ def __init__(
self.executed = []

def get_pip_command(self, embedded: bool = False) -> List[str]:
return [self._bin("python"), self.pip_embedded if embedded else self.pip]
return [
self._bin(self._executable),
self.pip_embedded if embedded else self.pip,
]

def _run(self, cmd: List[str], **kwargs: Any) -> int:
self.executed.append(cmd)
Expand Down
18 changes: 14 additions & 4 deletions tests/console/commands/env/test_info.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import sys

from pathlib import Path

import pytest

from poetry.utils._compat import WINDOWS
from poetry.utils.env import MockEnv


Expand All @@ -28,14 +31,21 @@ def test_env_info_displays_complete_info(tester):
Python: 3.7.0
Implementation: CPython
Path: {prefix}
Executable: {executable}
Valid: True
System
Platform: darwin
OS: posix
Python: {base_prefix}
Platform: darwin
OS: posix
Python: {base_version}
Path: {base_prefix}
Executable: {base_executable}
""".format(
prefix=str(Path("/prefix")), base_prefix=str(Path("/base/prefix"))
prefix=str(Path("/prefix")),
base_prefix=str(Path("/base/prefix")),
base_version=".".join(str(v) for v in sys.version_info[:3]),
executable=sys.executable,
base_executable="python" + (".exe" if WINDOWS else ""),
)

assert expected == tester.io.fetch_output()
Expand Down
37 changes: 37 additions & 0 deletions tests/utils/test_env.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
from poetry.core.semver.version import Version
from poetry.core.toml.file import TOMLFile
from poetry.factory import Factory
from poetry.utils._compat import WINDOWS
from poetry.utils.env import GET_BASE_PREFIX
from poetry.utils.env import EnvCommandError
from poetry.utils.env import EnvManager
Expand Down Expand Up @@ -964,3 +965,39 @@ def test_env_system_packages(tmp_path, config):
assert not venv_path.joinpath(
"lib", "python2.7", "no-global-site-packages.txt"
).exists()


def test_env_finds_the_correct_executables(tmp_dir, manager):
venv_path = Path(tmp_dir) / "Virtual Env"
manager.build_venv(str(venv_path), with_pip=True)
venv = VirtualEnv(venv_path)

default_executable = expected_executable = "python" + (".exe" if WINDOWS else "")
default_pip_executable = expected_pip_executable = "pip" + (
".exe" if WINDOWS else ""
)
major_executable = "python{}{}".format(
sys.version_info[0], ".exe" if WINDOWS else ""
)
major_pip_executable = "pip{}{}".format(
sys.version_info[0], ".exe" if WINDOWS else ""
)

if (
venv._bin_dir.joinpath(default_executable).exists()
and venv._bin_dir.joinpath(major_executable).exists()
):
venv._bin_dir.joinpath(default_executable).unlink()
expected_executable = major_executable

if (
venv._bin_dir.joinpath(default_pip_executable).exists()
and venv._bin_dir.joinpath(major_pip_executable).exists()
):
venv._bin_dir.joinpath(default_pip_executable).unlink()
expected_pip_executable = major_pip_executable

venv = VirtualEnv(venv_path)

assert Path(venv.python).name == expected_executable
assert Path(venv.pip).name == expected_pip_executable

0 comments on commit af920c5

Please sign in to comment.