图片解析应用
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.

139 lines
4.7 KiB

  1. import logging
  2. from optparse import Values
  3. from typing import Any, Iterable, List, Optional, Union
  4. from pip._vendor.packaging.version import LegacyVersion, Version
  5. from pip._internal.cli import cmdoptions
  6. from pip._internal.cli.req_command import IndexGroupCommand
  7. from pip._internal.cli.status_codes import ERROR, SUCCESS
  8. from pip._internal.commands.search import print_dist_installation_info
  9. from pip._internal.exceptions import CommandError, DistributionNotFound, PipError
  10. from pip._internal.index.collector import LinkCollector
  11. from pip._internal.index.package_finder import PackageFinder
  12. from pip._internal.models.selection_prefs import SelectionPreferences
  13. from pip._internal.models.target_python import TargetPython
  14. from pip._internal.network.session import PipSession
  15. from pip._internal.utils.misc import write_output
  16. logger = logging.getLogger(__name__)
  17. class IndexCommand(IndexGroupCommand):
  18. """
  19. Inspect information available from package indexes.
  20. """
  21. ignore_require_venv = True
  22. usage = """
  23. %prog versions <package>
  24. """
  25. def add_options(self) -> None:
  26. cmdoptions.add_target_python_options(self.cmd_opts)
  27. self.cmd_opts.add_option(cmdoptions.ignore_requires_python())
  28. self.cmd_opts.add_option(cmdoptions.pre())
  29. self.cmd_opts.add_option(cmdoptions.no_binary())
  30. self.cmd_opts.add_option(cmdoptions.only_binary())
  31. index_opts = cmdoptions.make_option_group(
  32. cmdoptions.index_group,
  33. self.parser,
  34. )
  35. self.parser.insert_option_group(0, index_opts)
  36. self.parser.insert_option_group(0, self.cmd_opts)
  37. def run(self, options: Values, args: List[str]) -> int:
  38. handlers = {
  39. "versions": self.get_available_package_versions,
  40. }
  41. logger.warning(
  42. "pip index is currently an experimental command. "
  43. "It may be removed/changed in a future release "
  44. "without prior warning."
  45. )
  46. # Determine action
  47. if not args or args[0] not in handlers:
  48. logger.error(
  49. "Need an action (%s) to perform.",
  50. ", ".join(sorted(handlers)),
  51. )
  52. return ERROR
  53. action = args[0]
  54. # Error handling happens here, not in the action-handlers.
  55. try:
  56. handlers[action](options, args[1:])
  57. except PipError as e:
  58. logger.error(e.args[0])
  59. return ERROR
  60. return SUCCESS
  61. def _build_package_finder(
  62. self,
  63. options: Values,
  64. session: PipSession,
  65. target_python: Optional[TargetPython] = None,
  66. ignore_requires_python: Optional[bool] = None,
  67. ) -> PackageFinder:
  68. """
  69. Create a package finder appropriate to the index command.
  70. """
  71. link_collector = LinkCollector.create(session, options=options)
  72. # Pass allow_yanked=False to ignore yanked versions.
  73. selection_prefs = SelectionPreferences(
  74. allow_yanked=False,
  75. allow_all_prereleases=options.pre,
  76. ignore_requires_python=ignore_requires_python,
  77. )
  78. return PackageFinder.create(
  79. link_collector=link_collector,
  80. selection_prefs=selection_prefs,
  81. target_python=target_python,
  82. )
  83. def get_available_package_versions(self, options: Values, args: List[Any]) -> None:
  84. if len(args) != 1:
  85. raise CommandError("You need to specify exactly one argument")
  86. target_python = cmdoptions.make_target_python(options)
  87. query = args[0]
  88. with self._build_session(options) as session:
  89. finder = self._build_package_finder(
  90. options=options,
  91. session=session,
  92. target_python=target_python,
  93. ignore_requires_python=options.ignore_requires_python,
  94. )
  95. versions: Iterable[Union[LegacyVersion, Version]] = (
  96. candidate.version for candidate in finder.find_all_candidates(query)
  97. )
  98. if not options.pre:
  99. # Remove prereleases
  100. versions = (
  101. version for version in versions if not version.is_prerelease
  102. )
  103. versions = set(versions)
  104. if not versions:
  105. raise DistributionNotFound(
  106. f"No matching distribution found for {query}"
  107. )
  108. formatted_versions = [str(ver) for ver in sorted(versions, reverse=True)]
  109. latest = formatted_versions[0]
  110. write_output(f"{query} ({latest})")
  111. write_output("Available versions: {}".format(", ".join(formatted_versions)))
  112. print_dist_installation_info(query, latest)