No way to access the builder in directives
I was asked in https://github.com/sphinx-doc/sphinx/issues/13072#issuecomment-3594904760 to open a new issue for this
Describe the bug
With the new logic discussed in #13072 I don't see a way how a directive can access the builder, to access e.g. app.builder.outdir and app.builder.name. The app can currently be fetched over self.state.document.settings.env.app which won't then work anymore.
You can find my code here: https://github.com/SAP/swagger-plugin-for-sphinx
How to Reproduce
n/a
Environment Information
Platform: linux; (Linux-5.14.21-150500.55.124-default-x86_64-with-glibc2.31)
Python version: 3.14.0 (main, Nov 10 2025, 09:33:32) [GCC 7.5.0])
Python implementation: CPython
Sphinx version: 9.0.0
Docutils version: 0.21.2
Jinja2 version: 3.1.6
Pygments version: 2.19.2
@kasium thanks for opening!
We may need to add more public attributes to env or similar to support this use-case. May I ask what the directive uses the builder name / outdir for?
A
Sure. outdir is used to find the right _static folder. builder.name is used to find out if we run with dirhtml as then some structures need to be changed
This also affects SphinxTransform implementations, i.e. I need a builder for resolving cross-refs in post-transforms. For example, I have a post-transform that creates references to inherited members that weren't documented in the current class.
The only thing I would note here, is that the "read phase", when directives are parsed and transforms are run (not post-transforms) are intended to be output agnostic, i.e. should not really rely on any particular builder. In turn, the cached environment/ast, created at the end of the read phase, can be used my multiple writers. Strictly speaking then, if you are using the builder in directives or transforms, then you are probably doing something wrong
Strictly speaking then, if you are using the builder in directives or transforms, then you are probably doing something wrong
Sorry, I meant post-transform. I've edited my message.
Strictly speaking then, if you are using the builder in directives or transforms, then you are probably doing something wrong
Sorry, I meant post-transform. I've edited my message.
I see you are using SphinxTransform, but shouldn't you then be using a SphinxPostTransform then (I think that's a thing)
There's only SphinxTransform, the difference is how you register it (app.add_post_transform vs app.add_transform).
Sure. outdir is used to find the right
_staticfolder.builder.nameis used to find out if we run withdirhtmlas then some structures need to be changed
The best fix for this seems to be some API to register/add files to be copied to the output or static directory, which (as Chris points out) should be builder-agnostic. Would this address your problem?
A
There's only
SphinxTransform, the difference is how you register it (app.add_post_transformvsapp.add_transform).
Chris meant sphinx.transforms.post_transforms.SphinxPostTransform (added ~six years ago in Sphinx 2.1). It handles filtering on builder type using private attributes, but doesn't expose details of the builder/etc.
A
One problem here is builder.get_relative_uri(), which currently requires a builder instance. This accounts for both uses of the builder object in Sphinx's core post-transforms (specifically ReferencesResolver). Two further ones are in viewcode.py (also creating refnodes) and linkcheck.py (I think this one is just bad design, the data should be stored on env rather than builder).
A
Another use case for me is inspecting capabilities of a builder, specifically which image types it supports, and whether it supports inline HTML.
I have a plugin for generating syntax diagrams. Depending on builder, it will either create an inline SVG (for HTML builders), create an SVG file and add an image node (for Epub/LaTeX, with further SVG to PDF conversion handled by other plugins), or insert a literal with text representation (for text/man builder).
See code here: https://github.com/sphinx-contrib/syntax/blob/a8111074411d5da6d48c0902a3cd30089a2323b4/sphinx_syntax/diagram.py#L302-L313