Skip to content

Commit 69aef59

Browse files
fix pypa#11847 for sdists
1 parent 2b43f64 commit 69aef59

File tree

1 file changed

+36
-18
lines changed

1 file changed

+36
-18
lines changed

src/pip/_internal/operations/prepare.py

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import mimetypes
88
import os
99
import shutil
10-
from typing import Dict, Iterable, List, Optional
10+
from typing import Dict, Iterable, List, Optional, Set
1111

1212
from pip._vendor.packaging.utils import canonicalize_name
1313

@@ -297,7 +297,9 @@ def _log_preparing_link(self, req: InstallRequirement) -> None:
297297
logger.info("Using cached %s", req.link.filename)
298298

299299
def _ensure_link_req_src_dir(
300-
self, req: InstallRequirement, parallel_builds: bool
300+
self,
301+
req: InstallRequirement,
302+
parallel_builds: bool,
301303
) -> None:
302304
"""Ensure source_dir of a linked InstallRequirement."""
303305
# Since source_dir is only set for editable requirements.
@@ -472,32 +474,44 @@ def _complete_partial_requirements(
472474
assert req.link
473475
links_to_fully_download[req.link] = req
474476

477+
reqs_with_newly_unpacked_source_dirs: Set[Link] = set()
478+
475479
batch_download = self._batch_download(
476480
links_to_fully_download.keys(),
477481
temp_dir,
478482
)
479483
for link, (filepath, _) in batch_download:
480484
logger.debug("Downloading link %s to %s", link, filepath)
481485
req = links_to_fully_download[link]
486+
# Record the downloaded file path so wheel reqs can extract a Distribution
487+
# in .get_dist().
482488
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)
496505

497506
# This step is necessary to ensure all lazy wheels are processed
498507
# successfully by the 'download', 'wheel', and 'install' commands.
499508
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+
)
501515

502516
def prepare_linked_requirement(
503517
self, req: InstallRequirement, parallel_builds: bool = False
@@ -568,7 +582,10 @@ def prepare_linked_requirements_more(
568582
)
569583

570584
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,
572589
) -> BaseDistribution:
573590
assert req.link
574591
link = req.link
@@ -600,7 +617,8 @@ def _prepare_linked_requirement(
600617
req.link = req.cached_wheel_source_link
601618
link = req.link
602619

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)
604622

605623
if link.is_existing_dir():
606624
local_file = None

0 commit comments

Comments
 (0)