From f699ea91e7a27cb4ea558a03018dc2b3af2fabd3 Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Thu, 13 Oct 2022 15:09:01 -0500 Subject: [PATCH 1/3] use .metadata distribution info when possible When performing `install --dry-run` and PEP 658 .metadata files are available to guide the resolve, do not download the associated wheels. Rather use the distribution information directly from the .metadata files when reporting the results on the CLI and in the --report file. --- src/pip/_internal/commands/install.py | 4 +++- src/pip/_internal/operations/prepare.py | 12 ++++++++++++ src/pip/_internal/req/req_install.py | 6 ++++++ src/pip/_internal/resolution/resolvelib/resolver.py | 7 +++++-- 4 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/pip/_internal/commands/install.py b/src/pip/_internal/commands/install.py index e081c27d2d2..24b60b2fb6f 100644 --- a/src/pip/_internal/commands/install.py +++ b/src/pip/_internal/commands/install.py @@ -398,7 +398,9 @@ def run(self, options: Values, args: List[str]) -> int: self.trace_basic_info(finder) requirement_set = resolver.resolve( - reqs, check_supported_wheels=not options.target_dir + reqs, + check_supported_wheels=not options.target_dir, + dry_run=options.dry_run, ) if options.json_report_file: diff --git a/src/pip/_internal/operations/prepare.py b/src/pip/_internal/operations/prepare.py index 4bf414cb005..7e5c59b3c42 100644 --- a/src/pip/_internal/operations/prepare.py +++ b/src/pip/_internal/operations/prepare.py @@ -400,6 +400,8 @@ def _fetch_metadata_using_link_data_attr( raise MetadataInconsistent( req, "Name", req.req.name, metadata_dist.raw_name ) + # (5) Store the dist in the install requirement for reporting + req.dist_from_metadata = metadata_dist return metadata_dist def _fetch_metadata_using_lazy_wheel( @@ -490,6 +492,16 @@ def prepare_linked_requirement( # None of the optimizations worked, fully prepare the requirement return self._prepare_linked_requirement(req, parallel_builds) + def prepare_download_info(self, reqs: Iterable[InstallRequirement]) -> None: + """ Prepare linked requirements with download_info, if needed. """ + # During install --dry-run, .metadata files or lazy wheels may be used when determining + # distribution dependencies. The associated wheel does not need to be downloaded so the + # download_info need to be derived from the link. If the link does not contain a hash no + # hash will be included in the download_info. + for req in reqs: + if req.download_info is None: + req.download_info = direct_url_from_link(req.link, req.source_dir) + def prepare_linked_requirements_more( self, reqs: Iterable[InstallRequirement], parallel_builds: bool = False ) -> None: diff --git a/src/pip/_internal/req/req_install.py b/src/pip/_internal/req/req_install.py index 5f29261c252..6dd97feefc0 100644 --- a/src/pip/_internal/req/req_install.py +++ b/src/pip/_internal/req/req_install.py @@ -185,6 +185,10 @@ def __init__( # This requirement needs more preparation before it can be built self.needs_more_preparation = False + # Distribution from the .metadata file referenced by the PEP 658 + # data-dist-info-metadata attribute. + self.dist_from_metadata: Optional[BaseDistribution] = None + def __str__(self) -> str: if self.req: s = str(self.req) @@ -568,6 +572,8 @@ def get_dist(self) -> BaseDistribution: return get_wheel_distribution( FilesystemWheel(self.local_file_path), canonicalize_name(self.name) ) + elif self.is_wheel and self.dist_from_metadata: + return self.dist_from_metadata raise AssertionError( f"InstallRequirement {self} has no metadata directory and no wheel: " f"can't make a distribution." diff --git a/src/pip/_internal/resolution/resolvelib/resolver.py b/src/pip/_internal/resolution/resolvelib/resolver.py index a605d6c254f..db929024d2a 100644 --- a/src/pip/_internal/resolution/resolvelib/resolver.py +++ b/src/pip/_internal/resolution/resolvelib/resolver.py @@ -68,7 +68,7 @@ def __init__( self._result: Optional[Result] = None def resolve( - self, root_reqs: List[InstallRequirement], check_supported_wheels: bool + self, root_reqs: List[InstallRequirement], check_supported_wheels: bool, dry_run: bool = False, ) -> RequirementSet: collected = self.factory.collect_root_requirements(root_reqs) provider = PipProvider( @@ -158,7 +158,10 @@ def resolve( req_set.add_named_requirement(ireq) reqs = req_set.all_requirements - self.factory.preparer.prepare_linked_requirements_more(reqs) + if dry_run: + self.factory.preparer.prepare_download_info(reqs) + else: + self.factory.preparer.prepare_linked_requirements_more(reqs) return req_set def get_installation_order( From 389fdaf3d00fdb540ac78705b3112fdc7e8e7804 Mon Sep 17 00:00:00 2001 From: Jonathan Helmus Date: Thu, 13 Oct 2022 15:24:45 -0500 Subject: [PATCH 2/3] add news files --- news/11512.bugfix.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/11512.bugfix.rst diff --git a/news/11512.bugfix.rst b/news/11512.bugfix.rst new file mode 100644 index 00000000000..a2169ec6e10 --- /dev/null +++ b/news/11512.bugfix.rst @@ -0,0 +1 @@ +Avoid downloading wheels when performing a ``--dry-run`` install when .metadata files are used. From fb2ed935405327d9d8923f92054ffa103c65ef02 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Thu, 13 Oct 2022 20:41:48 +0000 Subject: [PATCH 3/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- src/pip/_internal/operations/prepare.py | 2 +- src/pip/_internal/resolution/resolvelib/resolver.py | 5 ++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/src/pip/_internal/operations/prepare.py b/src/pip/_internal/operations/prepare.py index 7e5c59b3c42..a1adee85b8f 100644 --- a/src/pip/_internal/operations/prepare.py +++ b/src/pip/_internal/operations/prepare.py @@ -493,7 +493,7 @@ def prepare_linked_requirement( return self._prepare_linked_requirement(req, parallel_builds) def prepare_download_info(self, reqs: Iterable[InstallRequirement]) -> None: - """ Prepare linked requirements with download_info, if needed. """ + """Prepare linked requirements with download_info, if needed.""" # During install --dry-run, .metadata files or lazy wheels may be used when determining # distribution dependencies. The associated wheel does not need to be downloaded so the # download_info need to be derived from the link. If the link does not contain a hash no diff --git a/src/pip/_internal/resolution/resolvelib/resolver.py b/src/pip/_internal/resolution/resolvelib/resolver.py index db929024d2a..8717b436f37 100644 --- a/src/pip/_internal/resolution/resolvelib/resolver.py +++ b/src/pip/_internal/resolution/resolvelib/resolver.py @@ -68,7 +68,10 @@ def __init__( self._result: Optional[Result] = None def resolve( - self, root_reqs: List[InstallRequirement], check_supported_wheels: bool, dry_run: bool = False, + self, + root_reqs: List[InstallRequirement], + check_supported_wheels: bool, + dry_run: bool = False, ) -> RequirementSet: collected = self.factory.collect_root_requirements(root_reqs) provider = PipProvider(