freeze.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. import re
  2. import sys
  3. import pip
  4. from pip.req import InstallRequirement
  5. from pip.log import logger
  6. from pip.basecommand import Command
  7. from pip.util import get_installed_distributions
  8. from pip._vendor import pkg_resources
  9. class FreezeCommand(Command):
  10. """Output installed packages in requirements format."""
  11. name = 'freeze'
  12. usage = """
  13. %prog [options]"""
  14. summary = 'Output installed packages in requirements format.'
  15. def __init__(self, *args, **kw):
  16. super(FreezeCommand, self).__init__(*args, **kw)
  17. self.cmd_opts.add_option(
  18. '-r', '--requirement',
  19. dest='requirement',
  20. action='store',
  21. default=None,
  22. metavar='file',
  23. help="Use the order in the given requirements file and it's comments when generating output.")
  24. self.cmd_opts.add_option(
  25. '-f', '--find-links',
  26. dest='find_links',
  27. action='append',
  28. default=[],
  29. metavar='URL',
  30. help='URL for finding packages, which will be added to the output.')
  31. self.cmd_opts.add_option(
  32. '-l', '--local',
  33. dest='local',
  34. action='store_true',
  35. default=False,
  36. help='If in a virtualenv that has global access, do not output globally-installed packages.')
  37. self.parser.insert_option_group(0, self.cmd_opts)
  38. def setup_logging(self):
  39. logger.move_stdout_to_stderr()
  40. def run(self, options, args):
  41. requirement = options.requirement
  42. find_links = options.find_links or []
  43. local_only = options.local
  44. ## FIXME: Obviously this should be settable:
  45. find_tags = False
  46. skip_match = None
  47. skip_regex = options.skip_requirements_regex
  48. if skip_regex:
  49. skip_match = re.compile(skip_regex)
  50. dependency_links = []
  51. f = sys.stdout
  52. for dist in pkg_resources.working_set:
  53. if dist.has_metadata('dependency_links.txt'):
  54. dependency_links.extend(dist.get_metadata_lines('dependency_links.txt'))
  55. for link in find_links:
  56. if '#egg=' in link:
  57. dependency_links.append(link)
  58. for link in find_links:
  59. f.write('-f %s\n' % link)
  60. installations = {}
  61. for dist in get_installed_distributions(local_only=local_only):
  62. req = pip.FrozenRequirement.from_dist(dist, dependency_links, find_tags=find_tags)
  63. installations[req.name] = req
  64. if requirement:
  65. req_f = open(requirement)
  66. for line in req_f:
  67. if not line.strip() or line.strip().startswith('#'):
  68. f.write(line)
  69. continue
  70. if skip_match and skip_match.search(line):
  71. f.write(line)
  72. continue
  73. elif line.startswith('-e') or line.startswith('--editable'):
  74. if line.startswith('-e'):
  75. line = line[2:].strip()
  76. else:
  77. line = line[len('--editable'):].strip().lstrip('=')
  78. line_req = InstallRequirement.from_editable(line, default_vcs=options.default_vcs)
  79. elif (line.startswith('-r') or line.startswith('--requirement')
  80. or line.startswith('-Z') or line.startswith('--always-unzip')
  81. or line.startswith('-f') or line.startswith('-i')
  82. or line.startswith('--extra-index-url')
  83. or line.startswith('--find-links')
  84. or line.startswith('--index-url')):
  85. f.write(line)
  86. continue
  87. else:
  88. line_req = InstallRequirement.from_line(line)
  89. if not line_req.name:
  90. logger.notify("Skipping line because it's not clear what it would install: %s"
  91. % line.strip())
  92. logger.notify(" (add #egg=PackageName to the URL to avoid this warning)")
  93. continue
  94. if line_req.name not in installations:
  95. logger.warn("Requirement file contains %s, but that package is not installed"
  96. % line.strip())
  97. continue
  98. f.write(str(installations[line_req.name]))
  99. del installations[line_req.name]
  100. f.write('## The following requirements were added by pip --freeze:\n')
  101. for installation in sorted(installations.values(), key=lambda x: x.name):
  102. f.write(str(installation))