Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add machine readable download progress option #12084

Closed
Closed
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
d7a76d3
Add machine readable download progress option
joeyballentine Jun 13, 2023
13c0431
Adds news file
joeyballentine Jun 13, 2023
0045fd8
Fix mypy error
joeyballentine Jun 13, 2023
5f7ab61
lint
joeyballentine Jun 13, 2023
5127329
line length
joeyballentine Jun 13, 2023
813aac6
add newline
joeyballentine Jun 13, 2023
98742ea
use json
joeyballentine Jun 13, 2023
9080d82
fix import sorting
joeyballentine Jun 13, 2023
70ae242
format
joeyballentine Jun 13, 2023
13c11ee
PR suggestions
joeyballentine Jun 13, 2023
d0d96d9
use logger
joeyballentine Jun 13, 2023
f4ca354
add docs to user guide
joeyballentine Jun 13, 2023
dfc4d98
add test
joeyballentine Jun 13, 2023
d1d6a69
fix test, maybe
joeyballentine Jun 13, 2023
5f7782a
maybe this time
joeyballentine Jun 14, 2023
71f3444
attempting just using a network package
joeyballentine Jun 14, 2023
14eb09d
lint
joeyballentine Jun 14, 2023
7567e2a
PR suggestions
joeyballentine Jun 15, 2023
c0fbf13
I didn't see the comment about using -u
joeyballentine Jun 15, 2023
31dee38
lint + add a test (that may or may not work)
joeyballentine Jun 15, 2023
d73336b
remove bad test
joeyballentine Jun 15, 2023
a3d3ebf
Merge branch 'main' into machine-readable-progress
joeyballentine Jun 16, 2023
15f0c8a
Update with more realistic example
joeyballentine Jun 24, 2023
23f95d2
update null verbiage
joeyballentine Jun 24, 2023
fd16cbc
error suggestion
joeyballentine Jun 24, 2023
e88444e
Merge remote-tracking branch 'origin/machine-readable-progress' into …
joeyballentine Jun 24, 2023
d81de49
ruff
joeyballentine Jun 24, 2023
0d6bfc3
Merge branch 'main' into machine-readable-progress
joeyballentine Jun 25, 2023
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
1 change: 1 addition & 0 deletions news/11508.feature.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Add a new progress_bar type that allows machine-readable (json) download progress
7 changes: 5 additions & 2 deletions src/pip/_internal/cli/cmdoptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,12 @@ class PipOption(Option):
"--progress-bar",
dest="progress_bar",
type="choice",
choices=["on", "off"],
choices=["on", "off", "json"],
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, json] (default: on)"
),
)

log: Callable[..., Option] = partial(
Expand Down
32 changes: 31 additions & 1 deletion src/pip/_internal/cli/progress_bars.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import functools
from json import dumps
joeyballentine marked this conversation as resolved.
Show resolved Hide resolved
from typing import Callable, Generator, Iterable, Iterator, Optional, Tuple

from pip._vendor.rich.progress import (
Expand Down Expand Up @@ -55,14 +56,43 @@ def _rich_progress_bar(
progress.update(task_id, advance=len(chunk))


class _MachineReadableProgress:
def __init__(
self, iterable: Iterable[bytes], size: int, filename: Optional[str] = None
joeyballentine marked this conversation as resolved.
Show resolved Hide resolved
) -> None:
self._iterable = iter(iterable)
self._size = size
self._progress = 0
self._filename = filename

def __iter__(self) -> Iterator[bytes]:
return self

def __next__(self) -> bytes:
chunk = next(self._iterable)
self._progress += len(chunk)
progress_info = {
"file": self._filename,
"current": self._progress,
"total": self._size,
}
print(
joeyballentine marked this conversation as resolved.
Show resolved Hide resolved
f"PROGRESS:{dumps(progress_info)}",
joeyballentine marked this conversation as resolved.
Show resolved Hide resolved
flush=True,
)
return chunk


def get_download_progress_renderer(
*, bar_type: str, size: Optional[int] = None
*, bar_type: str, size: Optional[int] = None, filename: Optional[str] = None
) -> 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)
elif bar_type == "json":
return functools.partial(_MachineReadableProgress, size=size, filename=filename)
joeyballentine marked this conversation as resolved.
Show resolved Hide resolved
else:
return iter # no-op, when passed an iterator
4 changes: 3 additions & 1 deletion src/pip/_internal/network/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,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, filename=link.filename
joeyballentine marked this conversation as resolved.
Show resolved Hide resolved
)
return renderer(chunks)


Expand Down