Implementation:Ray project Ray Sphinx Callouts Extension
| Knowledge Sources | Ray |
|---|---|
| Domains | Documentation, Sphinx_Extensions |
| Last Updated | 2026-02-13 |
Overview
Sphinx Callouts Extension is a custom Sphinx extension that adds callout and annotations directives for rendering numbered circle markers in code blocks and their corresponding explanations in Ray documentation.
Description
This extension (callouts.py) implements two Sphinx directives (CalloutDirective and AnnotationsDirective) and a post-transform (CalloutIncludePostTransform) that together enable a code annotation pattern commonly found in technical books. The callout directive wraps a code-block or literalinclude directive, where inline comments of the form <1>, <2>, etc. are replaced with Unicode circled number characters (using the white circle/black numbers Unicode range starting at U+2460). The annotations directive provides the corresponding explanatory text for each numbered marker. The CalloutIncludePostTransform handles post-processing of literalinclude blocks by walking the document tree with a LiteralIncludeVisitor to perform the same marker-to-Unicode replacement on raw source content.
Usage
Use this extension when authoring Ray documentation pages that need annotated code examples. Add the callout directive around code blocks and use the annotations directive to explain each numbered marker. The extension is loaded automatically by conf.py through the extensions list entry callouts. Modify this file when changing the annotation style, supporting additional marker ranges, or fixing rendering issues.
Code Reference
Source Location
doc/source/_ext/callouts.py
Signature
BASE_NUM = 2459 # white circle, black numbers (Unicode range)
class CalloutIncludePostTransform(SphinxTransform):
"""Code block post-processor for literalinclude blocks used in callouts."""
default_priority = 400
def apply(self, **kwargs) -> None: ...
class LiteralIncludeVisitor(nodes.NodeVisitor):
"""Change a literal block upon visiting it."""
def visit_literal_block(self, node: nodes.literal_block) -> None: ...
class callout(nodes.General, nodes.Element):
"""Sphinx callout node."""
pass
class annotations(nodes.Element):
"""Sphinx annotations node."""
pass
class CalloutDirective(SphinxDirective):
"""Code callout directive with annotations for Sphinx."""
has_content = True
def run(self): ...
class AnnotationsDirective(SphinxDirective):
"""Annotations directive, used nested within a Callout directive."""
has_content = True
def run(self): ...
def setup(app):
"""Register nodes, directives, and post-transform with Sphinx."""
...
Import
# Loaded automatically via Sphinx extensions list in conf.py:
extensions = [
"callouts", # custom extension from _ext folder
...
]
# The extension's internal imports:
from docutils import nodes
from sphinx.util.docutils import SphinxDirective
from sphinx.transforms import SphinxTransform
I/O Contract
Inputs
| Input | Type | Description |
|---|---|---|
| RST content with callout directive | reStructuredText | A .. callout:: block wrapping a code-block or literalinclude |
| RST content with annotations directive | reStructuredText | A .. annotations:: block containing <N> marker explanations |
| Marker placeholders | string pattern | Inline comments of the form <1>, <2>, ..., <19> in code blocks |
| Sphinx app | sphinx.application.Sphinx | Application instance for registering nodes and directives |
Outputs
| Output | Type | Description |
|---|---|---|
| callout node | docutils node | Parsed callout container node in the Sphinx document tree |
| annotations node | docutils node | Parsed annotations container node in the Sphinx document tree |
| Rendered HTML | HTML | Code blocks with circled Unicode numbers and annotation text |
| Extension metadata | dict | Version "0.1", parallel_read_safe=True, parallel_write_safe=True |
Usage Examples
Using the callout and annotations directives in reStructuredText:
.. callout::
.. code-block:: python
from ray import tune
from ray.tune.search.hyperopt import HyperOptSearch
import keras
def objective(config): # <1>
...
search_space = {"activation": tune.choice(["relu", "tanh"])} # <2>
algo = HyperOptSearch()
tuner = tune.Tuner( # <3>
...
)
results = tuner.fit()
.. annotations::
<1> Wrap a Keras model in an objective function.
<2> Define a search space and initialize the search algorithm.
<3> Start a Tune run that maximizes accuracy.
The setup function registers the extension with Sphinx:
def setup(app):
app.add_node(
callout,
html=(visit_callout_node, depart_callout_node),
latex=(visit_callout_node, depart_callout_node),
text=(visit_callout_node, depart_callout_node),
)
app.add_node(annotations)
app.add_directive("callout", CalloutDirective)
app.add_directive("annotations", AnnotationsDirective)
app.add_post_transform(CalloutIncludePostTransform)
return {
"version": "0.1",
"parallel_read_safe": True,
"parallel_write_safe": True,
}
Related Pages
- Ray_project_Ray_Sphinx_Configuration - Main Sphinx conf.py that loads this extension
- Ray_project_Ray_Custom_Sphinx_Directives - Complementary custom directives for Ray documentation
- Ray - Ray project repository