Beispiel #1
0
 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)
Beispiel #2
0
    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,
        )
Beispiel #3
0
 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)
Beispiel #4
0
    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
Beispiel #5
0
    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
Beispiel #6
0
    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)
Beispiel #7
0
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
Beispiel #8
0
 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)
Beispiel #9
0
 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)
Beispiel #10
0
    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,
            )
Beispiel #11
0
    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,
            )
Beispiel #12
0
    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
Beispiel #13
0
    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."
            )
Beispiel #14
0
 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")
Beispiel #15
0
    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.")
Beispiel #16
0
    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)
Beispiel #17
0
    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,
        )
Beispiel #18
0
 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])
Beispiel #19
0
 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])
Beispiel #20
0
 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)
Beispiel #21
0
 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", [])
Beispiel #22
0
 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)
Beispiel #23
0
 def create_venv(self) -> None:
     with animate("creating virtual environment", self.do_animation):
         _run([self._python, "-m", "venv", self.root])
         self.upgrade_package("pip")