🐛 FIX: Make a document's own front matter available in env.metadata#1171
Open
holmboe wants to merge 1 commit into
Open
🐛 FIX: Make a document's own front matter available in env.metadata#1171holmboe wants to merge 1 commit into
holmboe wants to merge 1 commit into
Conversation
Sphinx's MetadataCollector only populates env.metadata on the
doctree-read event, i.e. after the whole document has been parsed,
whereas MyST substitutions are evaluated during the parse.
A document could therefore read other documents' front matter via
`env.metadata["other"]["key"]`, but its own entry was still empty,
so `{{ env.metadata[env.docname]["key"] }}` failed.
The renderer now eagerly seeds env.metadata when the front matter
token is rendered (the first token of the document).
Values are read back off the already-built field list, so they are
identical to what the collector stores later: bibliographic field
names are canonicalized via the language module, dedication/abstract
are skipped (docutils moves them outside the docinfo, so the
collector never stores them), and tocdepth is cast to int.
Closes executablebooks#947
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #947
Problem
Sphinx's
MetadataCollectoronly populatesenv.metadataon thedoctree-readevent, i.e. after the whole document has been parsed, whereas MyST substitutions are evaluated during the parse. A document could therefore read other documents' front matter viaenv.metadata["other"]["key"], but its own entry was still empty, so{{ env.metadata[env.docname]["key"] }}failed with anUndefinedError:Fix
The renderer now eagerly seeds
env.metadata[docname]when the front matter token is rendered (the first token of the document), so the rest of the parse can see it. This also benefits anything else readingenv.metadatamid-parse (directives,eval-rst, myst-nb).Values are read back off the already-built field list rather than re-stringified from the raw YAML, so they are identical to what the collector stores later at
doctree-read(which then harmlessly overwrites them). Three details needed to mirror the collector exactly:DocInfotransform);dedication/abstractare skipped — docutils moves them outside thedocinfo, so the collector never stores them (without the skip they would leak intoenv.metadatapermanently, caught by the existingtest_basic);tocdepthis cast toint, as the collector does.Scope note
The linked gist demonstrates two distinct problems. This PR fixes the self-reference case. Reading another document's metadata (
env.metadata["other-doc"]["key"]) remains inherently order-dependent (alphabetical read order, parallel-read partitioning, stale values on incremental builds since no dependency is recorded) — that would need post-read aggregation, a different feature. The docs update adds a warning admonition documenting this limitation.Testing
test_frontmatter_metadatawith doctree regressions; asserts the exactenv.metadatacontents (string values,inttocdepth) and a warning-free build. It fails without the fix.test_basicasserts the full metadata dict for a rich front matter (author/date/dedication/abstract), acting as a contract test that the eager values match the collector's.AI assistance disclosure
This PR was developed with substantial assistance from Claude Code (Anthropic): root-cause investigation, and drafting of the implementation, tests, and docs. I directed the work and made the design decisions (storing the same stringified values the collector produces, deriving them from the rendered field list so parity holds by construction, and limiting scope to the self-reference bug), and I have reviewed and verified the changes.
🤖 Generated with Claude Code