summaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/pip/_internal/cli/progress_bars.py
diff options
context:
space:
mode:
Diffstat (limited to '.venv/lib/python3.12/site-packages/pip/_internal/cli/progress_bars.py')
-rw-r--r--.venv/lib/python3.12/site-packages/pip/_internal/cli/progress_bars.py151
1 files changed, 151 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/pip/_internal/cli/progress_bars.py b/.venv/lib/python3.12/site-packages/pip/_internal/cli/progress_bars.py
new file mode 100644
index 0000000..af1bb6a
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/pip/_internal/cli/progress_bars.py
@@ -0,0 +1,151 @@
+from __future__ import annotations
+
+import functools
+import sys
+from collections.abc import Generator, Iterable, Iterator
+from typing import Callable, Literal, TypeVar
+
+from pip._vendor.rich.progress import (
+ BarColumn,
+ DownloadColumn,
+ FileSizeColumn,
+ MofNCompleteColumn,
+ Progress,
+ ProgressColumn,
+ SpinnerColumn,
+ TextColumn,
+ TimeElapsedColumn,
+ TimeRemainingColumn,
+ TransferSpeedColumn,
+)
+
+from pip._internal.cli.spinners import RateLimiter
+from pip._internal.req.req_install import InstallRequirement
+from pip._internal.utils.logging import get_console, get_indentation
+
+T = TypeVar("T")
+ProgressRenderer = Callable[[Iterable[T]], Iterator[T]]
+BarType = Literal["on", "off", "raw"]
+
+
+def _rich_download_progress_bar(
+ iterable: Iterable[bytes],
+ *,
+ bar_type: BarType,
+ size: int | None,
+ initial_progress: int | None = None,
+) -> Generator[bytes, None, None]:
+ assert bar_type == "on", "This should only be used in the default mode."
+
+ if not size:
+ total = float("inf")
+ columns: tuple[ProgressColumn, ...] = (
+ TextColumn("[progress.description]{task.description}"),
+ SpinnerColumn("line", speed=1.5),
+ FileSizeColumn(),
+ TransferSpeedColumn(),
+ TimeElapsedColumn(),
+ )
+ else:
+ total = size
+ columns = (
+ TextColumn("[progress.description]{task.description}"),
+ BarColumn(),
+ DownloadColumn(),
+ TransferSpeedColumn(),
+ TextColumn("{task.fields[time_description]}"),
+ TimeRemainingColumn(elapsed_when_finished=True),
+ )
+
+ progress = Progress(*columns, refresh_per_second=5)
+ task_id = progress.add_task(
+ " " * (get_indentation() + 2), total=total, time_description="eta"
+ )
+ if initial_progress is not None:
+ progress.update(task_id, advance=initial_progress)
+ with progress:
+ for chunk in iterable:
+ yield chunk
+ progress.update(task_id, advance=len(chunk))
+ progress.update(task_id, time_description="")
+
+
+def _rich_install_progress_bar(
+ iterable: Iterable[InstallRequirement], *, total: int
+) -> Iterator[InstallRequirement]:
+ columns = (
+ TextColumn("{task.fields[indent]}"),
+ BarColumn(),
+ MofNCompleteColumn(),
+ TextColumn("{task.description}"),
+ )
+ console = get_console()
+
+ bar = Progress(*columns, refresh_per_second=6, console=console, transient=True)
+ # Hiding the progress bar at initialization forces a refresh cycle to occur
+ # until the bar appears, avoiding very short flashes.
+ task = bar.add_task("", total=total, indent=" " * get_indentation(), visible=False)
+ with bar:
+ for req in iterable:
+ bar.update(task, description=rf"\[{req.name}]", visible=True)
+ yield req
+ bar.advance(task)
+
+
+def _raw_progress_bar(
+ iterable: Iterable[bytes],
+ *,
+ size: int | None,
+ initial_progress: int | None = None,
+) -> Generator[bytes, None, None]:
+ def write_progress(current: int, total: int) -> None:
+ sys.stdout.write(f"Progress {current} of {total}\n")
+ sys.stdout.flush()
+
+ current = initial_progress or 0
+ total = size or 0
+ rate_limiter = RateLimiter(0.25)
+
+ write_progress(current, total)
+ for chunk in iterable:
+ current += len(chunk)
+ if rate_limiter.ready() or current == total:
+ write_progress(current, total)
+ rate_limiter.reset()
+ yield chunk
+
+
+def get_download_progress_renderer(
+ *, bar_type: BarType, size: int | None = None, initial_progress: int | None = None
+) -> ProgressRenderer[bytes]:
+ """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_download_progress_bar,
+ bar_type=bar_type,
+ size=size,
+ initial_progress=initial_progress,
+ )
+ elif bar_type == "raw":
+ return functools.partial(
+ _raw_progress_bar,
+ size=size,
+ initial_progress=initial_progress,
+ )
+ else:
+ return iter # no-op, when passed an iterator
+
+
+def get_install_progress_renderer(
+ *, bar_type: BarType, total: int
+) -> ProgressRenderer[InstallRequirement]:
+ """Get an object that can be used to render the install progress.
+ Returns a callable, that takes an iterable to "wrap".
+ """
+ if bar_type == "on":
+ return functools.partial(_rich_install_progress_bar, total=total)
+ else:
+ return iter