Exemplo n.º 1
0
def list_packages(venv_container: VenvContainer, include_injected: bool) -> None:
    dirs: Collection[Path] = sorted(venv_container.iter_venv_dirs())
    if not dirs:
        print(f"nothing has been installed with pipx {sleep}")
        return

    print(f"venvs are in {bold(str(venv_container))}")
    print(f"apps are exposed on your $PATH at {bold(str(constants.LOCAL_BIN_DIR))}")

    venv_container.verify_shared_libs()

    if Pool:
        p = Pool()
        try:
            for package_summary in p.map(
                partial(get_package_summary, include_injected=include_injected), dirs,
            ):
                print(package_summary)
        finally:
            p.close()
            p.join()
    else:
        for package_summary in map(
            partial(get_package_summary, include_injected=include_injected), dirs,
        ):
            print(package_summary)
Exemplo n.º 2
0
def list_packages(venv_container: VenvContainer,
                  include_injected: bool) -> ExitCode:
    """Returns pipx exit code."""
    dirs: Collection[Path] = sorted(venv_container.iter_venv_dirs())
    if not dirs:
        print(f"nothing has been installed with pipx {sleep}")
        return EXIT_CODE_OK

    print(f"venvs are in {bold(str(venv_container))}")
    print(
        f"apps are exposed on your $PATH at {bold(str(constants.LOCAL_BIN_DIR))}"
    )

    venv_container.verify_shared_libs()

    all_venv_problems = VenvProblems()
    if Pool:
        p = Pool()
        try:
            for package_summary, venv_problems in p.map(
                    partial(get_package_summary,
                            include_injected=include_injected), dirs):
                print(package_summary)
                all_venv_problems.or_(venv_problems)
        finally:
            p.close()
            p.join()
    else:
        for package_summary, venv_problems in map(
                partial(get_package_summary,
                        include_injected=include_injected), dirs):
            print(package_summary)
            all_venv_problems.or_(venv_problems)

    if all_venv_problems.bad_venv_name:
        print(
            "\nOne or more packages contain out-of-date internal data installed from a\n"
            "previous pipx version and need to be updated.\n"
            "    To fix, execute: pipx reinstall-all")
    if all_venv_problems.invalid_interpreter:
        print("\nOne or more packages have a missing python interpreter.\n"
              "    To fix, execute: pipx reinstall-all")
    if all_venv_problems.missing_metadata:
        print(
            "\nOne or more packages have a missing internal pipx metadata.\n"
            "   They were likely installed using a pipx version before 0.15.0.0.\n"
            "   Please uninstall and install these package(s) to fix.")
    if all_venv_problems.not_installed:
        print("\nOne or more packages are not installed properly.\n"
              "   Please uninstall and install these package(s) to fix.")

    if all_venv_problems.any_():
        print()
        return EXIT_CODE_LIST_PROBLEM

    return EXIT_CODE_OK
Exemplo n.º 3
0
def list_packages(venv_container: VenvContainer):
    dirs = list(sorted(venv_container.iter_venv_dirs()))
    if not dirs:
        print(f"nothing has been installed with pipx {sleep}")
        return

    print(f"venvs are in {bold(str(venv_container))}")
    print(f"apps are exposed on your $PATH at {bold(str(constants.LOCAL_BIN_DIR))}")

    venv_container.verify_shared_libs()

    with Pool() as p:
        for package_summary in p.map(_get_package_summary, dirs):
            print(package_summary)
Exemplo n.º 4
0
def reinstall_all(
    venv_container: VenvContainer,
    local_bin_dir: Path,
    python: str,
    verbose: bool,
    *,
    skip: List[str],
) -> int:
    """Returns pipx shell exit code"""
    failed: List[str] = []
    for venv_dir in venv_container.iter_venv_dirs():
        if venv_dir.name in skip:
            continue
        try:
            reinstall(
                venv_dir=venv_dir,
                local_bin_dir=local_bin_dir,
                python=python,
                verbose=verbose,
            )
        except PipxError as e:
            print(e, file=sys.stderr)
            failed.append(venv_dir.name)
    if len(failed) > 0:
        raise PipxError(
            f"The following package(s) failed to reinstall: {', '.join(failed)}"
        )
    return 0
