codekingpro/portable-devtools
114k
1import sys2import shutil3import subprocess4 5from contextlib import suppress6from typing import List, Optional7from httpie.compat import is_frozen8 9 10class PipError(Exception):11 """An exception that occurs when pip exits with an error status code."""12 13 def __init__(self, stdout, stderr):14 self.stdout = stdout15 self.stderr = stderr16 17 18def _discover_system_pip() -> List[str]:19 # When we are running inside of a frozen binary, we need the system20 # pip to install plugins since there is no way for us to execute any21 # code outside of the HTTPie.22 #23 # We explicitly depend on system pip, so the SystemError should not24 # be executed (except for broken installations).25 def _check_pip_version(pip_location: Optional[str]) -> bool:26 if not pip_location:27 return False28 29 with suppress(subprocess.CalledProcessError):30 stdout = subprocess.check_output([pip_location, "--version"], text=True)31 return "python 3" in stdout32 33 targets = [34 "pip",35 "pip3"36 ]37 for target in targets:38 pip_location = shutil.which(target)39 if _check_pip_version(pip_location):40 return pip_location41 42 raise SystemError("Couldn't find 'pip' executable. Please ensure that pip in your system is available.")43 44 45def _run_pip_subprocess(pip_executable: List[str], args: List[str]) -> bytes:46 47 cmd = [*pip_executable, *args]48 try:49 process = subprocess.run(50 cmd,51 check=True,52 shell=False,53 stdout=subprocess.PIPE,54 stderr=subprocess.PIPE55 )56 except subprocess.CalledProcessError as error:57 raise PipError(error.stdout, error.stderr) from error58 else:59 return process.stdout60 61 62def run_pip(args: List[str]) -> bytes:63 if is_frozen:64 pip_executable = [_discover_system_pip()]65 else:66 pip_executable = [sys.executable, '-m', 'pip']67 68 return _run_pip_subprocess(pip_executable, args)69 