python (3.11.7)
       1  import logging
       2  import os
       3  from optparse import Values
       4  from typing import List
       5  
       6  from pip._internal.cli import cmdoptions
       7  from pip._internal.cli.cmdoptions import make_target_python
       8  from pip._internal.cli.req_command import RequirementCommand, with_cleanup
       9  from pip._internal.cli.status_codes import SUCCESS
      10  from pip._internal.operations.build.build_tracker import get_build_tracker
      11  from pip._internal.req.req_install import check_legacy_setup_py_options
      12  from pip._internal.utils.misc import ensure_dir, normalize_path, write_output
      13  from pip._internal.utils.temp_dir import TempDirectory
      14  
      15  logger = logging.getLogger(__name__)
      16  
      17  
      18  class ESC[4;38;5;81mDownloadCommand(ESC[4;38;5;149mRequirementCommand):
      19      """
      20      Download packages from:
      21  
      22      - PyPI (and other indexes) using requirement specifiers.
      23      - VCS project urls.
      24      - Local project directories.
      25      - Local or remote source archives.
      26  
      27      pip also supports downloading from "requirements files", which provide
      28      an easy way to specify a whole environment to be downloaded.
      29      """
      30  
      31      usage = """
      32        %prog [options] <requirement specifier> [package-index-options] ...
      33        %prog [options] -r <requirements file> [package-index-options] ...
      34        %prog [options] <vcs project url> ...
      35        %prog [options] <local project path> ...
      36        %prog [options] <archive url/path> ..."""
      37  
      38      def add_options(self) -> None:
      39          self.cmd_opts.add_option(cmdoptions.constraints())
      40          self.cmd_opts.add_option(cmdoptions.requirements())
      41          self.cmd_opts.add_option(cmdoptions.no_deps())
      42          self.cmd_opts.add_option(cmdoptions.global_options())
      43          self.cmd_opts.add_option(cmdoptions.no_binary())
      44          self.cmd_opts.add_option(cmdoptions.only_binary())
      45          self.cmd_opts.add_option(cmdoptions.prefer_binary())
      46          self.cmd_opts.add_option(cmdoptions.src())
      47          self.cmd_opts.add_option(cmdoptions.pre())
      48          self.cmd_opts.add_option(cmdoptions.require_hashes())
      49          self.cmd_opts.add_option(cmdoptions.progress_bar())
      50          self.cmd_opts.add_option(cmdoptions.no_build_isolation())
      51          self.cmd_opts.add_option(cmdoptions.use_pep517())
      52          self.cmd_opts.add_option(cmdoptions.no_use_pep517())
      53          self.cmd_opts.add_option(cmdoptions.check_build_deps())
      54          self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
      55  
      56          self.cmd_opts.add_option(
      57              "-d",
      58              "--dest",
      59              "--destination-dir",
      60              "--destination-directory",
      61              dest="download_dir",
      62              metavar="dir",
      63              default=os.curdir,
      64              help="Download packages into <dir>.",
      65          )
      66  
      67          cmdoptions.add_target_python_options(self.cmd_opts)
      68  
      69          index_opts = cmdoptions.make_option_group(
      70              cmdoptions.index_group,
      71              self.parser,
      72          )
      73  
      74          self.parser.insert_option_group(0, index_opts)
      75          self.parser.insert_option_group(0, self.cmd_opts)
      76  
      77      @with_cleanup
      78      def run(self, options: Values, args: List[str]) -> int:
      79          options.ignore_installed = True
      80          # editable doesn't really make sense for `pip download`, but the bowels
      81          # of the RequirementSet code require that property.
      82          options.editables = []
      83  
      84          cmdoptions.check_dist_restriction(options)
      85  
      86          options.download_dir = normalize_path(options.download_dir)
      87          ensure_dir(options.download_dir)
      88  
      89          session = self.get_default_session(options)
      90  
      91          target_python = make_target_python(options)
      92          finder = self._build_package_finder(
      93              options=options,
      94              session=session,
      95              target_python=target_python,
      96              ignore_requires_python=options.ignore_requires_python,
      97          )
      98  
      99          build_tracker = self.enter_context(get_build_tracker())
     100  
     101          directory = TempDirectory(
     102              delete=not options.no_clean,
     103              kind="download",
     104              globally_managed=True,
     105          )
     106  
     107          reqs = self.get_requirements(args, options, finder, session)
     108          check_legacy_setup_py_options(options, reqs)
     109  
     110          preparer = self.make_requirement_preparer(
     111              temp_build_dir=directory,
     112              options=options,
     113              build_tracker=build_tracker,
     114              session=session,
     115              finder=finder,
     116              download_dir=options.download_dir,
     117              use_user_site=False,
     118              verbosity=self.verbosity,
     119          )
     120  
     121          resolver = self.make_resolver(
     122              preparer=preparer,
     123              finder=finder,
     124              options=options,
     125              ignore_requires_python=options.ignore_requires_python,
     126              use_pep517=options.use_pep517,
     127              py_version_info=options.python_version,
     128          )
     129  
     130          self.trace_basic_info(finder)
     131  
     132          requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
     133  
     134          downloaded: List[str] = []
     135          for req in requirement_set.requirements.values():
     136              if req.satisfied_by is None:
     137                  assert req.name is not None
     138                  preparer.save_linked_requirement(req)
     139                  downloaded.append(req.name)
     140  
     141          preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
     142          requirement_set.warn_legacy_versions_and_specifiers()
     143  
     144          if downloaded:
     145              write_output("Successfully downloaded %s", " ".join(downloaded))
     146  
     147          return SUCCESS