Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/urllib3/exceptions.py: 58%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

127 statements  

1from __future__ import annotations 

2 

3import socket 

4import typing 

5import warnings 

6from email.errors import MessageDefect 

7from http.client import IncompleteRead as httplib_IncompleteRead 

8 

9if typing.TYPE_CHECKING: 

10 from .connection import HTTPConnection 

11 from .connectionpool import ConnectionPool 

12 from .response import HTTPResponse 

13 from .util.retry import Retry 

14 

15# Base Exceptions 

16 

17 

18class HTTPError(Exception): 

19 """Base exception used by this module.""" 

20 

21 

22class HTTPWarning(Warning): 

23 """Base warning used by this module.""" 

24 

25 

26_TYPE_REDUCE_RESULT = tuple[typing.Callable[..., object], tuple[object, ...]] 

27 

28 

29class PoolError(HTTPError): 

30 """Base exception for errors caused within a pool.""" 

31 

32 def __init__(self, pool: ConnectionPool, message: str) -> None: 

33 self.pool = pool 

34 self._message = message 

35 super().__init__(f"{pool}: {message}") 

36 

37 def __reduce__(self) -> _TYPE_REDUCE_RESULT: 

38 # For pickling purposes. 

39 return self.__class__, (None, self._message) 

40 

41 

42class RequestError(PoolError): 

43 """Base exception for PoolErrors that have associated URLs.""" 

44 

45 def __init__(self, pool: ConnectionPool, url: str, message: str) -> None: 

46 self.url = url 

47 super().__init__(pool, message) 

48 

49 def __reduce__(self) -> _TYPE_REDUCE_RESULT: 

50 # For pickling purposes. 

51 return self.__class__, (None, self.url, self._message) 

52 

53 

54class SSLError(HTTPError): 

55 """Raised when SSL certificate fails in an HTTPS connection.""" 

56 

57 

58class ProxyError(HTTPError): 

59 """Raised when the connection to a proxy fails.""" 

60 

61 # The original error is also available as __cause__. 

62 original_error: Exception 

63 

64 def __init__(self, message: str, error: Exception) -> None: 

65 super().__init__(message, error) 

66 self.original_error = error 

67 

68 

69class DecodeError(HTTPError): 

70 """Raised when automatic decoding based on Content-Type fails.""" 

71 

72 

73class ProtocolError(HTTPError): 

74 """Raised when something unexpected happens mid-request/response.""" 

75 

76 

77#: Renamed to ProtocolError but aliased for backwards compatibility. 

78ConnectionError = ProtocolError 

79 

80 

81# Leaf Exceptions 

82 

83 

84class MaxRetryError(RequestError): 

85 """Raised when the maximum number of retries is exceeded. 

86 

87 :param pool: The connection pool 

88 :type pool: :class:`~urllib3.connectionpool.HTTPConnectionPool` 

89 :param str url: The requested Url 

90 :param reason: The underlying error 

91 :type reason: :class:`Exception` 

92 

93 """ 

94 

95 def __init__( 

96 self, pool: ConnectionPool, url: str, reason: Exception | None = None 

97 ) -> None: 

98 self.reason = reason 

99 

100 message = f"Max retries exceeded with url: {url} (Caused by {reason!r})" 

101 

102 super().__init__(pool, url, message) 

103 

104 def __reduce__(self) -> _TYPE_REDUCE_RESULT: 

105 # For pickling purposes. 

106 return self.__class__, (None, self.url, self.reason) 

107 

108 

109class HostChangedError(RequestError): 

110 """Raised when an existing pool gets a request for a foreign host.""" 

111 

112 def __init__( 

113 self, pool: ConnectionPool, url: str, retries: Retry | int = 3 

114 ) -> None: 

115 message = f"Tried to open a foreign host with url: {url}" 

116 super().__init__(pool, url, message) 

117 self.retries = retries 

118 

119 

120class TimeoutStateError(HTTPError): 

121 """Raised when passing an invalid state to a timeout""" 

122 

123 

124class TimeoutError(HTTPError): 

125 """Raised when a socket timeout error occurs. 

126 

127 Catching this error will catch both :exc:`ReadTimeoutErrors 

128 <ReadTimeoutError>` and :exc:`ConnectTimeoutErrors <ConnectTimeoutError>`. 

129 """ 

130 

131 

132class ReadTimeoutError(TimeoutError, RequestError): 

133 """Raised when a socket timeout occurs while receiving data from a server""" 

134 

135 

136# This timeout error does not have a URL attached and needs to inherit from the 

137# base HTTPError 

138class ConnectTimeoutError(TimeoutError): 

139 """Raised when a socket timeout occurs while connecting to a server""" 

140 

141 

142class NewConnectionError(ConnectTimeoutError, HTTPError): 

143 """Raised when we fail to establish a new connection. Usually ECONNREFUSED.""" 

144 

145 def __init__(self, conn: HTTPConnection, message: str) -> None: 

146 self.conn = conn 

147 self._message = message 

148 super().__init__(f"{conn}: {message}") 

149 

150 def __reduce__(self) -> _TYPE_REDUCE_RESULT: 

151 # For pickling purposes. 

152 return self.__class__, (None, self._message) 

153 

154 @property 

155 def pool(self) -> HTTPConnection: 

156 warnings.warn( 

157 "The 'pool' property is deprecated and will be removed " 

158 "in urllib3 v2.1.0. Use 'conn' instead.", 

159 DeprecationWarning, 

160 stacklevel=2, 

161 ) 

162 

163 return self.conn 

164 

165 

166class NameResolutionError(NewConnectionError): 

167 """Raised when host name resolution fails.""" 

168 

169 def __init__(self, host: str, conn: HTTPConnection, reason: socket.gaierror): 

