|
7 | 7 | import mimetypes
|
8 | 8 | import os
|
9 | 9 | import shutil
|
10 |
| -from typing import Dict, Iterable, List, Optional |
| 10 | +from typing import Dict, Iterable, List, Optional, Set |
11 | 11 |
|
12 | 12 | from pip._vendor.packaging.utils import canonicalize_name
|
13 | 13 |
|
@@ -297,7 +297,9 @@ def _log_preparing_link(self, req: InstallRequirement) -> None:
|
297 | 297 | logger.info("Using cached %s", req.link.filename)
|
298 | 298 |
|
299 | 299 | def _ensure_link_req_src_dir(
|
300 |
| - self, req: InstallRequirement, parallel_builds: bool |
| 300 | + self, |
| 301 | + req: InstallRequirement, |
| 302 | + parallel_builds: bool, |
301 | 303 | ) -> None:
|
302 | 304 | """Ensure source_dir of a linked InstallRequirement."""
|
303 | 305 | # Since source_dir is only set for editable requirements.
|
@@ -472,32 +474,44 @@ def _complete_partial_requirements(
|
472 | 474 | assert req.link
|
473 | 475 | links_to_fully_download[req.link] = req
|
474 | 476 |
|
| 477 | + reqs_with_newly_unpacked_source_dirs: Set[Link] = set() |
| 478 | + |
475 | 479 | batch_download = self._batch_download(
|
476 | 480 | links_to_fully_download.keys(),
|
477 | 481 | temp_dir,
|
478 | 482 | )
|
479 | 483 | for link, (filepath, _) in batch_download:
|
480 | 484 | logger.debug("Downloading link %s to %s", link, filepath)
|
481 | 485 | req = links_to_fully_download[link]
|
| 486 | + # Record the downloaded file path so wheel reqs can extract a Distribution |
| 487 | + # in .get_dist(). |
482 | 488 | req.local_file_path = filepath
|
483 |
| - # TODO: This needs fixing for sdists |
484 |
| - # This is an emergency fix for #11847, which reports that |
485 |
| - # distributions get downloaded twice when metadata is loaded |
486 |
| - # from a PEP 658 standalone metadata file. Setting _downloaded |
487 |
| - # fixes this for wheels, but breaks the sdist case (tests |
488 |
| - # test_download_metadata). As PyPI is currently only serving |
489 |
| - # metadata for wheels, this is not an immediate issue. |
490 |
| - # Fixing the problem properly looks like it will require a |
491 |
| - # complete refactoring of the `prepare_linked_requirements_more` |
492 |
| - # logic, and I haven't a clue where to start on that, so for now |
493 |
| - # I have fixed the issue *just* for wheels. |
494 |
| - if req.is_wheel: |
495 |
| - self._downloaded[req.link.url] = filepath |
| 489 | + # Record that the file is downloaded so we don't do it again in |
| 490 | + # _prepare_linked_requirement(). |
| 491 | + self._downloaded[req.link.url] = filepath |
| 492 | + |
| 493 | + # If this is an sdist, we need to unpack it and set the .source_dir |
| 494 | + # immediately after downloading, as _prepare_linked_requirement() assumes |
| 495 | + # the req is either not downloaded at all, or both downloaded and |
| 496 | + # unpacked. The downloading and unpacking is is typically done with |
| 497 | + # unpack_url(), but we separate the downloading and unpacking steps here in |
| 498 | + # order to use the BatchDownloader. |
| 499 | + if not req.is_wheel: |
| 500 | + hashes = self._get_linked_req_hashes(req) |
| 501 | + assert filepath == _check_download_dir(req.link, temp_dir, hashes) |
| 502 | + self._ensure_link_req_src_dir(req, parallel_builds) |
| 503 | + unpack_file(filepath, req.source_dir) |
| 504 | + reqs_with_newly_unpacked_source_dirs.add(req.link) |
496 | 505 |
|
497 | 506 | # This step is necessary to ensure all lazy wheels are processed
|
498 | 507 | # successfully by the 'download', 'wheel', and 'install' commands.
|
499 | 508 | for req in partially_downloaded_reqs:
|
500 |
| - self._prepare_linked_requirement(req, parallel_builds) |
| 509 | + self._prepare_linked_requirement( |
| 510 | + req, |
| 511 | + parallel_builds, |
| 512 | + source_dir_exists_already=req.link |
| 513 | + in reqs_with_newly_unpacked_source_dirs, |
| 514 | + ) |
501 | 515 |
|
502 | 516 | def prepare_linked_requirement(
|
503 | 517 | self, req: InstallRequirement, parallel_builds: bool = False
|
@@ -568,7 +582,10 @@ def prepare_linked_requirements_more(
|
568 | 582 | )
|
569 | 583 |
|
570 | 584 | def _prepare_linked_requirement(
|
571 |
| - self, req: InstallRequirement, parallel_builds: bool |
| 585 | + self, |
| 586 | + req: InstallRequirement, |
| 587 | + parallel_builds: bool, |
| 588 | + source_dir_exists_already: bool = False, |
572 | 589 | ) -> BaseDistribution:
|
573 | 590 | assert req.link
|
574 | 591 | link = req.link
|
@@ -600,7 +617,8 @@ def _prepare_linked_requirement(
|
600 | 617 | req.link = req.cached_wheel_source_link
|
601 | 618 | link = req.link
|
602 | 619 |
|
603 |
| - self._ensure_link_req_src_dir(req, parallel_builds) |
| 620 | + if not source_dir_exists_already: |
| 621 | + self._ensure_link_req_src_dir(req, parallel_builds) |
604 | 622 |
|
605 | 623 | if link.is_existing_dir():
|
606 | 624 | local_file = None
|
|
0 commit comments