Skip to content

Commit 8159215

Browse files
chg: dev: As a directive we cannot add new generated files so the development approach changed.
Now all modules to build documentation for will be listed in the conf.py.
1 parent eee8ff2 commit 8159215

File tree

5 files changed

+85
-88
lines changed

5 files changed

+85
-88
lines changed

.gitignore

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@ build/*
99

1010
# Sphinx
1111
doc/_build/*
12-
doc/fixme/*
12+
13+
# Sphinx autoapi
14+
doc/autoapi/*
1315

1416
# Tox
1517
.tox/*

doc/conf.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -311,6 +311,9 @@
311311
# If true, do not generate a @detailmenu in the "Top" node's menu.
312312
# texinfo_no_detailmenu = False
313313

314+
# autoapi configuration
315+
autoapi_modules = {'autoapi': None}
316+
314317
# Configure PlantUML
315318
plantuml = 'java -jar ' + join(dirname(abspath(__name__)), 'plantuml.8030.jar')
316319
plantuml_output_format = 'svg'

doc/index.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
:hidden:
33

44
developer
5-
reference
5+
autoapi/autoapi
66

77
=======
88
autoapi
@@ -12,14 +12,15 @@ autoapi
1212

1313
.. image:: _static/images/logo.png
1414

15-
Automatic API reference documentation generation for Sphinx inspired by Doxygen
15+
Automatic API reference documentation generation for Sphinx inspired by
16+
Doxygen.
1617

1718

1819
Documentation
1920
=============
2021

2122
- :doc:`Developer Guide. <developer>`
22-
- :doc:`Internal Documentation Reference. <reference>`
23+
- :doc:`Internal Documentation Reference. <autoapi/autoapi>`
2324

2425

2526
Development

doc/reference.rst

Lines changed: 0 additions & 1 deletion
This file was deleted.

lib/autoapi/directive.py

Lines changed: 75 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -22,113 +22,105 @@
2222
from __future__ import unicode_literals, absolute_import
2323
from __future__ import print_function, division
2424

25-
from os.path import join, dirname, abspath
26-
from traceback import print_exc
25+
from os.path import join, dirname, abspath, exists
2726

2827
from jinja2.sandbox import SandboxedEnvironment
29-
30-
from docutils.parsers.rst import Directive
31-
from docutils.statemachine import ViewList
3228
from sphinx.util.osutil import ensuredir
3329
from sphinx.jinja2glue import BuiltinTemplateLoader
3430

3531
from . import __version__
3632
from .apinode import APINode
3733

3834

39-
class AutoAPI(Directive):
35+
def get_template_env(app):
4036
"""
41-
Autoapi directive.
37+
Get the template environment.
4238
43-
This directive will perform the following steps:
39+
.. note::
4440
45-
- Build a :class:`autoapi.apinode.APINode` tree with the module name
46-
specified as argument.
47-
- Render the Jinja2 template with the root node and append the result as
48-
content for this directive.
49-
- Traverse the tree and for each node, except for leaf nodes without public
50-
API, render the Jinja2 template and write the result as a new source
51-
file.
41+
Template should be loaded as a package_data using
42+
:py:function:`pkgutil.get_data`, but because we want the user to
43+
override the default template we need to hook it to the Sphinx loader,
44+
and thus a file system approach is required as it is implemented like
45+
that.
5246
"""
53-
required_arguments = 1
54-
optional_arguments = 0
55-
final_argument_whitespace = False
56-
has_content = True
57-
option_spec = {}
58-
59-
def autoapi_build(self, tree):
60-
"""
61-
"""
62-
env = self.state.document.settings.env
63-
64-
# DEBUG
65-
print('=' * 79)
66-
print(env.config.source_suffix)
67-
print(env.srcdir)
68-
print(env.doctreedir)
69-
print(env.found_docs)
70-
print('=' * 79)
47+
template_dir = [join(dirname(abspath(__file__)), 'template')]
48+
template_loader = BuiltinTemplateLoader()
49+
template_loader.init(app.builder, dirs=template_dir)
50+
template_env = SandboxedEnvironment(loader=template_loader)
51+
return template_env
7152

72-
# Get template
73-
# Note: Template should be loaded as a package_data using
74-
# pkgutil.get_data(), but because we want the user to override the
75-
# default template we need to hook it to the Sphinx loader, and thus
76-
# a file system approach is required as it is implemented like that.
77-
template_dir = [join(dirname(abspath(__file__)), 'template')]
78-
template_loader = BuiltinTemplateLoader()
79-
template_loader.init(env.app.builder, dirs=template_dir)
80-
template_env = SandboxedEnvironment(loader=template_loader)
81-
template = template_env.get_template('module.rst')
82-
83-
# Render root and append it to current node content
84-
autodoc = template.render(node=tree)
85-
self.content.extend(
86-
ViewList(initlist=autodoc.splitlines(), source=tree.name)
87-
)
88-
89-
# Render all remaining nodes as separated documents
90-
gen_dir = join(env.srcdir, 'fixme')
91-
ensuredir(gen_dir)
92-
93-
for name, node in tree.directory.items():
94-
95-
# Ignore leaf nodes with public API
96-
# Non-leaf nodes without public API are required to be rendered
97-
# in order to have an index of their subnodes.
98-
if node.is_leaf and not node.has_public_api():
99-
continue
10053

101-
out_file = join(gen_dir, name + env.config.source_suffix[0])
102-
with open(out_file, 'w') as fd:
103-
fd.write(template.render(node=node))
54+
def builder_inited(app):
55+
"""
56+
autoapi Sphinx extension hook for the ``builder-inited`` event.
10457
105-
def run(self):
106-
# Get name of the module that is directive argument
107-
module = self.arguments[0]
58+
This hook will read the configuration value ``autoapi_modules`` and render
59+
the modules described in it.
60+
"""
61+
# Get modules to build documentation for
62+
modules = app.config.autoapi_modules
63+
if not modules:
64+
return
10865

109-
try:
110-
# Build module tree
111-
tree = APINode(module)
66+
# Get template environment
67+
template_env = get_template_env(app)
11268

113-
# Generate content
114-
self.autoapi_build(tree)
69+
for module, options in modules.items():
11570

116-
except Exception as e:
117-
# Create a warning if the process failed
118-
print_exc()
119-
msg = 'Unable to build autoapi for {}: {}'.format(module, str(e))
120-
return [
121-
self.state.document.reporter.warning(msg, line=self.lineno)
122-
]
71+
# Get options
72+
defaults = {
73+
'override': True,
74+
'template': 'module.rst',
75+
'output': module
76+
}
77+
if options:
78+
defaults.update(options)
12379

124-
return []
80+
# Get template
81+
template = template_env.get_template(defaults['template'])
82+
83+
# Build API tree
84+
tree = APINode(module)
85+
86+
# Gather nodes to document
87+
# Ignore leaf nodes without public API
88+
# Non-leaf nodes without public API are required to be rendered
89+
# in order to have an index of their subnodes.
90+
nodes = [
91+
(name, node) for name, node in tree.directory.items()
92+
if node.has_public_api() or not node.is_leaf()
93+
]
94+
if not nodes:
95+
continue
96+
97+
# Define output directory
98+
out_dir = join(app.env.srcdir, defaults['output'])
99+
ensuredir(out_dir)
100+
101+
# Iterate nodes and render them
102+
for name, node in nodes:
103+
out_file = join(out_dir, name + app.config.source_suffix[0])
104+
105+
# Skip file if it override is off and it exists
106+
if not defaults['override'] and exists(out_file):
107+
continue
108+
109+
with open(out_file, 'w') as fd:
110+
fd.write(template.render(node=node))
125111

126112

127113
def setup(app):
114+
"""
115+
autoapi Sphinx extension setup.
116+
117+
See http://sphinx-doc.org/extdev/tutorial.html#the-setup-function
118+
"""
128119
# autodoc is required
129120
app.setup_extension('sphinx.ext.autodoc')
130-
app.add_directive('autoapi', AutoAPI)
131-
return {'version': __version__, 'parallel_read_safe': True}
121+
app.add_config_value('autoapi_modules', {}, True)
122+
app.connect(b'builder-inited', builder_inited)
123+
return {'version': __version__}
132124

133125

134-
__all__ = ['AutoAPI']
126+
__all__ = ['builder_inited', 'setup']

0 commit comments

Comments
 (0)