Exemplo n.º 5
0
def get_command_parser() -> argparse.ArgumentParser:
    venv_container = VenvContainer(constants.PIPX_LOCAL_VENVS)

    completer_venvs = InstalledVenvsCompleter(venv_container)

    parser = argparse.ArgumentParser(
        formatter_class=LineWrapRawTextHelpFormatter,
        description=PIPX_DESCRIPTION)

    subparsers = parser.add_subparsers(
        dest="command",
        description="Get help for commands with pipx COMMAND --help")

    _add_install(subparsers)
    _add_inject(subparsers, completer_venvs.use)
    _add_upgrade(subparsers, completer_venvs.use)
    _add_upgrade_all(subparsers)
    _add_uninstall(subparsers, completer_venvs.use)
    _add_uninstall_all(subparsers)
    _add_reinstall(subparsers, completer_venvs.use)
    _add_reinstall_all(subparsers)
    _add_list(subparsers)
    _add_run(subparsers)
    _add_runpip(subparsers, completer_venvs.use)
    _add_ensurepath(subparsers)

    parser.add_argument("--version",
                        action="store_true",
                        help="Print version and exit")
    subparsers.add_parser(
        "completions",
        help="Print instructions on enabling shell completions for pipx",
        description="Print instructions on enabling shell completions for pipx",
    )
    return parser
Exemplo n.º 6
0
def upgrade_all(venv_container: VenvContainer, verbose: bool, *,
                skip: List[str], force: bool):
    venv_error = False
    venvs_upgraded = 0
    for venv_dir in venv_container.iter_venv_dirs():
        venv = Venv(venv_dir, verbose=verbose)
        if (venv_dir.name in skip
                or "--editable" in venv.pipx_metadata.main_package.pip_args):
            continue
        try:
            venvs_upgraded += upgrade(
                venv_dir,
                venv.pipx_metadata.main_package.pip_args,
                verbose,
                upgrading_all=True,
                force=force,
            )

        except Exception:
            venv_error = True
            logging.error(f"Error encountered when upgrading {venv_dir.name}")

    if venvs_upgraded == 0:
        print(
            f"Versions did not change after running 'pip upgrade' for each package {sleep}"
        )
    if venv_error:
        raise PipxError("Some packages encountered errors during upgrade. "
                        "See specific error messages above.")
Exemplo n.º 7
0
def reinstall_all(
    venv_container: VenvContainer,
    local_bin_dir: Path,
    python: str,
    verbose: bool,
    *,
    skip: Sequence[str],
) -> ExitCode:
    """Returns pipx exit code."""
    pipx.shared_libs.shared_libs.upgrade(verbose=verbose)

    failed: List[str] = []
    for venv_dir in venv_container.iter_venv_dirs():
        if venv_dir.name in skip:
            continue
        try:
            package_exit = reinstall(
                venv_dir=venv_dir,
                local_bin_dir=local_bin_dir,
                python=python,
                verbose=verbose,
            )
        except PipxError as e:
            print(e, file=sys.stderr)
            failed.append(venv_dir.name)
        if package_exit != 0:
            failed.append(venv_dir.name)
    if len(failed) > 0:
        raise PipxError(
            f"The following package(s) failed to reinstall: {', '.join(failed)}"
        )
    # Any failure to install will raise PipxError, otherwise success
    return EXIT_CODE_OK
Exemplo n.º 8
0
def reinstall_all(
    venv_container: VenvContainer,
    local_bin_dir: Path,
    python: str,
    pip_args: List[str],
    venv_args: List[str],
    verbose: bool,
    include_dependencies: bool,
    *,
    skip: List[str],
):
    for venv_dir in venv_container.iter_venv_dirs():
        package = venv_dir.name
        if package in skip:
            continue
        uninstall(venv_dir, package, local_bin_dir, verbose)

        package_or_url = package
        install(
            venv_dir,
            package,
            package_or_url,
            local_bin_dir,
            python,
            pip_args,
            venv_args,
            verbose,
            force=True,
            include_dependencies=include_dependencies,
        )
Exemplo n.º 9
0
def upgrade_all(venv_container: VenvContainer, verbose: bool, *,
                skip: List[str], force: bool):
    packages_upgraded = 0
    num_packages = 0
    for venv_dir in venv_container.iter_venv_dirs():
        num_packages += 1
        package = venv_dir.name
        venv = Venv(venv_dir, verbose=verbose)
        if package in skip or "--editable" in venv.pipx_metadata.main_package.pip_args:
            continue
        try:
            packages_upgraded += upgrade(
                venv_dir,
                package,
                venv.pipx_metadata.main_package.pip_args,
                verbose,
                upgrading_all=True,
                force=force,
            )

        except Exception:
            logging.error(f"Error encountered when upgrading {package}")

    if packages_upgraded == 0:
        print(
            f"Versions did not change after running 'pip upgrade' for each package {sleep}"
        )
