diff options
Diffstat (limited to 'sphinx/ext/autosummary/generate.py')
-rw-r--r-- | sphinx/ext/autosummary/generate.py | 172 |
1 files changed, 96 insertions, 76 deletions
diff --git a/sphinx/ext/autosummary/generate.py b/sphinx/ext/autosummary/generate.py index ce9e4c2d8..178a2870a 100644 --- a/sphinx/ext/autosummary/generate.py +++ b/sphinx/ext/autosummary/generate.py @@ -1,85 +1,91 @@ +# -*- coding: utf-8 -*- """ -autosummary_generate.py OPTIONS FILES + sphinx.ext.autosummary.generate + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Generate automatic RST source files for items referred to in -autosummary:: directives. + Usable as a library or script to generate automatic RST source files for + items referred to in autosummary:: directives. -Each generated RST file contains a single auto*:: directive which -extracts the docstring of the referred item. + Each generated RST file contains a single auto*:: directive which + extracts the docstring of the referred item. -Example Makefile rule:: + Example Makefile rule:: - generate: - sphinx-autogen source/*.rst source/generated + generate: + sphinx-autogen source/*.rst source/generated + :copyright: Copyright 2007-2009 by the Sphinx team, see AUTHORS. + :license: BSD, see LICENSE for details. """ -import glob, re, inspect, os, optparse +import os +import re +import sys +import glob +import inspect + +from jinja2 import Environment, PackageLoader + from sphinx.ext.autosummary import import_by_name +from sphinx.util import ensuredir -from jinja import Environment, PackageLoader -env = Environment(loader=PackageLoader('sphinx.ext.autosummary', 'templates')) +# create our own templating environment, for module template only +env = Environment(loader=PackageLoader('sphinx.ext.autosummary', 'templates')) -def main(): - p = optparse.OptionParser(__doc__.strip()) - options, args = p.parse_args() - - if len(args) <2: - p.error("wrong number of arguments") - print 'generating docs from:', args[:-1] - generate_autosummary_docs(args[:-1], args[-1]) - -def generate_autosummary_docs(source_dir, output_dir): +def generate_autosummary_docs(sources, output_dir=None): # read names = {} - for name, loc in get_documented(source_dir).items(): + for name, loc in get_documented(sources).items(): for (filename, sec_title, keyword, toctree) in loc: if toctree is not None: path = os.path.join(os.path.dirname(filename), toctree) names[name] = os.path.abspath(path) - + # write for name, path in sorted(names.items()): - path = output_dir - - if not os.path.isdir(path): - os.makedirs(path) + if output_dir is not None: + path = output_dir + + ensuredir(path) try: obj, name = import_by_name(name) except ImportError, e: - print "Failed to import '%s': %s" % (name, e) + print >>sys.stderr, 'Failed to import %r: %s' % (name, e) continue fn = os.path.join(path, '%s.rst' % name) - - if os.path.exists(fn): - # skip + # skip it if it exists + if os.path.isfile(fn): continue f = open(fn, 'w') - try: - if inspect.ismodule(obj): - tmpl = env.get_template('module.html') - functions = [getattr(obj, item).__name__ for item in dir(obj) if inspect.isfunction(getattr(obj, item))] - classes = [getattr(obj, item).__name__ for item in dir(obj) if inspect.isclass(getattr(obj, item)) and not issubclass(getattr(obj, item), Exception)] - exceptions = [getattr(obj, item).__name__ for item in dir(obj) if inspect.isclass(getattr(obj, item)) and issubclass(getattr(obj, item), Exception)] - rendered = tmpl.render(name=name, - functions=functions, - classes=classes, - exceptions=exceptions, + tmpl = env.get_template('module') + functions = [getattr(obj, item).__name__ + for item in dir(obj) + if inspect.isfunction(getattr(obj, item))] + classes = [getattr(obj, item).__name__ + for item in dir(obj) + if inspect.isclass(getattr(obj, item)) + and not issubclass(getattr(obj, item), Exception)] + exceptions = [getattr(obj, item).__name__ + for item in dir(obj) + if inspect.isclass(getattr(obj, item)) + and issubclass(getattr(obj, item), Exception)] + rendered = tmpl.render(name=name, + functions=functions, + classes=classes, + exceptions=exceptions, len_functions=len(functions), len_classes=len(classes), - len_exceptions=len(exceptions) - - ) + len_exceptions=len(exceptions)) f.write(rendered) else: f.write('%s\n%s\n\n' % (name, '='*len(name))) - + if inspect.isclass(obj): if issubclass(obj, Exception): f.write(format_modulemember(name, 'autoexception')) @@ -96,40 +102,40 @@ def generate_autosummary_docs(source_dir, output_dir): finally: f.close() + def format_modulemember(name, directive): parts = name.split('.') mod, name = '.'.join(parts[:-1]), parts[-1] - return ".. currentmodule:: %s\n\n.. %s:: %s\n" % (mod, directive, name) + return '.. currentmodule:: %s\n\n.. %s:: %s\n' % (mod, directive, name) + def format_classmember(name, directive): parts = name.split('.') mod, name = '.'.join(parts[:-2]), '.'.join(parts[-2:]) - return ".. currentmodule:: %s\n\n.. %s:: %s\n" % (mod, directive, name) + return '.. currentmodule:: %s\n\n.. %s:: %s\n' % (mod, directive, name) + + +title_underline_re = re.compile('^[-=*_^#]{3,}\s*$') +autodoc_re = re.compile(r'.. auto(function|method|attribute|class|exception' + '|module)::\s*([A-Za-z0-9_.]+)\s*$') +autosummary_re = re.compile(r'^\.\.\s+autosummary::\s*') +module_re = re.compile(r'^\.\.\s+(current)?module::\s*([a-zA-Z0-9_.]+)\s*$') +autosummary_item_re = re.compile(r'^\s+([_a-zA-Z][a-zA-Z0-9_.]*)\s*') +toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$') def get_documented(filenames): """ - Find out what items are documented in source/*.rst - - Returns - ------- - documented : dict of list of (filename, title, keyword, toctree) - Dictionary whose keys are documented names of objects. - The value is a list of locations where the object was documented. - Each location is a tuple of filename, the current section title, - the name of the directive, and the value of the :toctree: argument - (if present) of the directive. + Find out what items are documented in the given filenames. + Returns a dict of list of (filename, title, keyword, toctree) Keys are + documented names of objects. The value is a list of locations where the + object was documented. Each location is a tuple of filename, the current + section title, the name of the directive, and the value of the :toctree: + argument (if present) of the directive. """ - - title_underline_re = re.compile("^[-=*_^#]{3,}\s*$") - autodoc_re = re.compile(".. auto(function|method|attribute|class|exception|module)::\s*([A-Za-z0-9_.]+)\s*$") - autosummary_re = re.compile(r'^\.\.\s+autosummary::\s*') - module_re = re.compile(r'^\.\.\s+(current)?module::\s*([a-zA-Z0-9_.]+)\s*$') - autosummary_item_re = re.compile(r'^\s+([_a-zA-Z][a-zA-Z0-9_.]*)\s*') - toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$') - + documented = {} - + for filename in filenames: current_title = [] last_line = None @@ -150,32 +156,34 @@ def get_documented(filenames): continue # skip options m = autosummary_item_re.match(line) - + if m: name = m.group(1).strip() - if current_module and not name.startswith(current_module + '.'): - name = "%s.%s" % (current_module, name) + if current_module and \ + not name.startswith(current_module + '.'): + name = '%s.%s' % (current_module, name) documented.setdefault(name, []).append( (filename, current_title, 'autosummary', toctree)) continue if line.strip() == '': continue in_autosummary = False - + m = autosummary_re.match(line) if m: in_autosummary = True continue - + m = autodoc_re.search(line) if m: name = m.group(2).strip() - if current_module and not name.startswith(current_module + '.'): - name = "%s.%s" % (current_module, name) - if m.group(1) == "module": + if current_module and \ + not name.startswith(current_module + '.'): + name = '%s.%s' % (current_module, name) + if m.group(1) == 'module': current_module = name documented.setdefault(name, []).append( - (filename, current_title, "auto" + m.group(1), None)) + (filename, current_title, 'auto' + m.group(1), None)) continue m = title_underline_re.match(line) @@ -191,5 +199,17 @@ def get_documented(filenames): last_line = line return documented -if __name__ == "__main__": + +def main(args=None): + if args is None: + args = sys.argv[1:] + + if len(args) < 2: + print >>sys.stderr, 'usage: %s sourcefile ... outputdir' % sys.argv[0] + + print 'generating docs from:', ', '.join(args[:-1]) + generate_autosummary_docs(args[:-1], args[-1]) + + +if __name__ == '__main__': main() |