fix: stop encoding detection from returning mojibake - #4467
fix: stop encoding detection from returning mojibake#4467BetterAndBetterII wants to merge 1 commit into
Conversation
detect_file_encoding no longer accepts a high-confidence charset_normalizer result outside COMMON_ENCODINGS. When detection is inconclusive or out of set, candidates are ranked inside that list so iso_8859_1 does not shadow later CJK codecs.
|
Thanks for picking this up so quickly. I had prototyped the same approach while drafting #4466, so I already had a corpus and harness on hand and ran this branch against it: 28 short/medium plain-text samples in their real-world legacy encodings, The fixes are real: the issue's shift_jis and latin-1 samples come back correct, and so do Spanish latin-1, Hebrew cp1255 and Arabic iso-8859-6 samples that are mojibake on
The mechanism is the same in every row: import os, tempfile
from unstructured.partition.text import partition_text
samples = [
("ru cp1251", "Привет, как дела? Это тестовое сообщение для проверки.", "cp1251"),
("th cp874 ", "สวัสดีครับ ยินดีต้อนรับสู่ห้องประชุมของเรา", "cp874"),
("ja cp932 ", "髙﨑様と﨑山様が来社されました。", "cp932"),
("ko cp949 ", "점심 메뉴는 똠얌꿍으로 예약했습니다.", "cp949"),
]
for name, text, enc in samples:
fd, path = tempfile.mkstemp(suffix=".txt"); os.close(fd)
with open(path, "wb") as f:
f.write(text.encode(enc))
try:
got = partition_text(filename=path)[0].text
print(name, "->", "ok" if got == text else f"MOJIBAKE {got!r}")
except Exception as e:
print(name, "->", f"RAISED {type(e).__name__}")
finally:
os.unlink(path)On this branch: On One measurement that may help: changing only the The mojibake rows are harder and I don't have a rule that solves them; on my corpus the same codec name at the same confidence can be the right answer for one input and the wrong one for another, so no membership check on the name separates them ( |
Summary
detect_file_encoding()accepted a high-confidencecharset_normalizer.detect()result even when that codec was outsideCOMMON_ENCODINGS. Those guesses (johab,windows-1250) still decoded, so theUnprocessableEntityErrorguard never fired and the mojibake became element text. That hits everything that reads text throughread_txt_file()(partition_text,partition_md,partition_html).A second path in the same function walked
COMMON_ENCODINGSand took the first codec that decoded.iso_8859_1maps every byte, so later CJK codecs on that list were unreachable.Fix
validate_encoding()(already present, previously unused).from_bytes(..., cp_isolation=COMMON_ENCODINGS)instead of first-success decode.Tests
detect_file_encodingrecovers the issue'sshift_jisandiso_8859_1samples via filename and file.detect()reachesshift_jisinstead of stopping atiso_8859_1.partition_textrecovers the same three samples.Fixes #4466