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.
 
 
 
 

131 lines
4.9 KiB

  1. from __future__ import absolute_import
  2. from email.parser import FeedParser
  3. import logging
  4. import os
  5. from pip.basecommand import Command
  6. from pip.status_codes import SUCCESS, ERROR
  7. from pip._vendor import pkg_resources
  8. logger = logging.getLogger(__name__)
  9. class ShowCommand(Command):
  10. """Show information about one or more installed packages."""
  11. name = 'show'
  12. usage = """
  13. %prog [options] <package> ..."""
  14. summary = 'Show information about installed packages.'
  15. def __init__(self, *args, **kw):
  16. super(ShowCommand, self).__init__(*args, **kw)
  17. self.cmd_opts.add_option(
  18. '-f', '--files',
  19. dest='files',
  20. action='store_true',
  21. default=False,
  22. help='Show the full list of installed files for each package.')
  23. self.parser.insert_option_group(0, self.cmd_opts)
  24. def run(self, options, args):
  25. if not args:
  26. logger.warning('ERROR: Please provide a package name or names.')
  27. return ERROR
  28. query = args
  29. results = search_packages_info(query)
  30. if not print_results(results, options.files):
  31. return ERROR
  32. return SUCCESS
  33. def search_packages_info(query):
  34. """
  35. Gather details from installed distributions. Print distribution name,
  36. version, location, and installed files. Installed files requires a
  37. pip generated 'installed-files.txt' in the distributions '.egg-info'
  38. directory.
  39. """
  40. installed = dict(
  41. [(p.project_name.lower(), p) for p in pkg_resources.working_set])
  42. query_names = [name.lower() for name in query]
  43. for dist in [installed[pkg] for pkg in query_names if pkg in installed]:
  44. package = {
  45. 'name': dist.project_name,
  46. 'version': dist.version,
  47. 'location': dist.location,
  48. 'requires': [dep.project_name for dep in dist.requires()],
  49. }
  50. file_list = None
  51. metadata = None
  52. if isinstance(dist, pkg_resources.DistInfoDistribution):
  53. # RECORDs should be part of .dist-info metadatas
  54. if dist.has_metadata('RECORD'):
  55. lines = dist.get_metadata_lines('RECORD')
  56. paths = [l.split(',')[0] for l in lines]
  57. paths = [os.path.join(dist.location, p) for p in paths]
  58. file_list = [os.path.relpath(p, dist.location) for p in paths]
  59. if dist.has_metadata('METADATA'):
  60. metadata = dist.get_metadata('METADATA')
  61. else:
  62. # Otherwise use pip's log for .egg-info's
  63. if dist.has_metadata('installed-files.txt'):
  64. paths = dist.get_metadata_lines('installed-files.txt')
  65. paths = [os.path.join(dist.egg_info, p) for p in paths]
  66. file_list = [os.path.relpath(p, dist.location) for p in paths]
  67. if dist.has_metadata('entry_points.txt'):
  68. entry_points = dist.get_metadata_lines('entry_points.txt')
  69. package['entry_points'] = entry_points
  70. if dist.has_metadata('PKG-INFO'):
  71. metadata = dist.get_metadata('PKG-INFO')
  72. # @todo: Should pkg_resources.Distribution have a
  73. # `get_pkg_info` method?
  74. feed_parser = FeedParser()
  75. feed_parser.feed(metadata)
  76. pkg_info_dict = feed_parser.close()
  77. for key in ('metadata-version', 'summary',
  78. 'home-page', 'author', 'author-email', 'license'):
  79. package[key] = pkg_info_dict.get(key)
  80. # use and short-circuit to check for None
  81. package['files'] = file_list and sorted(file_list)
  82. yield package
  83. def print_results(distributions, list_all_files):
  84. """
  85. Print the informations from installed distributions found.
  86. """
  87. results_printed = False
  88. for dist in distributions:
  89. results_printed = True
  90. logger.info("---")
  91. logger.info("Metadata-Version: %s" % dist.get('metadata-version'))
  92. logger.info("Name: %s" % dist['name'])
  93. logger.info("Version: %s" % dist['version'])
  94. logger.info("Summary: %s" % dist.get('summary'))
  95. logger.info("Home-page: %s" % dist.get('home-page'))
  96. logger.info("Author: %s" % dist.get('author'))
  97. logger.info("Author-email: %s" % dist.get('author-email'))
  98. logger.info("License: %s" % dist.get('license'))
  99. logger.info("Location: %s" % dist['location'])
  100. logger.info("Requires: %s" % ', '.join(dist['requires']))
  101. if list_all_files:
  102. logger.info("Files:")
  103. if dist['files'] is not None:
  104. for line in dist['files']:
  105. logger.info(" %s" % line.strip())
  106. else:
  107. logger.info("Cannot locate installed-files.txt")
  108. if 'entry_points' in dist:
  109. logger.info("Entry-points:")
  110. for line in dist['entry_points']:
  111. logger.info(" %s" % line.strip())
  112. return results_printed