From e5ab371d11151b64668ad722362da155492739cb Mon Sep 17 00:00:00 2001 From: Tzu-ping Chung Date: Mon, 10 Aug 2020 01:38:12 +0800 Subject: [PATCH] Pass in more structured context into exception This may help us provide better error messages if needed, instead of being stuck with an eagerly-rendered string. --- src/pip/_internal/exceptions.py | 39 ++++++++++++++++++------------ src/pip/_internal/network/utils.py | 16 +++++------- 2 files changed, 29 insertions(+), 26 deletions(-) diff --git a/src/pip/_internal/exceptions.py b/src/pip/_internal/exceptions.py index d7b5f946f11..c83fb7f75c7 100644 --- a/src/pip/_internal/exceptions.py +++ b/src/pip/_internal/exceptions.py @@ -12,7 +12,6 @@ from typing import Any, Optional, List, Dict, Text from pip._vendor.pkg_resources import Distribution - from pip._vendor.requests.models import Response, Request from pip._vendor.six import PY3 from pip._vendor.six.moves import configparser @@ -103,24 +102,32 @@ class PreviousBuildDirError(PipError): class NetworkResponseError(PipError): """HTTP connection error""" - def __init__(self, error_msg, response=None, request=None): - # type: (Text, Response, Request) -> None - """ - Initialize NetworkResponseError with `request` and `response` - objects. - """ - self.response = response - self.request = request - self.error_msg = error_msg - if (self.response is not None and not self.request and - hasattr(response, 'request')): - self.request = self.response.request - super(NetworkResponseError, self).__init__( - error_msg, response, request) + error_type = "Unknown Error" + + def __init__(self, status, reason, url): + # type: (int, Text, str) -> None + super(NetworkResponseError, self).__init__(status, reason, url) + self.status = status + self.reason = reason + self.url = url def __str__(self): # type: () -> str - return ensure_str(self.error_msg, errors="replace") + message = u"{} {}: {} for url: {}".format( + self.status, + self.error_type, + self.reason, + self.url, + ) + return ensure_str(message, errors="replace") + + +class NetworkResponseClientError(NetworkResponseError): + error_type = "Client Error" + + +class NetworkResponseServerError(NetworkResponseError): + error_type = "Server Error" class InvalidWheelFilename(InstallationError): diff --git a/src/pip/_internal/network/utils.py b/src/pip/_internal/network/utils.py index 12c05be2cbe..275311fbe23 100644 --- a/src/pip/_internal/network/utils.py +++ b/src/pip/_internal/network/utils.py @@ -1,6 +1,9 @@ from pip._vendor.requests.models import CONTENT_CHUNK_SIZE, Response -from pip._internal.exceptions import NetworkResponseError +from pip._internal.exceptions import ( + NetworkResponseClientError, + NetworkResponseServerError, +) from pip._internal.utils.typing import MYPY_CHECK_RUNNING if MYPY_CHECK_RUNNING: @@ -30,7 +33,6 @@ def raise_for_status(resp): # type: (Response) -> None - http_error_msg = u'' if isinstance(resp.reason, bytes): # We attempt to decode utf-8 first because some servers # choose to localize their reason strings. If the string @@ -44,15 +46,9 @@ def raise_for_status(resp): reason = resp.reason if 400 <= resp.status_code < 500: - http_error_msg = u'%s Client Error: %s for url: %s' % ( - resp.status_code, reason, resp.url) - + raise NetworkResponseClientError(resp.status_code, reason, resp.url) elif 500 <= resp.status_code < 600: - http_error_msg = u'%s Server Error: %s for url: %s' % ( - resp.status_code, reason, resp.url) - - if http_error_msg: - raise NetworkResponseError(http_error_msg, response=resp) + raise NetworkResponseServerError(resp.status_code, reason, resp.url) def response_chunks(response, chunk_size=CONTENT_CHUNK_SIZE):