m2m模型翻译
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

166 lines
5.6 KiB

6 months ago
  1. from pip._vendor.packaging.specifiers import SpecifierSet
  2. from pip._vendor.packaging.utils import NormalizedName, canonicalize_name
  3. from pip._internal.req.constructors import install_req_drop_extras
  4. from pip._internal.req.req_install import InstallRequirement
  5. from .base import Candidate, CandidateLookup, Requirement, format_name
  6. class ExplicitRequirement(Requirement):
  7. def __init__(self, candidate: Candidate) -> None:
  8. self.candidate = candidate
  9. def __str__(self) -> str:
  10. return str(self.candidate)
  11. def __repr__(self) -> str:
  12. return f"{self.__class__.__name__}({self.candidate!r})"
  13. @property
  14. def project_name(self) -> NormalizedName:
  15. # No need to canonicalize - the candidate did this
  16. return self.candidate.project_name
  17. @property
  18. def name(self) -> str:
  19. # No need to canonicalize - the candidate did this
  20. return self.candidate.name
  21. def format_for_error(self) -> str:
  22. return self.candidate.format_for_error()
  23. def get_candidate_lookup(self) -> CandidateLookup:
  24. return self.candidate, None
  25. def is_satisfied_by(self, candidate: Candidate) -> bool:
  26. return candidate == self.candidate
  27. class SpecifierRequirement(Requirement):
  28. def __init__(self, ireq: InstallRequirement) -> None:
  29. assert ireq.link is None, "This is a link, not a specifier"
  30. self._ireq = ireq
  31. self._extras = frozenset(canonicalize_name(e) for e in self._ireq.extras)
  32. def __str__(self) -> str:
  33. return str(self._ireq.req)
  34. def __repr__(self) -> str:
  35. return f"{self.__class__.__name__}({str(self._ireq.req)!r})"
  36. @property
  37. def project_name(self) -> NormalizedName:
  38. assert self._ireq.req, "Specifier-backed ireq is always PEP 508"
  39. return canonicalize_name(self._ireq.req.name)
  40. @property
  41. def name(self) -> str:
  42. return format_name(self.project_name, self._extras)
  43. def format_for_error(self) -> str:
  44. # Convert comma-separated specifiers into "A, B, ..., F and G"
  45. # This makes the specifier a bit more "human readable", without
  46. # risking a change in meaning. (Hopefully! Not all edge cases have
  47. # been checked)
  48. parts = [s.strip() for s in str(self).split(",")]
  49. if len(parts) == 0:
  50. return ""
  51. elif len(parts) == 1:
  52. return parts[0]
  53. return ", ".join(parts[:-1]) + " and " + parts[-1]
  54. def get_candidate_lookup(self) -> CandidateLookup:
  55. return None, self._ireq
  56. def is_satisfied_by(self, candidate: Candidate) -> bool:
  57. assert candidate.name == self.name, (
  58. f"Internal issue: Candidate is not for this requirement "
  59. f"{candidate.name} vs {self.name}"
  60. )
  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. assert self._ireq.req, "Specifier-backed ireq is always PEP 508"
  65. spec = self._ireq.req.specifier
  66. return spec.contains(candidate.version, prereleases=True)
  67. class SpecifierWithoutExtrasRequirement(SpecifierRequirement):
  68. """
  69. Requirement backed by an install requirement on a base package.
  70. Trims extras from its install requirement if there are any.
  71. """
  72. def __init__(self, ireq: InstallRequirement) -> None:
  73. assert ireq.link is None, "This is a link, not a specifier"
  74. self._ireq = install_req_drop_extras(ireq)
  75. self._extras = frozenset(canonicalize_name(e) for e in self._ireq.extras)
  76. class RequiresPythonRequirement(Requirement):
  77. """A requirement representing Requires-Python metadata."""
  78. def __init__(self, specifier: SpecifierSet, match: Candidate) -> None:
  79. self.specifier = specifier
  80. self._candidate = match
  81. def __str__(self) -> str:
  82. return f"Python {self.specifier}"
  83. def __repr__(self) -> str:
  84. return f"{self.__class__.__name__}({str(self.specifier)!r})"
  85. @property
  86. def project_name(self) -> NormalizedName:
  87. return self._candidate.project_name
  88. @property
  89. def name(self) -> str:
  90. return self._candidate.name
  91. def format_for_error(self) -> str:
  92. return str(self)
  93. def get_candidate_lookup(self) -> CandidateLookup:
  94. if self.specifier.contains(self._candidate.version, prereleases=True):
  95. return self._candidate, None
  96. return None, None
  97. def is_satisfied_by(self, candidate: Candidate) -> bool:
  98. assert candidate.name == self._candidate.name, "Not Python candidate"
  99. # We can safely always allow prereleases here since PackageFinder
  100. # already implements the prerelease logic, and would have filtered out
  101. # prerelease candidates if the user does not expect them.
  102. return self.specifier.contains(candidate.version, prereleases=True)
  103. class UnsatisfiableRequirement(Requirement):
  104. """A requirement that cannot be satisfied."""
  105. def __init__(self, name: NormalizedName) -> None:
  106. self._name = name
  107. def __str__(self) -> str:
  108. return f"{self._name} (unavailable)"
  109. def __repr__(self) -> str:
  110. return f"{self.__class__.__name__}({str(self._name)!r})"
  111. @property
  112. def project_name(self) -> NormalizedName:
  113. return self._name
  114. @property
  115. def name(self) -> str:
  116. return self._name
  117. def format_for_error(self) -> str:
  118. return str(self)
  119. def get_candidate_lookup(self) -> CandidateLookup:
  120. return None, None
  121. def is_satisfied_by(self, candidate: Candidate) -> bool:
  122. return False