Skip to content

Commit

Permalink
quiet all progress output from -q, and write progress to stderr
Browse files Browse the repository at this point in the history
  • Loading branch information
cosmicexplorer committed Aug 19, 2024
1 parent 61acf01 commit f42fb29
Show file tree
Hide file tree
Showing 5 changed files with 64 additions and 20 deletions.
55 changes: 41 additions & 14 deletions src/pip/_internal/cli/progress_bars.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ def _rich_progress_bar(
*,
bar_type: str,
size: int,
quiet: bool,
) -> Generator[bytes, None, None]:
assert bar_type == "on", "This should only be used in the default mode."

Expand All @@ -89,7 +90,9 @@ def _rich_progress_bar(
total = size
columns = _known_size_columns()

progress = Progress(*columns, console=Console(stderr=True), refresh_per_second=5)
progress = Progress(
*columns, console=Console(stderr=True, quiet=quiet), refresh_per_second=5
)
task_id = progress.add_task(_progress_task_prefix(), total=total)
with progress:
for chunk in iterable:
Expand All @@ -101,12 +104,15 @@ def _raw_progress_bar(
iterable: Iterable[bytes],
*,
size: Optional[int],
quiet: bool,
) -> Generator[bytes, None, None]:
prefix = _progress_task_prefix()

def write_progress(current: int, total: int) -> None:
sys.stdout.write(f"{prefix}Progress {current} of {total}\n")
sys.stdout.flush()
if quiet:
return
sys.stderr.write(f"{prefix}Progress {current} of {total}\n")
sys.stderr.flush()

current = 0
total = size or 0
Expand All @@ -122,16 +128,21 @@ def write_progress(current: int, total: int) -> None:


def get_download_progress_renderer(
*, bar_type: str, size: Optional[int] = None
*,
bar_type: str,
size: Optional[int] = None,
quiet: bool = False,
) -> DownloadProgressRenderer:
"""Get an object that can be used to render the download progress.
Returns a callable, that takes an iterable to "wrap".
"""
if bar_type == "on":
return functools.partial(_rich_progress_bar, bar_type=bar_type, size=size)
return functools.partial(
_rich_progress_bar, bar_type=bar_type, size=size, quiet=quiet
)
elif bar_type == "raw":
return functools.partial(_raw_progress_bar, size=size)
return functools.partial(_raw_progress_bar, size=size, quiet=quiet)
else:
return iter # no-op, when passed an iterator

Expand All @@ -158,7 +169,10 @@ def __exit__(self, ty: Any, val: Any, tb: Any) -> None: ...
@classmethod
@abc.abstractmethod
def create(
cls, num_tasks: int, known_total_length: Optional[int]
cls,
num_tasks: int,
known_total_length: Optional[int],
quiet: bool,
) -> "BatchedProgress": ...

@classmethod
Expand Down Expand Up @@ -191,7 +205,10 @@ def __exit__(self, ty: Any, val: Any, tb: Any) -> None:

@classmethod
def create(
cls, num_tasks: int, known_total_length: Optional[int]
cls,
num_tasks: int,
known_total_length: Optional[int],
quiet: bool,
) -> "BatchedNoOpProgressBar":
return cls()

Expand All @@ -201,20 +218,24 @@ def __init__(
self,
total_bytes: Optional[int],
prefix: str,
quiet: bool,
) -> None:
self._total_bytes = total_bytes
self._prefix = prefix
self._total_progress = 0
self._subtasks: List[Tuple[str, Optional[int]]] = []
self._rate_limiter = RateLimiter(0.25)
self._stream = sys.stdout
self._stream = sys.stderr
self._quiet = quiet

def add_subtask(self, description: str, total: Optional[int]) -> TaskID:
task_id = len(self._subtasks)
self._subtasks.append((description, total))
return TaskID(task_id)

def _write_immediate(self, line: str) -> None:
if self._quiet:
return
self._stream.write(f"{self._prefix}{line}\n")
self._stream.flush()

Expand Down Expand Up @@ -266,10 +287,10 @@ def __exit__(self, ty: Any, val: Any, tb: Any) -> None:

@classmethod
def create(
cls, num_tasks: int, known_total_length: Optional[int]
cls, num_tasks: int, known_total_length: Optional[int], quiet: bool
) -> "BatchedRawProgressBar":
prefix = _progress_task_prefix()
return cls(known_total_length, prefix)
return cls(known_total_length, prefix, quiet=quiet)


class BatchedRichProgressBar(BatchedProgress):
Expand All @@ -279,11 +300,13 @@ def __init__(
total_task_id: TaskID,
progress: Progress,
total_bytes_task_id: TaskID,
quiet: bool,
) -> None:
self._task_progress = task_progress
self._total_task_id = total_task_id
self._progress = progress
self._total_bytes_task_id = total_bytes_task_id
self._quiet = quiet
self._live: Optional[Live] = None

_TRIM_LEN = 20
Expand Down Expand Up @@ -328,7 +351,9 @@ def __enter__(self) -> "BatchedRichProgressBar":
padding=(0, 0),
)
)
self._live = Live(table, console=Console(stderr=True), refresh_per_second=5)
self._live = Live(
table, console=Console(stderr=True, quiet=self._quiet), refresh_per_second=5
)
self._task_progress.start_task(self._total_task_id)
self._progress.start_task(self._total_bytes_task_id)
self._live.__enter__()
Expand All @@ -340,7 +365,7 @@ def __exit__(self, ty: Any, val: Any, tb: Any) -> None:

