req_file.py 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. from __future__ import absolute_import
  2. import os
  3. import re
  4. from pip._vendor.six.moves.urllib import parse as urllib_parse
  5. from pip.download import get_file_content
  6. from pip.req.req_install import InstallRequirement
  7. from pip.utils import normalize_name
  8. _scheme_re = re.compile(r'^(http|https|file):', re.I)
  9. def _remove_prefixes(line, short_prefix, long_prefix):
  10. if line.startswith(short_prefix):
  11. return line[len(short_prefix):].lstrip()
  12. else:
  13. return _remove_prefix(line, long_prefix)
  14. def _remove_prefix(line, prefix):
  15. """Remove the prefix and eventually one '=' or spaces"""
  16. return re.sub(r'\s*=?\s*', '', line[len(prefix):])
  17. def parse_requirements(filename, finder=None, comes_from=None, options=None,
  18. session=None):
  19. if session is None:
  20. raise TypeError(
  21. "parse_requirements() missing 1 required keyword argument: "
  22. "'session'"
  23. )
  24. skip_match = None
  25. skip_regex = options.skip_requirements_regex if options else None
  26. if skip_regex:
  27. skip_match = re.compile(skip_regex)
  28. reqs_file_dir = os.path.dirname(os.path.abspath(filename))
  29. filename, content = get_file_content(
  30. filename,
  31. comes_from=comes_from,
  32. session=session,
  33. )
  34. for line_number, line in enumerate(content.splitlines(), 1):
  35. line = line.strip()
  36. # Remove comments from file and all spaces before it
  37. line = re.sub(r"(^|\s)+#.*$", "", line)
  38. if not line:
  39. continue
  40. if skip_match and skip_match.search(line):
  41. continue
  42. if line.startswith(('-r', '--requirement')):
  43. req_url = _remove_prefixes(line, '-r', '--requirement')
  44. if _scheme_re.search(filename):
  45. # Relative to a URL
  46. req_url = urllib_parse.urljoin(filename, req_url)
  47. elif not _scheme_re.search(req_url):
  48. req_url = os.path.join(os.path.dirname(filename), req_url)
  49. for item in parse_requirements(
  50. req_url, finder,
  51. comes_from=filename,
  52. options=options,
  53. session=session):
  54. yield item
  55. elif line.startswith(('-Z', '--always-unzip')):
  56. # No longer used, but previously these were used in
  57. # requirement files, so we'll ignore.
  58. pass
  59. elif line.startswith(('-f', '--find-links')):
  60. find_links = _remove_prefixes(line, '-f', '--find-links')
  61. # FIXME: it would be nice to keep track of the source of
  62. # the find_links:
  63. # support a find-links local path relative to a requirements file
  64. relative_to_reqs_file = os.path.join(reqs_file_dir, find_links)
  65. if os.path.exists(relative_to_reqs_file):
  66. find_links = relative_to_reqs_file
  67. if finder:
  68. finder.find_links.append(find_links)
  69. elif line.startswith(('-i', '--index-url')):
  70. index_url = _remove_prefixes(line, '-i', '--index-url')
  71. if finder:
  72. finder.index_urls = [index_url]
  73. elif line.startswith('--extra-index-url'):
  74. line = _remove_prefix(line, '--extra-index-url')
  75. if finder:
  76. finder.index_urls.append(line)
  77. elif line.startswith('--use-wheel'):
  78. # Default in 1.5
  79. pass
  80. elif line.startswith('--no-use-wheel'):
  81. if finder:
  82. finder.use_wheel = False
  83. elif line.startswith('--no-index'):
  84. if finder:
  85. finder.index_urls = []
  86. elif line.startswith("--allow-external"):
  87. line = _remove_prefix(line, '--allow-external')
  88. if finder:
  89. finder.allow_external |= set([normalize_name(line).lower()])
  90. elif line.startswith("--allow-all-external"):
  91. if finder:
  92. finder.allow_all_external = True
  93. # Remove in 7.0
  94. elif line.startswith("--no-allow-external"):
  95. pass
  96. # Remove in 7.0
  97. elif line.startswith("--no-allow-insecure"):
  98. pass
  99. # Remove after 7.0
  100. elif line.startswith("--allow-insecure"):
  101. line = _remove_prefix(line, '--allow-insecure')
  102. if finder:
  103. finder.allow_unverified |= set([normalize_name(line).lower()])
  104. elif line.startswith("--allow-unverified"):
  105. line = _remove_prefix(line, '--allow-unverified')
  106. if finder:
  107. finder.allow_unverified |= set([normalize_name(line).lower()])
  108. else:
  109. comes_from = '-r %s (line %s)' % (filename, line_number)
  110. if line.startswith(('-e', '--editable')):
  111. editable = _remove_prefixes(line, '-e', '--editable')
  112. req = InstallRequirement.from_editable(
  113. editable,
  114. comes_from=comes_from,
  115. default_vcs=options.default_vcs if options else None,
  116. isolated=options.isolated_mode if options else False,
  117. )
  118. else:
  119. req = InstallRequirement.from_line(
  120. line,
  121. comes_from,
  122. isolated=options.isolated_mode if options else False,
  123. )
  124. yield req