|
26 | 26 | VcsHashUnsupported,
|
27 | 27 | )
|
28 | 28 | from pip._internal.models.wheel import Wheel
|
29 |
| -from pip._internal.network.download import ( |
30 |
| - Downloader, |
31 |
| - complete_partial_requirement_downloads, |
32 |
| -) |
| 29 | +from pip._internal.network.download import BatchDownloader, Downloader |
33 | 30 | from pip._internal.network.lazy_wheel import (
|
34 | 31 | HTTPRangeRequestUnsupported,
|
35 | 32 | dist_from_wheel_url,
|
|
56 | 53 |
|
57 | 54 | from pip._internal.index.package_finder import PackageFinder
|
58 | 55 | from pip._internal.models.link import Link
|
59 |
| - from pip._internal.models.req_set import RequirementSet |
60 | 56 | from pip._internal.network.session import PipSession
|
61 | 57 | from pip._internal.req.req_install import InstallRequirement
|
62 | 58 | from pip._internal.req.req_tracker import RequirementTracker
|
@@ -329,6 +325,7 @@ def __init__(
|
329 | 325 | self.req_tracker = req_tracker
|
330 | 326 | self._session = session
|
331 | 327 | self._download = Downloader(session, progress_bar)
|
| 328 | + self._batch_download = BatchDownloader(session, progress_bar) |
332 | 329 | self.finder = finder
|
333 | 330 |
|
334 | 331 | # Where still-packed archives should be written to. If None, they are
|
@@ -356,10 +353,6 @@ def __init__(
|
356 | 353 |
|
357 | 354 | # Should wheels be downloaded lazily?
|
358 | 355 | self.use_lazy_wheel = lazy_wheel
|
359 |
| - # TODO: this field is only needed in |
360 |
| - # .complete_partial_requirements(). When the v1 resolver can be |
361 |
| - # removed, partial downloads can be completed outside of the resolver. |
362 |
| - self._progress_bar = progress_bar |
363 | 356 |
|
364 | 357 | # Memoized downloaded files, as mapping of url: (path, mime type)
|
365 | 358 | self._downloaded = {} # type: Dict[str, Tuple[str, str]]
|
@@ -498,16 +491,38 @@ def _fetch_metadata_using_lazy_wheel(self, link):
|
498 | 491 | logger.debug('%s does not support range requests', url)
|
499 | 492 | return None
|
500 | 493 |
|
501 |
| - def complete_partial_requirements(self, req_set): |
502 |
| - # type: (RequirementSet) -> None |
| 494 | + def _complete_partial_requirements( |
| 495 | + self, |
| 496 | + partially_downloaded_reqs, # type: Iterable[InstallRequirement] |
| 497 | + parallel_builds=False, # type: bool |
| 498 | + ): |
| 499 | + # type: (...) -> None |
503 | 500 | """Download any requirements which were only fetched by metadata."""
|
504 |
| - download_location = self.wheel_download_dir or self.download_dir |
505 |
| - complete_partial_requirement_downloads( |
506 |
| - self._session, |
507 |
| - self._progress_bar, |
508 |
| - req_set, |
509 |
| - download_location, |
| 501 | + # Download to a temporary directory. These will be copied over as |
| 502 | + # needed for downstream 'download', 'wheel', and 'install' commands. |
| 503 | + temp_dir = TempDirectory(kind="unpack", globally_managed=True).path |
| 504 | + |
| 505 | + # Map each link to the requirement that owns it. This allows us to set |
| 506 | + # `req.local_file_path` on the appropriate requirement after passing |
| 507 | + # all the links at once into BatchDownloader. |
| 508 | + links_to_fully_download = {} # type: Dict[Link, InstallRequirement] |
| 509 | + for req in partially_downloaded_reqs: |
| 510 | + assert req.link |
| 511 | + links_to_fully_download[req.link] = req |
| 512 | + |
| 513 | + batch_download = self._batch_download( |
| 514 | + links_to_fully_download.keys(), |
| 515 | + temp_dir, |
510 | 516 | )
|
| 517 | + for link, (filepath, _) in batch_download: |
| 518 | + logger.debug("Downloading link %s to %s", link, filepath) |
| 519 | + req = links_to_fully_download[link] |
| 520 | + req.local_file_path = filepath |
| 521 | + |
| 522 | + # This step is necessary to ensure all lazy wheels are processed |
| 523 | + # successfully by the 'download', 'wheel', and 'install' commands. |
| 524 | + for req in partially_downloaded_reqs: |
| 525 | + self._prepare_linked_requirement(req, parallel_builds) |
511 | 526 |
|
512 | 527 | def prepare_linked_requirement(self, req, parallel_builds=False):
|
513 | 528 | # type: (InstallRequirement, bool) -> Distribution
|
@@ -537,11 +552,20 @@ def prepare_linked_requirements_more(self, reqs, parallel_builds=False):
|
537 | 552 | req.needs_more_preparation = False
|
538 | 553 |
|
539 | 554 | # Prepare requirements we found were already downloaded for some
|
540 |
| - # reason. The other downloads will be completed elsewhere. |
| 555 | + # reason. The other downloads will be completed separately. |
| 556 | + partially_downloaded_reqs = [] # type: List[InstallRequirement] |
541 | 557 | for req in reqs:
|
542 |
| - if not req.needs_more_preparation: |
| 558 | + if req.needs_more_preparation: |
| 559 | + partially_downloaded_reqs.append(req) |
| 560 | + else: |
543 | 561 | self._prepare_linked_requirement(req, parallel_builds)
|
544 | 562 |
|
| 563 | + # TODO: separate this part out from RequirementPreparer when the v1 |
| 564 | + # resolver can be removed! |
| 565 | + self._complete_partial_requirements( |
| 566 | + partially_downloaded_reqs, parallel_builds=parallel_builds, |
| 567 | + ) |
| 568 | + |
545 | 569 | def _prepare_linked_requirement(self, req, parallel_builds):
|
546 | 570 | # type: (InstallRequirement, bool) -> Distribution
|
547 | 571 | assert req.link
|
|
0 commit comments