Skip to content

exporters: encoding="utf-8" across text writes; samm/file_helper to context manager - #518

Merged
sschleemilch merged 2 commits into
COVESA:masterfrom
SoundMatt:fix/exporters-utf8-encoding-and-samm-context-manager
May 12, 2026
Merged

exporters: encoding="utf-8" across text writes; samm/file_helper to context manager#518
sschleemilch merged 2 commits into
COVESA:masterfrom
SoundMatt:fix/exporters-utf8-encoding-and-samm-context-manager

Conversation

@SoundMatt

Copy link
Copy Markdown
Contributor

Problem

Two related file-handling hardening fixes across the exporters:

1. Missing encoding="utf-8" on text-write open() calls

Fourteen exporters (json, tree, yaml, csv, protobuf,
plantuml, go, id, franca, ddsidl, stats_utils, apigear,
s2dm/__init__, s2dm/reference_generator) opened output files
with open(path, "w") in text mode without specifying an encoding.

On platforms whose default text-file encoding is not UTF-8 (notably
Windows cp1252), writing a VSS spec containing non-ASCII characters —
e.g. ° in unit names, Ω in resistance units, accented characters
in descriptions — crashes with UnicodeEncodeError. Same shape on
non-UTF-8 Linux locales.

jsonschema.py already does this correctly; everything else didn't.

2. samm/helpers/file_helper.write_graph_to_file not using a context manager

The function opened the output .ttl file with output_file.open("w"),
wrote to it, then manually called .close() at the end. If any of the
intermediate .write() calls raised, the file descriptor would leak.
It also lacked the encoding fix from #1.

Fix

Two commits, one per problem:

  1. exporters: add encoding="utf-8" to all text-write open() calls
    — adds encoding="utf-8" to every open(path, "w") (and
    open(path, "w", newline="") for CSV) across the 14 exporters.

  2. exporters/samm: use context manager and utf-8 encoding in file_helper
    — wraps the two .write() calls in a with block and pins the
    encoding.

Notes

  • yaml.py had a confusing encoding="utf-8" kwarg passed to
    yaml.dump(), which is silently ignored when the dump target is a
    text-mode file (PyYAML only honours that kwarg on byte-mode
    streams). Left in place with a comment explaining why; the real
    fix is on open().
  • CSV's existing newline="" argument is preserved (correct for
    cross-platform CSV writing).
  • No new tests added: the fix is mechanical and the failure mode it
    prevents is platform/locale-specific. Happy to add a test if
    maintainers can suggest a clean way to simulate non-UTF-8 default
    encoding in CI.

Related

Companion to the validation hardening in #515, #516, and #517.

SoundMatt added 2 commits May 5, 2026 10:36
Fourteen exporters (json, tree, yaml, csv, protobuf, plantuml, go,
id, franca, ddsidl, stats_utils, apigear, s2dm/__init__,
s2dm/reference_generator) opened output files with `open(path, "w")`
in text mode without an explicit encoding. On platforms whose
default text-file encoding is not UTF-8 (most notably Windows
cp1252), writing a VSS spec containing non-ASCII characters — e.g.
"°" in unit names, "Ω" in resistance units, accented characters in
descriptions — crashes with `UnicodeEncodeError`.

Add `encoding="utf-8"` to every text-write open() call so the
exporters behave consistently across platforms. Matches the existing
correct usage in jsonschema.py.

Note: yaml.py also passes `encoding="utf-8"` to `yaml.dump()`, but
that argument is silently ignored when the dump target is a
text-mode file (it only applies to byte-mode streams). The fix here
is to set the encoding on `open()` itself; the yaml.dump kwarg is
left in place for clarity but commented to that effect.

The CSV exporter retains its `newline=""` argument (correct for
cross-platform CSV writing) and gains `encoding="utf-8"` alongside.

Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>
write_graph_to_file in samm/helpers/file_helper.py manually opened the
output .ttl file with output_file.open("w") and called
file_writer.close() at the bottom of the function. If any of the
.write() calls raised — e.g. a transient I/O error on the second
write("\n") — the file handle would leak. The file was also opened
without an explicit encoding, sharing the cross-platform crash hazard
fixed for the other exporters in the previous commit.

Wrap the writes in a `with` statement and pin encoding to UTF-8.
Same shape as the rest of the exporters now.

Signed-off-by: Matt Jones <47545907+SoundMatt@users.noreply.github.com>

@erikbosch erikbosch left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@sschleemilch
sschleemilch merged commit 0dcfa93 into COVESA:master May 12, 2026
5 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.

3 participants