requirements.py 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119
  1. from pip._vendor.packaging.utils import canonicalize_name
  2. from pip._internal.utils.typing import MYPY_CHECK_RUNNING
  3. from .base import Requirement, format_name
  4. if MYPY_CHECK_RUNNING:
  5. from typing import Sequence
  6. from pip._vendor.packaging.specifiers import SpecifierSet
  7. from pip._internal.req.req_install import InstallRequirement
  8. from .base import Candidate
  9. from .factory import Factory
  10. class ExplicitRequirement(Requirement):
  11. def __init__(self, candidate):
  12. # type: (Candidate) -> None
  13. self.candidate = candidate
  14. def __repr__(self):
  15. # type: () -> str
  16. return "{class_name}({candidate!r})".format(
  17. class_name=self.__class__.__name__,
  18. candidate=self.candidate,
  19. )
  20. @property
  21. def name(self):
  22. # type: () -> str
  23. # No need to canonicalise - the candidate did this
  24. return self.candidate.name
  25. def find_matches(self):
  26. # type: () -> Sequence[Candidate]
  27. return [self.candidate]
  28. def is_satisfied_by(self, candidate):
  29. # type: (Candidate) -> bool
  30. return candidate == self.candidate
  31. class SpecifierRequirement(Requirement):
  32. def __init__(self, ireq, factory):
  33. # type: (InstallRequirement, Factory) -> None
  34. assert ireq.link is None, "This is a link, not a specifier"
  35. self._ireq = ireq
  36. self._factory = factory
  37. self.extras = ireq.req.extras
  38. def __str__(self):
  39. # type: () -> str
  40. return str(self._ireq.req)
  41. def __repr__(self):
  42. # type: () -> str
  43. return "{class_name}({requirement!r})".format(
  44. class_name=self.__class__.__name__,
  45. requirement=str(self._ireq.req),
  46. )
  47. @property
  48. def name(self):
  49. # type: () -> str
  50. canonical_name = canonicalize_name(self._ireq.req.name)
  51. return format_name(canonical_name, self.extras)
  52. def find_matches(self):
  53. # type: () -> Sequence[Candidate]
  54. it = self._factory.iter_found_candidates(self._ireq, self.extras)
  55. return list(it)
  56. def is_satisfied_by(self, candidate):
  57. # type: (Candidate) -> bool
  58. assert candidate.name == self.name, \
  59. "Internal issue: Candidate is not for this requirement " \
  60. " {} vs {}".format(candidate.name, self.name)
  61. # We can safely always allow prereleases here since PackageFinder
  62. # already implements the prerelease logic, and would have filtered out
  63. # prerelease candidates if the user does not expect them.
  64. spec = self._ireq.req.specifier
  65. return spec.contains(candidate.version, prereleases=True)
  66. class RequiresPythonRequirement(Requirement):
  67. """A requirement representing Requires-Python metadata.
  68. """
  69. def __init__(self, specifier, match):
  70. # type: (SpecifierSet, Candidate) -> None
  71. self.specifier = specifier
  72. self._candidate = match
  73. def __repr__(self):
  74. # type: () -> str
  75. return "{class_name}({specifier!r})".format(
  76. class_name=self.__class__.__name__,
  77. specifier=str(self.specifier),
  78. )
  79. @property
  80. def name(self):
  81. # type: () -> str
  82. return self._candidate.name
  83. def find_matches(self):
  84. # type: () -> Sequence[Candidate]
  85. if self._candidate.version in self.specifier:
  86. return [self._candidate]
  87. return []
  88. def is_satisfied_by(self, candidate):
  89. # type: (Candidate) -> bool
  90. assert candidate.name == self._candidate.name, "Not Python candidate"
  91. # We can safely always allow prereleases here since PackageFinder
  92. # already implements the prerelease logic, and would have filtered out
  93. # prerelease candidates if the user does not expect them.
  94. return self.specifier.contains(candidate.version, prereleases=True)