Skip to content

pgn: escape and unescape header values#1198

Open
gaoflow wants to merge 2 commits into
niklasf:masterfrom
gaoflow:fix-pgn-tag-escaping
Open

pgn: escape and unescape header values#1198
gaoflow wants to merge 2 commits into
niklasf:masterfrom
gaoflow:fix-pgn-tag-escaping

Conversation

@gaoflow

@gaoflow gaoflow commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

Problem

The PGN specification represents a quote inside a string as \" and a backslash as \\. Header values are string tokens, but python-chess currently exposes those representation escapes through read_game() / read_headers() and writes semantic quotes or backslashes without escaping them.

For example, a valid [Event "The \"Open\""] header is returned as The \"Open\", while assigning the semantic value The "Open" exports an invalid header with bare inner quotes.

Fix

  • Decode the two PGN-defined string escapes before dispatching parsed header values. Unknown backslash sequences retain the existing forgiving import behavior.
  • Escape backslashes and quotes in StringExporterMixin, covering both string and file exporters.
  • Add a shared table of ordinary, quote, backslash, mixed, trailing-backslash, and bracket cases across read_game, read_headers, StringExporter, FileExporter, and export/read round trips.

Specification: https://www.saremba.de/chessgml/standards/pgn/pgn-complete.htm#c7

Testing

  • python test.py — 294 passed, 22 skipped (external engines/tablebases)
  • python -m mypy --strict chess — clean
  • python -m mypy --strict examples/**/*.py — clean
  • python -m pyright chess examples/**/*.py — zero errors
  • Independent exhaustive oracle: 5,461 short tag values matched PGN escaping and round-tripped

The README doctest needs a local stockfish binary; its three resulting failures reproduce unchanged on pristine origin/master.

@gaoflow

gaoflow commented Jul 16, 2026

Copy link
Copy Markdown
Contributor Author

The seven Ubuntu test jobs all stopped in .github/workflows/setup-ubuntu-latest.sh before installing this branch or running tests: apt returned 404 for libatopology2t64_1.2.11-1ubuntu0.2. Windows tests, all typing jobs, perft, and the README job passed. The README job runs apt-get update first, which is why the same Ubuntu dependency setup succeeded there. I cannot rerun failed jobs without repository admin rights.

@gaoflow
gaoflow force-pushed the fix-pgn-tag-escaping branch from 20eb44c to 75c3faf Compare July 17, 2026 05:26
@gaoflow

gaoflow commented Jul 17, 2026

Copy link
Copy Markdown
Contributor Author

The ubuntu job failures are environmental: the runner image's baked-in apt lists point at libatopology2t64_1.2.11-1ubuntu0.2, which the mirror no longer carries (404), and setup-ubuntu-latest.sh installs without refreshing the index. Added sudo apt-get update at the top of the script — that should unblock CI for every PR hitting image ubuntu24/20260714.240, not just this one. Happy to drop the commit if you'd rather fix it separately.

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