|
| 1 | +from typing import Any, Dict |
| 2 | + |
| 3 | +from pip._internal.req.req_install import InstallRequirement |
| 4 | +from pip._internal.req.req_set import RequirementSet |
| 5 | +from pip._internal.utils.direct_url_helpers import ( |
| 6 | + direct_url_for_editable, |
| 7 | + direct_url_from_link, |
| 8 | +) |
| 9 | + |
| 10 | + |
| 11 | +class InstallationReportItem: |
| 12 | + def __init__(self, install_req: InstallRequirement): |
| 13 | + self._install_req = install_req |
| 14 | + |
| 15 | + def to_json(self) -> Dict[str, Any]: |
| 16 | + if self._install_req.editable: |
| 17 | + is_direct = True |
| 18 | + direct_url = direct_url_for_editable( |
| 19 | + self._install_req.unpacked_source_directory |
| 20 | + ) |
| 21 | + elif self._install_req.original_link: |
| 22 | + is_direct = True |
| 23 | + direct_url = direct_url_from_link( |
| 24 | + self._install_req.original_link, |
| 25 | + self._install_req.source_dir, |
| 26 | + self._install_req.original_link_is_in_wheel_cache, |
| 27 | + ) |
| 28 | + else: |
| 29 | + assert self._install_req.link |
| 30 | + is_direct = False |
| 31 | + direct_url = direct_url_from_link(self._install_req.link) |
| 32 | + res = { |
| 33 | + # is_direct is true if requirement came from a direct URL reference (which |
| 34 | + # includes editable requirements), and false if the requirement was |
| 35 | + # downloaded from a PEP 503 index or --find-links. |
| 36 | + "is_direct": is_direct, |
| 37 | + # PEP 610 json for the download URL |
| 38 | + "download_info": direct_url.to_dict(), |
| 39 | + # PEP 566 json encoding for metadata |
| 40 | + # https://www.python.org/dev/peps/pep-0566/#json-compatible-metadata |
| 41 | + # TODO (MVP) self._install_req.metadata.to_json() |
| 42 | + "metadata": {}, |
| 43 | + } |
| 44 | + if self._install_req.user_supplied: |
| 45 | + # TODO (MVP) investigate why this does not reproduce the user supplied URL |
| 46 | + # in case of direct requirements |
| 47 | + res["requested"] = str(self._install_req.req) |
| 48 | + # TODO (LATER) information about the index for find-links for non-direct reqs |
| 49 | + # TODO (LATER) information about pip install options |
| 50 | + # TODO (MVP?) platform information (python version, etc) |
| 51 | + return res |
| 52 | + |
| 53 | + |
| 54 | +class InstallationReport: |
| 55 | + def __init__(self, items: Dict[str, InstallationReportItem]): |
| 56 | + self._items = items |
| 57 | + |
| 58 | + @classmethod |
| 59 | + def from_requirement_set( |
| 60 | + cls, requirement_set: RequirementSet |
| 61 | + ) -> "InstallationReport": |
| 62 | + items = {} |
| 63 | + for name, requirement in requirement_set.requirements.items(): |
| 64 | + item = InstallationReportItem(requirement) |
| 65 | + items[name] = item |
| 66 | + return InstallationReport(items) |
| 67 | + |
| 68 | + def to_json(self) -> Dict[str, Any]: |
| 69 | + return { |
| 70 | + "installed": {name: item.to_json() for name, item in self._items.items()} |
| 71 | + } |
0 commit comments