base.py 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. from pip._vendor.packaging.specifiers import SpecifierSet
  2. from pip._vendor.packaging.utils import canonicalize_name
  3. from pip._internal.req.req_install import InstallRequirement
  4. from pip._internal.utils.hashes import Hashes
  5. from pip._internal.utils.typing import MYPY_CHECK_RUNNING
  6. if MYPY_CHECK_RUNNING:
  7. from typing import FrozenSet, Iterable, Optional, Tuple
  8. from pip._vendor.packaging.version import _BaseVersion
  9. from pip._internal.models.link import Link
  10. CandidateLookup = Tuple[
  11. Optional["Candidate"],
  12. Optional[InstallRequirement],
  13. ]
  14. def format_name(project, extras):
  15. # type: (str, FrozenSet[str]) -> str
  16. if not extras:
  17. return project
  18. canonical_extras = sorted(canonicalize_name(e) for e in extras)
  19. return "{}[{}]".format(project, ",".join(canonical_extras))
  20. class Constraint(object):
  21. def __init__(self, specifier, hashes):
  22. # type: (SpecifierSet, Hashes) -> None
  23. self.specifier = specifier
  24. self.hashes = hashes
  25. @classmethod
  26. def empty(cls):
  27. # type: () -> Constraint
  28. return Constraint(SpecifierSet(), Hashes())
  29. @classmethod
  30. def from_ireq(cls, ireq):
  31. # type: (InstallRequirement) -> Constraint
  32. return Constraint(ireq.specifier, ireq.hashes(trust_internet=False))
  33. def __nonzero__(self):
  34. # type: () -> bool
  35. return bool(self.specifier) or bool(self.hashes)
  36. def __bool__(self):
  37. # type: () -> bool
  38. return self.__nonzero__()
  39. def __and__(self, other):
  40. # type: (InstallRequirement) -> Constraint
  41. if not isinstance(other, InstallRequirement):
  42. return NotImplemented
  43. specifier = self.specifier & other.specifier
  44. hashes = self.hashes & other.hashes(trust_internet=False)
  45. return Constraint(specifier, hashes)
  46. def is_satisfied_by(self, candidate):
  47. # type: (Candidate) -> bool
  48. # We can safely always allow prereleases here since PackageFinder
  49. # already implements the prerelease logic, and would have filtered out
  50. # prerelease candidates if the user does not expect them.
  51. return self.specifier.contains(candidate.version, prereleases=True)
  52. class Requirement(object):
  53. @property
  54. def project_name(self):
  55. # type: () -> str
  56. """The "project name" of a requirement.
  57. This is different from ``name`` if this requirement contains extras,
  58. in which case ``name`` would contain the ``[...]`` part, while this
  59. refers to the name of the project.
  60. """
  61. raise NotImplementedError("Subclass should override")
  62. @property
  63. def name(self):
  64. # type: () -> str
  65. """The name identifying this requirement in the resolver.
  66. This is different from ``project_name`` if this requirement contains
  67. extras, where ``project_name`` would not contain the ``[...]`` part.
  68. """
  69. raise NotImplementedError("Subclass should override")
  70. def is_satisfied_by(self, candidate):
  71. # type: (Candidate) -> bool
  72. return False
  73. def get_candidate_lookup(self):
  74. # type: () -> CandidateLookup
  75. raise NotImplementedError("Subclass should override")
  76. def format_for_error(self):
  77. # type: () -> str
  78. raise NotImplementedError("Subclass should override")
  79. class Candidate(object):
  80. @property
  81. def project_name(self):
  82. # type: () -> str
  83. """The "project name" of the candidate.
  84. This is different from ``name`` if this candidate contains extras,
  85. in which case ``name`` would contain the ``[...]`` part, while this
  86. refers to the name of the project.
  87. """
  88. raise NotImplementedError("Override in subclass")
  89. @property
  90. def name(self):
  91. # type: () -> str
  92. """The name identifying this candidate in the resolver.
  93. This is different from ``project_name`` if this candidate contains
  94. extras, where ``project_name`` would not contain the ``[...]`` part.
  95. """
  96. raise NotImplementedError("Override in subclass")
  97. @property
  98. def version(self):
  99. # type: () -> _BaseVersion
  100. raise NotImplementedError("Override in subclass")
  101. @property
  102. def is_installed(self):
  103. # type: () -> bool
  104. raise NotImplementedError("Override in subclass")
  105. @property
  106. def is_editable(self):
  107. # type: () -> bool
  108. raise NotImplementedError("Override in subclass")
  109. @property
  110. def source_link(self):
  111. # type: () -> Optional[Link]
  112. raise NotImplementedError("Override in subclass")
  113. def iter_dependencies(self, with_requires):
  114. # type: (bool) -> Iterable[Optional[Requirement]]
  115. raise NotImplementedError("Override in subclass")
  116. def get_install_requirement(self):
  117. # type: () -> Optional[InstallRequirement]
  118. raise NotImplementedError("Override in subclass")
  119. def format_for_error(self):
  120. # type: () -> str
  121. raise NotImplementedError("Subclass should override")