|
24 | 24 | #
|
25 | 25 | # --------------------------------------------------------------------------
|
26 | 26 | from __future__ import annotations
|
| 27 | +from functools import cache |
27 | 28 | import sys
|
28 | 29 | from typing import (
|
29 | 30 | Any,
|
| 31 | + Callable, |
| 32 | + NoReturn, |
30 | 33 | Optional,
|
31 | 34 | AsyncIterator as AsyncIteratorType,
|
32 | 35 | TYPE_CHECKING,
|
|
35 | 38 | Union,
|
36 | 39 | Type,
|
37 | 40 | MutableMapping,
|
| 41 | + Mapping, |
38 | 42 | )
|
39 | 43 | from types import TracebackType
|
40 | 44 | from collections.abc import AsyncIterator
|
|
88 | 92 | class ConnectionTimeoutError(Exception): ... # type: ignore[no-redef]
|
89 | 93 |
|
90 | 94 |
|
| 95 | +@cache |
| 96 | +def _get_detect() -> Callable[[bytes], Mapping[str, Any]]: |
| 97 | + try: |
| 98 | + from cchardet import detect |
| 99 | + |
| 100 | + return detect |
| 101 | + except ImportError: # pragma: no cover |
| 102 | + try: |
| 103 | + from chardet import detect |
| 104 | + |
| 105 | + return detect |
| 106 | + except ImportError: # pragma: no cover |
| 107 | + try: |
| 108 | + from charset_normalizer import detect |
| 109 | + |
| 110 | + return detect |
| 111 | + except ImportError as e: # pragma: no cover |
| 112 | + charset_import_err = e |
| 113 | + |
| 114 | + def error_detect(_: bytes) -> NoReturn: |
| 115 | + raise charset_import_err |
| 116 | + |
| 117 | + return error_detect |
| 118 | + |
| 119 | + |
91 | 120 | class AioHttpTransport(AsyncHttpTransport):
|
92 | 121 | """AioHttp HTTP sender implementation.
|
93 | 122 |
|
@@ -525,16 +554,7 @@ def text(self, encoding: Optional[str] = None) -> str:
|
525 | 554 | elif body is None:
|
526 | 555 | raise RuntimeError("Cannot guess the encoding of a not yet read body")
|
527 | 556 | else:
|
528 |
| - try: |
529 |
| - import cchardet as chardet |
530 |
| - except ImportError: # pragma: no cover |
531 |
| - try: |
532 |
| - import chardet # type: ignore |
533 |
| - except ImportError: # pragma: no cover |
534 |
| - import charset_normalizer as chardet # type: ignore[no-redef] |
535 |
| - # While "detect" can return a dict of float, in this context this won't happen |
536 |
| - # The cast is for pyright to be happy |
537 |
| - encoding = cast(Optional[str], chardet.detect(body)["encoding"]) |
| 557 | + encoding = _get_detect()(body)["encoding"] |
538 | 558 | if encoding == "utf-8" or encoding is None:
|
539 | 559 | encoding = "utf-8-sig"
|
540 | 560 |
|
|
0 commit comments