图片解析应用
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.

183 lines
6.3 KiB

  1. import logging
  2. import os
  3. import shutil
  4. from optparse import Values
  5. from typing import List
  6. from pip._internal.cache import WheelCache
  7. from pip._internal.cli import cmdoptions
  8. from pip._internal.cli.req_command import RequirementCommand, with_cleanup
  9. from pip._internal.cli.status_codes import SUCCESS
  10. from pip._internal.exceptions import CommandError
  11. from pip._internal.operations.build.build_tracker import get_build_tracker
  12. from pip._internal.req.req_install import (
  13. InstallRequirement,
  14. check_legacy_setup_py_options,
  15. )
  16. from pip._internal.utils.misc import ensure_dir, normalize_path
  17. from pip._internal.utils.temp_dir import TempDirectory
  18. from pip._internal.wheel_builder import build, should_build_for_wheel_command
  19. logger = logging.getLogger(__name__)
  20. class WheelCommand(RequirementCommand):
  21. """
  22. Build Wheel archives for your requirements and dependencies.
  23. Wheel is a built-package format, and offers the advantage of not
  24. recompiling your software during every install. For more details, see the
  25. wheel docs: https://wheel.readthedocs.io/en/latest/
  26. 'pip wheel' uses the build system interface as described here:
  27. https://pip.pypa.io/en/stable/reference/build-system/
  28. """
  29. usage = """
  30. %prog [options] <requirement specifier> ...
  31. %prog [options] -r <requirements file> ...
  32. %prog [options] [-e] <vcs project url> ...
  33. %prog [options] [-e] <local project path> ...
  34. %prog [options] <archive url/path> ..."""
  35. def add_options(self) -> None:
  36. self.cmd_opts.add_option(
  37. "-w",
  38. "--wheel-dir",
  39. dest="wheel_dir",
  40. metavar="dir",
  41. default=os.curdir,
  42. help=(
  43. "Build wheels into <dir>, where the default is the "
  44. "current working directory."
  45. ),
  46. )
  47. self.cmd_opts.add_option(cmdoptions.no_binary())
  48. self.cmd_opts.add_option(cmdoptions.only_binary())
  49. self.cmd_opts.add_option(cmdoptions.prefer_binary())
  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.constraints())
  55. self.cmd_opts.add_option(cmdoptions.editable())
  56. self.cmd_opts.add_option(cmdoptions.requirements())
  57. self.cmd_opts.add_option(cmdoptions.src())
  58. self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
  59. self.cmd_opts.add_option(cmdoptions.no_deps())
  60. self.cmd_opts.add_option(cmdoptions.progress_bar())
  61. self.cmd_opts.add_option(
  62. "--no-verify",
  63. dest="no_verify",
  64. action="store_true",
  65. default=False,
  66. help="Don't verify if built wheel is valid.",
  67. )
  68. self.cmd_opts.add_option(cmdoptions.config_settings())
  69. self.cmd_opts.add_option(cmdoptions.build_options())
  70. self.cmd_opts.add_option(cmdoptions.global_options())
  71. self.cmd_opts.add_option(
  72. "--pre",
  73. action="store_true",
  74. default=False,
  75. help=(
  76. "Include pre-release and development versions. By default, "
  77. "pip only finds stable versions."
  78. ),
  79. )
  80. self.cmd_opts.add_option(cmdoptions.require_hashes())
  81. index_opts = cmdoptions.make_option_group(
  82. cmdoptions.index_group,
  83. self.parser,
  84. )
  85. self.parser.insert_option_group(0, index_opts)
  86. self.parser.insert_option_group(0, self.cmd_opts)
  87. @with_cleanup
  88. def run(self, options: Values, args: List[str]) -> int:
  89. session = self.get_default_session(options)
  90. finder = self._build_package_finder(options, session)
  91. options.wheel_dir = normalize_path(options.wheel_dir)
  92. ensure_dir(options.wheel_dir)
  93. build_tracker = self.enter_context(get_build_tracker())
  94. directory = TempDirectory(
  95. delete=not options.no_clean,
  96. kind="wheel",
  97. globally_managed=True,
  98. )
  99. reqs = self.get_requirements(args, options, finder, session)
  100. check_legacy_setup_py_options(options, reqs)
  101. wheel_cache = WheelCache(options.cache_dir)
  102. preparer = self.make_requirement_preparer(
  103. temp_build_dir=directory,
  104. options=options,
  105. build_tracker=build_tracker,
  106. session=session,
  107. finder=finder,
  108. download_dir=options.wheel_dir,
  109. use_user_site=False,
  110. verbosity=self.verbosity,
  111. )
  112. resolver = self.make_resolver(
  113. preparer=preparer,
  114. finder=finder,
  115. options=options,
  116. wheel_cache=wheel_cache,
  117. ignore_requires_python=options.ignore_requires_python,
  118. use_pep517=options.use_pep517,
  119. )
  120. self.trace_basic_info(finder)
  121. requirement_set = resolver.resolve(reqs, check_supported_wheels=True)
  122. reqs_to_build: List[InstallRequirement] = []
  123. for req in requirement_set.requirements.values():
  124. if req.is_wheel:
  125. preparer.save_linked_requirement(req)
  126. elif should_build_for_wheel_command(req):
  127. reqs_to_build.append(req)
  128. preparer.prepare_linked_requirements_more(requirement_set.requirements.values())
  129. requirement_set.warn_legacy_versions_and_specifiers()
  130. # build wheels
  131. build_successes, build_failures = build(
  132. reqs_to_build,
  133. wheel_cache=wheel_cache,
  134. verify=(not options.no_verify),
  135. build_options=options.build_options or [],
  136. global_options=options.global_options or [],
  137. )
  138. for req in build_successes:
  139. assert req.link and req.link.is_wheel
  140. assert req.local_file_path
  141. # copy from cache to target directory
  142. try:
  143. shutil.copy(req.local_file_path, options.wheel_dir)
  144. except OSError as e:
  145. logger.warning(
  146. "Building wheel for %s failed: %s",
  147. req.name,
  148. e,
  149. )
  150. build_failures.append(req)
  151. if len(build_failures) != 0:
  152. raise CommandError("Failed to build one or more wheels")
  153. return SUCCESS