Team Ai
Datasetpublic

codekingpro/portable-devtools

sourceHugging Faceupdated 5mo agoView on Hugging Face
1likes15kdownloads
client_exceptions.py433 linesDownload Raw Back to aiohttp
1"""HTTP related errors."""
2
3import asyncio
4import warnings
5from typing import TYPE_CHECKING, Optional, Tuple, Union
6
7from multidict import MultiMapping
8
9from .typedefs import StrOrURL
10
11if TYPE_CHECKING:
12    import ssl
13
14    SSLContext = ssl.SSLContext
15else:
16    try:
17        import ssl
18
19        SSLContext = ssl.SSLContext
20    except ImportError:  # pragma: no cover
21        ssl = SSLContext = None  # type: ignore[assignment]
22
23if TYPE_CHECKING:
24    from .client_reqrep import ClientResponse, ConnectionKey, Fingerprint, RequestInfo
25    from .http_parser import RawResponseMessage
26else:
27    RequestInfo = ClientResponse = ConnectionKey = RawResponseMessage = None
28
29__all__ = (
30    "ClientError",
31    "ClientConnectionError",
32    "ClientConnectionResetError",
33    "ClientOSError",
34    "ClientConnectorError",
35    "ClientProxyConnectionError",
36    "ClientSSLError",
37    "ClientConnectorDNSError",
38    "ClientConnectorSSLError",
39    "ClientConnectorCertificateError",
40    "ConnectionTimeoutError",
41    "SocketTimeoutError",
42    "ServerConnectionError",
43    "ServerTimeoutError",
44    "ServerDisconnectedError",
45    "ServerFingerprintMismatch",
46    "ClientResponseError",
47    "ClientHttpProxyError",
48    "WSServerHandshakeError",
49    "ContentTypeError",
50    "ClientPayloadError",
51    "InvalidURL",
52    "InvalidUrlClientError",
53    "RedirectClientError",
54    "NonHttpUrlClientError",
55    "InvalidUrlRedirectClientError",
56    "NonHttpUrlRedirectClientError",
57    "WSMessageTypeError",
58)
59
60
61class ClientError(Exception):
62    """Base class for client connection errors."""
63
64
65class ClientResponseError(ClientError):
66    """Base class for exceptions that occur after getting a response.
67
68    request_info: An instance of RequestInfo.
69    history: A sequence of responses, if redirects occurred.
70    status: HTTP status code.
71    message: Error message.
72    headers: Response headers.
73    """
74
75    def __init__(
76        self,
77        request_info: RequestInfo,
78        history: Tuple[ClientResponse, ...],
79        *,
80        code: Optional[int] = None,
81        status: Optional[int] = None,
82        message: str = "",
83        headers: Optional[MultiMapping[str]] = None,
84    ) -> None:
85        self.request_info = request_info
86        if code is not None:
87            if status is not None:
88                raise ValueError(
89                    "Both code and status arguments are provided; "
90                    "code is deprecated, use status instead"
91                )
92            warnings.warn(
93                "code argument is deprecated, use status instead",
94                DeprecationWarning,
95                stacklevel=2,
96            )
97        if status is not None:
98            self.status = status
99        elif code is not None:
100            self.status = code
101        else:
102            self.status = 0
103        self.message = message
104        self.headers = headers
105        self.history = history
106        self.args = (request_info, history)
107
108    def __str__(self) -> str:
109        return "{}, message={!r}, url={!r}".format(
110            self.status,
111            self.message,
112            str(self.request_info.real_url),
113        )
114
115    def __repr__(self) -> str:
116        args = f"{self.request_info!r}, {self.history!r}"
117        if self.status != 0:
118            args += f", status={self.status!r}"
119        if self.message != "":
120            args += f", message={self.message!r}"
121        if self.headers is not None:
122            args += f", headers={self.headers!r}"
123        return f"{type(self).__name__}({args})"
124
125    @property
126    def code(self) -> int:
127        warnings.warn(
128            "code property is deprecated, use status instead",
129            DeprecationWarning,
130            stacklevel=2,
131        )
132        return self.status
133
134    @code.setter
135    def code(self, value: int) -> None:
136        warnings.warn(
137            "code property is deprecated, use status instead",
138            DeprecationWarning,
139            stacklevel=2,
140        )
141        self.status = value
142
143
144class ContentTypeError(ClientResponseError):
145    """ContentType found is not valid."""
146
147
148class WSServerHandshakeError(ClientResponseError):
149    """websocket server handshake error."""
150
151
152class ClientHttpProxyError(ClientResponseError):
153    """HTTP proxy error.
154
155    Raised in :class:`aiohttp.connector.TCPConnector` if
156    proxy responds with status other than ``200 OK``
157    on ``CONNECT`` request.
158    """
159
160
161class TooManyRedirects(ClientResponseError):
162    """Client was redirected too many times."""
163
164
165class ClientConnectionError(ClientError):
166    """Base class for client socket errors."""
167
168
169class ClientConnectionResetError(ClientConnectionError, ConnectionResetError):
170    """ConnectionResetError"""
171
172
173class ClientOSError(ClientConnectionError, OSError):
174    """OSError error."""
175
176
177class ClientConnectorError(ClientOSError):
178    """Client connector error.
179
180    Raised in :class:`aiohttp.connector.TCPConnector` if
181        a connection can not be established.
182    """
183
184    def __init__(self, connection_key: ConnectionKey, os_error: OSError) -> None:
185        self._conn_key = connection_key
186        self._os_error = os_error
187        super().__init__(os_error.errno, os_error.strerror)
188        self.args = (connection_key, os_error)
189
190    @property
191    def os_error(self) -> OSError:
192        return self._os_error
193
194    @property
195    def host(self) -> str:
196        return self._conn_key.host
197
198    @property
199    def port(self) -> Optional[int]:
200        return self._conn_key.port
201
202    @property
203    def ssl(self) -> Union[SSLContext, bool, "Fingerprint"]:
204        return self._conn_key.ssl
205
206    def __str__(self) -> str:
207        return "Cannot connect to host {0.host}:{0.port} ssl:{1} [{2}]".format(
208            self, "default" if self.ssl is True else self.ssl, self.strerror
209        )
210
211    # OSError.__reduce__ does too much black magick
212    __reduce__ = BaseException.__reduce__
213
214
215class ClientConnectorDNSError(ClientConnectorError):
216    """DNS resolution failed during client connection.
217
218    Raised in :class:`aiohttp.connector.TCPConnector` if
219        DNS resolution fails.
220    """
221
222
223class ClientProxyConnectionError(ClientConnectorError):
224    """Proxy connection error.
225
226    Raised in :class:`aiohttp.connector.TCPConnector` if
227        connection to proxy can not be established.
228    """
229
230
231class UnixClientConnectorError(ClientConnectorError):
232    """Unix connector error.
233
234    Raised in :py:class:`aiohttp.connector.UnixConnector`
235    if connection to unix socket can not be established.
236    """
237
238    def __init__(
239        self, path: str, connection_key: ConnectionKey, os_error: OSError
240    ) -> None:
241        self._path = path
242        super().__init__(connection_key, os_error)
243
244    @property
245    def path(self) -> str:
246        return self._path
247
248    def __str__(self) -> str:
249        return "Cannot connect to unix socket {0.path} ssl:{1} [{2}]".format(
250            self, "default" if self.ssl is True else self.ssl, self.strerror
251        )
252
253
254class ServerConnectionError(ClientConnectionError):
255    """Server connection errors."""
256
257
258class ServerDisconnectedError(ServerConnectionError):
259    """Server disconnected."""
260
261    def __init__(self, message: Union[RawResponseMessage, str, None] = None) -> None:
262        if message is None:
263            message = "Server disconnected"
264
265        self.args = (message,)
266        self.message = message
267
268
269class ServerTimeoutError(ServerConnectionError, asyncio.TimeoutError):
270    """Server timeout error."""
271
272
273class ConnectionTimeoutError(ServerTimeoutError):
274    """Connection timeout error."""
275
276
277class SocketTimeoutError(ServerTimeoutError):
278    """Socket timeout error."""
279
280
281class ServerFingerprintMismatch(ServerConnectionError):
282    """SSL certificate does not match expected fingerprint."""
283
284    def __init__(self, expected: bytes, got: bytes, host: str, port: int) -> None:
285        self.expected = expected
286        self.got = got
287        self.host = host
288        self.port = port
289        self.args = (expected, got, host, port)
290
291    def __repr__(self) -> str:
292        return "<{} expected={!r} got={!r} host={!r} port={!r}>".format(
293            self.__class__.__name__, self.expected, self.got, self.host, self.port
294        )
295
296
297class ClientPayloadError(ClientError):
298    """Response payload error."""
299
300
301class InvalidURL(ClientError, ValueError):
302    """Invalid URL.
303
304    URL used for fetching is malformed, e.g. it doesn't contains host
305    part.
306    """
307
308    # Derive from ValueError for backward compatibility
309
310    def __init__(self, url: StrOrURL, description: Union[str, None] = None) -> None:
311        # The type of url is not yarl.URL because the exception can be raised
312        # on URL(url) call
313        self._url = url
314        self._description = description
315
316        if description:
317            super().__init__(url, description)
318        else:
319            super().__init__(url)
320
321    @property
322    def url(self) -> StrOrURL:
323        return self._url
324
325    @property
326    def description(self) -> "str | None":
327        return self._description
328
329    def __repr__(self) -> str:
330        return f"<{self.__class__.__name__} {self}>"
331
332    def __str__(self) -> str:
333        if self._description:
334            return f"{self._url} - {self._description}"
335        return str(self._url)
336
337
338class InvalidUrlClientError(InvalidURL):
339    """Invalid URL client error."""
340
341
342class RedirectClientError(ClientError):
343    """Client redirect error."""
344
345
346class NonHttpUrlClientError(ClientError):
347    """Non http URL client error."""
348
349
350class InvalidUrlRedirectClientError(InvalidUrlClientError, RedirectClientError):
351    """Invalid URL redirect client error."""
352
353
354class NonHttpUrlRedirectClientError(NonHttpUrlClientError, RedirectClientError):
355    """Non http URL redirect client error."""
356
357
358class ClientSSLError(ClientConnectorError):
359    """Base error for ssl.*Errors."""
360
361
362if ssl is not None:
363    cert_errors = (ssl.CertificateError,)
364    cert_errors_bases = (
365        ClientSSLError,
366        ssl.CertificateError,
367    )
368
369    ssl_errors = (ssl.SSLError,)
370    ssl_error_bases = (ClientSSLError, ssl.SSLError)
371else:  # pragma: no cover
372    cert_errors = tuple()
373    cert_errors_bases = (
374        ClientSSLError,
375        ValueError,
376    )
377
378    ssl_errors = tuple()
379    ssl_error_bases = (ClientSSLError,)
380
381
382class ClientConnectorSSLError(*ssl_error_bases):  # type: ignore[misc]
383    """Response ssl error."""
384
385
386class ClientConnectorCertificateError(*cert_errors_bases):  # type: ignore[misc]
387    """Response certificate error."""
388
389    _conn_key: ConnectionKey
390
391    def __init__(
392        # TODO: If we require ssl in future, this can become ssl.CertificateError
393        self,
394        connection_key: ConnectionKey,
395        certificate_error: Exception,
396    ) -> None:
397        if isinstance(certificate_error, cert_errors + (OSError,)):
398            # ssl.CertificateError has errno and strerror, so we should be fine
399            os_error = certificate_error
400        else:
401            os_error = OSError()
402
403        super().__init__(connection_key, os_error)
404        self._certificate_error = certificate_error
405        self.args = (connection_key, certificate_error)
406
407    @property
408    def certificate_error(self) -> Exception:
409        return self._certificate_error
410
411    @property
412    def host(self) -> str:
413        return self._conn_key.host
414
415    @property
416    def port(self) -> Optional[int]:
417        return self._conn_key.port
418
419    @property
420    def ssl(self) -> bool:
421        return self._conn_key.is_ssl
422
423    def __str__(self) -> str:
424        return (
425            "Cannot connect to host {0.host}:{0.port} ssl:{0.ssl} "
426            "[{0.certificate_error.__class__.__name__}: "
427            "{0.certificate_error.args}]".format(self)
428        )
429
430
431class WSMessageTypeError(TypeError):
432    """WebSocket message type is not valid."""
433 
codekingpro/portable-devtools · Team Ai