diff --git a/news/11171.feature.rst b/news/11171.feature.rst new file mode 100644 index 000000000..3c4e2d2d2 --- /dev/null +++ b/news/11171.feature.rst @@ -0,0 +1 @@ +Add ability to force progress bars to be used, for allowing progress bars to be shown in subprocesses. diff --git a/src/pip/_internal/cli/cmdoptions.py b/src/pip/_internal/cli/cmdoptions.py index d05e502f9..ed8114e72 100644 --- a/src/pip/_internal/cli/cmdoptions.py +++ b/src/pip/_internal/cli/cmdoptions.py @@ -226,9 +226,12 @@ progress_bar: Callable[..., Option] = partial( "--progress-bar", dest="progress_bar", type="choice", - choices=["on", "off"], + choices=["on", "off", "forced"], default="on", - help="Specify whether the progress bar should be used [on, off] (default: on)", + help=( + "Specify whether the progress bar should be used [on, off, forced]" + " (default: on)" + ), ) log: Callable[..., Option] = partial( diff --git a/src/pip/_internal/cli/progress_bars.py b/src/pip/_internal/cli/progress_bars.py index 0ad14031c..2b088418c 100644 --- a/src/pip/_internal/cli/progress_bars.py +++ b/src/pip/_internal/cli/progress_bars.py @@ -1,6 +1,7 @@ import functools from typing import Callable, Generator, Iterable, Iterator, Optional, Tuple +from pip._vendor.rich.console import Console from pip._vendor.rich.progress import ( BarColumn, DownloadColumn, @@ -25,7 +26,9 @@ def _rich_progress_bar( bar_type: str, size: int, ) -> Generator[bytes, None, None]: - assert bar_type == "on", "This should only be used in the default mode." + assert ( + bar_type == "on" or bar_type == "forced" + ), "This should only be used in the default mode or if forced." if not size: total = float("inf") @@ -47,7 +50,13 @@ def _rich_progress_bar( TimeRemainingColumn(), ) - progress = Progress(*columns, refresh_per_second=30) + progress = Progress( + *columns, + refresh_per_second=30, + console=Console( + force_terminal=bar_type == "forced", + ), + ) task_id = progress.add_task(" " * (get_indentation() + 2), total=total) with progress: for chunk in iterable: @@ -62,7 +71,7 @@ def get_download_progress_renderer( Returns a callable, that takes an iterable to "wrap". """ - if bar_type == "on": + if bar_type == "on" or bar_type == "forced": return functools.partial(_rich_progress_bar, bar_type=bar_type, size=size) else: return iter # no-op, when passed an iterator