freeze.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. from __future__ import absolute_import
  2. import logging
  3. import re
  4. import pip
  5. from pip.compat import stdlib_pkgs
  6. from pip.req import InstallRequirement
  7. from pip.utils import get_installed_distributions
  8. from pip._vendor import pkg_resources
  9. logger = logging.getLogger(__name__)
  10. # packages to exclude from freeze output
  11. freeze_excludes = stdlib_pkgs + ['setuptools', 'pip', 'distribute']
  12. def freeze(
  13. requirement=None,
  14. find_links=None, local_only=None, user_only=None, skip_regex=None,
  15. find_tags=False,
  16. default_vcs=None,
  17. isolated=False):
  18. find_links = find_links or []
  19. skip_match = None
  20. if skip_regex:
  21. skip_match = re.compile(skip_regex)
  22. dependency_links = []
  23. for dist in pkg_resources.working_set:
  24. if dist.has_metadata('dependency_links.txt'):
  25. dependency_links.extend(
  26. dist.get_metadata_lines('dependency_links.txt')
  27. )
  28. for link in find_links:
  29. if '#egg=' in link:
  30. dependency_links.append(link)
  31. for link in find_links:
  32. yield '-f %s' % link
  33. installations = {}
  34. for dist in get_installed_distributions(local_only=local_only,
  35. skip=freeze_excludes,
  36. user_only=user_only):
  37. req = pip.FrozenRequirement.from_dist(
  38. dist,
  39. dependency_links,
  40. find_tags=find_tags,
  41. )
  42. installations[req.name] = req
  43. if requirement:
  44. with open(requirement) as req_file:
  45. for line in req_file:
  46. if (not line.strip() or
  47. line.strip().startswith('#') or
  48. (skip_match and skip_match.search(line)) or
  49. line.startswith((
  50. '-r', '--requirement',
  51. '-Z', '--always-unzip',
  52. '-f', '--find-links',
  53. '-i', '--index-url',
  54. '--extra-index-url'))):
  55. yield line.rstrip()
  56. continue
  57. if line.startswith('-e') or line.startswith('--editable'):
  58. if line.startswith('-e'):
  59. line = line[2:].strip()
  60. else:
  61. line = line[len('--editable'):].strip().lstrip('=')
  62. line_req = InstallRequirement.from_editable(
  63. line,
  64. default_vcs=default_vcs,
  65. isolated=isolated,
  66. )
  67. else:
  68. line_req = InstallRequirement.from_line(
  69. line,
  70. isolated=isolated,
  71. )
  72. if not line_req.name:
  73. logger.info(
  74. "Skipping line because it's not clear what it "
  75. "would install: %s",
  76. line.strip(),
  77. )
  78. logger.info(
  79. " (add #egg=PackageName to the URL to avoid"
  80. " this warning)"
  81. )
  82. elif line_req.name not in installations:
  83. logger.warning(
  84. "Requirement file contains %s, but that package is"
  85. " not installed",
  86. line.strip(),
  87. )
  88. else:
  89. yield str(installations[line_req.name]).rstrip()
  90. del installations[line_req.name]
  91. yield(
  92. '## The following requirements were added by '
  93. 'pip freeze:'
  94. )
  95. for installation in sorted(
  96. installations.values(), key=lambda x: x.name.lower()):
  97. yield str(installation).rstrip()