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

75 statements  

« prev     ^ index     » next       coverage.py v7.2.2, created at 2023-03-26 06:12 +0000

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

33import contextlib 

34import typing 

35 

36if typing.TYPE_CHECKING: 

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

38 

39 

40class HTTPError(Exception): 

41 """ 

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

43 

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

45 and then calling `.raise_for_status()`. 

46 

47 For example: 

48 

49 ``` 

50 try: 

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

52 response.raise_for_status() 

53 except httpx.HTTPError as exc: 

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

55 ``` 

56 """ 

57 

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

59 super().__init__(message) 

60 self._request: typing.Optional["Request"] = None 

61 

62 @property 

63 def request(self) -> "Request": 

64 if self._request is None: 

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

66 return self._request 

67 

68 @request.setter 

69 def request(self, request: "Request") -> None: 

70 self._request = request 

71 

72 

73class RequestError(HTTPError): 

74 """ 

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

76 """ 

77 

78 def __init__( 

79 self, message: str, *, request: typing.Optional["Request"] = None 

80 ) -> 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__( 

234 self, message: str, *, request: "Request", response: "Response" 

235 ) -> None: 

236 super().__init__(message) 

237 self.request = request 

238 self.response = response 

239 

240 

241class InvalidURL(Exception): 

242 """ 

243 URL is improperly formed or cannot be parsed. 

244 """ 

245 

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

247 super().__init__(message) 

248 

249 

250class CookieConflict(Exception): 

251 """ 

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

253 

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

255 """ 

256 

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

258 super().__init__(message) 

259 

260 

261# Stream exceptions... 

262 

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

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

265 

266 

267class StreamError(RuntimeError): 

268 """ 

269 The base class for stream exceptions. 

270 

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

272 an invalid way. 

273 """ 

274 

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

276 super().__init__(message) 

277 

278 

279class StreamConsumed(StreamError): 

280 """ 

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

282 been streamed. 

283 """ 

284 

285 def __init__(self) -> None: 

286 message = ( 

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

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

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

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

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

292 "content more than once." 

293 ) 

294 super().__init__(message) 

295 

296 

297class StreamClosed(StreamError): 

298 """ 

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

300 closed. 

301 """ 

302 

303 def __init__(self) -> None: 

304 message = ( 

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

306 ) 

307 super().__init__(message) 

308 

309 

310class ResponseNotRead(StreamError): 

311 """ 

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

313 """ 

314 

315 def __init__(self) -> None: 

316 message = "Attempted to access streaming response content, without having called `read()`." 

317 super().__init__(message) 

318 

319 

320class RequestNotRead(StreamError): 

321 """ 

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

323 """ 

324 

325 def __init__(self) -> None: 

326 message = "Attempted to access streaming request content, without having called `read()`." 

327 super().__init__(message) 

328 

329 

330@contextlib.contextmanager 

331def request_context( 

332 request: typing.Optional["Request"] = None, 

333) -> typing.Iterator[None]: 

334 """ 

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

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

337 """ 

338 try: 

339 yield 

340 except RequestError as exc: 

341 if request is not None: 

342 exc.request = request 

343 raise exc