@classmethod
def create(
cls, num_tasks: int, known_total_length: Optional[int]
cls, num_tasks: int, known_total_length: Optional[int], quiet: bool
) -> "BatchedRichProgressBar":
task_columns = _task_columns()
task_progress = Progress(*task_columns)
Expand All @@ -365,4 +390,6 @@ def create(
total=total,
)

return cls(task_progress, total_task_id, progress, total_bytes_task_id)
return cls(
task_progress, total_task_id, progress, total_bytes_task_id, quiet=quiet
)
1 change: 1 addition & 0 deletions src/pip/_internal/cli/req_command.py
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ def make_requirement_preparer(
use_user_site=use_user_site,
lazy_wheel=lazy_wheel,
verbosity=verbosity,
quietness=options.quiet,
batch_download_parallelism=batch_download_parallelism,
legacy_resolver=legacy_resolver,
)
Expand Down
17 changes: 14 additions & 3 deletions src/pip/_internal/network/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ def _prepare_download(
resp: Response,
link: Link,
progress_bar: str,
quiet: bool = False,
) -> Iterable[bytes]:
total_length = _get_http_response_size(resp)

Expand All @@ -85,7 +86,9 @@ def _prepare_download(
if not show_progress:
return chunks

renderer = get_download_progress_renderer(bar_type=progress_bar, size=total_length)
renderer = get_download_progress_renderer(
bar_type=progress_bar, size=total_length, quiet=quiet
)
return renderer(chunks)


Expand Down Expand Up @@ -163,9 +166,11 @@ def __init__(
self,
session: PipSession,
progress_bar: str,
quiet: bool = False,
) -> None:
self._session = session
self._progress_bar = progress_bar
self._quiet = quiet

def __call__(self, link: Link, location: str) -> Tuple[str, str]:
"""Download the file given by link into location."""
Expand All @@ -181,7 +186,7 @@ def __call__(self, link: Link, location: str) -> Tuple[str, str]:
filename = _get_http_response_filename(resp.headers, resp.url, link)
filepath = os.path.join(location, filename)

chunks = _prepare_download(resp, link, self._progress_bar)
chunks = _prepare_download(resp, link, self._progress_bar, self._quiet)
with open(filepath, "wb") as content_file:
for chunk in chunks:
content_file.write(chunk)
Expand Down Expand Up @@ -291,10 +296,12 @@ def __init__(
self,
session: PipSession,
progress_bar: str,
quiet: bool = False,
max_parallelism: Optional[int] = None,
) -> None:
self._session = session
self._progress_bar = progress_bar
self._quiet = quiet

if max_parallelism is None:
max_parallelism = 1
Expand Down Expand Up @@ -331,7 +338,11 @@ def __call__(
semaphore = Semaphore(value=self._max_parallelism)
batched_progress = BatchedProgress.select_progress_bar(
self._progress_bar
).create(num_tasks=total_downloads, known_total_length=total_length)
).create(
num_tasks=total_downloads,
known_total_length=total_length,
quiet=self._quiet,
)

# Distribute request i/o across equivalent threads.
# NB: event-based/async is likely a better model than thread-per-request, but
Expand Down
10 changes: 7 additions & 3 deletions src/pip/_internal/operations/prepare.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,7 +215,7 @@ def _check_download_dir(
class RequirementPreparer:
"""Prepares a Requirement"""

def __init__(
def __init__( # noqa: PLR0913
self,
build_dir: str,
download_dir: Optional[str],
Expand All @@ -230,6 +230,7 @@ def __init__(
use_user_site: bool,
lazy_wheel: bool,
verbosity: int,
quietness: int,
batch_download_parallelism: Optional[int],
legacy_resolver: bool,
) -> None:
Expand All @@ -239,9 +240,12 @@ def __init__(
self.build_dir = build_dir
self.build_tracker = build_tracker
self._session = session
self._download = Downloader(session, progress_bar)
self._download = Downloader(session, progress_bar, quiet=quietness > 0)
self._batch_download = BatchDownloader(
session, progress_bar, max_parallelism=batch_download_parallelism
session,
progress_bar,
quiet=quietness > 0,
max_parallelism=batch_download_parallelism,
)
self.finder = finder

Expand Down
1 change: 1 addition & 0 deletions tests/unit/test_req.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ def _basic_resolver(
use_user_site=False,
lazy_wheel=False,
verbosity=0,
quietness=0,
batch_download_parallelism=None,
legacy_resolver=True,
)
Expand Down

0 comments on commit f42fb29

Please sign in to comment.