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

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

76 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""" 

33from __future__ import annotations 

34 

35import contextlib 

36import typing 

37 

38if typing.TYPE_CHECKING: 

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

40 

41 

42class HTTPError(Exception): 

43 """ 

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

45 

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

47 and then calling `.raise_for_status()`. 

48 

49 For example: 

50 

51 ``` 

52 try: 

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

54 response.raise_for_status() 

55 except httpx.HTTPError as exc: 

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

57 ``` 

58 """ 

59 

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

61 super().__init__(message) 

62 self._request: Request | None = None 

63 

64 @property 

65 def request(self) -> Request: 

66 if self._request is None: 

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

68 return self._request 

69 

70 @request.setter 

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

72 self._request = request 

73 

74 

75class RequestError(HTTPError): 

76 """ 

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

78 """ 

79 

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

81 super().__init__(message) 

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

83 # instance to associate it with. 

84 # 

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

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

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

88 self._request = request 

89 

90 

91class TransportError(RequestError): 

92 """ 

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

94 """ 

95 

96 

97# Timeout exceptions... 

98 

99 

100class TimeoutException(TransportError): 

101 """ 

102 The base class for timeout errors. 

103 

104 An operation has timed out. 

105 """ 

106 

107 

108class ConnectTimeout(TimeoutException): 

109 """ 

110 Timed out while connecting to the host. 

111 """ 

112 

113 

114class ReadTimeout(TimeoutException): 

115 """ 

116 Timed out while receiving data from the host. 

117 """ 

118 

119 

120class WriteTimeout(TimeoutException): 

121 """ 

122 Timed out while sending data to the host. 

123 """ 

124 

125 

126class PoolTimeout(TimeoutException): 

127 """ 

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

129 """ 

130 

131 

132# Core networking exceptions... 

133 

134 

135class NetworkError(TransportError): 

136 """ 

137 The base class for network-related errors. 

138 

139 An error occurred while interacting with the network. 

140 """ 

141 

142 

143class ReadError(NetworkError): 

144 """ 

145 Failed to receive data from the network. 

146 """ 

147 

148 

149class WriteError(NetworkError): 

150 """ 

151 Failed to send data through the network. 

152 """ 

153 

154 

155class ConnectError(NetworkError): 

156 """ 

157 Failed to establish a connection. 

158 """ 

159 

160 

161class CloseError(NetworkError): 

162 """ 

163 Failed to close a connection. 

164 """ 

165 

166 

167# Other transport exceptions... 

168 

169 

170class ProxyError(TransportError): 

171 """ 

172 An error occurred while establishing a proxy connection. 

173 """ 

174 

175 

176class UnsupportedProtocol(TransportError): 

177 """ 

178 Attempted to make a request to an unsupported protocol. 

179 

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

181 """ 

182 

183 

184class ProtocolError(TransportError): 

185 """ 

186 The protocol was violated. 

187 """ 

188 

189 

190class LocalProtocolError(ProtocolError): 

191 """ 

192 A protocol was violated by the client. 

193 

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

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

196 using `client.send()`. 

197 """ 

198 

199 

200class RemoteProtocolError(ProtocolError): 

201 """ 

202 The protocol was violated by the server. 

203 

204 For example, returning malformed HTTP. 

205 """ 

206 

207 

208# Other request exceptions... 

209 

210 

211class DecodingError(RequestError): 

212 """ 

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

214 """ 

215 

216 

217class TooManyRedirects(RequestError): 

218 """ 

219 Too many redirects. 

220 """ 

221 

222 

223# Client errors 

224 

225 

226class HTTPStatusError(HTTPError): 

227 """ 

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

229 

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

231 """ 

232 

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

234 super().__init__(message) 

235 self.request = request 

236 self.response = response 

237 

238 

239class InvalidURL(Exception): 

240 """ 

241 URL is improperly formed or cannot be parsed. 

242 """ 

243 

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

245 super().__init__(message) 

246 

247 

248class CookieConflict(Exception): 

249 """ 

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

251 

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

253 """ 

254 

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

256 super().__init__(message) 

257 

258 

259# Stream exceptions... 

260 

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

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

263 

264 

265class StreamError(RuntimeError): 

266 """ 

267 The base class for stream exceptions. 

268 

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

270 an invalid way. 

271 """ 

272 

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

274 super().__init__(message) 

275 

276 

277class StreamConsumed(StreamError): 

278 """ 

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

280 been streamed. 

281 """ 

282 

283 def __init__(self) -> None: 

284 message = ( 

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

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

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

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

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

290 "content more than once." 

291 ) 

292 super().__init__(message) 

293 

294 

295class StreamClosed(StreamError): 

296 """ 

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

298 closed. 

299 """ 

300 

301 def __init__(self) -> None: 

302 message = ( 

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

304 ) 

305 super().__init__(message) 

306 

307 

308class ResponseNotRead(StreamError): 

309 """ 

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

311 """ 

312 

313 def __init__(self) -> None: 

314 message = ( 

315 "Attempted to access streaming response content," 

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

317 ) 

318 super().__init__(message) 

319 

320 

321class RequestNotRead(StreamError): 

322 """ 

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

324 """ 

325 

326 def __init__(self) -> None: 

327 message = ( 

328 "Attempted to access streaming request content," 

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

330 ) 

331 super().__init__(message) 

332 

333 

334@contextlib.contextmanager 

335def request_context( 

336 request: Request | None = None, 

337) -> typing.Iterator[None]: 

338 """ 

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

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

341 """ 

342 try: 

343 yield 

344 except RequestError as exc: 

345 if request is not None: 

346 exc.request = request 

347 raise exc