Exemplo n.º 10
0
def list_packages(
    venv_container: VenvContainer,
    include_injected: bool,
    json_format: bool,
    short_format: bool,
) -> ExitCode:
    """Returns pipx exit code."""
    venv_dirs: Collection[Path] = sorted(venv_container.iter_venv_dirs())
    if not venv_dirs:
        print(f"nothing has been installed with pipx {sleep}", file=sys.stderr)

    venv_container.verify_shared_libs()

    if json_format:
        all_venv_problems = list_json(venv_dirs)
    elif short_format:
        all_venv_problems = list_short(venv_dirs)
    else:
        if not venv_dirs:
            return EXIT_CODE_OK
        all_venv_problems = list_text(venv_dirs, include_injected,
                                      str(venv_container))

    if all_venv_problems.bad_venv_name:
        logger.warning(
            "\nOne or more packages contain out-of-date internal data installed from a\n"
            "previous pipx version and need to be updated.\n"
            "    To fix, execute: pipx reinstall-all")
    if all_venv_problems.invalid_interpreter:
        logger.warning(
            "\nOne or more packages have a missing python interpreter.\n"
            "    To fix, execute: pipx reinstall-all")
    if all_venv_problems.missing_metadata:
        logger.warning(
            "\nOne or more packages have a missing internal pipx metadata.\n"
            "   They were likely installed using a pipx version before 0.15.0.0.\n"
            "   Please uninstall and install these package(s) to fix.")
    if all_venv_problems.not_installed:
        logger.warning(
            "\nOne or more packages are not installed properly.\n"
            "   Please uninstall and install these package(s) to fix.")

    if all_venv_problems.any_():
        print("", file=sys.stderr)
        return EXIT_CODE_LIST_PROBLEM

    return EXIT_CODE_OK
Exemplo n.º 11
0
def uninstall_all(venv_container: VenvContainer, local_bin_dir: Path,
                  verbose: bool) -> ExitCode:
    """Returns pipx exit code."""
    all_success = True
    for venv_dir in venv_container.iter_venv_dirs():
        return_val = uninstall(venv_dir, local_bin_dir, verbose)
        all_success &= return_val == 0

    return EXIT_CODE_OK if all_success else EXIT_CODE_UNINSTALL_ERROR
Exemplo n.º 12
0
def reinstall_all(
    venv_container: VenvContainer,
    local_bin_dir: Path,
    python: str,
    verbose: bool,
    *,
    skip: List[str],
):
    for venv_dir in venv_container.iter_venv_dirs():
        package = venv_dir.name
        if package in skip:
            continue

        venv = Venv(venv_dir, verbose=verbose)

        if venv.pipx_metadata.main_package.package_or_url is not None:
            package_or_url = venv.pipx_metadata.main_package.package_or_url
        else:
            package_or_url = package

        uninstall(venv_dir, package, local_bin_dir, verbose)

        # install main package first
        install(
            venv_dir,
            package,
            package_or_url,
            local_bin_dir,
            python,
            venv.pipx_metadata.main_package.pip_args,
            venv.pipx_metadata.venv_args,
            verbose,
            force=True,
            include_dependencies=venv.pipx_metadata.main_package.
            include_dependencies,
        )

        # now install injected packages
        for (
                injected_name,
                injected_package,
        ) in venv.pipx_metadata.injected_packages.items():
            if injected_package.package_or_url is None:
                # This should never happen, but package_or_url is type
                #   Optional[str] so mypy thinks it could be None
                raise PipxError("Internal Error injecting package")
            inject(
                venv_dir,
                injected_name,
                injected_package.package_or_url,
                injected_package.pip_args,
                verbose=verbose,
                include_apps=injected_package.include_apps,
                include_dependencies=injected_package.include_dependencies,
                force=True,
            )
Exemplo n.º 13
0
def upgrade_all(
    venv_container: VenvContainer,
    verbose: bool,
    *,
    include_injected: bool,
    skip: Sequence[str],
    force: bool,
) -> ExitCode:
    """Returns pipx exit code."""
    venv_error = False
    venvs_upgraded = 0
    for venv_dir in venv_container.iter_venv_dirs():
        venv = Venv(venv_dir, verbose=verbose)
        if (
            venv_dir.name in skip
            or "--editable" in venv.pipx_metadata.main_package.pip_args
        ):
            continue
        try:
            venvs_upgraded += _upgrade_venv(
                venv_dir,
                venv.pipx_metadata.main_package.pip_args,
                verbose,
                include_injected=include_injected,
                upgrading_all=True,
                force=force,
            )

        except PipxError as e:
            venv_error = True
            logger.error(f"Error encountered when upgrading {venv_dir.name}:")
            logger.error(f"{e}\n")

    if venvs_upgraded == 0:
        print(
            f"Versions did not change after running 'pip upgrade' for each package {sleep}"
        )
    if venv_error:
        raise PipxError(
            "\nSome packages encountered errors during upgrade.\n"
            "    See specific error messages above."
        )

    return EXIT_CODE_OK
