__init__.py 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. #!/usr/bin/env python
  2. from __future__ import absolute_import
  3. import locale
  4. import logging
  5. import os
  6. import optparse
  7. import warnings
  8. import sys
  9. # 2016-06-17 barry@debian.org: urllib3 1.14 added optional support for socks,
  10. # but if invoked (i.e. imported), it will issue a warning to stderr if socks
  11. # isn't available. requests unconditionally imports urllib3's socks contrib
  12. # module, triggering this warning. The warning breaks DEP-8 tests (because of
  13. # the stderr output) and is just plain annoying in normal usage. I don't want
  14. # to add socks as yet another dependency for pip, nor do I want to allow-stder
  15. # in the DEP-8 tests, so just suppress the warning. pdb tells me this has to
  16. # be done before the import of pip.vcs.
  17. from pip._vendor.urllib3.exceptions import DependencyWarning
  18. warnings.filterwarnings("ignore", category=DependencyWarning) # noqa
  19. # We want to inject the use of SecureTransport as early as possible so that any
  20. # references or sessions or what have you are ensured to have it, however we
  21. # only want to do this in the case that we're running on macOS and the linked
  22. # OpenSSL is too old to handle TLSv1.2
  23. try:
  24. import ssl
  25. except ImportError:
  26. pass
  27. else:
  28. # Checks for OpenSSL 1.0.1 on MacOS
  29. if sys.platform == "darwin" and ssl.OPENSSL_VERSION_NUMBER < 0x1000100f:
  30. try:
  31. from pip._vendor.urllib3.contrib import securetransport
  32. except (ImportError, OSError):
  33. pass
  34. else:
  35. securetransport.inject_into_urllib3()
  36. from pip import __version__
  37. from pip._internal import cmdoptions
  38. from pip._internal.exceptions import CommandError, PipError
  39. from pip._internal.utils.misc import get_installed_distributions, get_prog
  40. from pip._internal.utils import deprecation
  41. from pip._internal.vcs import git, mercurial, subversion, bazaar # noqa
  42. from pip._internal.baseparser import (
  43. ConfigOptionParser, UpdatingDefaultsHelpFormatter,
  44. )
  45. from pip._internal.commands import get_summaries, get_similar_commands
  46. from pip._internal.commands import commands_dict
  47. from pip._vendor.urllib3.exceptions import InsecureRequestWarning
  48. logger = logging.getLogger(__name__)
  49. # Hide the InsecureRequestWarning from urllib3
  50. warnings.filterwarnings("ignore", category=InsecureRequestWarning)
  51. def autocomplete():
  52. """Command and option completion for the main option parser (and options)
  53. and its subcommands (and options).
  54. Enable by sourcing one of the completion shell scripts (bash, zsh or fish).
  55. """
  56. # Don't complete if user hasn't sourced bash_completion file.
  57. if 'PIP_AUTO_COMPLETE' not in os.environ:
  58. return
  59. cwords = os.environ['COMP_WORDS'].split()[1:]
  60. cword = int(os.environ['COMP_CWORD'])
  61. try:
  62. current = cwords[cword - 1]
  63. except IndexError:
  64. current = ''
  65. subcommands = [cmd for cmd, summary in get_summaries()]
  66. options = []
  67. # subcommand
  68. try:
  69. subcommand_name = [w for w in cwords if w in subcommands][0]
  70. except IndexError:
  71. subcommand_name = None
  72. parser = create_main_parser()
  73. # subcommand options
  74. if subcommand_name:
  75. # special case: 'help' subcommand has no options
  76. if subcommand_name == 'help':
  77. sys.exit(1)
  78. # special case: list locally installed dists for show and uninstall
  79. should_list_installed = (
  80. subcommand_name in ['show', 'uninstall'] and
  81. not current.startswith('-')
  82. )
  83. if should_list_installed:
  84. installed = []
  85. lc = current.lower()
  86. for dist in get_installed_distributions(local_only=True):
  87. if dist.key.startswith(lc) and dist.key not in cwords[1:]:
  88. installed.append(dist.key)
  89. # if there are no dists installed, fall back to option completion
  90. if installed:
  91. for dist in installed:
  92. print(dist)
  93. sys.exit(1)
  94. subcommand = commands_dict[subcommand_name]()
  95. for opt in subcommand.parser.option_list_all:
  96. if opt.help != optparse.SUPPRESS_HELP:
  97. for opt_str in opt._long_opts + opt._short_opts:
  98. options.append((opt_str, opt.nargs))
  99. # filter out previously specified options from available options
  100. prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]]
  101. options = [(x, v) for (x, v) in options if x not in prev_opts]
  102. # filter options by current input
  103. options = [(k, v) for k, v in options if k.startswith(current)]
  104. for option in options:
  105. opt_label = option[0]
  106. # append '=' to options which require args
  107. if option[1] and option[0][:2] == "--":
  108. opt_label += '='
  109. print(opt_label)
  110. else:
  111. # show main parser options only when necessary
  112. if current.startswith('-') or current.startswith('--'):
  113. opts = [i.option_list for i in parser.option_groups]
  114. opts.append(parser.option_list)
  115. opts = (o for it in opts for o in it)
  116. for opt in opts:
  117. if opt.help != optparse.SUPPRESS_HELP:
  118. subcommands += opt._long_opts + opt._short_opts
  119. print(' '.join([x for x in subcommands if x.startswith(current)]))
  120. sys.exit(1)
  121. def create_main_parser():
  122. parser_kw = {
  123. 'usage': '\n%prog <command> [options]',
  124. 'add_help_option': False,
  125. 'formatter': UpdatingDefaultsHelpFormatter(),
  126. 'name': 'global',
  127. 'prog': get_prog(),
  128. }
  129. parser = ConfigOptionParser(**parser_kw)
  130. parser.disable_interspersed_args()
  131. pip_pkg_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  132. parser.version = 'pip %s from %s (python %s)' % (
  133. __version__, pip_pkg_dir, sys.version[:3],
  134. )
  135. # add the general options
  136. gen_opts = cmdoptions.make_option_group(cmdoptions.general_group, parser)
  137. parser.add_option_group(gen_opts)
  138. parser.main = True # so the help formatter knows
  139. # create command listing for description
  140. command_summaries = get_summaries()
  141. description = [''] + ['%-27s %s' % (i, j) for i, j in command_summaries]
  142. parser.description = '\n'.join(description)
  143. return parser
  144. def parseopts(args):
  145. parser = create_main_parser()
  146. # Note: parser calls disable_interspersed_args(), so the result of this
  147. # call is to split the initial args into the general options before the
  148. # subcommand and everything else.
  149. # For example:
  150. # args: ['--timeout=5', 'install', '--user', 'INITools']
  151. # general_options: ['--timeout==5']
  152. # args_else: ['install', '--user', 'INITools']
  153. general_options, args_else = parser.parse_args(args)
  154. # --version
  155. if general_options.version:
  156. sys.stdout.write(parser.version)
  157. sys.stdout.write(os.linesep)
  158. sys.exit()
  159. # pip || pip help -> print_help()
  160. if not args_else or (args_else[0] == 'help' and len(args_else) == 1):
  161. parser.print_help()
  162. sys.exit()
  163. # the subcommand name
  164. cmd_name = args_else[0]
  165. if cmd_name not in commands_dict:
  166. guess = get_similar_commands(cmd_name)
  167. msg = ['unknown command "%s"' % cmd_name]
  168. if guess:
  169. msg.append('maybe you meant "%s"' % guess)
  170. raise CommandError(' - '.join(msg))
  171. # all the args without the subcommand
  172. cmd_args = args[:]
  173. cmd_args.remove(cmd_name)
  174. return cmd_name, cmd_args
  175. def check_isolated(args):
  176. isolated = False
  177. if "--isolated" in args:
  178. isolated = True
  179. return isolated
  180. def main(args=None):
  181. if args is None:
  182. args = sys.argv[1:]
  183. # Configure our deprecation warnings to be sent through loggers
  184. deprecation.install_warning_logger()
  185. autocomplete()
  186. try:
  187. cmd_name, cmd_args = parseopts(args)
  188. except PipError as exc:
  189. sys.stderr.write("ERROR: %s" % exc)
  190. sys.stderr.write(os.linesep)
  191. sys.exit(1)
  192. # Needed for locale.getpreferredencoding(False) to work
  193. # in pip._internal.utils.encoding.auto_decode
  194. try:
  195. locale.setlocale(locale.LC_ALL, '')
  196. except locale.Error as e:
  197. # setlocale can apparently crash if locale are uninitialized
  198. logger.debug("Ignoring error %s when setting locale", e)
  199. command = commands_dict[cmd_name](isolated=check_isolated(cmd_args))
  200. return command.main(cmd_args)