sphinx-autocodelink
Automatically add links to code blocks in Sphinx documentation.
This extension is similar to sphinx-codeautolink,
except it uses dynamic analysis to resolve links instead of static analysis.
The dynamic analysis is based on how Sphinx-Gallery resolves links
for its 'reference_url' configuration option.
Installation
pip install sphinx-autocodelink
Add the extension to your Sphinx conf.py:
extensions = [
...,
'sphinx_autocodelink',
]
Usage
Links only appear on code you actually run through one of the two mechanisms below. Each is opt-in
by use: nothing happens unless you write the directive, or add the scraper -- there's no
conf.py switch to flip.
The autocodelink directive
Write it wherever you want a code block executed and linked. It only affects that one block:
.. autocodelink::
import pkg
pkg.thing()
No figure or other output is produced, just a syntax-highlighted, linked code block. Doctest-style
content (>>>) also works, with prompts stripped before execution.
Sphinx-Gallery
Sphinx-Gallery already executes your example scripts; this hooks into that execution instead of
running anything itself. Add AutoCodeLinkScraper alongside your real image scraper(s):
from sphinx_autocodelink.gallery import AutoCodeLinkScraper
sphinx_gallery_conf = {
'image_scrapers': (AutoCodeLinkScraper(), ...), # ... = your other scraper(s), if any
}
Sphinx-Gallery's own parallel=True mode runs each example in a separate worker process, bypassing
Sphinx's usual mechanism for merging data back into the main build. AutoCodeLinkScraper writes its
records to disk instead, so they survive regardless.
Limitation: only resolves identifiers in an example's own top-level (module) scope. A root identifier that only ever exists inside one of the example's own helper functions -- a local variable, a parameter -- isn't resolvable:
def plot_it(mesh):
smoothed = mesh.smooth_taubin() # not linked: `smoothed` never leaves plot_it's own scope
smoothed.plot()
plot_it(pv.Sphere())
There's no workaround for Sphinx-Gallery examples specifically -- this is different from the
standalone .. autocodelink:: directive and record_namespace(), which do resolve this case (see
Resolving identifiers local to a helper
function); that mechanism traces the code's own
execution, which isn't available to hook into Sphinx-Gallery's own execution of an example script.
A local name that's also bound at module level, to a value of the same type, resolves anyway -- resolution matches identifier text against the module namespace by name, not by real lexical scope, so a same-named module-level variable is indistinguishable from the local one shadowing it. Not a workaround to rely on deliberately: a same-named module-level variable of a different type resolves to the wrong link, not to no link at all.
If sphinx_gallery_conf['reference_url'] is also configured for a module AutoCodeLinkScraper
covers too, both will try to link the same identifiers. This extension runs its own embedding after
Sphinx-Gallery's, and skips anything already inside a link -- so the two don't produce broken,
nested <a> tags, but Sphinx-Gallery's own (usually less precise, since it's static analysis rather
than the real executed object) link wins wherever both would apply. Prefer intersphinx_mapping
over reference_url, which this extension already reads and which covers every page, not just
gallery pages -- then there's nothing to fall back to it for.
Backreferences index
.. autocodelink-index:: lists every linked name and the pages that reference it, filled in once
the whole site's links are known:
.. autocodelink-index::
Pass a documented dotted name to show just its own references -- handy on that name's own API page:
.. autocodelink-index:: pkg.thing
Add :label: to wrap the list in a real section with that title, instead of rendering inline --
important if anything in your setup (e.g. an "on this page" sidebar built from real headings) needs
a genuine section rather than inline content. Add :hide-empty: to omit the whole section, title
included, when there's nothing to show, instead of printing "No references found.":
.. autocodelink-index:: pkg.thing
:label: Used In
:hide-empty:
Referencing pages show their real title by default (read straight from Sphinx's own tracked
document titles), not their docname. Add :no-titles: to show docnames instead.
Set autocodelink_autodoc_backrefs = True to append exactly that -- a hidden-if-empty "Used In"
section -- to every autodoc-documented object's own docstring automatically, via
autodoc-process-docstring. Off by default; requires sphinx.ext.autodoc (directly, or via
something that depends on it, e.g. numpydoc).
Grouping by category. AutoCodeLinkScraper tags every page it records 'Sphinx Gallery' by
default (pass category= to change or clear it); .. autocodelink:: and record_namespace() take
an optional category=/:category: of your own choosing. .. autocodelink-index:: uses this to
group referencing pages -- but only adaptively: :group: auto (the default) groups by category only
when a given entry's references actually span more than one category, otherwise it's today's flat
list either way, so a name referenced from just one place never gets a pointless one-item subheading.
Force it with :group: always or :group: never. Untagged pages fall under a generic
'Documentation' bucket whenever grouping does happen -- unless the recording happens from inside
an object's own description (e.g. a docstring's Examples section, rendered through autodoc or a
domain directive like .. py:function::), in which case it's tagged 'Docstring Examples' instead.
Detected automatically when record_namespace()/.. autocodelink:: are given the calling
directive's own state; not available to AutoCodeLinkScraper, since Sphinx-Gallery examples don't
run inside any object's own description in the first place.
Set autocodelink_category_labels to rename categories' displayed group headings, without
changing the category strings themselves (what :group: actually groups by) -- e.g. to drop
implementation detail your readers don't need ("Sphinx Gallery" is a mechanism, not something
a reader needs to know about):
autocodelink_category_labels = {
'Sphinx Gallery': 'Gallery Examples',
'Documentation': 'API Reference',
}
Long lists. Each rendered list (a whole flat list, or one category's group) shows at most 8
entries; past that it shows the first 5 and tucks the rest behind a <details> "N more" toggle, so
a heavily-used name's index entry doesn't turn into a wall of links.
Resolving identifiers local to a helper function
Only a script's top-level namespace is resolvable by default -- a root identifier that only ever
exists inside one of the script's own helper functions (a local variable, a parameter) has nothing
to look it up against, even though the code accessing it is right there. Use
exec_with_local_scopes() in place of a plain exec() to also resolve those:
from sphinx_autocodelink import exec_with_local_scopes
namespace = exec_with_local_scopes(compile(code, filename, 'exec'), {}, filename)
It runs code exactly as exec(code, namespace) would, and returns a namespace with every one of
the script's own function calls' own locals merged in underneath -- at the cost of some precision, a
local name in one call can shadow what globals (or a different call) bound under the same name.
Only frames compiled from filename are captured, so calls into library internals aren't traced or
merged in.
Library use
A consumer that already executes example code for its own purposes (e.g. to render a figure) can
skip the directive and AutoCodeLinkScraper entirely, and call record_namespace() directly with
the resulting namespace. For example, pyvista's pyvista-plot directive
already builds its own namespace via exec(code, ns) to render a figure; adding autolinking is one
extra call after that. Passing the directive's own state (see "Grouping by category" above) picks
up the 'Docstring Examples' category automatically, when the consumer's own directive is itself
used inside an object's own description:
from sphinx_autocodelink import record_namespace
record_namespace(env=env, docname=env.docname, source=code, namespace=ns, state=self.state)
Then, from the consumer's own setup(app), call app.setup_extension('sphinx_autocodelink'):
def setup(app):
app.setup_extension('sphinx_autocodelink')
app.add_directive('pyvista-plot', PlotDirective)
...
Development
uv sync --group dev
uv run pytest
uv run pre-commit run --all-files
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file sphinx_autocodelink-0.5.2.tar.gz.
File metadata
- Download URL: sphinx_autocodelink-0.5.2.tar.gz
- Upload date:
- Size: 35.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
cc3ff944dcce7f8f1532d2a123f9608d1cc144ce4bd8ca4fcbbb2c65caf07fd6
|
|
| MD5 |
a16373bddbc3c5c79c14c22359ba0702
|
|
| BLAKE2b-256 |
ebe098f1ce8e1f3c0f0391e5b8ac55abcfbc2a8e01910f19199c869b45dfdce2
|
Provenance
The following attestation bundles were made for sphinx_autocodelink-0.5.2.tar.gz:
Publisher:
ci.yml on user27182/sphinx-autocodelink
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sphinx_autocodelink-0.5.2.tar.gz -
Subject digest:
cc3ff944dcce7f8f1532d2a123f9608d1cc144ce4bd8ca4fcbbb2c65caf07fd6 - Sigstore transparency entry: 2509389176
- Sigstore integration time:
-
Permalink:
user27182/sphinx-autocodelink@53a9ef0fa8d3ebb3a9eff907e7e03d1316821ab0 -
Branch / Tag:
refs/tags/v0.5.2 - Owner: https://github.com/user27182
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@53a9ef0fa8d3ebb3a9eff907e7e03d1316821ab0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file sphinx_autocodelink-0.5.2-py3-none-any.whl.
File metadata
- Download URL: sphinx_autocodelink-0.5.2-py3-none-any.whl
- Upload date:
- Size: 21.4 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
695e82efdf4cb8e425a47e2f80211c9f2f9c5046d97f6ca80fca201aeb26e000
|
|
| MD5 |
9ed48d1e2584304d9f664a1ca2495464
|
|
| BLAKE2b-256 |
0ba680f5106a0aae1384549e3e04823fb682297cda1558ba0708842ddd04899e
|
Provenance
The following attestation bundles were made for sphinx_autocodelink-0.5.2-py3-none-any.whl:
Publisher:
ci.yml on user27182/sphinx-autocodelink
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
sphinx_autocodelink-0.5.2-py3-none-any.whl -
Subject digest:
695e82efdf4cb8e425a47e2f80211c9f2f9c5046d97f6ca80fca201aeb26e000 - Sigstore transparency entry: 2509389332
- Sigstore integration time:
-
Permalink:
user27182/sphinx-autocodelink@53a9ef0fa8d3ebb3a9eff907e7e03d1316821ab0 -
Branch / Tag:
refs/tags/v0.5.2 - Owner: https://github.com/user27182
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
ci.yml@53a9ef0fa8d3ebb3a9eff907e7e03d1316821ab0 -
Trigger Event:
push
-
Statement type: