def install( venv_dir: Path, package: str, package_or_url: str, local_bin_dir: Path, python: str, pip_args: List[str], venv_args: List[str], verbose: bool, *, force: bool, include_dependencies: bool, ): try: exists = venv_dir.exists() and next(venv_dir.iterdir()) except StopIteration: exists = False if exists: if force: print(f"Installing to existing directory {str(venv_dir)!r}") else: print(f"{package!r} already seems to be installed. " f"Not modifying existing installation in {str(venv_dir)!r}. " "Pass '--force' to force installation.") return venv = Venv(venv_dir, python=python, verbose=verbose) try: venv.create_venv(venv_args, pip_args) venv.install_package(package_or_url, pip_args) if venv.get_venv_metadata_for_package(package).package_version is None: venv.remove_venv() raise PipxError( f"Could not find package {package}. Is the name correct?") _run_post_install_actions(venv, package, local_bin_dir, venv_dir, include_dependencies, force=force) except (Exception, KeyboardInterrupt): print("") venv.remove_venv() raise
def _run_post_install_actions( venv: Venv, package: str, local_bin_dir: Path, venv_dir: Path, include_dependencies: bool, *, force: bool, ): metadata = venv.get_venv_metadata_for_package(package) if not 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 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 len(metadata.app_paths_of_dependencies.keys()): raise PipxError( f"No apps associated with package {package}. " "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 {package}." "If you are attempting to install a library, pipx should not be used. " "Consider using pip or a similar tool instead.") if metadata.apps: pass elif 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 {package} 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, metadata.app_paths, package, force=force) if include_dependencies: for _, app_paths in metadata.app_paths_of_dependencies.items(): _expose_apps_globally(local_bin_dir, app_paths, package, force=force) 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)