Improve style of the pip upgrade prompt
This style makes the upgrade prompt less of blurb of yellow text, making
it easier to read while clarifying the presentation style to make it
easier to figure out what the user is supposed to run.
@@ -5,15 +5,20 @@ import logging
import optparse
import os.path
import sys
+from dataclasses import dataclass
from typing import Any, Dict, Optional
from pip._vendor.packaging.version import parse as parse_version
+from pip._vendor.rich.console import Group
+from pip._vendor.rich.markup import escape
+from pip._vendor.rich.text import Text
from pip._internal.index.collector import LinkCollector
from pip._internal.index.package_finder import PackageFinder
from pip._internal.metadata import get_default_environment
from pip._internal.models.selection_prefs import SelectionPreferences
from pip._internal.network.session import PipSession
+from pip._internal.utils.entrypoints import get_best_invocation_for_this_pip
from pip._internal.utils.filesystem import adjacent_tmp_file, check_path_owner, replace
from pip._internal.utils.misc import ensure_dir
@@ -107,6 +112,28 @@ class SelfCheckState:
pass
+@dataclass
+class UpgradePrompt:
+ old: str
+ new: str
+
+ def __rich__(self) -> Group:
+ pip_cmd = get_best_invocation_for_this_pip()
+
+ notice = "[bold][[reset][blue]notice[reset][bold]][reset]"
+ return Group(
+ Text(),
+ Text.from_markup(
+ f"{notice} A new release of pip available: "
+ f"[red]{self.old}[reset] -> [green]{self.new}[reset]"
+ ),
+ Text.from_markup(
+ f"{notice} To update, run: "
+ f"[green]{escape(pip_cmd)} install --upgrade pip"
+ ),
+ )
+
+
def was_installed_by_pip(pkg: str) -> bool:
"""Checks whether pkg was installed by pip
@@ -179,25 +206,10 @@ def pip_self_version_check(session: PipSession, options: optparse.Values) -> Non
if not local_version_is_older:
return
- # We cannot tell how the current pip is available in the current
- # command context, so be pragmatic here and suggest the command
- # that's always available. This does not accommodate spaces in
- # `sys.executable` on purpose as it is not possible to do it
- # correctly without knowing the user's shell. Thus,
- # it won't be done until possible through the standard library.
- # Do not be tempted to use the undocumented subprocess.list2cmdline.
- # It is considered an internal implementation detail for a reason.
- pip_cmd = f"{sys.executable} -m pip"
- logger.warning(
- "You are using pip version %s; however, version %s is "
- "available.\nYou should consider upgrading via the "
- "'%s install --upgrade pip' command.",
- local_version,
- remote_version_str,
- pip_cmd,
+ logger.info(
+ "[present-rich] %s",
+ UpgradePrompt(old=str(local_version), new=remote_version_str),
)
except Exception:
- logger.debug(
- "There was an error checking the latest version of pip",
- exc_info=True,
- )
+ logger.warning("There was an error checking the latest version of pip.")
+ logger.debug("See below for error", exc_info=True)
