wheel.py 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. # -*- coding: utf-8 -*-
  2. from __future__ import absolute_import
  3. import os
  4. import sys
  5. from pip.basecommand import Command
  6. from pip.index import PackageFinder
  7. from pip.log import logger
  8. from pip.exceptions import CommandError, PreviousBuildDirError
  9. from pip.req import InstallRequirement, RequirementSet, parse_requirements
  10. from pip.util import normalize_path
  11. from pip.wheel import WheelBuilder
  12. from pip import cmdoptions
  13. DEFAULT_WHEEL_DIR = os.path.join(normalize_path(os.curdir), 'wheelhouse')
  14. class WheelCommand(Command):
  15. """
  16. Build Wheel archives for your requirements and dependencies.
  17. Wheel is a built-package format, and offers the advantage of not recompiling your software during every install.
  18. For more details, see the wheel docs: http://wheel.readthedocs.org/en/latest.
  19. Requirements: setuptools>=0.8, and wheel.
  20. 'pip wheel' uses the bdist_wheel setuptools extension from the wheel package to build individual wheels.
  21. """
  22. name = 'wheel'
  23. usage = """
  24. %prog [options] <requirement specifier> ...
  25. %prog [options] -r <requirements file> ...
  26. %prog [options] <vcs project url> ...
  27. %prog [options] <local project path> ...
  28. %prog [options] <archive url/path> ..."""
  29. summary = 'Build wheels from your requirements.'
  30. def __init__(self, *args, **kw):
  31. super(WheelCommand, self).__init__(*args, **kw)
  32. cmd_opts = self.cmd_opts
  33. cmd_opts.add_option(
  34. '-w', '--wheel-dir',
  35. dest='wheel_dir',
  36. metavar='dir',
  37. default=DEFAULT_WHEEL_DIR,
  38. help="Build wheels into <dir>, where the default is '<cwd>/wheelhouse'.")
  39. cmd_opts.add_option(cmdoptions.use_wheel.make())
  40. cmd_opts.add_option(cmdoptions.no_use_wheel.make())
  41. cmd_opts.add_option(
  42. '--build-option',
  43. dest='build_options',
  44. metavar='options',
  45. action='append',
  46. help="Extra arguments to be supplied to 'setup.py bdist_wheel'.")
  47. cmd_opts.add_option(cmdoptions.requirements.make())
  48. cmd_opts.add_option(cmdoptions.download_cache.make())
  49. cmd_opts.add_option(cmdoptions.no_deps.make())
  50. cmd_opts.add_option(cmdoptions.build_dir.make())
  51. cmd_opts.add_option(
  52. '--global-option',
  53. dest='global_options',
  54. action='append',
  55. metavar='options',
  56. help="Extra global options to be supplied to the setup.py "
  57. "call before the 'bdist_wheel' command.")
  58. cmd_opts.add_option(
  59. '--pre',
  60. action='store_true',
  61. default=False,
  62. help="Include pre-release and development versions. By default, pip only finds stable versions.")
  63. cmd_opts.add_option(cmdoptions.no_clean.make())
  64. index_opts = cmdoptions.make_option_group(cmdoptions.index_group, self.parser)
  65. self.parser.insert_option_group(0, index_opts)
  66. self.parser.insert_option_group(0, cmd_opts)
  67. def run(self, options, args):
  68. # confirm requirements
  69. try:
  70. import wheel.bdist_wheel
  71. except ImportError:
  72. raise CommandError("'pip wheel' requires the 'wheel' package. To fix this, run: pip install wheel")
  73. try:
  74. import pkg_resources
  75. except ImportError:
  76. raise CommandError(
  77. "'pip wheel' requires setuptools >= 0.8 for dist-info support."
  78. " To fix this, run: pip install --upgrade setuptools"
  79. )
  80. else:
  81. if not hasattr(pkg_resources, 'DistInfoDistribution'):
  82. raise CommandError(
  83. "'pip wheel' requires setuptools >= 0.8 for dist-info "
  84. "support. To fix this, run: pip install --upgrade "
  85. "setuptools"
  86. )
  87. index_urls = [options.index_url] + options.extra_index_urls
  88. if options.no_index:
  89. logger.notify('Ignoring indexes: %s' % ','.join(index_urls))
  90. index_urls = []
  91. if options.use_mirrors:
  92. logger.deprecated("1.7",
  93. "--use-mirrors has been deprecated and will be removed"
  94. " in the future. Explicit uses of --index-url and/or "
  95. "--extra-index-url is suggested.")
  96. if options.mirrors:
  97. logger.deprecated("1.7",
  98. "--mirrors has been deprecated and will be removed in "
  99. " the future. Explicit uses of --index-url and/or "
  100. "--extra-index-url is suggested.")
  101. index_urls += options.mirrors
  102. session = self._build_session(options)
  103. finder = PackageFinder(find_links=options.find_links,
  104. index_urls=index_urls,
  105. use_wheel=options.use_wheel,
  106. allow_external=options.allow_external,
  107. allow_unverified=options.allow_unverified,
  108. allow_all_external=options.allow_all_external,
  109. allow_all_prereleases=options.pre,
  110. process_dependency_links=
  111. options.process_dependency_links,
  112. session=session,
  113. )
  114. options.build_dir = os.path.abspath(options.build_dir)
  115. requirement_set = RequirementSet(
  116. build_dir=options.build_dir,
  117. src_dir=None,
  118. download_dir=None,
  119. download_cache=options.download_cache,
  120. ignore_dependencies=options.ignore_dependencies,
  121. ignore_installed=True,
  122. session=session,
  123. wheel_download_dir=options.wheel_dir
  124. )
  125. # make the wheelhouse
  126. if not os.path.exists(options.wheel_dir):
  127. os.makedirs(options.wheel_dir)
  128. #parse args and/or requirements files
  129. for name in args:
  130. requirement_set.add_requirement(
  131. InstallRequirement.from_line(name, None))
  132. for filename in options.requirements:
  133. for req in parse_requirements(
  134. filename,
  135. finder=finder,
  136. options=options,
  137. session=session):
  138. if req.editable:
  139. logger.notify("ignoring %s" % req.url)
  140. continue
  141. requirement_set.add_requirement(req)
  142. #fail if no requirements
  143. if not requirement_set.has_requirements:
  144. opts = {'name': self.name}
  145. msg = ('You must give at least one requirement '
  146. 'to %(name)s (see "pip help %(name)s")' % opts)
  147. logger.error(msg)
  148. return
  149. try:
  150. #build wheels
  151. wb = WheelBuilder(
  152. requirement_set,
  153. finder,
  154. options.wheel_dir,
  155. build_options = options.build_options or [],
  156. global_options = options.global_options or []
  157. )
  158. wb.build()
  159. except PreviousBuildDirError:
  160. options.no_clean = True
  161. raise
  162. finally:
  163. if not options.no_clean:
  164. requirement_set.cleanup_files()