Skip to content

Decode JCAMP-DX parameter files as UTF-8, not as the locale encoding - #203

Merged
headmeister merged 2 commits into
isi-nmr:masterfrom
gdevenyi:fix/jcampdx-utf8-encoding
Aug 10, 2026
Merged

Decode JCAMP-DX parameter files as UTF-8, not as the locale encoding#203
headmeister merged 2 commits into
isi-nmr:masterfrom
gdevenyi:fix/jcampdx-utf8-encoding

Conversation

@gdevenyi

@gdevenyi gdevenyi commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

Fixes #196.

Spec 2.2:

Although JCAMP-DX is nominally an ASCII standard, ParaVision 360 writes parameter files as UTF-8, and string values may contain non-ASCII characters […] Decode as UTF-8, and do not assume one byte per character when working with the declared maximum length.

All four open() sites in jcampdx.py used Python's default text encoding, so the format's encoding came from the process locale.

Change

  • ENCODING = "utf-8" named next to the other format constants, passed at JCAMPDX.version, load_parameter, read_jcampdx and write.
  • read_jcampdx no longer reports a valid UTF-8 file as "is not a text file"; UnicodeDecodeError and OSError now get distinct messages.
  • test/synthetic.py:write_jcampdx writes UTF-8 too, so a fixture can carry the strings ParaVision actually writes.

Test

test_utf8_values_survive_a_non_utf8_locale writes the PV360 T2-map VisuFGElemComment values (σ of Signal Intensity, Fit χ²) and reads them back in a subprocess under LC_ALL=C with UTF-8 mode off. Without the fix that subprocess exits non-zero with JcampdxFileError: ... is not a text file; with it the strings round-trip. No vendor data is touched.

Suite: 2141 passed, 12 skipped (baseline 2140/12 — the one new test).

@gdevenyi
gdevenyi force-pushed the fix/jcampdx-utf8-encoding branch from 8275c9c to 50ebee8 Compare August 8, 2026 19:50
`ruff format --check` reported twelve files as unformatted, so any change
touching one of them dragged unrelated reflow into its diff. Run the
formatter once, on its own, so subsequent changes show only what they
actually change.

Formatting only: no behaviour changes, and `ruff check` is clean before and
after. The suite is unchanged at 2140 passed, 12 skipped.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017SNrm3jFhpTPShP8xGkePC
Spec 2.2 says ParaVision 360 writes parameter files as UTF-8 and that a
reader must decode them as UTF-8. Every read and the write instead used
Python's default text encoding, i.e. locale.getpreferredencoding(False).

Under LC_ALL=C -- a container, a CI runner, a batch scheduler -- reading a
PV360 parameter-map visu_pars raised UnicodeDecodeError, which read_jcampdx
then reported as the misleading "is not a text file". Under a single-byte
code page it would be worse: the file decodes without error into the wrong
string.

Name the encoding once, next to the format constants it belongs with, and
pass it at the four open sites. Split the error handling so a genuine I/O
failure no longer claims the file is not text.

Closes isi-nmr#196

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017SNrm3jFhpTPShP8xGkePC
@gdevenyi
gdevenyi force-pushed the fix/jcampdx-utf8-encoding branch from 50ebee8 to 5ca2726 Compare August 8, 2026 20:50
@gdevenyi

gdevenyi commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

Rebased onto #213 (ruff format), so this branch carries that commit until #213 merges — merge #213 first and this diff reduces to its own change. Verified after the rebase: ruff check and ruff format --check clean, full suite green.

Integration check across all eleven conformance PRs merged together: 2164 passed, 12 skipped; corpus load test 3202 → 3207 of 3478 with zero newly broken datasets.

@headmeister
headmeister merged commit e1b2750 into isi-nmr:master Aug 10, 2026
7 checks passed
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.

JCAMP-DX files are opened with the locale encoding rather than UTF-8, so PV360 files with non-ASCII strings are rejected or corrupted (spec 2.2)

2 participants