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.

225 lines
7.8 KiB

6 months ago
  1. import os
  2. import textwrap
  3. from optparse import Values
  4. from typing import Any, List
  5. from pip._internal.cli.base_command import Command
  6. from pip._internal.cli.status_codes import ERROR, SUCCESS
  7. from pip._internal.exceptions import CommandError, PipError
  8. from pip._internal.utils import filesystem
  9. from pip._internal.utils.logging import getLogger
  10. logger = getLogger(__name__)
  11. class CacheCommand(Command):
  12. """
  13. Inspect and manage pip's wheel cache.
  14. Subcommands:
  15. - dir: Show the cache directory.
  16. - info: Show information about the cache.
  17. - list: List filenames of packages stored in the cache.
  18. - remove: Remove one or more package from the cache.
  19. - purge: Remove all items from the cache.
  20. ``<pattern>`` can be a glob expression or a package name.
  21. """
  22. ignore_require_venv = True
  23. usage = """
  24. %prog dir
  25. %prog info
  26. %prog list [<pattern>] [--format=[human, abspath]]
  27. %prog remove <pattern>
  28. %prog purge
  29. """
  30. def add_options(self) -> None:
  31. self.cmd_opts.add_option(
  32. "--format",
  33. action="store",
  34. dest="list_format",
  35. default="human",
  36. choices=("human", "abspath"),
  37. help="Select the output format among: human (default) or abspath",
  38. )
  39. self.parser.insert_option_group(0, self.cmd_opts)
  40. def run(self, options: Values, args: List[str]) -> int:
  41. handlers = {
  42. "dir": self.get_cache_dir,
  43. "info": self.get_cache_info,
  44. "list": self.list_cache_items,
  45. "remove": self.remove_cache_items,
  46. "purge": self.purge_cache,
  47. }
  48. if not options.cache_dir:
  49. logger.error("pip cache commands can not function since cache is disabled.")
  50. return ERROR
  51. # Determine action
  52. if not args or args[0] not in handlers:
  53. logger.error(
  54. "Need an action (%s) to perform.",
  55. ", ".join(sorted(handlers)),
  56. )
  57. return ERROR
  58. action = args[0]
  59. # Error handling happens here, not in the action-handlers.
  60. try:
  61. handlers[action](options, args[1:])
  62. except PipError as e:
  63. logger.error(e.args[0])
  64. return ERROR
  65. return SUCCESS
  66. def get_cache_dir(self, options: Values, args: List[Any]) -> None:
  67. if args:
  68. raise CommandError("Too many arguments")
  69. logger.info(options.cache_dir)
  70. def get_cache_info(self, options: Values, args: List[Any]) -> None:
  71. if args:
  72. raise CommandError("Too many arguments")
  73. num_http_files = len(self._find_http_files(options))
  74. num_packages = len(self._find_wheels(options, "*"))
  75. http_cache_location = self._cache_dir(options, "http-v2")
  76. old_http_cache_location = self._cache_dir(options, "http")
  77. wheels_cache_location = self._cache_dir(options, "wheels")
  78. http_cache_size = filesystem.format_size(
  79. filesystem.directory_size(http_cache_location)
  80. + filesystem.directory_size(old_http_cache_location)
  81. )
  82. wheels_cache_size = filesystem.format_directory_size(wheels_cache_location)
  83. message = (
  84. textwrap.dedent(
  85. """
  86. Package index page cache location (pip v23.3+): {http_cache_location}
  87. Package index page cache location (older pips): {old_http_cache_location}
  88. Package index page cache size: {http_cache_size}
  89. Number of HTTP files: {num_http_files}
  90. Locally built wheels location: {wheels_cache_location}
  91. Locally built wheels size: {wheels_cache_size}
  92. Number of locally built wheels: {package_count}
  93. """ # noqa: E501
  94. )
  95. .format(
  96. http_cache_location=http_cache_location,
  97. old_http_cache_location=old_http_cache_location,
  98. http_cache_size=http_cache_size,
  99. num_http_files=num_http_files,
  100. wheels_cache_location=wheels_cache_location,
  101. package_count=num_packages,
  102. wheels_cache_size=wheels_cache_size,
  103. )
  104. .strip()
  105. )
  106. logger.info(message)
  107. def list_cache_items(self, options: Values, args: List[Any]) -> None:
  108. if len(args) > 1:
  109. raise CommandError("Too many arguments")
  110. if args:
  111. pattern = args[0]
  112. else:
  113. pattern = "*"
  114. files = self._find_wheels(options, pattern)
  115. if options.list_format == "human":
  116. self.format_for_human(files)
  117. else:
  118. self.format_for_abspath(files)
  119. def format_for_human(self, files: List[str]) -> None:
  120. if not files:
  121. logger.info("No locally built wheels cached.")
  122. return
  123. results = []
  124. for filename in files:
  125. wheel = os.path.basename(filename)
  126. size = filesystem.format_file_size(filename)
  127. results.append(f" - {wheel} ({size})")
  128. logger.info("Cache contents:\n")
  129. logger.info("\n".join(sorted(results)))
  130. def format_for_abspath(self, files: List[str]) -> None:
  131. if files:
  132. logger.info("\n".join(sorted(files)))
  133. def remove_cache_items(self, options: Values, args: List[Any]) -> None:
  134. if len(args) > 1:
  135. raise CommandError("Too many arguments")
  136. if not args:
  137. raise CommandError("Please provide a pattern")
  138. files = self._find_wheels(options, args[0])
  139. no_matching_msg = "No matching packages"
  140. if args[0] == "*":
  141. # Only fetch http files if no specific pattern given
  142. files += self._find_http_files(options)
  143. else:
  144. # Add the pattern to the log message
  145. no_matching_msg += f' for pattern "{args[0]}"'
  146. if not files:
  147. logger.warning(no_matching_msg)
  148. for filename in files:
  149. os.unlink(filename)
  150. logger.verbose("Removed %s", filename)
  151. logger.info("Files removed: %s", len(files))
  152. def purge_cache(self, options: Values, args: List[Any]) -> None:
  153. if args:
  154. raise CommandError("Too many arguments")
  155. return self.remove_cache_items(options, ["*"])
  156. def _cache_dir(self, options: Values, subdir: str) -> str:
  157. return os.path.join(options.cache_dir, subdir)
  158. def _find_http_files(self, options: Values) -> List[str]:
  159. old_http_dir = self._cache_dir(options, "http")
  160. new_http_dir = self._cache_dir(options, "http-v2")
  161. return filesystem.find_files(old_http_dir, "*") + filesystem.find_files(
  162. new_http_dir, "*"
  163. )
  164. def _find_wheels(self, options: Values, pattern: str) -> List[str]:
  165. wheel_dir = self._cache_dir(options, "wheels")
  166. # The wheel filename format, as specified in PEP 427, is:
  167. # {distribution}-{version}(-{build})?-{python}-{abi}-{platform}.whl
  168. #
  169. # Additionally, non-alphanumeric values in the distribution are
  170. # normalized to underscores (_), meaning hyphens can never occur
  171. # before `-{version}`.
  172. #
  173. # Given that information:
  174. # - If the pattern we're given contains a hyphen (-), the user is
  175. # providing at least the version. Thus, we can just append `*.whl`
  176. # to match the rest of it.
  177. # - If the pattern we're given doesn't contain a hyphen (-), the
  178. # user is only providing the name. Thus, we append `-*.whl` to
  179. # match the hyphen before the version, followed by anything else.
  180. #
  181. # PEP 427: https://www.python.org/dev/peps/pep-0427/
  182. pattern = pattern + ("*.whl" if "-" in pattern else "-*.whl")
  183. return filesystem.find_files(wheel_dir, pattern)