MCPcopy Create free account
hub / github.com/agentforce314/clawcodex / _read_text_with_encoding

Function _read_text_with_encoding

src/command_system/input_processing.py:309–355  ·  view source on GitHub ↗

Read ``path`` as text, picking a decoder from any leading BOM. Falls back to utf-8 with ``errors="replace"`` for the common case (no BOM). When a BOM is present we use the codec it implies (with ``errors="replace"`` so a malformed trailing byte doesn't bring down the whole read).

(path: str)

Source from the content-addressed store, hash-verified

307
308
309def _read_text_with_encoding(path: str) -> str | None:
310 """Read ``path`` as text, picking a decoder from any leading BOM.
311
312 Falls back to utf-8 with ``errors="replace"`` for the common case
313 (no BOM). When a BOM is present we use the codec it implies (with
314 ``errors="replace"`` so a malformed trailing byte doesn't bring
315 down the whole read).
316
317 Post-decode garbage check: if the decoded text is mostly U+FFFD
318 replacement characters, returns ``None`` so the caller drops the
319 attachment instead of inlining mojibake. This closes the adversarial
320 case where a binary blob starts with `\\xff\\xfe` (fake UTF-16 BOM)
321 and an extension we haven't enumerated — without the check, the
322 BOM short-circuit would route the blob to the text branch and the
323 `errors="replace"` decode would land replacement-char mojibake in
324 the prompt (same failure family as Bug A even though no NULs leak).
325
326 Returns ``None`` on OSError or on garbled-decode so the caller
327 matches the existing "drop this attachment silently" behaviour for
328 unreadable files. Callers should still emit a binary-style reminder
329 via the @-mention `binary` attachment kind when this returns None
330 for a non-OSError reason — see ``expand_at_mentions``.
331 """
332 try:
333 with open(path, "rb") as fh:
334 head = fh.read(4)
335 except OSError:
336 return None
337 encoding = _detect_bom_encoding(head) or "utf-8"
338 try:
339 with open(path, "r", encoding=encoding, errors="replace") as fh:
340 data = fh.read()
341 except OSError:
342 return None
343 except (LookupError, UnicodeError):
344 # Pathological codec name from a future BOM check, or a UTF-32
345 # decode failure with errors=replace (rare but theoretically
346 # possible). Fall back to a raw utf-8 replacement read so the
347 # path still produces *some* text rather than a silent drop.
348 try:
349 with open(path, "r", encoding="utf-8", errors="replace") as fh:
350 data = fh.read()
351 except OSError:
352 return None
353 if _decoded_text_looks_garbled(data):
354 return None
355 return data
356
357
358def _binary_hint_for_ext(ext: str) -> str:

Callers 1

expand_at_mentionsFunction · 0.85

Calls 3

_detect_bom_encodingFunction · 0.85
readMethod · 0.45

Tested by

no test coverage detected