Exemplo n.º 14
0
def upgrade_all(
    venv_container: VenvContainer,
    pip_args: List[str],
    verbose: bool,
    *,
    include_dependencies: bool,
    skip: List[str],
    force: bool,
):
    packages_upgraded = 0
    num_packages = 0
    for venv_dir in venv_container.iter_venv_dirs():
        num_packages += 1
        package = venv_dir.name
        if package in skip:
            continue
        if package == "pipx":
            package_or_url = PIPX_PACKAGE_NAME
        else:
            package_or_url = package
        try:
            packages_upgraded += upgrade(
                venv_dir,
                package,
                package_or_url,
                pip_args,
                verbose,
                upgrading_all=True,
                include_dependencies=include_dependencies,
                force=force,
            )
        except Exception:
            logging.error(f"Error encountered when upgrading {package}")

    if packages_upgraded == 0:
        print(
            f"Versions did not change after running 'pip upgrade' for each package {sleep}"
        )
Exemplo n.º 15
0
def install(
    venv_dir: Optional[Path],
    package_name: Optional[str],
    package_spec: str,
    local_bin_dir: Path,
    python: str,
    pip_args: List[str],
    venv_args: List[str],
    verbose: bool,
    *,
    force: bool,
    include_dependencies: bool,
    suffix: str = "",
):
    # package_spec is anything pip-installable, including package_name, vcs spec,
    #   zip file, or tar.gz file.

    if package_name is None:
        package_name = package_name_from_spec(package_spec,
                                              python,
                                              pip_args=pip_args,
                                              verbose=verbose)
    if venv_dir is None:
        venv_container = VenvContainer(constants.PIPX_LOCAL_VENVS)
        venv_dir = venv_container.get_venv_dir(package_name)
        if suffix != "":
            venv_dir = venv_dir.parent / f"{venv_dir.stem}{suffix}"

    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"{venv_dir.name!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=package_name,
            package_or_url=package_spec,
            pip_args=pip_args,
            include_dependencies=include_dependencies,
            include_apps=True,
            is_main_package=True,
            suffix=suffix,
        )
        run_post_install_actions(
            venv,
            package_name,
            local_bin_dir,
            venv_dir,
            include_dependencies,
            force=force,
        )
    except (Exception, KeyboardInterrupt):
        print("")
        venv.remove_venv()
        raise
