Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/httpx/_exceptions.py: 64%

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

77 statements  

1""" 

2Our exception hierarchy: 

3 

4* HTTPError 

5 x RequestError 

6 + TransportError 

7 - TimeoutException 

8 · ConnectTimeout 

9 · ReadTimeout 

10 · WriteTimeout 

11 · PoolTimeout 

12 - NetworkError 

13 · ConnectError 

14 · ReadError 

15 · WriteError 

16 · CloseError 

17 - ProtocolError 

18 · LocalProtocolError 

19 · RemoteProtocolError 

20 - ProxyError 

21 - UnsupportedProtocol 

22 + DecodingError 

23 + TooManyRedirects 

24 x HTTPStatusError 

25* InvalidURL 

26* CookieConflict 

27* StreamError 

28 x StreamConsumed 

29 x StreamClosed 

30 x ResponseNotRead 

31 x RequestNotRead 

32""" 

33 

34from __future__ import annotations 

35 

36import contextlib 

37import typing 

38 

39if typing.TYPE_CHECKING: 

40 from ._models import Request, Response # pragma: no cover 

41 

42__all__ = [ 

43 "CloseError", 

44 "ConnectError", 

45 "ConnectTimeout", 

46 "CookieConflict", 

47 "DecodingError", 

48 "HTTPError", 

49 "HTTPStatusError", 

50 "InvalidURL", 

51 "LocalProtocolError", 

52 "NetworkError", 

53 "PoolTimeout", 

54 "ProtocolError", 

55 "ProxyError", 

56 "ReadError", 

57 "ReadTimeout", 

58 "RemoteProtocolError", 

59 "RequestError", 

60 "RequestNotRead", 

61 "ResponseNotRead", 

62 "StreamClosed", 

63 "StreamConsumed", 

64 "StreamError", 

65 "TimeoutException", 

66 "TooManyRedirects", 

67 "TransportError", 

68 "UnsupportedProtocol", 

69 "WriteError", 

70 "WriteTimeout", 

71] 

72 

73 

74class HTTPError(Exception): 

75 """ 

76 Base class for `RequestError` and `HTTPStatusError`. 

77 

78 Useful for `try...except` blocks when issuing a request, 

79 and then calling `.raise_for_status()`. 

80 

81 For example: 

82 

83 ``` 

84 try: 

85 response = httpx.get("https://www.example.com") 

86 response.raise_for_status() 

87 except httpx.HTTPError as exc: 

88 print(f"HTTP Exception for {exc.request.url} - {exc}") 

89 ``` 

90 """ 

91 

92 def __init__(self, message: str) -> None: 

93 super().__init__(message) 

94 self._request: Request | None = None 

95 

96 @property 

97 def request(self) -> Request: 

98 if self._request is None: 

99 raise RuntimeError("The .request property has not been set.") 

100 return self._request 

101 

102 @request.setter 

103 def request(self, request: Request) -> None: 

104 self._request = request 

105 

106 

107class RequestError(HTTPError): 

108 """ 

109 Base class for all exceptions that may occur when issuing a `.request()`. 

110 """ 

111 

112 def __init__(self, message: str, *, request: Request | None = None) -> None: 

113 super().__init__(message) 

114 # At the point an exception is raised we won't typically have a request 

115 # instance to associate it with. 

116 # 

117 # The 'request_context' context manager is used within the Client and 

118 # Response methods in order to ensure that any raised exceptions 

119 # have a `.request` property set on them. 

120 self._request = request 

121 

122 

123class TransportError(RequestError): 

124 """ 

125 Base class for all exceptions that occur at the level of the Transport API. 

126 """ 

127 

128 

129# Timeout exceptions... 

130 

131 

132class TimeoutException(TransportError): 

133 """ 

134 The base class for timeout errors. 

135 

136 An operation has timed out. 

137 """ 

138 

139 

140class ConnectTimeout(TimeoutException): 

141 """ 

142 Timed out while connecting to the host. 

143 """ 

144 

145 

146class ReadTimeout(TimeoutException): 

147 """ 

148 Timed out while receiving data from the host. 

149 """ 

150 

151 

152class WriteTimeout(TimeoutException): 

153 """ 

154 Timed out while sending data to the host. 

155 """ 

156 

157 

158class PoolTimeout(TimeoutException): 

159 """ 

160 Timed out waiting to acquire a connection from the pool. 

161 """ 

162 

163 

164# Core networking exceptions... 

165 

166 

167class NetworkError(TransportError): 

168 """ 

169 The base class for network-related errors. 

170 

171 An error occurred while interacting with the network. 

172 """ 

173 

174 

175class ReadError(NetworkError): 

176 """ 

177 Failed to receive data from the network. 

178 """ 

179 

180 

181class WriteError(NetworkError): 

182 """ 

183 Failed to send data through the network. 

184 """ 

185 

186 

187class ConnectError(NetworkError): 

