|
| 1 | +Examples |
| 2 | +======== |
| 3 | + |
| 4 | +Getting a Project's Dependencies |
| 5 | +-------------------------------- |
| 6 | + |
| 7 | +`pypi_simple` can be used to fetch a project's dependencies (specifically, the |
| 8 | +dependencies for each of the project's distribution packages) as follows. |
| 9 | + |
| 10 | +Note that Warehouse only began storing the contents of package :file:`METADATA` |
| 11 | +files in May 2023. Packages uploaded prior to that point are gradually having |
| 12 | +their metadata "backfilled" in; see |
| 13 | +<https://github.com/pypi/warehouse/issues/8254> for updates. |
| 14 | + |
| 15 | +.. code:: python |
| 16 | +
|
| 17 | + # Requirements: |
| 18 | + # Python 3.8+ |
| 19 | + # packaging 23.1+ |
| 20 | + # pypi_simple 1.3+ |
| 21 | +
|
| 22 | + from packaging.metadata import parse_email |
| 23 | + from pypi_simple import PyPISimple |
| 24 | +
|
| 25 | + with PyPISimple() as client: |
| 26 | + page = client.get_project_page("pypi-simple") |
| 27 | + for pkg in page.packages: |
| 28 | + if pkg.has_metadata: |
| 29 | + src = client.get_package_metadata(pkg) |
| 30 | + md, _ = parse_email(src) |
| 31 | + if deps := md.get("requires_dist"): |
| 32 | + print(f"Dependencies for {pkg.filename}:") |
| 33 | + for d in deps: |
| 34 | + print(f" {d}") |
| 35 | + else: |
| 36 | + print(f"Dependencies for {pkg.filename}: NONE") |
| 37 | + else: |
| 38 | + print(f"{pkg.filename}: No metadata available") |
| 39 | + print() |
| 40 | +
|
| 41 | +
|
| 42 | +Downloading With a Rich Progress Bar |
| 43 | +------------------------------------ |
| 44 | + |
| 45 | +The `PyPISimple.download_package()` method can be passed a callable for |
| 46 | +constructing a progress bar to use when downloading. `pypi_simple` has |
| 47 | +built-in support for using a tqdm_ progress bar, but any progress bar can be |
| 48 | +used if you provide the right structure. |
| 49 | + |
| 50 | +Here is an example of using a progress bar from rich_. The progress bar uses |
| 51 | +the default settings; adding customization is left as an exercise to the |
| 52 | +reader. |
| 53 | + |
| 54 | +.. _tqdm: https://tqdm.github.io |
| 55 | +.. _rich: https://github.com/Textualize/rich |
| 56 | + |
| 57 | +.. code:: python |
| 58 | +
|
| 59 | + from __future__ import annotations |
| 60 | + from dataclasses import InitVar, dataclass, field |
| 61 | + from types import TracebackType |
| 62 | + from pypi_simple import PyPISimple |
| 63 | + from rich.progress import Progress, TaskID |
| 64 | +
|
| 65 | + @dataclass |
| 66 | + class RichProgress: |
| 67 | + bar: Progress = field(init=False, default_factory=Progress) |
| 68 | + task_id: TaskID = field(init=False) |
| 69 | + size: InitVar[int | None] |
| 70 | +
|
| 71 | + def __post_init__(self, size: int | None) -> None: |
| 72 | + self.task_id = self.bar.add_task("Downloading...", total=size) |
| 73 | +
|
| 74 | + def __enter__(self) -> RichProgress: |
| 75 | + self.bar.start() |
| 76 | + return self |
| 77 | +
|
| 78 | + def __exit__( |
| 79 | + self, |
| 80 | + _exc_type: type[BaseException] | None, |
| 81 | + _exc_val: BaseException | None, |
| 82 | + _exc_tb: TracebackType | None, |
| 83 | + ) -> None: |
| 84 | + self.bar.stop() |
| 85 | +
|
| 86 | + def update(self, increment: int) -> None: |
| 87 | + self.bar.update(self.task_id, advance=increment) |
| 88 | +
|
| 89 | +
|
| 90 | + with PyPISimple() as client: |
| 91 | + page = client.get_project_page("numpy") |
| 92 | + pkg = page.packages[-1] |
| 93 | + client.download_package(pkg, path=pkg.filename, progress=RichProgress) |
0 commit comments