Skip to content

Commit 60a1a66

Browse files
ichard26q0w
andauthored
Suppress the progress bar with --quiet and --log (#13467)
If users still want the progress bar, then --progress-bar on will do the trick. To make this work, a new "auto" mode has been added. It's equivalent to "on" when running at default or higher verbosity, "off" otherwise. Co-authored-by: q0w <[email protected]>
1 parent ca77126 commit 60a1a66

File tree

8 files changed

+41
-13
lines changed

8 files changed

+41
-13
lines changed

news/10915.bugfix.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
Suppress the progress bar, when running with ``--log`` and ``--quiet``.
2+
3+
Consequently, a new ``auto`` mode for ``--progress-bar`` has been added.
4+
``auto`` will enable progress bars unless suppressed by ``--quiet``,
5+
while ``on`` will always enable progress bars.

src/pip/_internal/cli/base_command.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,9 @@ def _main(self, args: list[str]) -> int:
176176
if options.debug_mode:
177177
self.verbosity = 2
178178

179+
if hasattr(options, "progress_bar") and options.progress_bar == "auto":
180+
options.progress_bar = "on" if self.verbosity >= 0 else "off"
181+
179182
reconfigure(no_color=options.no_color)
180183
level_number = setup_logging(
181184
verbosity=self.verbosity,

src/pip/_internal/cli/cmdoptions.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -228,9 +228,13 @@ class PipOption(Option):
228228
"--progress-bar",
229229
dest="progress_bar",
230230
type="choice",
231-
choices=["on", "off", "raw"],
232-
default="on",
233-
help="Specify whether the progress bar should be used [on, off, raw] (default: on)",
231+
choices=["auto", "on", "off", "raw"],
232+
default="auto",
233+
help=(
234+
"Specify whether the progress bar should be used. In 'auto'"
235+
" mode, --quiet will suppress all progress bars."
236+
" [auto, on, off, raw] (default: auto)"
237+
),
234238
)
235239

236240
log: Callable[..., Option] = partial(

src/pip/_internal/cli/progress_bars.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import functools
44
import sys
55
from collections.abc import Generator, Iterable, Iterator
6-
from typing import Callable, TypeVar
6+
from typing import Callable, Literal, TypeVar
77

88
from pip._vendor.rich.progress import (
99
BarColumn,
@@ -25,12 +25,13 @@
2525

2626
T = TypeVar("T")
2727
ProgressRenderer = Callable[[Iterable[T]], Iterator[T]]
28+
BarType = Literal["on", "off", "raw"]
2829

2930

3031
def _rich_download_progress_bar(
3132
iterable: Iterable[bytes],
3233
*,
33-
bar_type: str,
34+
bar_type: BarType,
3435
size: int | None,
3536
initial_progress: int | None = None,
3637
) -> Generator[bytes, None, None]:
@@ -112,7 +113,7 @@ def write_progress(current: int, total: int) -> None:
112113

113114

114115
def get_download_progress_renderer(
115-
*, bar_type: str, size: int | None = None, initial_progress: int | None = None
116+
*, bar_type: BarType, size: int | None = None, initial_progress: int | None = None
116117
) -> ProgressRenderer[bytes]:
117118
"""Get an object that can be used to render the download progress.
118119
@@ -136,7 +137,7 @@ def get_download_progress_renderer(
136137

137138

138139
def get_install_progress_renderer(
139-
*, bar_type: str, total: int
140+
*, bar_type: BarType, total: int
140141
) -> ProgressRenderer[InstallRequirement]:
141142
"""Get an object that can be used to render the install progress.
142143
Returns a callable, that takes an iterable to "wrap".

src/pip/_internal/network/download.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
from pip._vendor.urllib3._collections import HTTPHeaderDict
1818
from pip._vendor.urllib3.exceptions import ReadTimeoutError
1919

20-
from pip._internal.cli.progress_bars import get_download_progress_renderer
20+
from pip._internal.cli.progress_bars import BarType, get_download_progress_renderer
2121
from pip._internal.exceptions import IncompleteDownloadError, NetworkConnectionError
2222
from pip._internal.models.index import PyPI
2323
from pip._internal.models.link import Link
@@ -47,7 +47,7 @@ def _get_http_response_etag_or_last_modified(resp: Response) -> str | None:
4747
def _log_download(
4848
resp: Response,
4949
link: Link,
50-
progress_bar: str,
50+
progress_bar: BarType,
5151
total_length: int | None,
5252
range_start: int | None = 0,
5353
) -> Iterable[bytes]:
@@ -166,7 +166,7 @@ class Downloader:
166166
def __init__(
167167
self,
168168
session: PipSession,
169-
progress_bar: str,
169+
progress_bar: BarType,
170170
resume_retries: int,
171171
) -> None:
172172
assert (

src/pip/_internal/operations/prepare.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
from collections.abc import Iterable
1111
from dataclasses import dataclass
1212
from pathlib import Path
13+
from typing import TYPE_CHECKING
1314

1415
from pip._vendor.packaging.utils import canonicalize_name
1516

@@ -54,6 +55,9 @@
5455
from pip._internal.utils.unpacking import unpack_file
5556
from pip._internal.vcs import vcs
5657

58+
if TYPE_CHECKING:
59+
from pip._internal.cli.progress_bars import BarType
60+
5761
logger = getLogger(__name__)
5862

5963

@@ -229,7 +233,7 @@ def __init__(
229233
check_build_deps: bool,
230234
build_tracker: BuildTracker,
231235
session: PipSession,
232-
progress_bar: str,
236+
progress_bar: BarType,
233237
finder: PackageFinder,
234238
require_hashes: bool,
235239
use_user_site: bool,

src/pip/_internal/req/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
from collections.abc import Generator, Sequence
66
from dataclasses import dataclass
77

8-
from pip._internal.cli.progress_bars import get_install_progress_renderer
8+
from pip._internal.cli.progress_bars import BarType, get_install_progress_renderer
99
from pip._internal.utils.logging import indent_log
1010

1111
from .req_file import parse_requirements
@@ -44,7 +44,7 @@ def install_given_reqs(
4444
warn_script_location: bool,
4545
use_user_site: bool,
4646
pycompile: bool,
47-
progress_bar: str,
47+
progress_bar: BarType,
4848
) -> list[InstallationResult]:
4949
"""
5050
Install everything in the given list.

tests/functional/test_install_config.py

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,3 +539,14 @@ def set_password(self, url, username):
539539
assert function_name + " was called" in result.stderr
540540
else:
541541
assert function_name + " was called" not in result.stderr
542+
543+
544+
@pytest.mark.network
545+
def test_install_quiet_log(script: PipTestEnvironment, data: TestData) -> None:
546+
"""
547+
Test suppressing the progress bar with --quiet and --log.
548+
"""
549+
logfile = script.scratch_path / "log"
550+
result = script.pip("install", "-qqq", "setuptools==62.0.0", "--log", logfile)
551+
assert result.stdout == ""
552+
assert result.stderr == ""

0 commit comments

Comments
 (0)