Exemplo n.º 16
0
def run_pipx_command(args: argparse.Namespace) -> ExitCode:  # noqa: C901
    verbose = args.verbose if "verbose" in args else False
    pip_args = get_pip_args(vars(args))
    venv_args = get_venv_args(vars(args))

    venv_container = VenvContainer(constants.PIPX_LOCAL_VENVS)

    if "package" in args:
        package = args.package
        if urllib.parse.urlparse(package).scheme:
            raise PipxError("Package cannot be a url")

        if "spec" in args and args.spec is not None:
            if urllib.parse.urlparse(args.spec).scheme:
                if "#egg=" not in args.spec:
                    args.spec = args.spec + f"#egg={package}"

        venv_dir = venv_container.get_venv_dir(package)
        logger.info(f"Virtual Environment location is {venv_dir}")
    if "skip" in args:
        skip_list = [canonicalize_name(x) for x in args.skip]

    if args.command == "run":
        package_or_url = (args.spec if
                          ("spec" in args and args.spec is not None) else
                          args.app_with_args[0])
        use_cache = not args.no_cache
        commands.run(
            args.app_with_args[0],
            package_or_url,
            args.app_with_args[1:],
            args.python,
            pip_args,
            venv_args,
            args.pypackages,
            verbose,
            use_cache,
        )
        # We should never reach here because run() is NoReturn.
        return ExitCode(1)
    elif args.command == "install":
        return commands.install(
            None,
            None,
            args.package_spec,
            constants.LOCAL_BIN_DIR,
            args.python,
            pip_args,
            venv_args,
            verbose,
            force=args.force,
            include_dependencies=args.include_deps,
            suffix=args.suffix,
        )
    elif args.command == "inject":
        return commands.inject(
            venv_dir,
            None,
            args.dependencies,
            pip_args,
            verbose=verbose,
            include_apps=args.include_apps,
            include_dependencies=args.include_deps,
            force=args.force,
        )
    elif args.command == "upgrade":
        return commands.upgrade(
            venv_dir,
            pip_args,
            verbose,
            include_injected=args.include_injected,
            force=args.force,
        )
    elif args.command == "upgrade-all":
        return commands.upgrade_all(
            venv_container,
            verbose,
            include_injected=args.include_injected,
            skip=skip_list,
            force=args.force,
        )
    elif args.command == "list":
        return commands.list_packages(venv_container, args.include_injected)
    elif args.command == "uninstall":
        return commands.uninstall(venv_dir, constants.LOCAL_BIN_DIR, verbose)
    elif args.command == "uninstall-all":
        return commands.uninstall_all(venv_container, constants.LOCAL_BIN_DIR,
                                      verbose)
    elif args.command == "reinstall":
        return commands.reinstall(
            venv_dir=venv_dir,
            local_bin_dir=constants.LOCAL_BIN_DIR,
            python=args.python,
            verbose=verbose,
        )
    elif args.command == "reinstall-all":
        return commands.reinstall_all(
            venv_container,
            constants.LOCAL_BIN_DIR,
            args.python,
            verbose,
            skip=skip_list,
        )
    elif args.command == "runpip":
        if not venv_dir:
            raise PipxError("Developer error: venv_dir is not defined.")
        return commands.run_pip(package, venv_dir, args.pipargs, args.verbose)
    elif args.command == "ensurepath":
        try:
            return commands.ensure_pipx_paths(force=args.force)
        except Exception as e:
            logger.debug("Uncaught Exception:", exc_info=True)
            raise PipxError(str(e), wrap_message=False)
    elif args.command == "completions":
        print(constants.completion_instructions)
        return ExitCode(0)
    else:
        raise PipxError(f"Unknown command {args.command}")
Exemplo n.º 17
0
 def __init__(self, venv_container: VenvContainer) -> None:
     self.packages = [
         str(p.name) for p in sorted(venv_container.iter_venv_dirs())
     ]
Exemplo n.º 18
0
def uninstall_all(venv_container: VenvContainer, local_bin_dir: Path,
                  verbose: bool):
    for venv_dir in venv_container.iter_venv_dirs():
        package = venv_dir.name
        uninstall(venv_dir, package, local_bin_dir, verbose)
Exemplo n.º 19
0
def install(
    venv_dir: Optional[Path],
    package_name: Optional[str],
    package_spec: str,
    local_bin_dir: Path,
    python: str,
    pip_args: List[str],
    venv_args: List[str],
    verbose: bool,
    *,
    force: bool,
    include_dependencies: bool,
    suffix: str = "",
) -> ExitCode:
    """Returns pipx exit code."""
    # package_spec is anything pip-installable, including package_name, vcs spec,
    #   zip file, or tar.gz file.

    if package_name is None:
        package_name = package_name_from_spec(package_spec,
                                              python,
                                              pip_args=pip_args,
                                              verbose=verbose)
    if venv_dir is None:
        venv_container = VenvContainer(constants.PIPX_LOCAL_VENVS)
        venv_dir = venv_container.get_venv_dir(f"{package_name}{suffix}")

    try:
        exists = venv_dir.exists() and bool(next(venv_dir.iterdir()))
    except StopIteration:
        exists = False

    venv = Venv(venv_dir, python=python, verbose=verbose)
    if exists:
        if force:
            print(f"Installing to existing venv {venv.name!r}")
        else:
            print(
                pipx_wrap(f"""
                    {venv.name!r} already seems to be installed. Not modifying
                    existing installation in {str(venv_dir)!r}. Pass '--force'
                    to force installation.
                    """))
            return EXIT_CODE_INSTALL_VENV_EXISTS

    try:
        venv.create_venv(venv_args, pip_args)
        venv.install_package(
            package_name=package_name,
            package_or_url=package_spec,
            pip_args=pip_args,
            include_dependencies=include_dependencies,
            include_apps=True,
            is_main_package=True,
            suffix=suffix,
        )
        run_post_install_actions(
            venv,
            package_name,
            local_bin_dir,
            venv_dir,
            include_dependencies,
            force=force,
        )
    except (Exception, KeyboardInterrupt):
        print()
        venv.remove_venv()
        raise

    # Any failure to install will raise PipxError, otherwise success
    return EXIT_CODE_OK