def get_package_summary( path: Path, *, package: str = None, new_install: bool = False, include_injected: bool = False, ) -> str: venv = Venv(path) python_path = venv.python_path.resolve() package_metadata = venv.get_package_metadata(package) package = package_metadata.package or venv.root.name if not python_path.is_file(): return f" package {red(bold(package))} has invalid interpreter {str(python_path)}" if not venv.package_metadata: return ( f" package {red(bold(package))} has missing internal pipx metadata.\n" f" It was likely installed using a pipx version before 0.15.0.0.\n" f" Please uninstall and install this package, or reinstall-all to fix." ) if package_metadata.package_version is None: not_installed = red("is not installed") return f" package {bold(package)} {not_installed} in the venv {str(path)}" apps = package_metadata.apps + package_metadata.apps_of_dependencies exposed_app_paths = _get_exposed_app_paths_for_package( venv.bin_path, apps, constants.LOCAL_BIN_DIR) exposed_binary_names = sorted(p.name for p in exposed_app_paths) unavailable_binary_names = sorted({ add_suffix(name, package_metadata.suffix) for name in package_metadata.apps } - set(exposed_binary_names)) # The following is to satisfy mypy that python_version is str and not # Optional[str] python_version = (venv.pipx_metadata.python_version if venv.pipx_metadata.python_version is not None else "") return _get_list_output( python_version, python_path, package_metadata.package_version, package, new_install, exposed_binary_names, unavailable_binary_names, venv.pipx_metadata.injected_packages if include_injected else None, suffix=package_metadata.suffix, )
def run_post_install_actions( venv: Venv, package: str, local_bin_dir: Path, venv_dir: Path, include_dependencies: bool, *, force: bool, ): package_metadata = venv.get_package_metadata(package) package = package_metadata.package or package display_name = f"{package}{package_metadata.suffix}" if not package_metadata.app_paths and not include_dependencies: # No apps associated with this package and we aren't including dependencies. # This package has nothing for pipx to use, so this is an error. for dep, dependent_apps in package_metadata.app_paths_of_dependencies.items( ): print( f"Note: Dependent package '{dep}' contains {len(dependent_apps)} apps" ) for app in dependent_apps: print(f" - {app.name}") if venv.safe_to_remove(): venv.remove_venv() if package_metadata.app_paths_of_dependencies: raise PipxError( f"No apps associated with package {display_name}. " "Try again with '--include-deps' to include apps of dependent packages, " "which are listed above. " "If you are attempting to install a library, pipx should not be used. " "Consider using pip or a similar tool instead.") else: raise PipxError( f"No apps associated with package {display_name}. " "If you are attempting to install a library, pipx should not be used. " "Consider using pip or a similar tool instead.") if package_metadata.apps: pass elif package_metadata.apps_of_dependencies and include_dependencies: pass else: # No apps associated with this package and we aren't including dependencies. # This package has nothing for pipx to use, so this is an error. if venv.safe_to_remove(): venv.remove_venv() raise PipxError( f"No apps associated with package {display_name} or its dependencies." "If you are attempting to install a library, pipx should not be used. " "Consider using pip or a similar tool instead.") expose_apps_globally( local_bin_dir, package_metadata.app_paths, package, force=force, suffix=package_metadata.suffix, ) if include_dependencies: for _, app_paths in package_metadata.app_paths_of_dependencies.items(): expose_apps_globally( local_bin_dir, app_paths, package, force=force, suffix=package_metadata.suffix, ) print(get_package_summary( venv_dir, package=package, new_install=True, )) warn_if_not_on_path(local_bin_dir) print(f"done! {stars}", file=sys.stderr)
def upgrade( venv_dir: Path, package: str, pip_args: List[str], verbose: bool, *, upgrading_all: bool, force: bool, ) -> int: """Returns nonzero if package was upgraded, 0 if version did not change""" 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) if not venv.package_metadata: print( f"Not upgrading {red(bold(package))}. It has missing internal pipx metadata.\n" f" It was likely installed using a pipx version before 0.15.0.0.\n" f" Please uninstall and install this package, or reinstall-all to fix." ) return 0 package_metadata = venv.get_package_metadata(package) package = package_metadata.package or package if package_metadata.package_or_url is None: raise PipxError( f"Internal Error: package {package} has corrupt pipx metadata.") package_or_url = package_metadata.package_or_url old_version = package_metadata.package_version include_apps = package_metadata.include_apps include_dependencies = package_metadata.include_dependencies # Upgrade shared libraries (pip, setuptools and wheel) venv.upgrade_packaging_libraries(pip_args) venv.upgrade_package( package, package_or_url, pip_args, include_dependencies=include_dependencies, include_apps=include_apps, is_main_package=True, suffix=package_metadata.suffix, ) # TODO 20191026: upgrade injected packages also (Issue #79) package_metadata = venv.get_package_metadata(package) package = package_metadata.package or package display_name = f"{package_metadata.package}{package_metadata.suffix}" new_version = package_metadata.package_version expose_apps_globally( constants.LOCAL_BIN_DIR, package_metadata.app_paths, package, force=force, suffix=package_metadata.suffix, ) if include_dependencies: for _, app_paths in package_metadata.app_paths_of_dependencies.items(): expose_apps_globally( constants.LOCAL_BIN_DIR, app_paths, package, force=force, suffix=package_metadata.suffix, ) if old_version == new_version: if upgrading_all: pass else: print( f"{display_name} is already at latest version {old_version} (location: {str(venv_dir)})" ) return 0 else: print( f"upgraded package {display_name} from {old_version} to {new_version} (location: {str(venv_dir)})" ) return 1