Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/aiohttp/client_exceptions.py: 56%
135 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:56 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:56 +0000
1"""HTTP related errors."""
3import asyncio
4import warnings
5from typing import TYPE_CHECKING, Any, Optional, Tuple, Union
7from .http_parser import RawResponseMessage
8from .typedefs import LooseHeaders
10try:
11 import ssl
13 SSLContext = ssl.SSLContext
14except ImportError: # pragma: no cover
15 ssl = SSLContext = None # type: ignore[assignment]
18if TYPE_CHECKING: # pragma: no cover
19 from .client_reqrep import ClientResponse, ConnectionKey, Fingerprint, RequestInfo
20else:
21 RequestInfo = ClientResponse = ConnectionKey = None
23__all__ = (
24 "ClientError",
25 "ClientConnectionError",
26 "ClientOSError",
27 "ClientConnectorError",
28 "ClientProxyConnectionError",
29 "ClientSSLError",
30 "ClientConnectorSSLError",
31 "ClientConnectorCertificateError",
32 "ServerConnectionError",
33 "ServerTimeoutError",
34 "ServerDisconnectedError",
35 "ServerFingerprintMismatch",
36 "ClientResponseError",
37 "ClientHttpProxyError",
38 "WSServerHandshakeError",
39 "ContentTypeError",
40 "ClientPayloadError",
41 "InvalidURL",
42)
45class ClientError(Exception):
46 """Base class for client connection errors."""
49class ClientResponseError(ClientError):
50 """Connection error during reading response.
52 request_info: instance of RequestInfo
53 """
55 def __init__(
56 self,
57 request_info: RequestInfo,
58 history: Tuple[ClientResponse, ...],
59 *,
60 code: Optional[int] = None,
61 status: Optional[int] = None,
62 message: str = "",
63 headers: Optional[LooseHeaders] = None,
64 ) -> None:
65 self.request_info = request_info
66 if code is not None:
67 if status is not None:
68 raise ValueError(
69 "Both code and status arguments are provided; "
70 "code is deprecated, use status instead"
71 )
72 warnings.warn(
73 "code argument is deprecated, use status instead",
74 DeprecationWarning,
75 stacklevel=2,
76 )
77 if status is not None:
78 self.status = status
79 elif code is not None:
80 self.status = code
81 else:
82 self.status = 0
83 self.message = message
84 self.headers = headers
85 self.history = history
86 self.args = (request_info, history)
88 def __str__(self) -> str:
89 return "{}, message={!r}, url={!r}".format(
90 self.status,
91 self.message,
92 self.request_info.real_url,
93 )
95 def __repr__(self) -> str:
96 args = f"{self.request_info!r}, {self.history!r}"
97 if self.status != 0:
98 args += f", status={self.status!r}"
99 if self.message != "":
100 args += f", message={self.message!r}"
101 if self.headers is not None:
102 args += f", headers={self.headers!r}"
103 return f"{type(self).__name__}({args})"
105 @property
106 def code(self) -> int:
107 warnings.warn(
108 "code property is deprecated, use status instead",
109 DeprecationWarning,
110 stacklevel=2,
111 )
112 return self.status
114 @code.setter
115 def code(self, value: int) -> None:
116 warnings.warn(
117 "code property is deprecated, use status instead",
118 DeprecationWarning,
119 stacklevel=2,
120 )
121 self.status = value
124class ContentTypeError(ClientResponseError):
125 """ContentType found is not valid."""
128class WSServerHandshakeError(ClientResponseError):
129 """websocket server handshake error."""
132class ClientHttpProxyError(ClientResponseError):
133 """HTTP proxy error.
135 Raised in :class:`aiohttp.connector.TCPConnector` if
136 proxy responds with status other than ``200 OK``
137 on ``CONNECT`` request.
138 """
141class TooManyRedirects(ClientResponseError):
142 """Client was redirected too many times."""
145class ClientConnectionError(ClientError):
146 """Base class for client socket errors."""
149class ClientOSError(ClientConnectionError, OSError):
150 """OSError error."""
153class ClientConnectorError(ClientOSError):
154 """Client connector error.
156 Raised in :class:`aiohttp.connector.TCPConnector` if
157 a connection can not be established.
158 """
160 def __init__(self, connection_key: ConnectionKey, os_error: OSError) -> None:
161 self._conn_key = connection_key
162 self._os_error = os_error
163 super().__init__(os_error.errno, os_error.strerror)
164 self.args = (connection_key, os_error)
166 @property
167 def os_error(self) -> OSError:
168 return self._os_error
170 @property
171 def host(self) -> str:
172 return self._conn_key.host
174 @property
175 def port(self) -> Optional[int]:
176 return self._conn_key.port
178 @property
179 def ssl(self) -> Union[SSLContext, None, bool, "Fingerprint"]:
180 return self._conn_key.ssl
182 def __str__(self) -> str:
183 return "Cannot connect to host {0.host}:{0.port} ssl:{1} [{2}]".format(
184 self, self.ssl if self.ssl is not None else "default", self.strerror
185 )
187 # OSError.__reduce__ does too much black magick
188 __reduce__ = BaseException.__reduce__
191class ClientProxyConnectionError(ClientConnectorError):
192 """Proxy connection error.
194 Raised in :class:`aiohttp.connector.TCPConnector` if
195 connection to proxy can not be established.
196 """
199class UnixClientConnectorError(ClientConnectorError):
200 """Unix connector error.
202 Raised in :py:class:`aiohttp.connector.UnixConnector`
203 if connection to unix socket can not be established.
204 """
206 def __init__(
207 self, path: str, connection_key: ConnectionKey, os_error: OSError
208 ) -> None:
209 self._path = path
210 super().__init__(connection_key, os_error)
212 @property
213 def path(self) -> str:
214 return self._path
216 def __str__(self) -> str:
217 return "Cannot connect to unix socket {0.path} ssl:{1} [{2}]".format(
218 self, self.ssl if self.ssl is not None else "default", self.strerror
219 )
222class ServerConnectionError(ClientConnectionError):
223 """Server connection errors."""
226class ServerDisconnectedError(ServerConnectionError):
227 """Server disconnected."""
229 def __init__(self, message: Union[RawResponseMessage, str, None] = None) -> None:
230 if message is None:
231 message = "Server disconnected"
233 self.args = (message,)
234 self.message = message
237class ServerTimeoutError(ServerConnectionError, asyncio.TimeoutError):
238 """Server timeout error."""
241class ServerFingerprintMismatch(ServerConnectionError):
242 """SSL certificate does not match expected fingerprint."""
244 def __init__(self, expected: bytes, got: bytes, host: str, port: int) -> None:
245 self.expected = expected
246 self.got = got
247 self.host = host
248 self.port = port
249 self.args = (expected, got, host, port)
251 def __repr__(self) -> str:
252 return "<{} expected={!r} got={!r} host={!r} port={!r}>".format(
253 self.__class__.__name__, self.expected, self.got, self.host, self.port
254 )
257class ClientPayloadError(ClientError):
258 """Response payload error."""
261class InvalidURL(ClientError, ValueError):
262 """Invalid URL.
264 URL used for fetching is malformed, e.g. it doesn't contains host
265 part.
266 """
268 # Derive from ValueError for backward compatibility
270 def __init__(self, url: Any) -> None:
271 # The type of url is not yarl.URL because the exception can be raised
272 # on URL(url) call
273 super().__init__(url)
275 @property
276 def url(self) -> Any:
277 return self.args[0]
279 def __repr__(self) -> str:
280 return f"<{self.__class__.__name__} {self.url}>"
283class ClientSSLError(ClientConnectorError):
284 """Base error for ssl.*Errors."""
287if ssl is not None:
288 cert_errors = (ssl.CertificateError,)
289 cert_errors_bases = (
290 ClientSSLError,
291 ssl.CertificateError,
292 )
294 ssl_errors = (ssl.SSLError,)
295 ssl_error_bases = (ClientSSLError, ssl.SSLError)
296else: # pragma: no cover
297 cert_errors = tuple()
298 cert_errors_bases = (
299 ClientSSLError,
300 ValueError,
301 )
303 ssl_errors = tuple()
304 ssl_error_bases = (ClientSSLError,)
307class ClientConnectorSSLError(*ssl_error_bases): # type: ignore[misc]
308 """Response ssl error."""
311class ClientConnectorCertificateError(*cert_errors_bases): # type: ignore[misc]
312 """Response certificate error."""
314 def __init__(
315 self, connection_key: ConnectionKey, certificate_error: Exception
316 ) -> None:
317 self._conn_key = connection_key
318 self._certificate_error = certificate_error
319 self.args = (connection_key, certificate_error)
321 @property
322 def certificate_error(self) -> Exception:
323 return self._certificate_error
325 @property
326 def host(self) -> str:
327 return self._conn_key.host
329 @property
330 def port(self) -> Optional[int]:
331 return self._conn_key.port
333 @property
334 def ssl(self) -> bool:
335 return self._conn_key.is_ssl
337 def __str__(self) -> str:
338 return (
339 "Cannot connect to host {0.host}:{0.port} ssl:{0.ssl} "
340 "[{0.certificate_error.__class__.__name__}: "
341 "{0.certificate_error.args}]".format(self)
342 )