Path: blob/master/venv/Lib/site-packages/pip/_internal/commands/cache.py
811 views
from __future__ import absolute_import12import logging3import os4import textwrap56import pip._internal.utils.filesystem as filesystem7from pip._internal.cli.base_command import Command8from pip._internal.cli.status_codes import ERROR, SUCCESS9from pip._internal.exceptions import CommandError, PipError10from pip._internal.utils.typing import MYPY_CHECK_RUNNING1112if MYPY_CHECK_RUNNING:13from optparse import Values14from typing import Any, List151617logger = logging.getLogger(__name__)181920class CacheCommand(Command):21"""22Inspect and manage pip's wheel cache.2324Subcommands:2526dir: Show the cache directory.27info: Show information about the cache.28list: List filenames of packages stored in the cache.29remove: Remove one or more package from the cache.30purge: Remove all items from the cache.3132<pattern> can be a glob expression or a package name.33"""3435ignore_require_venv = True36usage = """37%prog dir38%prog info39%prog list [<pattern>]40%prog remove <pattern>41%prog purge42"""4344def run(self, options, args):45# type: (Values, List[Any]) -> int46handlers = {47"dir": self.get_cache_dir,48"info": self.get_cache_info,49"list": self.list_cache_items,50"remove": self.remove_cache_items,51"purge": self.purge_cache,52}5354if not options.cache_dir:55logger.error("pip cache commands can not "56"function since cache is disabled.")57return ERROR5859# Determine action60if not args or args[0] not in handlers:61logger.error("Need an action ({}) to perform.".format(62", ".join(sorted(handlers)))63)64return ERROR6566action = args[0]6768# Error handling happens here, not in the action-handlers.69try:70handlers[action](options, args[1:])71except PipError as e:72logger.error(e.args[0])73return ERROR7475return SUCCESS7677def get_cache_dir(self, options, args):78# type: (Values, List[Any]) -> None79if args:80raise CommandError('Too many arguments')8182logger.info(options.cache_dir)8384def get_cache_info(self, options, args):85# type: (Values, List[Any]) -> None86if args:87raise CommandError('Too many arguments')8889num_packages = len(self._find_wheels(options, '*'))9091cache_location = self._wheels_cache_dir(options)92cache_size = filesystem.format_directory_size(cache_location)9394message = textwrap.dedent("""95Location: {location}96Size: {size}97Number of wheels: {package_count}98""").format(99location=cache_location,100package_count=num_packages,101size=cache_size,102).strip()103104logger.info(message)105106def list_cache_items(self, options, args):107# type: (Values, List[Any]) -> None108if len(args) > 1:109raise CommandError('Too many arguments')110111if args:112pattern = args[0]113else:114pattern = '*'115116files = self._find_wheels(options, pattern)117118if not files:119logger.info('Nothing cached.')120return121122results = []123for filename in files:124wheel = os.path.basename(filename)125size = filesystem.format_file_size(filename)126results.append(' - {} ({})'.format(wheel, size))127logger.info('Cache contents:\n')128logger.info('\n'.join(sorted(results)))129130def remove_cache_items(self, options, args):131# type: (Values, List[Any]) -> None132if len(args) > 1:133raise CommandError('Too many arguments')134135if not args:136raise CommandError('Please provide a pattern')137138files = self._find_wheels(options, args[0])139if not files:140raise CommandError('No matching packages')141142for filename in files:143os.unlink(filename)144logger.debug('Removed %s', filename)145logger.info('Files removed: %s', len(files))146147def purge_cache(self, options, args):148# type: (Values, List[Any]) -> None149if args:150raise CommandError('Too many arguments')151152return self.remove_cache_items(options, ['*'])153154def _wheels_cache_dir(self, options):155# type: (Values) -> str156return os.path.join(options.cache_dir, 'wheels')157158def _find_wheels(self, options, pattern):159# type: (Values, str) -> List[str]160wheel_dir = self._wheels_cache_dir(options)161162# The wheel filename format, as specified in PEP 427, is:163# {distribution}-{version}(-{build})?-{python}-{abi}-{platform}.whl164#165# Additionally, non-alphanumeric values in the distribution are166# normalized to underscores (_), meaning hyphens can never occur167# before `-{version}`.168#169# Given that information:170# - If the pattern we're given contains a hyphen (-), the user is171# providing at least the version. Thus, we can just append `*.whl`172# to match the rest of it.173# - If the pattern we're given doesn't contain a hyphen (-), the174# user is only providing the name. Thus, we append `-*.whl` to175# match the hyphen before the version, followed by anything else.176#177# PEP 427: https://www.python.org/dev/peps/pep-0427/178pattern = pattern + ("*.whl" if "-" in pattern else "-*.whl")179180return filesystem.find_files(wheel_dir, pattern)181182183