Rebuild Sphinx documentation on changes, with hot reloading in the browser.
The build management system controls the Sphinx documentation build process with support for pre/post-build commands, error handling, and integration with the file watching system.
The main class responsible for executing Sphinx builds when files change.
class Builder:
def __init__(
self,
sphinx_args,
*,
url_host,
pre_build_commands,
post_build_commands
):
"""
Initialize builder with Sphinx arguments and command hooks.
Parameters:
- sphinx_args: list[str] - Arguments to pass to sphinx-build
- url_host: str - Host:port string for server URL display
- pre_build_commands: list[list[str]] - Commands to run before build
- post_build_commands: list[list[str]] - Commands to run after successful build
"""
def __call__(self, *, changed_paths):
"""
Execute build process when files change.
Parameters:
- changed_paths: Sequence[Path] - Paths of files that changed (triggers rebuild)
Returns:
- None
Side Effects:
- Runs pre-build commands
- Executes sphinx-build with configured arguments
- Runs post-build commands (only if build succeeds)
- Prints status messages and server URL
- Handles build errors gracefully
"""The build process follows a specific sequence:
Usage Example:
from sphinx_autobuild.build import Builder
from pathlib import Path
# Initialize builder
builder = Builder(
sphinx_args=['-b', 'html', 'docs', '_build/html'],
url_host='127.0.0.1:8000',
pre_build_commands=[['echo', 'Starting build']],
post_build_commands=[['echo', 'Build complete']]
)
# Trigger build
changed_files = [Path('docs/index.rst'), Path('docs/api.rst')]
builder(changed_paths=changed_files)Handles pre-build and post-build command execution with error management.
def _run_commands(self, commands, log_context):
"""
Execute a list of commands in sequence.
Parameters:
- commands: list[list[str]] - List of commands to execute
- log_context: str - Context string for logging ('pre-build' or 'post-build')
Returns:
- int - Return code (0 for success, non-zero for failure)
Error Handling:
- Prints error message and traceback on command failure
- Returns early on first command failure
- Server continues running even after command failures
"""Integrates with different versions of Sphinx, handling version-specific argument formats.
Sphinx Version Compatibility:
python -m sphinx build command formatpython -m sphinx command formatBuild Arguments: The builder accepts all standard sphinx-build arguments:
# Common Sphinx arguments
sphinx_args = [
'-b', 'html', # Builder type
'-E', # Don't use saved environment
'-a', # Write all files
'-v', # Verbose output
'-W', # Turn warnings into errors
'-d', '_build/doctrees', # Doctree directory
'docs', # Source directory
'_build/html' # Output directory
]from sphinx_autobuild.build import Builder
# Simple builder with no extra commands
builder = Builder(
sphinx_args=['docs', '_build/html'],
url_host='localhost:8000',
pre_build_commands=[],
post_build_commands=[]
)
# Trigger rebuild
builder(changed_paths=[])from sphinx_autobuild.build import Builder
import shlex
# Complex builder with multiple commands
pre_build = [
['python', 'scripts/generate_api.py'],
['python', '-c', 'print("API docs generated")']
]
post_build = [
['python', 'scripts/validate_links.py'],
shlex.split('find _build -name "*.html" -exec echo "Generated: {}" \\;')
]
builder = Builder(
sphinx_args=['-b', 'html', '-E', '-v', 'docs', '_build/html'],
url_host='192.168.1.100:8080',
pre_build_commands=pre_build,
post_build_commands=post_build
)from sphinx_autobuild.build import Builder
from sphinx_autobuild.server import RebuildServer
from sphinx_autobuild.filter import IgnoreFilter
from pathlib import Path
# Create builder
builder = Builder(
sphinx_args=['docs', '_build/html'],
url_host='127.0.0.1:8000',
pre_build_commands=[],
post_build_commands=[]
)
# Create file watcher that uses builder as callback
watch_dirs = [Path('docs')]
ignore_filter = IgnoreFilter([], [])
server = RebuildServer(watch_dirs, ignore_filter, builder)When Sphinx build fails:
Pre/post-build command failures:
# Command not found
pre_build_commands = [['nonexistent-command', 'arg']]
# Output: "Pre-build command exited with exit code: 127"
# Sphinx syntax error
# Output: "Sphinx exited with exit code: 2"
# Server continues serving stale content
# Permission denied
post_build_commands = [['chmod', '000', '/protected/file']]
# Output: "Post-build command exited with exit code: 1"Install with Tessl CLI
npx tessl i tessl/pypi-sphinx-autobuild