Path: blob/master/venv/Lib/site-packages/pip/_internal/exceptions.py
811 views
"""Exceptions used throughout package"""12# The following comment should be removed at some point in the future.3# mypy: disallow-untyped-defs=False45from __future__ import absolute_import67from itertools import chain, groupby, repeat89from pip._vendor.six import iteritems1011from pip._internal.utils.typing import MYPY_CHECK_RUNNING1213if MYPY_CHECK_RUNNING:14from typing import Optional15from pip._vendor.pkg_resources import Distribution16from pip._internal.req.req_install import InstallRequirement171819class PipError(Exception):20"""Base pip exception"""212223class ConfigurationError(PipError):24"""General exception in configuration"""252627class InstallationError(PipError):28"""General exception during installation"""293031class UninstallationError(PipError):32"""General exception during uninstallation"""333435class NoneMetadataError(PipError):36"""37Raised when accessing "METADATA" or "PKG-INFO" metadata for a38pip._vendor.pkg_resources.Distribution object and39`dist.has_metadata('METADATA')` returns True but40`dist.get_metadata('METADATA')` returns None (and similarly for41"PKG-INFO").42"""4344def __init__(self, dist, metadata_name):45# type: (Distribution, str) -> None46"""47:param dist: A Distribution object.48:param metadata_name: The name of the metadata being accessed49(can be "METADATA" or "PKG-INFO").50"""51self.dist = dist52self.metadata_name = metadata_name5354def __str__(self):55# type: () -> str56# Use `dist` in the error message because its stringification57# includes more information, like the version and location.58return (59'None {} metadata found for distribution: {}'.format(60self.metadata_name, self.dist,61)62)636465class DistributionNotFound(InstallationError):66"""Raised when a distribution cannot be found to satisfy a requirement"""676869class RequirementsFileParseError(InstallationError):70"""Raised when a general error occurs parsing a requirements file line."""717273class BestVersionAlreadyInstalled(PipError):74"""Raised when the most up-to-date version of a package is already75installed."""767778class BadCommand(PipError):79"""Raised when virtualenv or a command is not found"""808182class CommandError(PipError):83"""Raised when there is an error in command-line arguments"""848586class PreviousBuildDirError(PipError):87"""Raised when there's a previous conflicting build directory"""888990class InvalidWheelFilename(InstallationError):91"""Invalid wheel filename."""929394class UnsupportedWheel(InstallationError):95"""Unsupported wheel."""969798class HashErrors(InstallationError):99"""Multiple HashError instances rolled into one for reporting"""100101def __init__(self):102self.errors = []103104def append(self, error):105self.errors.append(error)106107def __str__(self):108lines = []109self.errors.sort(key=lambda e: e.order)110for cls, errors_of_cls in groupby(self.errors, lambda e: e.__class__):111lines.append(cls.head)112lines.extend(e.body() for e in errors_of_cls)113if lines:114return '\n'.join(lines)115116def __nonzero__(self):117return bool(self.errors)118119def __bool__(self):120return self.__nonzero__()121122123class HashError(InstallationError):124"""125A failure to verify a package against known-good hashes126127:cvar order: An int sorting hash exception classes by difficulty of128recovery (lower being harder), so the user doesn't bother fretting129about unpinned packages when he has deeper issues, like VCS130dependencies, to deal with. Also keeps error reports in a131deterministic order.132:cvar head: A section heading for display above potentially many133exceptions of this kind134:ivar req: The InstallRequirement that triggered this error. This is135pasted on after the exception is instantiated, because it's not136typically available earlier.137138"""139req = None # type: Optional[InstallRequirement]140head = ''141142def body(self):143"""Return a summary of me for display under the heading.144145This default implementation simply prints a description of the146triggering requirement.147148:param req: The InstallRequirement that provoked this error, with149its link already populated by the resolver's _populate_link().150151"""152return ' {}'.format(self._requirement_name())153154def __str__(self):155return '{}\n{}'.format(self.head, self.body())156157def _requirement_name(self):158"""Return a description of the requirement that triggered me.159160This default implementation returns long description of the req, with161line numbers162163"""164return str(self.req) if self.req else 'unknown package'165166167class VcsHashUnsupported(HashError):168"""A hash was provided for a version-control-system-based requirement, but169we don't have a method for hashing those."""170171order = 0172head = ("Can't verify hashes for these requirements because we don't "173"have a way to hash version control repositories:")174175176class DirectoryUrlHashUnsupported(HashError):177"""A hash was provided for a version-control-system-based requirement, but178we don't have a method for hashing those."""179180order = 1181head = ("Can't verify hashes for these file:// requirements because they "182"point to directories:")183184185class HashMissing(HashError):186"""A hash was needed for a requirement but is absent."""187188order = 2189head = ('Hashes are required in --require-hashes mode, but they are '190'missing from some requirements. Here is a list of those '191'requirements along with the hashes their downloaded archives '192'actually had. Add lines like these to your requirements files to '193'prevent tampering. (If you did not enable --require-hashes '194'manually, note that it turns on automatically when any package '195'has a hash.)')196197def __init__(self, gotten_hash):198"""199:param gotten_hash: The hash of the (possibly malicious) archive we200just downloaded201"""202self.gotten_hash = gotten_hash203204def body(self):205# Dodge circular import.206from pip._internal.utils.hashes import FAVORITE_HASH207208package = None209if self.req:210# In the case of URL-based requirements, display the original URL211# seen in the requirements file rather than the package name,212# so the output can be directly copied into the requirements file.213package = (self.req.original_link if self.req.original_link214# In case someone feeds something downright stupid215# to InstallRequirement's constructor.216else getattr(self.req, 'req', None))217return ' {} --hash={}:{}'.format(package or 'unknown package',218FAVORITE_HASH,219self.gotten_hash)220221222class HashUnpinned(HashError):223"""A requirement had a hash specified but was not pinned to a specific224version."""225226order = 3227head = ('In --require-hashes mode, all requirements must have their '228'versions pinned with ==. These do not:')229230231class HashMismatch(HashError):232"""233Distribution file hash values don't match.234235:ivar package_name: The name of the package that triggered the hash236mismatch. Feel free to write to this after the exception is raise to237improve its error message.238239"""240order = 4241head = ('THESE PACKAGES DO NOT MATCH THE HASHES FROM THE REQUIREMENTS '242'FILE. If you have updated the package versions, please update '243'the hashes. Otherwise, examine the package contents carefully; '244'someone may have tampered with them.')245246def __init__(self, allowed, gots):247"""248:param allowed: A dict of algorithm names pointing to lists of allowed249hex digests250:param gots: A dict of algorithm names pointing to hashes we251actually got from the files under suspicion252"""253self.allowed = allowed254self.gots = gots255256def body(self):257return ' {}:\n{}'.format(self._requirement_name(),258self._hash_comparison())259260def _hash_comparison(self):261"""262Return a comparison of actual and expected hash values.263264Example::265266Expected sha256 abcdeabcdeabcdeabcdeabcdeabcdeabcdeabcdeabcde267or 123451234512345123451234512345123451234512345268Got bcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdefbcdef269270"""271def hash_then_or(hash_name):272# For now, all the decent hashes have 6-char names, so we can get273# away with hard-coding space literals.274return chain([hash_name], repeat(' or'))275276lines = []277for hash_name, expecteds in iteritems(self.allowed):278prefix = hash_then_or(hash_name)279lines.extend((' Expected {} {}'.format(next(prefix), e))280for e in expecteds)281lines.append(' Got {}\n'.format(282self.gots[hash_name].hexdigest()))283return '\n'.join(lines)284285286class UnsupportedPythonVersion(InstallationError):287"""Unsupported python version according to Requires-Python package288metadata."""289290291class ConfigurationFileCouldNotBeLoaded(ConfigurationError):292"""When there are errors while loading a configuration file293"""294295def __init__(self, reason="could not be loaded", fname=None, error=None):296super(ConfigurationFileCouldNotBeLoaded, self).__init__(error)297self.reason = reason298self.fname = fname299self.error = error300301def __str__(self):302if self.fname is not None:303message_part = " in {}.".format(self.fname)304else:305assert self.error is not None306message_part = ".\n{}\n".format(self.error.message)307return "Configuration file {}{}".format(self.reason, message_part)308309310