Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/chardet/__init__.py: 57%
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
Shortcuts on this page
r m x toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""Universal character encoding detector — 0BSD-licensed rewrite."""
3from __future__ import annotations
5from collections.abc import Iterable
7from chardet._utils import (
8 _DEFAULT_CHUNK_SIZE,
9 DEFAULT_MAX_BYTES,
10 MINIMUM_THRESHOLD,
11 _resolve_prefer_superset,
12 _validate_max_bytes,
13 _warn_deprecated_chunk_size,
14)
15from chardet._version import __version__
16from chardet.detector import UniversalDetector
17from chardet.enums import EncodingEra, LanguageFilter
18from chardet.output_names import apply_compat_names, apply_preferred_superset
19from chardet.pipeline import DetectionDict, DetectionResult
20from chardet.pipeline.orchestrator import run_pipeline
21from chardet.registry import _validate_encoding, normalize_encodings
23__all__ = [
24 "DEFAULT_MAX_BYTES",
25 "MINIMUM_THRESHOLD",
26 "DetectionDict",
27 "DetectionResult",
28 "EncodingEra",
29 "LanguageFilter",
30 "UniversalDetector",
31 "__version__",
32 "detect",
33 "detect_all",
34]
37def __getattr__(name: str) -> object:
38 """Resolve the deprecated ``chardet.equivalences`` submodule on demand.
40 Before the 7.5 split, ``chardet/__init__.py`` imported that module for
41 its own use, which as a side effect made ``chardet.equivalences`` work
42 without an explicit ``import chardet.equivalences``. This package now
43 imports :mod:`chardet.output_names` instead, so the attribute is bound
44 lazily here: importing the shim eagerly would fire its deprecation
45 warning on every ``import chardet``.
46 """
47 if name == "equivalences":
48 # ``from chardet import equivalences`` would re-enter this function:
49 # the import machinery probes the parent package with ``hasattr``
50 # first. Kept local so the shim stays off the eager import path.
51 import importlib # noqa: PLC0415
53 return importlib.import_module("chardet.equivalences")
54 msg = f"module {__name__!r} has no attribute {name!r}"
55 raise AttributeError(msg)
58def detect( # noqa: PLR0913
59 byte_str: bytes | bytearray,
60 should_rename_legacy: bool = False,
61 encoding_era: EncodingEra = EncodingEra.ALL,
62 chunk_size: int = _DEFAULT_CHUNK_SIZE,
63 max_bytes: int = DEFAULT_MAX_BYTES,
64 *,
65 prefer_superset: bool = False,
66 compat_names: bool = True,
67 include_encodings: Iterable[str] | None = None,
68 exclude_encodings: Iterable[str] | None = None,
69 no_match_encoding: str = "cp1252",
70 empty_input_encoding: str = "utf-8",
71) -> DetectionDict:
72 """Detect the encoding of the given byte string.
74 :param byte_str: The byte sequence to detect encoding for.
75 :param should_rename_legacy: Deprecated alias for *prefer_superset*.
76 :param encoding_era: Restrict candidate encodings to the given era.
77 :param chunk_size: Deprecated -- accepted for backward compatibility but
78 has no effect.
79 :param max_bytes: Maximum number of bytes to examine from *byte_str*.
80 :param prefer_superset: If ``True``, remap subset encodings in the result
81 to their decode-safe Windows/CP superset equivalents (e.g.,
82 ISO-8859-1 -> Windows-1252, EUC-KR -> CP949). Recommended when the
83 result will be used to decode: detection examines at most
84 *max_bytes* of input, and only the superset is guaranteed to decode
85 bytes beyond that window. The remap is skipped when the superset
86 cannot decode the examined window itself (the Windows code pages
87 leave a few C1 positions undefined that the ISO subsets map), so
88 the reported name always decodes what was examined. If ``False``
89 (default), the detected
90 encoding is reported under its own name --- note this only skips
91 the renaming step; it is not a promise of the *smallest* matching
92 encoding, since detection may natively choose a superset that fits
93 the data better. The default will change to ``True`` in chardet
94 8.0; pass ``False`` explicitly if you depend on subset names.
95 :param compat_names: If ``True`` (default), return encoding names
96 compatible with chardet 5.x/6.x. If ``False``, return raw Python
97 codec names.
98 :param include_encodings: If given, restrict detection to only these
99 encodings (names or aliases).
100 :param exclude_encodings: If given, remove these encodings from the
101 candidate set.
102 :param no_match_encoding: Encoding to return when no candidate survives
103 the pipeline. Defaults to ``"cp1252"``.
104 :param empty_input_encoding: Encoding to return for empty input. Defaults
105 to ``"utf-8"``.
106 :returns: A dictionary with keys ``"encoding"``, ``"confidence"``, and
107 ``"language"``.
108 """
109 _warn_deprecated_chunk_size(chunk_size)
110 _validate_max_bytes(max_bytes)
111 prefer_superset = _resolve_prefer_superset(should_rename_legacy, prefer_superset)
112 include = normalize_encodings(include_encodings, "include_encodings")
113 exclude = normalize_encodings(exclude_encodings, "exclude_encodings")
114 no_match = _validate_encoding(no_match_encoding, "no_match_encoding")
115 empty = _validate_encoding(empty_input_encoding, "empty_input_encoding")
116 data = byte_str if isinstance(byte_str, bytes) else bytes(byte_str)
117 results = run_pipeline(
118 data,
119 encoding_era,
120 max_bytes=max_bytes,
121 include_encodings=include,
122 exclude_encodings=exclude,
123 no_match_encoding=no_match,
124 empty_input_encoding=empty,
125 )
126 result = results[0].to_dict()
127 if prefer_superset:
128 apply_preferred_superset(result, data[:max_bytes])
129 if compat_names:
130 apply_compat_names(result)
131 return result
134def detect_all( # noqa: PLR0913
135 byte_str: bytes | bytearray,
136 ignore_threshold: bool = False,
137 should_rename_legacy: bool = False,
138 encoding_era: EncodingEra = EncodingEra.ALL,
139 chunk_size: int = _DEFAULT_CHUNK_SIZE,
140 max_bytes: int = DEFAULT_MAX_BYTES,
141 *,
142 prefer_superset: bool = False,
143 compat_names: bool = True,
144 include_encodings: Iterable[str] | None = None,
145 exclude_encodings: Iterable[str] | None = None,
146 no_match_encoding: str = "cp1252",
147 empty_input_encoding: str = "utf-8",
148) -> list[DetectionDict]:
149 """Detect all possible encodings of the given byte string.
151 When *ignore_threshold* is False (the default), results with confidence
152 <= MINIMUM_THRESHOLD (0.20) are filtered out. If all results are below
153 the threshold, the full unfiltered list is returned as a fallback so the
154 caller always receives at least one result.
156 :param byte_str: The byte sequence to detect encoding for.
157 :param ignore_threshold: If ``True``, return all candidate encodings
158 regardless of confidence score.
159 :param should_rename_legacy: Deprecated alias for *prefer_superset*.
160 :param encoding_era: Restrict candidate encodings to the given era.
161 :param chunk_size: Deprecated -- accepted for backward compatibility but
162 has no effect.
163 :param max_bytes: Maximum number of bytes to examine from *byte_str*.
164 :param prefer_superset: If ``True``, remap subset encodings in the
165 results to their decode-safe Windows/CP superset equivalents.
166 If ``False`` (default), skip the renaming --- not a promise of the
167 smallest matching encoding. The default will change to ``True``
168 in chardet 8.0. See :func:`detect` for details.
169 :param compat_names: If ``True`` (default), return encoding names
170 compatible with chardet 5.x/6.x. If ``False``, return raw Python
171 codec names.
172 :param include_encodings: If given, restrict detection to only these
173 encodings (names or aliases).
174 :param exclude_encodings: If given, remove these encodings from the
175 candidate set.
176 :param no_match_encoding: Encoding to return when no candidate survives
177 the pipeline. Defaults to ``"cp1252"``.
178 :param empty_input_encoding: Encoding to return for empty input. Defaults
179 to ``"utf-8"``.
180 :returns: A list of dictionaries, sorted by descending confidence.
181 """
182 _warn_deprecated_chunk_size(chunk_size)
183 _validate_max_bytes(max_bytes)
184 prefer_superset = _resolve_prefer_superset(should_rename_legacy, prefer_superset)
185 include = normalize_encodings(include_encodings, "include_encodings")
186 exclude = normalize_encodings(exclude_encodings, "exclude_encodings")
187 no_match = _validate_encoding(no_match_encoding, "no_match_encoding")
188 empty = _validate_encoding(empty_input_encoding, "empty_input_encoding")
189 data = byte_str if isinstance(byte_str, bytes) else bytes(byte_str)
190 results = run_pipeline(
191 data,
192 encoding_era,
193 max_bytes=max_bytes,
194 include_encodings=include,
195 exclude_encodings=exclude,
196 no_match_encoding=no_match,
197 empty_input_encoding=empty,
198 full_ranking=True,
199 )
200 dicts = [r.to_dict() for r in results]
201 if not ignore_threshold:
202 filtered = [d for d in dicts if d["confidence"] > MINIMUM_THRESHOLD]
203 if filtered:
204 dicts = filtered
205 window = data[:max_bytes]
206 for d in dicts:
207 if prefer_superset:
208 apply_preferred_superset(d, window)
209 if compat_names:
210 apply_compat_names(d)
211 return sorted(dicts, key=lambda d: d["confidence"], reverse=True)