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

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

121 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 super().__init__(f"{pool}: {message}") 

35 

36 def __reduce__(self) -> _TYPE_REDUCE_RESULT: 

37 # For pickling purposes. 

38 return self.__class__, (None, None) 

39 

40 

41class RequestError(PoolError): 

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

43 

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

45 self.url = url 

46 super().__init__(pool, message) 

47 

48 def __reduce__(self) -> _TYPE_REDUCE_RESULT: 

49 # For pickling purposes. 

50 return self.__class__, (None, self.url, None) 

51 

52 

53class SSLError(HTTPError): 

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

55 

56 

57class ProxyError(HTTPError): 

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

59 

60 # The original error is also available as __cause__. 

61 original_error: Exception 

62 

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

64 super().__init__(message, error) 

65 self.original_error = error 

66 

67 

68class DecodeError(HTTPError): 

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

70 

71 

72class ProtocolError(HTTPError): 

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

74 

75 

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

77ConnectionError = ProtocolError 

78 

79 

80# Leaf Exceptions 

81 

82 

83class MaxRetryError(RequestError): 

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

85 

86 :param pool: The connection pool 

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

88 :param str url: The requested Url 

89 :param reason: The underlying error 

90 :type reason: :class:`Exception` 

91 

92 """ 

93 

94 def __init__( 

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

96 ) -> None: 

97 self.reason = reason 

98 

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

100 

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

102 

103 

104class HostChangedError(RequestError): 

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

106 

107 def __init__( 

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

109 ) -> None: 

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

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

112 self.retries = retries 

113 

114 

115class TimeoutStateError(HTTPError): 

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

117 

118 

119class TimeoutError(HTTPError): 

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

121 

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

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

124 """ 

125 

126 

127class ReadTimeoutError(TimeoutError, RequestError): 

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

129 

130 

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

132# base HTTPError 

133class ConnectTimeoutError(TimeoutError): 

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

135 

136 

137class NewConnectionError(ConnectTimeoutError, HTTPError): 

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

139 

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

141 self.conn = conn 

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

143 

144 def __reduce__(self) -> _TYPE_REDUCE_RESULT: 

145 # For pickling purposes. 

146 return self.__class__, (None, None) 

147 

148 @property 

149 def pool(self) -> HTTPConnection: 

150 warnings.warn( 

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

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

153 DeprecationWarning, 

154 stacklevel=2, 

155 ) 

156 

157 return self.conn 

158 

159 

160class NameResolutionError(NewConnectionError): 

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

162 

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

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

165 super().__init__(conn, message) 

166 

167 def __reduce__(self) -> _TYPE_REDUCE_RESULT: 

168 # For pickling purposes. 

169 return self.__class__, (None, None, None) 

170 

171 

172class EmptyPoolError(PoolError): 

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

174 

175 

176class FullPoolError(PoolError): 

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

178 

179 

180class ClosedPoolError(PoolError): 

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

182 

183 

184class LocationValueError(ValueError, HTTPError): 

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

186 

187 

188class LocationParseError(LocationValueError): 

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

190 

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

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

193 super().__init__(message) 

194 

195 self.location = location 

196 

197 

198class URLSchemeUnknown(LocationValueError): 

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

200 

201 def __init__(self, scheme: str): 

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

203 super().__init__(message) 

204 

205 self.scheme = scheme 

206 

207 

208class ResponseError(HTTPError): 

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

210 

211 GENERIC_ERROR = "too many error responses" 

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

213 

214 

215class SecurityWarning(HTTPWarning): 

216 """Warned when performing security reducing actions""" 

217 

218 

219class InsecureRequestWarning(SecurityWarning): 

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

221 

222 

223class NotOpenSSLWarning(SecurityWarning): 

224 """Warned when using unsupported SSL library""" 

225 

226 

227class SystemTimeWarning(SecurityWarning): 

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

229 

230 

231class InsecurePlatformWarning(SecurityWarning): 

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

233 

234 

235class DependencyWarning(HTTPWarning): 

236 """ 

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

238 dependencies. 

239 """ 

240 

241 

242class ResponseNotChunked(ProtocolError, ValueError): 

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

244 

245 

246class BodyNotHttplibCompatible(HTTPError): 

247 """ 

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

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

250 """ 

251 

252 

253class IncompleteRead(HTTPError, httplib_IncompleteRead): 

254 """ 

255 Response length doesn't match expected Content-Length 

256 

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

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

259 """ 

260 

261 partial: int # type: ignore[assignment] 

262 expected: int 

263 

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

265 self.partial = partial 

266 self.expected = expected 

267 

268 def __repr__(self) -> str: 

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

270 self.partial, 

271 self.expected, 

272 ) 

273 

274 

275class InvalidChunkLength(HTTPError, httplib_IncompleteRead): 

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

277 

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

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

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

281 self.response = response 

282 self.length = length 

283 

284 def __repr__(self) -> str: 

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

286 self.length, 

287 self.partial, 

288 ) 

289 

290 

291class InvalidHeader(HTTPError): 

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

293 

294 

295class ProxySchemeUnknown(AssertionError, URLSchemeUnknown): 

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

297 

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

299 

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

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

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

303 if scheme == "localhost": 

304 scheme = None 

305 if scheme is None: 

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

307 else: 

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

309 super().__init__(message) 

310 

311 

312class ProxySchemeUnsupported(ValueError): 

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

314 

315 

316class HeaderParsingError(HTTPError): 

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

318 

319 def __init__( 

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

321 ) -> None: 

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

323 super().__init__(message) 

324 

325 

326class UnrewindableBodyError(HTTPError): 

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