Technical Documentation with Sphinx, Paver, and Cog
Posted on Thu 14 July 2016 in Documentation
Doug Hellmann presents a robust workflow for technical documentation that eliminates repetitive manual work and errors in code examples.
The Problem to Solve¶
"Automation is important for my sense of well being. I hate dealing with mundane repetitive tasks."
Common Challenges: - Keeping code examples updated - Multiple output formats (HTML, PDF, blog) - Repetitive tasks of building and publishing - Copy-paste errors in program output
The Solution: Trio of Tools¶
Sphinx: Documentation Engine¶
- reStructuredText conversion to multiple formats
- Customizable themes with Jinja templates
- Automatic generation of indices and cross-references
Paver: Build Automation¶
# pavement.py
@task
def html():
"""Build HTML documentation"""
call_task('cog')
sphinx_build('html')
@task
def pdf():
"""Build PDF documentation"""
call_task('cog')
sphinx_build('latex')
make_pdf()
Solves: Automation of repetitive build processes
Cog: Automatic Code Insertion¶
.. cog::
import cog
import subprocess
result = subprocess.run(['python', 'example.py'],
capture_output=True, text=True)
cog.out(result.stdout)
.. cog::
Key Advantage: Program output is automatically updated when regenerating documentation.
Production Workflow¶
1. Writing in reStructuredText¶
Usage Example
=============
We run the script:
.. cog::
cog.out("$ python my_script.py\n")
result = subprocess.run(['python', 'my_script.py'],
capture_output=True, text=True)
cog.out(result.stdout)
.. cog::
2. Automated Build¶
# A single command for everything
paver html
# Or for multiple destinations
paver all_formats
3. Multi-Destination Publishing¶
- Python Module of the Week (PyMOTW)
- Personal Blog
- Project Website
- O'Reilly Blog
- PDF Documentation
Advantages of the Approach¶
Guaranteed Consistency¶
- Examples always updated with real code
- Uniform format across multiple destinations
- No manual transcription errors
Maximized Efficiency¶
- One source, multiple outputs
- Complete automation of the pipeline
- Focus on content, not process
Maintainability¶
- Changes in a single source propagate automatically
- Integrated testing of code examples
- Unique versioning for all documentation
Practical Implementation¶
# full pavement.py
from paver.easy import *
import paver.doctools
@task
def cog():
"""Run Cog to update code examples"""
sh('cog -r *.rst')
@task
@needs('cog')
def html():
"""Build HTML docs"""
paver.doctools.html()
@task
@needs('cog')
def blog_post():
"""Generate blog post version"""
# Custom blog formatting
pass
This workflow represents intelligent automation of technical documentation: write once, publish everywhere, always updated.
Original source: Doug Hellmann