Add a way to get a simpler invocation of pip

This makes it possible to provide more terse suggestions that are still
correct, depending on the user's environment.
This commit is contained in:
Pradyun Gedam 2022-03-11 12:36:42 +00:00
parent c4470ba3bd
commit ea0d976d9f
1 changed files with 47 additions and 0 deletions

View File

@ -1,7 +1,23 @@
import itertools
import os
import shutil
import sys
from typing import List, Optional
from pip._internal.cli.main import main
from pip._internal.utils.compat import WINDOWS
_EXECUTABLE_NAMES = [
"pip",
f"pip{sys.version_info.major}",
f"pip{sys.version_info.major}.{sys.version_info.minor}",
]
if WINDOWS:
_allowed_extensions = {"", ".exe", ".EXE"}
_EXECUTABLE_NAMES = [
"".join(parts)
for parts in itertools.product(_EXECUTABLE_NAMES, _allowed_extensions)
]
def _wrapper(args: Optional[List[str]] = None) -> int:
@ -25,3 +41,34 @@ def _wrapper(args: Optional[List[str]] = None) -> int:
"running pip directly.\n"
)
return main(args)
def get_best_invocation_for_this_pip() -> str:
"""Try to figure out the best way to invoke pip in the current environment."""
binary_directory = "Scripts" if WINDOWS else "bin"
binary_prefix = os.path.join(sys.prefix, binary_directory)
# Try to use pip[X[.Y]] names, if those executables for this environment are
# the first on PATH with that name.
exe_are_in_PATH = binary_prefix in os.environ.get("PATH", "").split(os.pathsep)
if exe_are_in_PATH:
for exe_name in _EXECUTABLE_NAMES:
if shutil.which(exe_name) == os.path.join(binary_prefix, exe_name):
return exe_name
# Use the `-m` invocation, if there's no "nice" invocation.
return f"{get_best_invocation_for_this_python()} -m pip"
def get_best_invocation_for_this_python() -> str:
"""Try to figure out the best way to invoke the current Python."""
exe = sys.executable
exe_name = os.path.basename(exe)
# Try to use the basename, if it's the first executable.
found_executable = shutil.which(exe_name)
if found_executable and os.path.samefile(found_executable, exe):
return exe_name
# Use the full executable name, because we couldn't find something simpler.
return exe