170 message = f"Failed to resolve '{host}' ({reason})" 

171 self._host = host 

172 self._reason = reason 

173 super().__init__(conn, message) 

174 

175 def __reduce__(self) -> _TYPE_REDUCE_RESULT: 

176 # For pickling purposes. 

177 return self.__class__, (self._host, None, self._reason) 

178 

179 

180class EmptyPoolError(PoolError): 

181 """Raised when a pool runs out of connections and no more are allowed.""" 

182 

183 

184class FullPoolError(PoolError): 

185 """Raised when we try to add a connection to a full pool in blocking mode.""" 

186 

187 

188class ClosedPoolError(PoolError): 

189 """Raised when a request enters a pool after the pool has been closed.""" 

190 

191 

192class LocationValueError(ValueError, HTTPError): 

193 """Raised when there is something wrong with a given URL input.""" 

194 

195 

196class LocationParseError(LocationValueError): 

197 """Raised when get_host or similar fails to parse the URL input.""" 

198 

199 def __init__(self, location: str) -> None: 

200 message = f"Failed to parse: {location}" 

201 super().__init__(message) 

202 

203 self.location = location 

204 

205 

206class URLSchemeUnknown(LocationValueError): 

207 """Raised when a URL input has an unsupported scheme.""" 

208 

209 def __init__(self, scheme: str): 

210 message = f"Not supported URL scheme {scheme}" 

211 super().__init__(message) 

212 

213 self.scheme = scheme 

214 

215 

216class ResponseError(HTTPError): 

217 """Used as a container for an error reason supplied in a MaxRetryError.""" 

218 

219 GENERIC_ERROR = "too many error responses" 

220 SPECIFIC_ERROR = "too many {status_code} error responses" 

221 

222 

223class SecurityWarning(HTTPWarning): 

224 """Warned when performing security reducing actions""" 

225 

226 

227class InsecureRequestWarning(SecurityWarning): 

228 """Warned when making an unverified HTTPS request.""" 

229 

230 

231class NotOpenSSLWarning(SecurityWarning): 

232 """Warned when using unsupported SSL library""" 

233 

234 

235class SystemTimeWarning(SecurityWarning): 

236 """Warned when system time is suspected to be wrong""" 

237 

238 

239class InsecurePlatformWarning(SecurityWarning): 

240 """Warned when certain TLS/SSL configuration is not available on a platform.""" 

241 

242 

243class DependencyWarning(HTTPWarning): 

244 """ 

245 Warned when an attempt is made to import a module with missing optional 

246 dependencies. 

247 """ 

248 

249 

250class ResponseNotChunked(ProtocolError, ValueError): 

251 """Response needs to be chunked in order to read it as chunks.""" 

252 

253 

254class BodyNotHttplibCompatible(HTTPError): 

255 """ 

256 Body should be :class:`http.client.HTTPResponse` like 

257 (have an fp attribute which returns raw chunks) for read_chunked(). 

258 """ 

259 

260 

261class IncompleteRead(HTTPError, httplib_IncompleteRead): 

262 """ 

263 Response length doesn't match expected Content-Length 

264 

265 Subclass of :class:`http.client.IncompleteRead` to allow int value 

266 for ``partial`` to avoid creating large objects on streamed reads. 

267 """ 

268 

269 partial: int # type: ignore[assignment] 

270 expected: int 

271 

272 def __init__(self, partial: int, expected: int) -> None: 

273 self.partial = partial 

274 self.expected = expected 

275 

276 def __repr__(self) -> str: 

277 return "IncompleteRead(%i bytes read, %i more expected)" % ( 

278 self.partial, 

279 self.expected, 

280 ) 

281 

282 

283class InvalidChunkLength(HTTPError, httplib_IncompleteRead): 

284 """Invalid chunk length in a chunked response.""" 

285 

286 def __init__(self, response: HTTPResponse, length: bytes) -> None: 

287 self.partial: int = response.tell() # type: ignore[assignment] 

288 self.expected: int | None = response.length_remaining 

289 self.response = response 

290 self.length = length 

291 

292 def __repr__(self) -> str: 

293 return "InvalidChunkLength(got length %r, %i bytes read)" % ( 

294 self.length, 

295 self.partial, 

296 ) 

297 

298 

299class InvalidHeader(HTTPError): 

300 """The header provided was somehow invalid.""" 

301 

302 

303class ProxySchemeUnknown(AssertionError, URLSchemeUnknown): 

304 """ProxyManager does not support the supplied scheme""" 

305 

306 # TODO(t-8ch): Stop inheriting from AssertionError in v2.0. 

307 

308 def __init__(self, scheme: str | None) -> None: 

309 # 'localhost' is here because our URL parser parses 

310 # localhost:8080 -> scheme=localhost, remove if we fix this. 

311 if scheme == "localhost": 

312 scheme = None 

313 if scheme is None: 

314 message = "Proxy URL had no scheme, should start with http:// or https://" 

315 else: 

316 message = f"Proxy URL had unsupported scheme {scheme}, should use http:// or https://" 

317 super().__init__(message) 

318 

319 

320class ProxySchemeUnsupported(ValueError): 

321 """Fetching HTTPS resources through HTTPS proxies is unsupported""" 

322 

323 

324class HeaderParsingError(HTTPError): 

325 """Raised by assert_header_parsing, but we convert it to a log.warning statement.""" 

326 

327 def __init__( 

328 self, defects: list[MessageDefect], unparsed_data: bytes | str | None 

329 ) -> None: 

330 message = f"{defects or 'Unknown'}, unparsed data: {unparsed_data!r}" 

331 super().__init__(message) 

332 

333 

334class UnrewindableBodyError(HTTPError): 

335 """urllib3 encountered an error when trying to rewind a body"""