Skip to content

Decode ShExC as UTF-8 first; use chardet only as a fallback - #5

Open
ericprud wants to merge 1 commit into
linkml:mainfrom
ericprud:shexc-utf8-first
Open

ericprud wants to merge 1 commit into
linkml:mainfrom
ericprud:shexc-utf8-first

Conversation

@ericprud

Copy link
Copy Markdown
Contributor

load_shex_file() (in pyshexc/parser_impl/generate_shexj.py) decoded with whatever chardet guessed whenever its confidence was above 0.9. chardet only samples the start of the data, so a large file that is ASCII for a long stretch before its first non-ASCII character gets reported as ascii with confidence 1.0, and loading crashes. For example, chardet 7.4.3 on FHIR R4's 690 KB fhir.shex:

UnicodeDecodeError: 'ascii' codec can't decode byte 0xe2 in position 253640

Fix: ShExC is UTF-8 by definition, so decode as UTF-8 first (utf-8-sig, which also strips a BOM). Only if that fails, use chardet's guess, with latin-1 as a last resort that can't fail. This also fixes a second crash: a short non-UTF-8 file got low confidence from chardet, so the old code sent it to the UTF-8 default and failed. This is the same fix as linkml/PyShEx#117.

Tests: new tests/test_encoding.py, using tmp_path so nothing tracked is written:

  • UTF-8 after ~320 KB of ASCII: decodes and parses (failed before with the ascii error)
  • A Latin-1 file: loads without crashing (failed before with a utf-8 error)
  • A UTF-8 BOM is still stripped

Known unrelated failure: tests/test_shexc.py::TestShExCValidation::test_shex_schema fails on main too (CI has been red since #4). One shexTest schema containing <http://a.example/dir1/dir2/s/p1?q=v> gets a lexer token recognition error, so parse() returns None. All other tests pass: 17 passed, 2 skipped.

🤖 Generated with Claude Code

load_shex_file() trusted chardet whenever it was > 0.9 confident, but
chardet samples only the start of the data: for FHIR R4's fhir.shex
(690 KB, first non-ASCII byte ~250 KB in) it reports ascii with
confidence 1.0, and decode('ascii') raises UnicodeDecodeError. ShExC is
UTF-8 by definition, so try that first (utf-8-sig, which also strips a
BOM) and only guess for files that aren't valid UTF-8.

The old code also crashed on short non-UTF-8 files: chardet's low
confidence sent them to the UTF-8 default. Now chardet's guess is used
whatever its confidence, with latin-1 as a last resort that can't fail.

Same fix as linkml/PyShEx#117.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant