1from __future__ import absolute_import
2from .packages.six.moves.http_client import (
3    IncompleteRead as httplib_IncompleteRead
4)
5# Base Exceptions
6
7
8class HTTPError(Exception):
9    "Base exception used by this module."
10    pass
11
12
13class HTTPWarning(Warning):
14    "Base warning used by this module."
15    pass
16
17
18class PoolError(HTTPError):
19    "Base exception for errors caused within a pool."
20    def __init__(self, pool, message):
21        self.pool = pool
22        HTTPError.__init__(self, "%s: %s" % (pool, message))
23
24    def __reduce__(self):
25        # For pickling purposes.
26        return self.__class__, (None, None)
27
28
29class RequestError(PoolError):
30    "Base exception for PoolErrors that have associated URLs."
31    def __init__(self, pool, url, message):
32        self.url = url
33        PoolError.__init__(self, pool, message)
34
35    def __reduce__(self):
36        # For pickling purposes.
37        return self.__class__, (None, self.url, None)
38
39
40class SSLError(HTTPError):
41    "Raised when SSL certificate fails in an HTTPS connection."
42    pass
43
44
45class ProxyError(HTTPError):
46    "Raised when the connection to a proxy fails."
47    pass
48
49
50class DecodeError(HTTPError):
51    "Raised when automatic decoding based on Content-Type fails."
52    pass
53
54
55class ProtocolError(HTTPError):
56    "Raised when something unexpected happens mid-request/response."
57    pass
58
59
60#: Renamed to ProtocolError but aliased for backwards compatibility.
61ConnectionError = ProtocolError
62
63
64# Leaf Exceptions
65
66class MaxRetryError(RequestError):
67    """Raised when the maximum number of retries is exceeded.
68
69    :param pool: The connection pool
70    :type pool: :class:`~urllib3.connectionpool.HTTPConnectionPool`
71    :param string url: The requested Url
72    :param exceptions.Exception reason: The underlying error
73
74    """
75
76    def __init__(self, pool, url, reason=None):
77        self.reason = reason
78
79        message = "Max retries exceeded with url: %s (Caused by %r)" % (
80            url, reason)
81
82        RequestError.__init__(self, pool, url, message)
83
84
85class HostChangedError(RequestError):
86    "Raised when an existing pool gets a request for a foreign host."
87
88    def __init__(self, pool, url, retries=3):
89        message = "Tried to open a foreign host with url: %s" % url
90        RequestError.__init__(self, pool, url, message)
91        self.retries = retries
92
93
94class TimeoutStateError(HTTPError):
95    """ Raised when passing an invalid state to a timeout """
96    pass
97
98
99class TimeoutError(HTTPError):
100    """ Raised when a socket timeout error occurs.
101
102    Catching this error will catch both :exc:`ReadTimeoutErrors
103    <ReadTimeoutError>` and :exc:`ConnectTimeoutErrors <ConnectTimeoutError>`.
104    """
105    pass
106
107
108class ReadTimeoutError(TimeoutError, RequestError):
109    "Raised when a socket timeout occurs while receiving data from a server"
110    pass
111
112
113# This timeout error does not have a URL attached and needs to inherit from the
114# base HTTPError
115class ConnectTimeoutError(TimeoutError):
116    "Raised when a socket timeout occurs while connecting to a server"
117    pass
118
119
120class NewConnectionError(ConnectTimeoutError, PoolError):
121    "Raised when we fail to establish a new connection. Usually ECONNREFUSED."
122    pass
123
124
125class EmptyPoolError(PoolError):
126    "Raised when a pool runs out of connections and no more are allowed."
127    pass
128
129
130class ClosedPoolError(PoolError):
131    "Raised when a request enters a pool after the pool has been closed."
132    pass
133
134
135class LocationValueError(ValueError, HTTPError):
136    "Raised when there is something wrong with a given URL input."
137    pass
138
139
140class LocationParseError(LocationValueError):
141    "Raised when get_host or similar fails to parse the URL input."
142
143    def __init__(self, location):
144        message = "Failed to parse: %s" % location
145        HTTPError.__init__(self, message)
146
147        self.location = location
148
149
150class ResponseError(HTTPError):
151    "Used as a container for an error reason supplied in a MaxRetryError."
152    GENERIC_ERROR = 'too many error responses'
153    SPECIFIC_ERROR = 'too many {status_code} error responses'
154
155
156class SecurityWarning(HTTPWarning):
157    "Warned when performing security reducing actions"
158    pass
159
160
161class SubjectAltNameWarning(SecurityWarning):
162    "Warned when connecting to a host with a certificate missing a SAN."
163    pass
164
165
166class InsecureRequestWarning(SecurityWarning):
167    "Warned when making an unverified HTTPS request."
168    pass
169
170
171class SystemTimeWarning(SecurityWarning):
172    "Warned when system time is suspected to be wrong"
173    pass
174
175
176class InsecurePlatformWarning(SecurityWarning):
177    "Warned when certain SSL configuration is not available on a platform."
178    pass
179
180
181class SNIMissingWarning(HTTPWarning):
182    "Warned when making a HTTPS request without SNI available."
183    pass
184
185
186class DependencyWarning(HTTPWarning):
187    """
188    Warned when an attempt is made to import a module with missing optional
189    dependencies.
190    """
191    pass
192
193
194class ResponseNotChunked(ProtocolError, ValueError):
195    "Response needs to be chunked in order to read it as chunks."
196    pass
197
198
199class BodyNotHttplibCompatible(HTTPError):
200    """
201    Body should be httplib.HTTPResponse like (have an fp attribute which
202    returns raw chunks) for read_chunked().
203    """
204    pass
205
206
207class IncompleteRead(HTTPError, httplib_IncompleteRead):
208    """
209    Response length doesn't match expected Content-Length
210
211    Subclass of http_client.IncompleteRead to allow int value
212    for `partial` to avoid creating large objects on streamed
213    reads.
214    """
215    def __init__(self, partial, expected):
216        super(IncompleteRead, self).__init__(partial, expected)
217
218    def __repr__(self):
219        return ('IncompleteRead(%i bytes read, '
220                '%i more expected)' % (self.partial, self.expected))
221
222
223class InvalidHeader(HTTPError):
224    "The header provided was somehow invalid."
225    pass
226
227
228class ProxySchemeUnknown(AssertionError, ValueError):
229    "ProxyManager does not support the supplied scheme"
230    # TODO(t-8ch): Stop inheriting from AssertionError in v2.0.
231
232    def __init__(self, scheme):
233        message = "Not supported proxy scheme %s" % scheme
234        super(ProxySchemeUnknown, self).__init__(message)
235
236
237class HeaderParsingError(HTTPError):
238    "Raised by assert_header_parsing, but we convert it to a log.warning statement."
239    def __init__(self, defects, unparsed_data):
240        message = '%s, unparsed data: %r' % (defects or 'Unknown', unparsed_data)
241        super(HeaderParsingError, self).__init__(message)
242
243
244class UnrewindableBodyError(HTTPError):
245    "urllib3 encountered an error when trying to rewind a body"
246    pass
247