图片解析应用
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

147 lines
5.2 KiB

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