1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
|
"""
Extension for building Qt-like documentation.
- Method lists preceding the actual method documentation
- Inherited members documented separately
- Members inherited from Qt have links to qt-project documentation
- Signal documentation
"""
def setup(app):
# probably we will be making a wrapper around autodoc
app.setup_extension('sphinx.ext.autodoc')
# would it be useful to define a new domain?
#app.add_domain(QtDomain)
## Add new configuration options
app.add_config_value('todo_include_todos', False, False)
## Nodes are the basic objects representing documentation directives
## and roles
app.add_node(Todolist)
app.add_node(Todo,
html=(visit_todo_node, depart_todo_node),
latex=(visit_todo_node, depart_todo_node),
text=(visit_todo_node, depart_todo_node))
## New directives like ".. todo:"
app.add_directive('todo', TodoDirective)
app.add_directive('todolist', TodolistDirective)
## Connect callbacks to specific hooks in the build process
app.connect('doctree-resolved', process_todo_nodes)
app.connect('env-purge-doc', purge_todos)
from docutils import nodes
from sphinx.util.compat import Directive
from sphinx.util.compat import make_admonition
# Just a general node
class Todolist(nodes.General, nodes.Element):
pass
# .. and its directive
class TodolistDirective(Directive):
# all directives have 'run' method that returns a list of nodes
def run(self):
return [Todolist('')]
# Admonition classes are like notes or warnings
class Todo(nodes.Admonition, nodes.Element):
pass
def visit_todo_node(self, node):
self.visit_admonition(node)
def depart_todo_node(self, node):
self.depart_admonition(node)
class TodoDirective(Directive):
# this enables content in the directive
has_content = True
def run(self):
env = self.state.document.settings.env
# create a new target node for linking to
targetid = "todo-%d" % env.new_serialno('todo')
targetnode = nodes.target('', '', ids=[targetid])
# make the admonition node
ad = make_admonition(Todo, self.name, [('Todo')], self.options,
self.content, self.lineno, self.content_offset,
self.block_text, self.state, self.state_machine)
# store a handle in a global list of all todos
if not hasattr(env, 'todo_all_todos'):
env.todo_all_todos = []
env.todo_all_todos.append({
'docname': env.docname,
'lineno': self.lineno,
'todo': ad[0].deepcopy(),
'target': targetnode,
})
# return both the linking target and the node itself
return [targetnode] + ad
# env data is persistent across source files so we purge whenever the source file has changed.
def purge_todos(app, env, docname):
if not hasattr(env, 'todo_all_todos'):
return
env.todo_all_todos = [todo for todo in env.todo_all_todos
if todo['docname'] != docname]
# called at the end of resolving phase; we will convert temporary nodes
# into finalized nodes
def process_todo_nodes(app, doctree, fromdocname):
if not app.config.todo_include_todos:
for node in doctree.traverse(Todo):
node.parent.remove(node)
# Replace all todolist nodes with a list of the collected todos.
# Augment each todo with a backlink to the original location.
env = app.builder.env
for node in doctree.traverse(Todolist):
if not app.config.todo_include_todos:
node.replace_self([])
continue
content = []
for todo_info in env.todo_all_todos:
para = nodes.paragraph()
filename = env.doc2path(todo_info['docname'], base=None)
description = (
('(The original entry is located in %s, line %d and can be found ') %
(filename, todo_info['lineno']))
para += nodes.Text(description, description)
# Create a reference
newnode = nodes.reference('', '')
innernode = nodes.emphasis(('here'), ('here'))
newnode['refdocname'] = todo_info['docname']
newnode['refuri'] = app.builder.get_relative_uri(
fromdocname, todo_info['docname'])
newnode['refuri'] += '#' + todo_info['target']['refid']
newnode.append(innernode)
para += newnode
para += nodes.Text('.)', '.)')
# Insert into the todolist
content.append(todo_info['todo'])
content.append(para)
node.replace_self(content)
|