|
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 |
|
@@ -472,32 +472,44 @@ def _complete_partial_requirements(
|
472 | 472 | assert req.link
|
473 | 473 | links_to_fully_download[req.link] = req
|
474 | 474 |
|
| 475 | + reqs_with_newly_unpacked_source_dirs: Set[Link] = set() |
| 476 | + |
475 | 477 | batch_download = self._batch_download(
|
476 | 478 | links_to_fully_download.keys(),
|
477 | 479 | temp_dir,
|
478 | 480 | )
|
479 | 481 | for link, (filepath, _) in batch_download:
|
480 | 482 | logger.debug("Downloading link %s to %s", link, filepath)
|
481 | 483 | req = links_to_fully_download[link]
|
| 484 | + # Record the downloaded file path so wheel reqs can extract a Distribution |
| 485 | + # in .get_dist(). |
482 | 486 | 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 |
| 487 | + # Record that the file is downloaded so we don't do it again in |
| 488 | + # _prepare_linked_requirement(). |
| 489 | + self._downloaded[req.link.url] = filepath |
| 490 | + |
| 491 | + # If this is an sdist, we need to unpack it and set the .source_dir |
| 492 | + # immediately after downloading, as _prepare_linked_requirement() assumes |
| 493 | + # the req is either not downloaded at all, or both downloaded and |
| 494 | + # unpacked. The downloading and unpacking is is typically done with |
| 495 | + # unpack_url(), but we separate the downloading and unpacking steps here in |
| 496 | + # order to use the BatchDownloader. |
| 497 | + if not req.is_wheel: |
| 498 | + hashes = self._get_linked_req_hashes(req) |
| 499 | + assert filepath == _check_download_dir(req.link, temp_dir, hashes) |
| 500 | + self._ensure_link_req_src_dir(req, parallel_builds) |
| 501 | + unpack_file(filepath, req.source_dir) |
| 502 | + reqs_with_newly_unpacked_source_dirs.add(req.link) |
496 | 503 |
|
497 | 504 | # This step is necessary to ensure all lazy wheels are processed
|
498 | 505 | # successfully by the 'download', 'wheel', and 'install' commands.
|
499 | 506 | for req in partially_downloaded_reqs:
|
500 |
| - self._prepare_linked_requirement(req, parallel_builds) |
| 507 | + self._prepare_linked_requirement( |
| 508 | + req, |
| 509 | + parallel_builds, |
| 510 | + source_dir_exists_already=req.link |
| 511 | + in reqs_with_newly_unpacked_source_dirs, |
| 512 | + ) |
501 | 513 |
|
502 | 514 | def prepare_linked_requirement(
|
503 | 515 | self, req: InstallRequirement, parallel_builds: bool = False
|
@@ -568,7 +580,10 @@ def prepare_linked_requirements_more(
|
568 | 580 | )
|
569 | 581 |
|
570 | 582 | def _prepare_linked_requirement(
|
571 |
| - self, req: InstallRequirement, parallel_builds: bool |
| 583 | + self, |
| 584 | + req: InstallRequirement, |
| 585 | + parallel_builds: bool, |
| 586 | + source_dir_exists_already: bool = False, |
572 | 587 | ) -> BaseDistribution:
|
573 | 588 | assert req.link
|
574 | 589 | link = req.link
|
@@ -600,7 +615,8 @@ def _prepare_linked_requirement(
|
600 | 615 | req.link = req.cached_wheel_source_link
|
601 | 616 | link = req.link
|
602 | 617 |
|
603 |
| - self._ensure_link_req_src_dir(req, parallel_builds) |
| 618 | + if not source_dir_exists_already: |
| 619 | + self._ensure_link_req_src_dir(req, parallel_builds) |
604 | 620 |
|
605 | 621 | if link.is_existing_dir():
|
606 | 622 | local_file = None
|
|
0 commit comments