Path: blob/main/test/lib/python3.9/site-packages/pip/_internal/commands/cache.py
4804 views
import os1import textwrap2from optparse import Values3from typing import Any, List45import pip._internal.utils.filesystem as filesystem6from pip._internal.cli.base_command import Command7from pip._internal.cli.status_codes import ERROR, SUCCESS8from pip._internal.exceptions import CommandError, PipError9from pip._internal.utils.logging import getLogger1011logger = getLogger(__name__)121314class CacheCommand(Command):15"""16Inspect and manage pip's wheel cache.1718Subcommands:1920- dir: Show the cache directory.21- info: Show information about the cache.22- list: List filenames of packages stored in the cache.23- remove: Remove one or more package from the cache.24- purge: Remove all items from the cache.2526``<pattern>`` can be a glob expression or a package name.27"""2829ignore_require_venv = True30usage = """31%prog dir32%prog info33%prog list [<pattern>] [--format=[human, abspath]]34%prog remove <pattern>35%prog purge36"""3738def add_options(self) -> None:3940self.cmd_opts.add_option(41"--format",42action="store",43dest="list_format",44default="human",45choices=("human", "abspath"),46help="Select the output format among: human (default) or abspath",47)4849self.parser.insert_option_group(0, self.cmd_opts)5051def run(self, options: Values, args: List[str]) -> int:52handlers = {53"dir": self.get_cache_dir,54"info": self.get_cache_info,55"list": self.list_cache_items,56"remove": self.remove_cache_items,57"purge": self.purge_cache,58}5960if not options.cache_dir:61logger.error("pip cache commands can not function since cache is disabled.")62return ERROR6364# Determine action65if not args or args[0] not in handlers:66logger.error(67"Need an action (%s) to perform.",68", ".join(sorted(handlers)),69)70return ERROR7172action = args[0]7374# Error handling happens here, not in the action-handlers.75try:76handlers[action](options, args[1:])77except PipError as e:78logger.error(e.args[0])79return ERROR8081return SUCCESS8283def get_cache_dir(self, options: Values, args: List[Any]) -> None:84if args:85raise CommandError("Too many arguments")8687logger.info(options.cache_dir)8889def get_cache_info(self, options: Values, args: List[Any]) -> None:90if args:91raise CommandError("Too many arguments")9293num_http_files = len(self._find_http_files(options))94num_packages = len(self._find_wheels(options, "*"))9596http_cache_location = self._cache_dir(options, "http")97wheels_cache_location = self._cache_dir(options, "wheels")98http_cache_size = filesystem.format_directory_size(http_cache_location)99wheels_cache_size = filesystem.format_directory_size(wheels_cache_location)100101message = (102textwrap.dedent(103"""104Package index page cache location: {http_cache_location}105Package index page cache size: {http_cache_size}106Number of HTTP files: {num_http_files}107Wheels location: {wheels_cache_location}108Wheels size: {wheels_cache_size}109Number of wheels: {package_count}110"""111)112.format(113http_cache_location=http_cache_location,114http_cache_size=http_cache_size,115num_http_files=num_http_files,116wheels_cache_location=wheels_cache_location,117package_count=num_packages,118wheels_cache_size=wheels_cache_size,119)120.strip()121)122123logger.info(message)124125def list_cache_items(self, options: Values, args: List[Any]) -> None:126if len(args) > 1:127raise CommandError("Too many arguments")128129if args:130pattern = args[0]131else:132pattern = "*"133134files = self._find_wheels(options, pattern)135if options.list_format == "human":136self.format_for_human(files)137else:138self.format_for_abspath(files)139140def format_for_human(self, files: List[str]) -> None:141if not files:142logger.info("Nothing cached.")143return144145results = []146for filename in files:147wheel = os.path.basename(filename)148size = filesystem.format_file_size(filename)149results.append(f" - {wheel} ({size})")150logger.info("Cache contents:\n")151logger.info("\n".join(sorted(results)))152153def format_for_abspath(self, files: List[str]) -> None:154if not files:155return156157results = []158for filename in files:159results.append(filename)160161logger.info("\n".join(sorted(results)))162163def remove_cache_items(self, options: Values, args: List[Any]) -> None:164if len(args) > 1:165raise CommandError("Too many arguments")166167if not args:168raise CommandError("Please provide a pattern")169170files = self._find_wheels(options, args[0])171172no_matching_msg = "No matching packages"173if args[0] == "*":174# Only fetch http files if no specific pattern given175files += self._find_http_files(options)176else:177# Add the pattern to the log message178no_matching_msg += ' for pattern "{}"'.format(args[0])179180if not files:181logger.warning(no_matching_msg)182183for filename in files:184os.unlink(filename)185logger.verbose("Removed %s", filename)186logger.info("Files removed: %s", len(files))187188def purge_cache(self, options: Values, args: List[Any]) -> None:189if args:190raise CommandError("Too many arguments")191192return self.remove_cache_items(options, ["*"])193194def _cache_dir(self, options: Values, subdir: str) -> str:195return os.path.join(options.cache_dir, subdir)196197def _find_http_files(self, options: Values) -> List[str]:198http_dir = self._cache_dir(options, "http")199return filesystem.find_files(http_dir, "*")200201def _find_wheels(self, options: Values, pattern: str) -> List[str]:202wheel_dir = self._cache_dir(options, "wheels")203204# The wheel filename format, as specified in PEP 427, is:205# {distribution}-{version}(-{build})?-{python}-{abi}-{platform}.whl206#207# Additionally, non-alphanumeric values in the distribution are208# normalized to underscores (_), meaning hyphens can never occur209# before `-{version}`.210#211# Given that information:212# - If the pattern we're given contains a hyphen (-), the user is213# providing at least the version. Thus, we can just append `*.whl`214# to match the rest of it.215# - If the pattern we're given doesn't contain a hyphen (-), the216# user is only providing the name. Thus, we append `-*.whl` to217# match the hyphen before the version, followed by anything else.218#219# PEP 427: https://www.python.org/dev/peps/pep-0427/220pattern = pattern + ("*.whl" if "-" in pattern else "-*.whl")221222return filesystem.find_files(wheel_dir, pattern)223224225