PageRenderTime 57ms CodeModel.GetById 28ms RepoModel.GetById 0ms app.codeStats 0ms

/pip/__init__.py

https://github.com/ptthiem/pip
Python | 272 lines | 251 code | 10 blank | 11 comment | 17 complexity | d6996c285d82b5585ba2f7b756faa428 MD5 | raw file
  1. #!/usr/bin/env python
  2. import os
  3. import optparse
  4. import sys
  5. import re
  6. from pip.exceptions import InstallationError, CommandError, PipError
  7. from pip.log import logger
  8. from pip.util import get_installed_distributions, get_prog
  9. from pip.vcs import git, mercurial, subversion, bazaar # noqa
  10. from pip.baseparser import ConfigOptionParser, UpdatingDefaultsHelpFormatter
  11. from pip.commands import commands, get_summaries, get_similar_commands
  12. # This fixes a peculiarity when importing via __import__ - as we are
  13. # initialising the pip module, "from pip import cmdoptions" is recursive
  14. # and appears not to work properly in that situation.
  15. import pip.cmdoptions
  16. cmdoptions = pip.cmdoptions
  17. # The version as used in the setup.py and the docs conf.py
  18. __version__ = "1.6.dev1"
  19. def autocomplete():
  20. """Command and option completion for the main option parser (and options)
  21. and its subcommands (and options).
  22. Enable by sourcing one of the completion shell scripts (bash or zsh).
  23. """
  24. # Don't complete if user hasn't sourced bash_completion file.
  25. if 'PIP_AUTO_COMPLETE' not in os.environ:
  26. return
  27. cwords = os.environ['COMP_WORDS'].split()[1:]
  28. cword = int(os.environ['COMP_CWORD'])
  29. try:
  30. current = cwords[cword - 1]
  31. except IndexError:
  32. current = ''
  33. subcommands = [cmd for cmd, summary in get_summaries()]
  34. options = []
  35. # subcommand
  36. try:
  37. subcommand_name = [w for w in cwords if w in subcommands][0]
  38. except IndexError:
  39. subcommand_name = None
  40. parser = create_main_parser()
  41. # subcommand options
  42. if subcommand_name:
  43. # special case: 'help' subcommand has no options
  44. if subcommand_name == 'help':
  45. sys.exit(1)
  46. # special case: list locally installed dists for uninstall command
  47. if subcommand_name == 'uninstall' and not current.startswith('-'):
  48. installed = []
  49. lc = current.lower()
  50. for dist in get_installed_distributions(local_only=True):
  51. if dist.key.startswith(lc) and dist.key not in cwords[1:]:
  52. installed.append(dist.key)
  53. # if there are no dists installed, fall back to option completion
  54. if installed:
  55. for dist in installed:
  56. print(dist)
  57. sys.exit(1)
  58. subcommand = commands[subcommand_name]()
  59. options += [(opt.get_opt_string(), opt.nargs)
  60. for opt in subcommand.parser.option_list_all
  61. if opt.help != optparse.SUPPRESS_HELP]
  62. # filter out previously specified options from available options
  63. prev_opts = [x.split('=')[0] for x in cwords[1:cword - 1]]
  64. options = [(x, v) for (x, v) in options if x not in prev_opts]
  65. # filter options by current input
  66. options = [(k, v) for k, v in options if k.startswith(current)]
  67. for option in options:
  68. opt_label = option[0]
  69. # append '=' to options which require args
  70. if option[1]:
  71. opt_label += '='
  72. print(opt_label)
  73. else:
  74. # show main parser options only when necessary
  75. if current.startswith('-') or current.startswith('--'):
  76. opts = [i.option_list for i in parser.option_groups]
  77. opts.append(parser.option_list)
  78. opts = (o for it in opts for o in it)
  79. subcommands += [i.get_opt_string() for i in opts
  80. if i.help != optparse.SUPPRESS_HELP]
  81. print(' '.join([x for x in subcommands if x.startswith(current)]))
  82. sys.exit(1)
  83. def create_main_parser():
  84. parser_kw = {
  85. 'usage': '\n%prog <command> [options]',
  86. 'add_help_option': False,
  87. 'formatter': UpdatingDefaultsHelpFormatter(),
  88. 'name': 'global',
  89. 'prog': get_prog(),
  90. }
  91. parser = ConfigOptionParser(**parser_kw)
  92. parser.disable_interspersed_args()
  93. pip_pkg_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
  94. parser.version = 'pip %s from %s (python %s)' % (
  95. __version__, pip_pkg_dir, sys.version[:3])
  96. # add the general options
  97. gen_opts = cmdoptions.make_option_group(cmdoptions.general_group, parser)
  98. parser.add_option_group(gen_opts)
  99. parser.main = True # so the help formatter knows
  100. # create command listing for description
  101. command_summaries = get_summaries()
  102. description = [''] + ['%-27s %s' % (i, j) for i, j in command_summaries]
  103. parser.description = '\n'.join(description)
  104. return parser
  105. def parseopts(args):
  106. parser = create_main_parser()
  107. # Note: parser calls disable_interspersed_args(), so the result of this call
  108. # is to split the initial args into the general options before the
  109. # subcommand and everything else.
  110. # For example:
  111. # args: ['--timeout=5', 'install', '--user', 'INITools']
  112. # general_options: ['--timeout==5']
  113. # args_else: ['install', '--user', 'INITools']
  114. general_options, args_else = parser.parse_args(args)
  115. # --version
  116. if general_options.version:
  117. sys.stdout.write(parser.version)
  118. sys.stdout.write(os.linesep)
  119. sys.exit()
  120. # pip || pip help -> print_help()
  121. if not args_else or (args_else[0] == 'help' and len(args_else) == 1):
  122. parser.print_help()
  123. sys.exit()
  124. # the subcommand name
  125. cmd_name = args_else[0].lower()
  126. #all the args without the subcommand
  127. cmd_args = args[:]
  128. cmd_args.remove(args_else[0].lower())
  129. if cmd_name not in commands:
  130. guess = get_similar_commands(cmd_name)
  131. msg = ['unknown command "%s"' % cmd_name]
  132. if guess:
  133. msg.append('maybe you meant "%s"' % guess)
  134. raise CommandError(' - '.join(msg))
  135. return cmd_name, cmd_args
  136. def main(initial_args=None):
  137. if initial_args is None:
  138. initial_args = sys.argv[1:]
  139. autocomplete()
  140. try:
  141. cmd_name, cmd_args = parseopts(initial_args)
  142. except PipError:
  143. e = sys.exc_info()[1]
  144. sys.stderr.write("ERROR: %s" % e)
  145. sys.stderr.write(os.linesep)
  146. sys.exit(1)
  147. command = commands[cmd_name]()
  148. return command.main(cmd_args)
  149. def bootstrap():
  150. """
  151. Bootstrapping function to be called from install-pip.py script.
  152. """
  153. return main(['install', '--upgrade', 'pip'] + sys.argv[1:])
  154. ############################################################
  155. ## Writing freeze files
  156. class FrozenRequirement(object):
  157. def __init__(self, name, req, editable, comments=()):
  158. self.name = name
  159. self.req = req
  160. self.editable = editable
  161. self.comments = comments
  162. _rev_re = re.compile(r'-r(\d+)$')
  163. _date_re = re.compile(r'-(20\d\d\d\d\d\d)$')
  164. @classmethod
  165. def from_dist(cls, dist, dependency_links, find_tags=False):
  166. location = os.path.normcase(os.path.abspath(dist.location))
  167. comments = []
  168. from pip.vcs import vcs, get_src_requirement
  169. if vcs.get_backend_name(location):
  170. editable = True
  171. try:
  172. req = get_src_requirement(dist, location, find_tags)
  173. except InstallationError:
  174. ex = sys.exc_info()[1]
  175. logger.warn("Error when trying to get requirement for VCS system %s, falling back to uneditable format" % ex)
  176. req = None
  177. if req is None:
  178. logger.warn('Could not determine repository location of %s' % location)
  179. comments.append('## !! Could not determine repository location')
  180. req = dist.as_requirement()
  181. editable = False
  182. else:
  183. editable = False
  184. req = dist.as_requirement()
  185. specs = req.specs
  186. assert len(specs) == 1 and specs[0][0] == '=='
  187. version = specs[0][1]
  188. ver_match = cls._rev_re.search(version)
  189. date_match = cls._date_re.search(version)
  190. if ver_match or date_match:
  191. svn_backend = vcs.get_backend('svn')
  192. if svn_backend:
  193. svn_location = svn_backend(
  194. ).get_location(dist, dependency_links)
  195. if not svn_location:
  196. logger.warn(
  197. 'Warning: cannot find svn location for %s' % req)
  198. comments.append('## FIXME: could not find svn URL in dependency_links for this package:')
  199. else:
  200. comments.append('# Installing as editable to satisfy requirement %s:' % req)
  201. if ver_match:
  202. rev = ver_match.group(1)
  203. else:
  204. rev = '{%s}' % date_match.group(1)
  205. editable = True
  206. req = '%s@%s#egg=%s' % (svn_location, rev, cls.egg_name(dist))
  207. return cls(dist.project_name, req, editable, comments)
  208. @staticmethod
  209. def egg_name(dist):
  210. name = dist.egg_name()
  211. match = re.search(r'-py\d\.\d$', name)
  212. if match:
  213. name = name[:match.start()]
  214. return name
  215. def __str__(self):
  216. req = self.req
  217. if self.editable:
  218. req = '-e %s' % req
  219. return '\n'.join(list(self.comments) + [str(req)]) + '\n'
  220. if __name__ == '__main__':
  221. exit = main()
  222. if exit:
  223. sys.exit(exit)