188 """ 

189 Failed to establish a connection. 

190 """ 

191 

192 

193class CloseError(NetworkError): 

194 """ 

195 Failed to close a connection. 

196 """ 

197 

198 

199# Other transport exceptions... 

200 

201 

202class ProxyError(TransportError): 

203 """ 

204 An error occurred while establishing a proxy connection. 

205 """ 

206 

207 

208class UnsupportedProtocol(TransportError): 

209 """ 

210 Attempted to make a request to an unsupported protocol. 

211 

212 For example issuing a request to `ftp://www.example.com`. 

213 """ 

214 

215 

216class ProtocolError(TransportError): 

217 """ 

218 The protocol was violated. 

219 """ 

220 

221 

222class LocalProtocolError(ProtocolError): 

223 """ 

224 A protocol was violated by the client. 

225 

226 For example if the user instantiated a `Request` instance explicitly, 

227 failed to include the mandatory `Host:` header, and then issued it directly 

228 using `client.send()`. 

229 """ 

230 

231 

232class RemoteProtocolError(ProtocolError): 

233 """ 

234 The protocol was violated by the server. 

235 

236 For example, returning malformed HTTP. 

237 """ 

238 

239 

240# Other request exceptions... 

241 

242 

243class DecodingError(RequestError): 

244 """ 

245 Decoding of the response failed, due to a malformed encoding. 

246 """ 

247 

248 

249class TooManyRedirects(RequestError): 

250 """ 

251 Too many redirects. 

252 """ 

253 

254 

255# Client errors 

256 

257 

258class HTTPStatusError(HTTPError): 

259 """ 

260 The response had an error HTTP status of 4xx or 5xx. 

261 

262 May be raised when calling `response.raise_for_status()` 

263 """ 

264 

265 def __init__(self, message: str, *, request: Request, response: Response) -> None: 

266 super().__init__(message) 

267 self.request = request 

268 self.response = response 

269 

270 

271class InvalidURL(Exception): 

272 """ 

273 URL is improperly formed or cannot be parsed. 

274 """ 

275 

276 def __init__(self, message: str) -> None: 

277 super().__init__(message) 

278 

279 

280class CookieConflict(Exception): 

281 """ 

282 Attempted to lookup a cookie by name, but multiple cookies existed. 

283 

284 Can occur when calling `response.cookies.get(...)`. 

285 """ 

286 

287 def __init__(self, message: str) -> None: 

288 super().__init__(message) 

289 

290 

291# Stream exceptions... 

292 

293# These may occur as the result of a programming error, by accessing 

294# the request/response stream in an invalid manner. 

295 

296 

297class StreamError(RuntimeError): 

298 """ 

299 The base class for stream exceptions. 

300 

301 The developer made an error in accessing the request stream in 

302 an invalid way. 

303 """ 

304 

305 def __init__(self, message: str) -> None: 

306 super().__init__(message) 

307 

308 

309class StreamConsumed(StreamError): 

310 """ 

311 Attempted to read or stream content, but the content has already 

312 been streamed. 

313 """ 

314 

315 def __init__(self) -> None: 

316 message = ( 

317 "Attempted to read or stream some content, but the content has " 

318 "already been streamed. For requests, this could be due to passing " 

319 "a generator as request content, and then receiving a redirect " 

320 "response or a secondary request as part of an authentication flow." 

321 "For responses, this could be due to attempting to stream the response " 

322 "content more than once." 

323 ) 

324 super().__init__(message) 

325 

326 

327class StreamClosed(StreamError): 

328 """ 

329 Attempted to read or stream response content, but the request has been 

330 closed. 

331 """ 

332 

333 def __init__(self) -> None: 

334 message = ( 

335 "Attempted to read or stream content, but the stream has " "been closed." 

336 ) 

337 super().__init__(message) 

338 

339 

340class ResponseNotRead(StreamError): 

341 """ 

342 Attempted to access streaming response content, without having called `read()`. 

343 """ 

344 

345 def __init__(self) -> None: 

346 message = ( 

347 "Attempted to access streaming response content," 

348 " without having called `read()`." 

349 ) 

350 super().__init__(message) 

351 

352 

353class RequestNotRead(StreamError): 

354 """ 

355 Attempted to access streaming request content, without having called `read()`. 

356 """ 

357 

358 def __init__(self) -> None: 

359 message = ( 

360 "Attempted to access streaming request content," 

361 " without having called `read()`." 

362 ) 

363 super().__init__(message) 

364 

365 

366@contextlib.contextmanager 

367def request_context( 

368 request: Request | None = None, 

369) -> typing.Iterator[None]: 

370 """ 

371 A context manager that can be used to attach the given request context 

372 to any `RequestError` exceptions that are raised within the block. 

373 """ 

374 try: 

375 yield 

376 except RequestError as exc: 

377 if request is not None: 

378 exc.request = request 

379 raise exc