Skip to content

Commit 129e858

Browse files
[azure-core] Cache the search for charset detection library (#43092)
* [azure-core] Import charset library once * update pr num * use unique name for import error * Black formatting * Redundant ignore * lazy wrapper * black * Import typo --------- Co-authored-by: antisch <[email protected]>
1 parent 89a9fd9 commit 129e858

File tree

2 files changed

+32
-10
lines changed

2 files changed

+32
-10
lines changed

sdk/core/azure-core/CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88

99
### Bugs Fixed
1010

11+
- Fixed repeated import attempts of cchardet and chardet when charset_normalizer is used #43092
12+
1113
### Other Changes
1214

1315
- Updated `BearerTokenCredentialPolicy` and `AsyncBearerTokenCredentialPolicy` to set the `enable_cae` parameter to `True` by default. This change enables Continuous Access Evaluation (CAE) for all token requests made through these policies. #42941

sdk/core/azure-core/azure/core/pipeline/transport/_aiohttp.py

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,12 @@
2424
#
2525
# --------------------------------------------------------------------------
2626
from __future__ import annotations
27+
from functools import cache
2728
import sys
2829
from typing import (
2930
Any,
31+
Callable,
32+
NoReturn,
3033
Optional,
3134
AsyncIterator as AsyncIteratorType,
3235
TYPE_CHECKING,
@@ -35,6 +38,7 @@
3538
Union,
3639
Type,
3740
MutableMapping,
41+
Mapping,
3842
)
3943
from types import TracebackType
4044
from collections.abc import AsyncIterator
@@ -88,6 +92,31 @@
8892
class ConnectionTimeoutError(Exception): ... # type: ignore[no-redef]
8993

9094

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+
91120
class AioHttpTransport(AsyncHttpTransport):
92121
"""AioHttp HTTP sender implementation.
93122
@@ -525,16 +554,7 @@ def text(self, encoding: Optional[str] = None) -> str:
525554
elif body is None:
526555
raise RuntimeError("Cannot guess the encoding of a not yet read body")
527556
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"]
538558
if encoding == "utf-8" or encoding is None:
539559
encoding = "utf-8-sig"
540560

0 commit comments

Comments
 (0)