Skip to content

Commit f200fa3

Browse files
jawwad-aliclaude
andcommitted
fix(bundler): dump_yaml writes literal UTF-8 (allow_unicode=True)
dump_yaml called yaml.safe_dump without allow_unicode=True, so non-ASCII content was written as \xNN / \uXXXX escapes instead of literal UTF-8 — a round-trip readability loss for bundle config. The centralized helper _utils.dump_frontmatter and the extensions/presets config writers all pass allow_unicode=True; align dump_yaml with them. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 8db7228 commit f200fa3

2 files changed

Lines changed: 33 additions & 1 deletion

File tree

src/specify_cli/bundler/lib/yamlio.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,13 @@ def dump_yaml(path: Path, data: Any, *, within: Path | None = None) -> Path:
6060
try:
6161
path.parent.mkdir(parents=True, exist_ok=True)
6262
with path.open("w", encoding="utf-8") as handle:
63-
yaml.safe_dump(data, handle, sort_keys=False, default_flow_style=False)
63+
yaml.safe_dump(
64+
data,
65+
handle,
66+
sort_keys=False,
67+
default_flow_style=False,
68+
allow_unicode=True,
69+
)
6470
except OSError as exc:
6571
raise BundlerError(f"Could not write {path}: {exc}") from exc
6672
return path

tests/unit/test_bundler_yamlio.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""Unit tests for the bundler YAML I/O helpers."""
2+
from __future__ import annotations
3+
4+
from pathlib import Path
5+
6+
from specify_cli.bundler.lib.yamlio import dump_yaml, load_yaml
7+
8+
9+
def test_dump_yaml_preserves_unicode(tmp_path: Path):
10+
# dump_yaml must write literal UTF-8, not \xNN / \uXXXX escapes, so bundle
11+
# config stays human-readable — matching _utils.dump_frontmatter and the
12+
# extensions/presets config writers (all allow_unicode=True).
13+
path = tmp_path / "f.yml"
14+
data = {"note": "café-münchen", "url": "https://例え.example"}
15+
dump_yaml(path, data)
16+
raw = path.read_text(encoding="utf-8")
17+
assert "café-münchen" in raw
18+
assert "例え" in raw
19+
assert "\\x" not in raw and "\\u" not in raw
20+
21+
22+
def test_dump_yaml_round_trips_unicode(tmp_path: Path):
23+
path = tmp_path / "f.yml"
24+
data = {"note": "café", "city": "münchen"}
25+
dump_yaml(path, data)
26+
assert load_yaml(path) == data

0 commit comments

Comments
 (0)