def _upgrade_package_no_metadata(self, package: str, pip_args: List[str]) -> None: with animate(f"upgrading {full_package_description(package, package)}", self.do_animation): pip_process = self._run_pip(["install"] + pip_args + ["--upgrade", package]) subprocess_post_check(pip_process)
def upgrade_package( self, package_name: str, package_or_url: str, pip_args: List[str], include_dependencies: bool, include_apps: bool, is_main_package: bool, suffix: str = "", ) -> None: with animate( f"upgrading {full_package_description(package_name, package_or_url)}", self.do_animation, ): pip_process = self._run_pip(["install"] + pip_args + ["--upgrade", package_or_url]) subprocess_post_check(pip_process) self._update_package_metadata( package_name=package_name, package_or_url=package_or_url, pip_args=pip_args, include_dependencies=include_dependencies, include_apps=include_apps, is_main_package=is_main_package, suffix=suffix, )
def create(self, pip_args: List[str], verbose: bool = False): if not self.is_valid: with animate("creating shared libraries", not verbose): run([DEFAULT_PYTHON, "-m", "venv", "--clear", self.root]) # ignore installed packages to ensure no unexpected patches from the OS vendor # are used self.upgrade(["--ignore-installed"] + pip_args, verbose)
def install_package_no_deps(self, package_or_url: str, pip_args: List[str]) -> str: try: with animate(f"determining package name from {package_or_url!r}", self.do_animation): old_package_set = self.list_installed_packages() cmd = ["install"] + ["--no-dependencies" ] + pip_args + [package_or_url] self._run_pip(cmd) except PipxError as e: logging.info(e) raise PipxError( f"Cannot determine package name from spec {package_or_url!r}. " f"Check package spec for errors.") installed_packages = self.list_installed_packages() - old_package_set if len(installed_packages) == 1: package = installed_packages.pop() logging.info(f"Determined package name: {package}") else: logging.info(f"old_package_set = {old_package_set}") logging.info(f"install_packages = {installed_packages}") raise PipxError( f"Cannot determine package name from spec {package_or_url!r}. " f"Check package spec for errors.") return package
def install_package_no_deps(self, package_or_url: str, pip_args: List[str]) -> str: with animate(f"determining package name from {package_or_url!r}", self.do_animation): old_package_set = self.list_installed_packages() cmd = ["install"] + ["--no-dependencies" ] + pip_args + [package_or_url] pip_process = self._run_pip(cmd) subprocess_post_check(pip_process, raise_error=False) if pip_process.returncode: raise PipxError(f""" Cannot determine package name from spec {package_or_url!r}. Check package spec for errors. """) installed_packages = self.list_installed_packages() - old_package_set if len(installed_packages) == 1: package_name = installed_packages.pop() logger.info(f"Determined package name: {package_name}") else: logger.info(f"old_package_set = {old_package_set}") logger.info(f"install_packages = {installed_packages}") raise PipxError(f""" Cannot determine package name from spec {package_or_url!r}. Check package spec for errors. """) return package_name
def upgrade(self, pip_args: List[str], verbose: bool = False): # Don't try to upgrade multiple times per run if self.has_been_updated_this_run: logging.info(f"Already upgraded libraries in {self.root}") return logging.info(f"Upgrading shared libraries in {self.root}") ignored_args = ["--editable"] _pip_args = [arg for arg in pip_args if arg not in ignored_args] if not verbose: _pip_args.append("-q") try: with animate("upgrading shared libraries", not verbose): run([ self.python_path, "-m", "pip", "--disable-pip-version-check", "install", *_pip_args, "--upgrade", "pip", "setuptools", "wheel", ]) self.has_been_updated_this_run = True self.pip_path.touch() except Exception: logging.error("Failed to upgrade shared libraries", exc_info=True)
def upgrade( venv_dir: Path, package: str, package_or_url: str, pip_args: List[str], verbose: bool, *, upgrading_all: bool, ) -> int: if not venv_dir.is_dir(): raise PipxError( f"Package is not installed. Expected to find {str(venv_dir)}, " "but it does not exist.") venv = Venv(venv_dir, verbose=verbose) old_version = venv.get_package_version(package) do_animation = not verbose try: with animate(f"upgrading pip for package {package_or_url!r}", do_animation): venv.upgrade_package("pip", pip_args) except Exception: logging.error("Failed to upgrade pip", exc_info=True) with animate(f"upgrading package {package_or_url!r}", do_animation): venv.upgrade_package(package_or_url, pip_args) new_version = venv.get_package_version(package) if old_version == new_version: if upgrading_all: pass else: print( f"{package} is already at latest version {old_version} (location: {str(venv_dir)})" ) return 0 binary_paths = venv.get_package_binary_paths(package) expose_binaries_globally(local_bin_dir, binary_paths, package) print( f"upgraded package {package} from {old_version} to {new_version} (location: {str(venv_dir)})" ) return 1
def create(self, verbose: bool = False) -> None: if not self.is_valid: with animate("creating shared libraries", not verbose): run_verify( [DEFAULT_PYTHON, "-m", "venv", "--clear", self.root]) # ignore installed packages to ensure no unexpected patches from the OS vendor # are used self.upgrade(pip_args=["--force-reinstall"], verbose=verbose)
def install_package(self, package_or_url: str, pip_args: List[str]) -> None: with animate(f"installing package {package_or_url!r}", self.do_animation): if pip_args is None: pip_args = [] cmd = ["install"] + pip_args + [package_or_url] self._run_pip(cmd)
def install_package( self, package_name: str, package_or_url: str, pip_args: List[str], include_dependencies: bool, include_apps: bool, is_main_package: bool, suffix: str = "", ) -> None: # package_name in package specifier can mismatch URL due to user error package_or_url = fix_package_name(package_or_url, package_name) # check syntax and clean up spec and pip_args (package_or_url, pip_args) = parse_specifier_for_install(package_or_url, pip_args) with animate( f"installing {full_package_description(package_name, package_or_url)}", self.do_animation, ): # do not use -q with `pip install` so subprocess_post_check_pip_errors # has more information to analyze in case of failure. cmd = ([str(self.python_path), "-m", "pip", "install"] + pip_args + [package_or_url]) # no logging because any errors will be specially logged by # subprocess_post_check_handle_pip_error() pip_process = run_subprocess(cmd, log_stdout=False, log_stderr=False) subprocess_post_check_handle_pip_error(pip_process) if pip_process.returncode: raise PipxError( f"Error installing {full_package_description(package_name, package_or_url)}." ) self._update_package_metadata( package_name=package_name, package_or_url=package_or_url, pip_args=pip_args, include_dependencies=include_dependencies, include_apps=include_apps, is_main_package=is_main_package, suffix=suffix, ) # Verify package installed ok if self.package_metadata[package_name].package_version is None: raise PipxError( f"Unable to install " f"{full_package_description(package_name, package_or_url)}.\n" f"Check the name or spec for errors, and verify that it can " f"be installed with pip.", wrap_message=False, )
def install_package( self, package: str, package_or_url: str, pip_args: List[str], include_dependencies: bool, include_apps: bool, is_main_package: bool, suffix: str = "", ) -> None: if pip_args is None: pip_args = [] # package name in package specifier can mismatch URL due to user error package_or_url = fix_package_name(package_or_url, package) # check syntax and clean up spec and pip_args (package_or_url, pip_args) = parse_specifier_for_install( package_or_url, pip_args ) with animate( f"installing {full_package_description(package, package_or_url)}", self.do_animation, ): cmd = ["install"] + pip_args + [package_or_url] pip_process = self._run_pip(cmd) subprocess_post_check(pip_process, raise_error=False) if pip_process.returncode: raise PipxError( f"Error installing {full_package_description(package, package_or_url)}." ) self._update_package_metadata( package=package, package_or_url=package_or_url, pip_args=pip_args, include_dependencies=include_dependencies, include_apps=include_apps, is_main_package=is_main_package, suffix=suffix, ) # Verify package installed ok if self.package_metadata[package].package_version is None: raise PipxError( f"Unable to install " f"{full_package_description(package, package_or_url)}.\n" f"Check the name or spec for errors, and verify that it can " f"be installed with pip.", wrap_message=False, )
def install_package( self, package: Optional[str], # if None, will be determined in this function package_or_url: str, pip_args: List[str], include_dependencies: bool, include_apps: bool, is_main_package: bool, ) -> None: with animate(f"installing package {package_or_url!r}", self.do_animation): if pip_args is None: pip_args = [] if package is None: # If no package name is supplied, install only main package # first in order to see what its name is old_package_set = self.list_installed_packages() cmd = ["install"] + pip_args + ["--no-dependencies" ] + [package_or_url] self._run_pip(cmd) installed_packages = self.list_installed_packages( ) - old_package_set if len(installed_packages) == 1: package = installed_packages.pop() logging.info(f"Determined package name: '{package}'") else: package = None cmd = ["install"] + pip_args + [package_or_url] self._run_pip(cmd) if package is None: logging.warning( f"Cannot determine package name for package_or_url='{package_or_url}'. " f"Unable to retrieve package metadata. " f"Unable to verify if package was installed properly.") return self._update_package_metadata( package=package, package_or_url=package_or_url, pip_args=pip_args, include_dependencies=include_dependencies, include_apps=include_apps, is_main_package=is_main_package, ) # Verify package installed ok if self.package_metadata[package].package_version is None: raise PackageInstallFailureError
def install_package( self, package: Optional[str], # if None, will be determined in this function package_or_url: str, pip_args: List[str], include_dependencies: bool, include_apps: bool, is_main_package: bool, ) -> None: if pip_args is None: pip_args = [] if package is None: # If no package name is supplied, install only main package # first in order to see what its name is package = self.install_package_no_deps(package_or_url, pip_args) try: with animate( f"installing {full_package_description(package, package_or_url)}", self.do_animation, ): cmd = ["install"] + pip_args + [package_or_url] self._run_pip(cmd) except PipxError as e: logging.info(e) raise PipxError( f"Error installing " f"{full_package_description(package, package_or_url)}." ) self._update_package_metadata( package=package, package_or_url=package_or_url, pip_args=pip_args, include_dependencies=include_dependencies, include_apps=include_apps, is_main_package=is_main_package, ) # Verify package installed ok if self.package_metadata[package].package_version is None: raise PipxError( f"Unable to install " f"{full_package_description(package, package_or_url)}.\n" f"Check the name or spec for errors, and verify that it can " f"be installed with pip." )
def create_venv(self, venv_args: List[str], pip_args: List[str]) -> None: with animate("creating virtual environment", self.do_animation): cmd = [self._python, "-m", "venv", "--without-pip"] run(cmd + venv_args + [str(self.root)]) shared_libs.create(pip_args, self.verbose) pipx_pth = get_site_packages(self.python_path) / PIPX_SHARED_PTH # write path pointing to the shared libs site-packages directory # example pipx_pth location: # ~/.local/pipx/venvs/black/lib/python3.8/site-packages/pipx_shared.pth # example shared_libs.site_packages location: # ~/.local/pipx/shared/lib/python3.6/site-packages # # https://docs.python.org/3/library/site.html # A path configuration file is a file whose name has the form 'name.pth'. # its contents are additional items (one per line) to be added to sys.path pipx_pth.write_text(str(shared_libs.site_packages) + "\n", encoding="utf-8")
def install_package( self, package: str, package_or_url: str, pip_args: List[str], include_dependencies: bool, include_apps: bool, is_main_package: bool, suffix: str = "", ) -> None: if pip_args is None: pip_args = [] # check syntax and clean up spec and pip_args (package_or_url, pip_args) = parse_specifier_for_install(package_or_url, pip_args) try: with animate( f"installing {full_package_description(package, package_or_url)}", self.do_animation, ): cmd = ["install"] + pip_args + [package_or_url] self._run_pip(cmd) except PipxError as e: logging.info(e) raise PipxError( f"Error installing " f"{full_package_description(package, package_or_url)}.") self._update_package_metadata( package=package, package_or_url=package_or_url, pip_args=pip_args, include_dependencies=include_dependencies, include_apps=include_apps, is_main_package=is_main_package, suffix=suffix, ) # Verify package installed ok if self.package_metadata[package].package_version is None: raise PipxError( f"Unable to install " f"{full_package_description(package, package_or_url)}.\n" f"Check the name or spec for errors, and verify that it can " f"be installed with pip.")
def upgrade(self, *, pip_args: Optional[List[str]] = None, verbose: bool = False) -> None: if not self.is_valid: self.create(verbose=verbose) return # Don't try to upgrade multiple times per run if self.has_been_updated_this_run: logger.info(f"Already upgraded libraries in {self.root}") return if pip_args is None: pip_args = [] logger.info(f"Upgrading shared libraries in {self.root}") ignored_args = ["--editable"] _pip_args = [arg for arg in pip_args if arg not in ignored_args] if not verbose: _pip_args.append("-q") try: with animate("upgrading shared libraries", not verbose): upgrade_process = run_subprocess([ self.python_path, "-m", "pip", "--disable-pip-version-check", "install", *_pip_args, "--upgrade", "pip", "setuptools", "wheel", ]) subprocess_post_check(upgrade_process) self.has_been_updated_this_run = True self.pip_path.touch() except Exception: logger.error("Failed to upgrade shared libraries", exc_info=True)
def upgrade_package( self, package: str, package_or_url: str, pip_args: List[str], include_dependencies: bool, include_apps: bool, is_main_package: bool, ) -> None: with animate(f"upgrading package {package_or_url!r}", self.do_animation): self._run_pip(["install"] + pip_args + ["--upgrade", package_or_url]) self._update_package_metadata( package=package, package_or_url=package_or_url, pip_args=pip_args, include_dependencies=include_dependencies, include_apps=include_apps, is_main_package=is_main_package, )
def install_package(self, package_or_url: str) -> None: with animate(f"installing package {package_or_url!r}", self.do_animation): self._run_pip(["install", package_or_url])
def _upgrade_package_no_metadata(self, package_or_url: str, pip_args: List[str]) -> None: with animate(f"upgrading package {package_or_url!r}", self.do_animation): self._run_pip(["install"] + pip_args + ["--upgrade", package_or_url])
def create_venv(self, venv_args: List[str], pip_args: List[str]) -> None: with animate("creating virtual environment", self.do_animation): _run([self._python, "-m", "venv"] + venv_args + [str(self.root)]) ignored_args = ["--editable"] _pip_args = [arg for arg in pip_args if arg not in ignored_args] self.upgrade_package("pip", _pip_args)
def create_venv(self, venv_args) -> None: with animate("creating virtual environment", self.do_animation): _run([self._python, "-m", "venv"] + venv_args + [str(self.root)]) self.upgrade_package("pip", [])
def create(self, pip_args: List[str], verbose: bool = False): if not self.is_valid: with animate("creating shared libraries", not verbose): run([DEFAULT_PYTHON, "-m", "venv", "--clear", self.root]) self.upgrade(pip_args, verbose)
def create_venv(self) -> None: with animate("creating virtual environment", self.do_animation): _run([self._python, "-m", "venv", self.root]) self.upgrade_package("pip")