Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions news/13354.bugfix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Stop animating progress bars and status spinners when running on CI, even
if ``FORCE_COLOR`` is set.
30 changes: 1 addition & 29 deletions src/pip/_internal/network/session.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
from pip._internal.utils.glibc import libc_ver
from pip._internal.utils.misc import (
build_url_from_netloc,
looks_like_ci,
parse_netloc,
redact_auth_from_url,
)
Expand Down Expand Up @@ -79,35 +80,6 @@
]


# These are environment variables present when running under various
# CI systems. For each variable, some CI systems that use the variable
# are indicated. The collection was chosen so that for each of a number
# of popular systems, at least one of the environment variables is used.
# This list is used to provide some indication of and lower bound for
# CI traffic to PyPI. Thus, it is okay if the list is not comprehensive.
# For more background, see: https://github.com/pypa/pip/issues/5499
CI_ENVIRONMENT_VARIABLES = (
# Azure Pipelines
"BUILD_BUILDID",
# Jenkins
"BUILD_ID",
# AppVeyor, CircleCI, Codeship, Gitlab CI, Shippable, Travis CI
"CI",
# Explicit environment variable.
"PIP_IS_CI",
)


def looks_like_ci() -> bool:
"""
Return whether it looks like pip is running under CI.
"""
# We don't use the method of checking for a tty (e.g. using isatty())
# because some CI systems mimic a tty (e.g. Travis CI). Thus that
# method doesn't provide definitive information in either direction.
return any(name in os.environ for name in CI_ENVIRONMENT_VARIABLES)


@functools.lru_cache(maxsize=1)
def user_agent() -> str:
"""
Expand Down
14 changes: 11 additions & 3 deletions src/pip/_internal/utils/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
from pip._internal.utils._log import VERBOSE, getLogger
from pip._internal.utils.compat import WINDOWS
from pip._internal.utils.deprecation import DEPRECATION_MSG_PREFIX
from pip._internal.utils.misc import StreamWrapper, ensure_dir
from pip._internal.utils.misc import StreamWrapper, ensure_dir, looks_like_ci

_log_state = threading.local()
_stdout_console = None
Expand Down Expand Up @@ -320,8 +320,16 @@ def setup_logging(verbosity: int, no_color: bool, user_log_file: str | None) ->
["user_log"] if include_user_log else []
)
global _stdout_console, stderr_console
_stdout_console = PipConsole(file=sys.stdout, no_color=no_color, soft_wrap=True)
_stderr_console = PipConsole(file=sys.stderr, no_color=no_color, soft_wrap=True)
console_options: dict[str, Any] = {"no_color": no_color, "soft_wrap": True}
if looks_like_ci():
# Don't animate progress bars and status spinners when running
# in CI. A lot of CI workflows use FORCE_COLOR and similar envvars
# so their CI output remains colorized, but this causes rich to
# assume a fully interactive terminal, resulting in any animated
# output to span many lines which is distracting (and unhelpful).
console_options["force_interactive"] = False
_stdout_console = PipConsole(file=sys.stdout, **console_options)
_stderr_console = PipConsole(file=sys.stderr, **console_options)

logging.config.dictConfig(
{
Expand Down
28 changes: 28 additions & 0 deletions src/pip/_internal/utils/misc.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@
"ensure_dir",
"remove_auth_from_url",
"check_externally_managed",
"looks_like_ci",
"ConfiguredBuildBackendHookCaller",
]

Expand All @@ -65,6 +66,23 @@
OnErr = Callable[[FunctionType, Path, ExcInfo], Any]

FILE_CHUNK_SIZE = 1024 * 1024
# These are environment variables present when running under various
# CI systems. For each variable, some CI systems that use the variable
# are indicated. The collection was chosen so that for each of a number
# of popular systems, at least one of the environment variables is used.
# This list is used to provide some indication of and lower bound for
# CI traffic to PyPI. Thus, it is okay if the list is not comprehensive.
# For more background, see: https://github.com/pypa/pip/issues/5499
CI_ENVIRONMENT_VARIABLES = (
# Azure Pipelines
"BUILD_BUILDID",
# Jenkins
"BUILD_ID",
# AppVeyor, CircleCI, Codeship, Gitlab CI, Shippable, Travis CI
"CI",
# Explicit environment variable.
"PIP_IS_CI",
)


def get_pip_version() -> str:
Expand Down Expand Up @@ -785,3 +803,13 @@ def warn_if_run_as_root() -> None:
"Use the --root-user-action option if you know what you are doing and "
"want to suppress this warning."
)


def looks_like_ci() -> bool:
"""
Return whether it looks like pip is running under CI.
"""
# We don't use the method of checking for a tty (e.g. using isatty())
# because some CI systems mimic a tty (e.g. Travis CI). Thus that
# method doesn't provide definitive information in either direction.
return any(name in os.environ for name in CI_ENVIRONMENT_VARIABLES)
2 changes: 1 addition & 1 deletion tests/unit/test_network_session.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@
)
from pip._internal.models.link import Link
from pip._internal.network.session import (
CI_ENVIRONMENT_VARIABLES,
HTTPAdapter,
PipSession,
user_agent,
)
from pip._internal.utils.misc import CI_ENVIRONMENT_VARIABLES

from tests.lib.output import render_to_text
from tests.lib.server import make_mock_server, server_running
Expand Down
Loading