mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
initial code brought over from numpy. Now we need to do some simplification of the numpy code.
This commit is contained in:
parent
324145853e
commit
b2141637e5
3
setup.py
3
setup.py
@ -177,7 +177,8 @@ setup(
|
|||||||
entry_points={
|
entry_points={
|
||||||
'console_scripts': [
|
'console_scripts': [
|
||||||
'sphinx-build = sphinx:main',
|
'sphinx-build = sphinx:main',
|
||||||
'sphinx-quickstart = sphinx.quickstart:main'
|
'sphinx-quickstart = sphinx.quickstart:main',
|
||||||
|
'sphinx-autogen = sphinx.scripts.autosummary_generate:main',
|
||||||
],
|
],
|
||||||
'distutils.commands': [
|
'distutils.commands': [
|
||||||
'build_sphinx = sphinx.setup_command:BuildDoc',
|
'build_sphinx = sphinx.setup_command:BuildDoc',
|
||||||
|
328
sphinx/ext/autosummary/__init__.py
Normal file
328
sphinx/ext/autosummary/__init__.py
Normal file
@ -0,0 +1,328 @@
|
|||||||
|
"""
|
||||||
|
===========
|
||||||
|
autosummary
|
||||||
|
===========
|
||||||
|
|
||||||
|
Sphinx extension that adds an autosummary:: directive, which can be
|
||||||
|
used to generate function/method/attribute/etc. summary lists, similar
|
||||||
|
to those output eg. by Epydoc and other API doc generation tools.
|
||||||
|
|
||||||
|
An :autolink: role is also provided.
|
||||||
|
|
||||||
|
autosummary directive
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
The autosummary directive has the form::
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
:nosignatures:
|
||||||
|
:toctree: generated/
|
||||||
|
|
||||||
|
module.function_1
|
||||||
|
module.function_2
|
||||||
|
...
|
||||||
|
|
||||||
|
and it generates an output table (containing signatures, optionally)
|
||||||
|
|
||||||
|
======================== =============================================
|
||||||
|
module.function_1(args) Summary line from the docstring of function_1
|
||||||
|
module.function_2(args) Summary line from the docstring
|
||||||
|
...
|
||||||
|
======================== =============================================
|
||||||
|
|
||||||
|
If the :toctree: option is specified, files matching the function names
|
||||||
|
are inserted to the toctree with the given prefix:
|
||||||
|
|
||||||
|
generated/module.function_1
|
||||||
|
generated/module.function_2
|
||||||
|
...
|
||||||
|
|
||||||
|
Note: The file names contain the module:: or currentmodule:: prefixes.
|
||||||
|
|
||||||
|
.. seealso:: autosummary_generate.py
|
||||||
|
|
||||||
|
|
||||||
|
autolink role
|
||||||
|
-------------
|
||||||
|
|
||||||
|
The autolink role functions as ``:obj:`` when the name referred can be
|
||||||
|
resolved to a Python object, and otherwise it becomes simple emphasis.
|
||||||
|
This can be used as the default role to make links 'smart'.
|
||||||
|
|
||||||
|
"""
|
||||||
|
import sys, os, posixpath, re
|
||||||
|
|
||||||
|
from docutils.parsers.rst import directives
|
||||||
|
from docutils.statemachine import ViewList
|
||||||
|
from docutils import nodes
|
||||||
|
|
||||||
|
import sphinx.addnodes, sphinx.roles, sphinx.builder
|
||||||
|
from sphinx.util import patfilter
|
||||||
|
|
||||||
|
from docscrape_sphinx import get_doc_object
|
||||||
|
import inspect
|
||||||
|
|
||||||
|
def setup(app):
|
||||||
|
app.add_directive('autosummary', autosummary_directive, True, (0, 0, False),
|
||||||
|
toctree=directives.unchanged,
|
||||||
|
nosignatures=directives.flag)
|
||||||
|
app.add_role('autolink', autolink_role)
|
||||||
|
|
||||||
|
app.add_node(autosummary_toc,
|
||||||
|
html=(autosummary_toc_visit_html, autosummary_toc_depart_noop),
|
||||||
|
latex=(autosummary_toc_visit_latex, autosummary_toc_depart_noop))
|
||||||
|
app.connect('doctree-read', process_autosummary_toc)
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# autosummary_toc node
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class autosummary_toc(nodes.comment):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def process_autosummary_toc(app, doctree):
|
||||||
|
"""
|
||||||
|
Insert items described in autosummary:: to the TOC tree, but do
|
||||||
|
not generate the toctree:: list.
|
||||||
|
|
||||||
|
"""
|
||||||
|
env = app.builder.env
|
||||||
|
crawled = {}
|
||||||
|
def crawl_toc(node, depth=1):
|
||||||
|
crawled[node] = True
|
||||||
|
for j, subnode in enumerate(node):
|
||||||
|
try:
|
||||||
|
if (isinstance(subnode, autosummary_toc)
|
||||||
|
and isinstance(subnode[0], sphinx.addnodes.toctree)):
|
||||||
|
env.note_toctree(env.docname, subnode[0])
|
||||||
|
continue
|
||||||
|
except IndexError:
|
||||||
|
continue
|
||||||
|
if not isinstance(subnode, nodes.section):
|
||||||
|
continue
|
||||||
|
if subnode not in crawled:
|
||||||
|
crawl_toc(subnode, depth+1)
|
||||||
|
crawl_toc(doctree)
|
||||||
|
|
||||||
|
def autosummary_toc_visit_html(self, node):
|
||||||
|
"""Hide autosummary toctree list in HTML output"""
|
||||||
|
raise nodes.SkipNode
|
||||||
|
|
||||||
|
def autosummary_toc_visit_latex(self, node):
|
||||||
|
"""Show autosummary toctree (= put the referenced pages here) in Latex"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def autosummary_toc_depart_noop(self, node):
|
||||||
|
pass
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# .. autosummary::
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def autosummary_directive(dirname, arguments, options, content, lineno,
|
||||||
|
content_offset, block_text, state, state_machine):
|
||||||
|
"""
|
||||||
|
Pretty table containing short signatures and summaries of functions etc.
|
||||||
|
|
||||||
|
autosummary also generates a (hidden) toctree:: node.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
names = []
|
||||||
|
names += [x.strip() for x in content if x.strip()]
|
||||||
|
|
||||||
|
table, warnings, real_names = get_autosummary(names, state,
|
||||||
|
'nosignatures' in options)
|
||||||
|
node = table
|
||||||
|
|
||||||
|
env = state.document.settings.env
|
||||||
|
suffix = env.config.source_suffix
|
||||||
|
all_docnames = env.found_docs.copy()
|
||||||
|
dirname = posixpath.dirname(env.docname)
|
||||||
|
|
||||||
|
if 'toctree' in options:
|
||||||
|
tree_prefix = options['toctree'].strip()
|
||||||
|
docnames = []
|
||||||
|
for name in names:
|
||||||
|
name = real_names.get(name, name)
|
||||||
|
|
||||||
|
docname = tree_prefix + name
|
||||||
|
if docname.endswith(suffix):
|
||||||
|
docname = docname[:-len(suffix)]
|
||||||
|
docname = posixpath.normpath(posixpath.join(dirname, docname))
|
||||||
|
if docname not in env.found_docs:
|
||||||
|
warnings.append(state.document.reporter.warning(
|
||||||
|
'toctree references unknown document %r' % docname,
|
||||||
|
line=lineno))
|
||||||
|
docnames.append(docname)
|
||||||
|
|
||||||
|
tocnode = sphinx.addnodes.toctree()
|
||||||
|
tocnode['includefiles'] = docnames
|
||||||
|
tocnode['maxdepth'] = -1
|
||||||
|
tocnode['glob'] = None
|
||||||
|
|
||||||
|
tocnode = autosummary_toc('', '', tocnode)
|
||||||
|
return warnings + [node] + [tocnode]
|
||||||
|
else:
|
||||||
|
return warnings + [node]
|
||||||
|
|
||||||
|
def get_autosummary(names, state, no_signatures=False):
|
||||||
|
"""
|
||||||
|
Generate a proper table node for autosummary:: directive.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
names : list of str
|
||||||
|
Names of Python objects to be imported and added to the table.
|
||||||
|
document : document
|
||||||
|
Docutils document object
|
||||||
|
|
||||||
|
"""
|
||||||
|
document = state.document
|
||||||
|
|
||||||
|
real_names = {}
|
||||||
|
warnings = []
|
||||||
|
|
||||||
|
prefixes = ['']
|
||||||
|
prefixes.insert(0, document.settings.env.currmodule)
|
||||||
|
|
||||||
|
table = nodes.table('')
|
||||||
|
group = nodes.tgroup('', cols=2)
|
||||||
|
table.append(group)
|
||||||
|
group.append(nodes.colspec('', colwidth=30))
|
||||||
|
group.append(nodes.colspec('', colwidth=70))
|
||||||
|
body = nodes.tbody('')
|
||||||
|
group.append(body)
|
||||||
|
|
||||||
|
def append_row(*column_texts):
|
||||||
|
row = nodes.row('')
|
||||||
|
for text in column_texts:
|
||||||
|
node = nodes.paragraph('')
|
||||||
|
vl = ViewList()
|
||||||
|
vl.append(text, '<autosummary>')
|
||||||
|
state.nested_parse(vl, 0, node)
|
||||||
|
row.append(nodes.entry('', node))
|
||||||
|
body.append(row)
|
||||||
|
|
||||||
|
for name in names:
|
||||||
|
try:
|
||||||
|
obj, real_name = import_by_name(name, prefixes=prefixes)
|
||||||
|
except ImportError:
|
||||||
|
warnings.append(document.reporter.warning(
|
||||||
|
'failed to import %s' % name))
|
||||||
|
append_row(":obj:`%s`" % name, "")
|
||||||
|
continue
|
||||||
|
|
||||||
|
real_names[name] = real_name
|
||||||
|
|
||||||
|
doc = get_doc_object(obj)
|
||||||
|
|
||||||
|
if doc['Summary']:
|
||||||
|
title = " ".join(doc['Summary'])
|
||||||
|
else:
|
||||||
|
title = ""
|
||||||
|
qualifier = 'obj'
|
||||||
|
if inspect.ismodule(obj):
|
||||||
|
qualifier = 'mod'
|
||||||
|
col1 = ":"+qualifier+":`%s <%s>`" % (name, real_name)
|
||||||
|
if doc['Signature']:
|
||||||
|
sig = re.sub('^[a-zA-Z_0-9.-]*', '',
|
||||||
|
doc['Signature'].replace('*', r'\*'))
|
||||||
|
if '=' in sig:
|
||||||
|
# abbreviate optional arguments
|
||||||
|
sig = re.sub(r', ([a-zA-Z0-9_]+)=', r'[, \1=', sig, count=1)
|
||||||
|
sig = re.sub(r'\(([a-zA-Z0-9_]+)=', r'([\1=', sig, count=1)
|
||||||
|
sig = re.sub(r'=[^,)]+,', ',', sig)
|
||||||
|
sig = re.sub(r'=[^,)]+\)$', '])', sig)
|
||||||
|
# shorten long strings
|
||||||
|
sig = re.sub(r'(\[.{16,16}[^,)]*?),.*?\]\)', r'\1, ...])', sig)
|
||||||
|
else:
|
||||||
|
sig = re.sub(r'(\(.{16,16}[^,)]*?),.*?\)', r'\1, ...)', sig)
|
||||||
|
col1 += " " + sig
|
||||||
|
col2 = title
|
||||||
|
append_row(col1, col2)
|
||||||
|
|
||||||
|
return table, warnings, real_names
|
||||||
|
|
||||||
|
def import_by_name(name, prefixes=[None]):
|
||||||
|
"""
|
||||||
|
Import a Python object that has the given name, under one of the prefixes.
|
||||||
|
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
name : str
|
||||||
|
Name of a Python object, eg. 'numpy.ndarray.view'
|
||||||
|
prefixes : list of (str or None), optional
|
||||||
|
Prefixes to prepend to the name (None implies no prefix).
|
||||||
|
The first prefixed name that results to successful import is used.
|
||||||
|
|
||||||
|
Returns
|
||||||
|
-------
|
||||||
|
obj
|
||||||
|
The imported object
|
||||||
|
name
|
||||||
|
Name of the imported object (useful if `prefixes` was used)
|
||||||
|
|
||||||
|
"""
|
||||||
|
for prefix in prefixes:
|
||||||
|
try:
|
||||||
|
if prefix:
|
||||||
|
prefixed_name = '.'.join([prefix, name])
|
||||||
|
else:
|
||||||
|
prefixed_name = name
|
||||||
|
return _import_by_name(prefixed_name), prefixed_name
|
||||||
|
except ImportError:
|
||||||
|
pass
|
||||||
|
raise ImportError
|
||||||
|
|
||||||
|
def _import_by_name(name):
|
||||||
|
"""Import a Python object given its full name"""
|
||||||
|
try:
|
||||||
|
name_parts = name.split('.')
|
||||||
|
last_j = 0
|
||||||
|
modname = None
|
||||||
|
for j in reversed(range(1, len(name_parts)+1)):
|
||||||
|
last_j = j
|
||||||
|
modname = '.'.join(name_parts[:j])
|
||||||
|
try:
|
||||||
|
__import__(modname)
|
||||||
|
except ImportError:
|
||||||
|
continue
|
||||||
|
if modname in sys.modules:
|
||||||
|
break
|
||||||
|
|
||||||
|
if last_j < len(name_parts):
|
||||||
|
obj = sys.modules[modname]
|
||||||
|
for obj_name in name_parts[last_j:]:
|
||||||
|
obj = getattr(obj, obj_name)
|
||||||
|
return obj
|
||||||
|
else:
|
||||||
|
return sys.modules[modname]
|
||||||
|
except (ValueError, ImportError, AttributeError, KeyError), e:
|
||||||
|
raise ImportError(e)
|
||||||
|
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
# :autolink: (smart default role)
|
||||||
|
#------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
def autolink_role(typ, rawtext, etext, lineno, inliner,
|
||||||
|
options={}, content=[]):
|
||||||
|
"""
|
||||||
|
Smart linking role.
|
||||||
|
|
||||||
|
Expands to ":obj:`text`" if `text` is an object that can be imported;
|
||||||
|
otherwise expands to "*text*".
|
||||||
|
"""
|
||||||
|
r = sphinx.roles.xfileref_role('obj', rawtext, etext, lineno, inliner,
|
||||||
|
options, content)
|
||||||
|
pnode = r[0][0]
|
||||||
|
|
||||||
|
prefixes = [None]
|
||||||
|
#prefixes.insert(0, inliner.document.settings.env.currmodule)
|
||||||
|
try:
|
||||||
|
obj, name = import_by_name(pnode['reftarget'], prefixes)
|
||||||
|
except ImportError:
|
||||||
|
content = pnode[0]
|
||||||
|
r[0][0] = nodes.emphasis(rawtext, content[0].astext(),
|
||||||
|
classes=content['classes'])
|
||||||
|
return r
|
500
sphinx/ext/autosummary/docscrape.py
Normal file
500
sphinx/ext/autosummary/docscrape.py
Normal file
@ -0,0 +1,500 @@
|
|||||||
|
"""Extract reference documentation from the NumPy source tree.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
import inspect
|
||||||
|
import textwrap
|
||||||
|
import re
|
||||||
|
import pydoc
|
||||||
|
from StringIO import StringIO
|
||||||
|
from warnings import warn
|
||||||
|
|
||||||
|
class Reader(object):
|
||||||
|
"""A line-based string reader.
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self, data):
|
||||||
|
"""
|
||||||
|
Parameters
|
||||||
|
----------
|
||||||
|
data : str
|
||||||
|
String with lines separated by '\n'.
|
||||||
|
|
||||||
|
"""
|
||||||
|
if isinstance(data,list):
|
||||||
|
self._str = data
|
||||||
|
else:
|
||||||
|
self._str = data.split('\n') # store string as list of lines
|
||||||
|
|
||||||
|
self.reset()
|
||||||
|
|
||||||
|
def __getitem__(self, n):
|
||||||
|
return self._str[n]
|
||||||
|
|
||||||
|
def reset(self):
|
||||||
|
self._l = 0 # current line nr
|
||||||
|
|
||||||
|
def read(self):
|
||||||
|
if not self.eof():
|
||||||
|
out = self[self._l]
|
||||||
|
self._l += 1
|
||||||
|
return out
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def seek_next_non_empty_line(self):
|
||||||
|
for l in self[self._l:]:
|
||||||
|
if l.strip():
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
self._l += 1
|
||||||
|
|
||||||
|
def eof(self):
|
||||||
|
return self._l >= len(self._str)
|
||||||
|
|
||||||
|
def read_to_condition(self, condition_func):
|
||||||
|
start = self._l
|
||||||
|
for line in self[start:]:
|
||||||
|
if condition_func(line):
|
||||||
|
return self[start:self._l]
|
||||||
|
self._l += 1
|
||||||
|
if self.eof():
|
||||||
|
return self[start:self._l+1]
|
||||||
|
return []
|
||||||
|
|
||||||
|
def read_to_next_empty_line(self):
|
||||||
|
self.seek_next_non_empty_line()
|
||||||
|
def is_empty(line):
|
||||||
|
return not line.strip()
|
||||||
|
return self.read_to_condition(is_empty)
|
||||||
|
|
||||||
|
def read_to_next_unindented_line(self):
|
||||||
|
def is_unindented(line):
|
||||||
|
return (line.strip() and (len(line.lstrip()) == len(line)))
|
||||||
|
return self.read_to_condition(is_unindented)
|
||||||
|
|
||||||
|
def peek(self,n=0):
|
||||||
|
if self._l + n < len(self._str):
|
||||||
|
return self[self._l + n]
|
||||||
|
else:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
def is_empty(self):
|
||||||
|
return not ''.join(self._str).strip()
|
||||||
|
|
||||||
|
|
||||||
|
class NumpyDocString(object):
|
||||||
|
def __init__(self,docstring):
|
||||||
|
docstring = docstring.split('\n')
|
||||||
|
|
||||||
|
# De-indent paragraph
|
||||||
|
try:
|
||||||
|
indent = min(len(s) - len(s.lstrip()) for s in docstring
|
||||||
|
if s.strip())
|
||||||
|
except ValueError:
|
||||||
|
indent = 0
|
||||||
|
|
||||||
|
for n,line in enumerate(docstring):
|
||||||
|
docstring[n] = docstring[n][indent:]
|
||||||
|
|
||||||
|
self._doc = Reader(docstring)
|
||||||
|
self._parsed_data = {
|
||||||
|
'Signature': '',
|
||||||
|
'Summary': '',
|
||||||
|
'Extended Summary': [],
|
||||||
|
'Parameters': [],
|
||||||
|
'Returns': [],
|
||||||
|
'Raises': [],
|
||||||
|
'Warns': [],
|
||||||
|
'Other Parameters': [],
|
||||||
|
'Attributes': [],
|
||||||
|
'Methods': [],
|
||||||
|
'See Also': [],
|
||||||
|
'Notes': [],
|
||||||
|
'Warnings': [],
|
||||||
|
'References': '',
|
||||||
|
'Examples': '',
|
||||||
|
'index': {}
|
||||||
|
}
|
||||||
|
|
||||||
|
self._parse()
|
||||||
|
|
||||||
|
def __getitem__(self,key):
|
||||||
|
return self._parsed_data[key]
|
||||||
|
|
||||||
|
def __setitem__(self,key,val):
|
||||||
|
if not self._parsed_data.has_key(key):
|
||||||
|
warn("Unknown section %s" % key)
|
||||||
|
else:
|
||||||
|
self._parsed_data[key] = val
|
||||||
|
|
||||||
|
def _is_at_section(self):
|
||||||
|
self._doc.seek_next_non_empty_line()
|
||||||
|
|
||||||
|
if self._doc.eof():
|
||||||
|
return False
|
||||||
|
|
||||||
|
l1 = self._doc.peek().strip() # e.g. Parameters
|
||||||
|
|
||||||
|
if l1.startswith('.. index::'):
|
||||||
|
return True
|
||||||
|
|
||||||
|
l2 = self._doc.peek(1).strip() # ---------- or ==========
|
||||||
|
return l2.startswith('-'*len(l1)) or l2.startswith('='*len(l1))
|
||||||
|
|
||||||
|
def _strip(self,doc):
|
||||||
|
i = 0
|
||||||
|
j = 0
|
||||||
|
for i,line in enumerate(doc):
|
||||||
|
if line.strip(): break
|
||||||
|
|
||||||
|
for j,line in enumerate(doc[::-1]):
|
||||||
|
if line.strip(): break
|
||||||
|
|
||||||
|
return doc[i:len(doc)-j]
|
||||||
|
|
||||||
|
def _read_to_next_section(self):
|
||||||
|
section = self._doc.read_to_next_empty_line()
|
||||||
|
|
||||||
|
while not self._is_at_section() and not self._doc.eof():
|
||||||
|
if not self._doc.peek(-1).strip(): # previous line was empty
|
||||||
|
section += ['']
|
||||||
|
|
||||||
|
section += self._doc.read_to_next_empty_line()
|
||||||
|
|
||||||
|
return section
|
||||||
|
|
||||||
|
def _read_sections(self):
|
||||||
|
while not self._doc.eof():
|
||||||
|
data = self._read_to_next_section()
|
||||||
|
name = data[0].strip()
|
||||||
|
|
||||||
|
if name.startswith('..'): # index section
|
||||||
|
yield name, data[1:]
|
||||||
|
elif len(data) < 2:
|
||||||
|
yield StopIteration
|
||||||
|
else:
|
||||||
|
yield name, self._strip(data[2:])
|
||||||
|
|
||||||
|
def _parse_param_list(self,content):
|
||||||
|
r = Reader(content)
|
||||||
|
params = []
|
||||||
|
while not r.eof():
|
||||||
|
header = r.read().strip()
|
||||||
|
if ' : ' in header:
|
||||||
|
arg_name, arg_type = header.split(' : ')[:2]
|
||||||
|
else:
|
||||||
|
arg_name, arg_type = header, ''
|
||||||
|
|
||||||
|
desc = r.read_to_next_unindented_line()
|
||||||
|
for n,line in enumerate(desc):
|
||||||
|
desc[n] = line.strip()
|
||||||
|
desc = desc #'\n'.join(desc)
|
||||||
|
|
||||||
|
params.append((arg_name,arg_type,desc))
|
||||||
|
|
||||||
|
return params
|
||||||
|
|
||||||
|
|
||||||
|
_name_rgx = re.compile(r"^\s*(:(?P<role>\w+):`(?P<name>[a-zA-Z0-9_.-]+)`|"
|
||||||
|
r" (?P<name2>[a-zA-Z0-9_.-]+))\s*", re.X)
|
||||||
|
def _parse_see_also(self, content):
|
||||||
|
"""
|
||||||
|
func_name : Descriptive text
|
||||||
|
continued text
|
||||||
|
another_func_name : Descriptive text
|
||||||
|
func_name1, func_name2, :meth:`func_name`, func_name3
|
||||||
|
|
||||||
|
"""
|
||||||
|
items = []
|
||||||
|
|
||||||
|
def parse_item_name(text):
|
||||||
|
"""Match ':role:`name`' or 'name'"""
|
||||||
|
m = self._name_rgx.match(text)
|
||||||
|
if m:
|
||||||
|
g = m.groups()
|
||||||
|
if g[1] is None:
|
||||||
|
return g[3], None
|
||||||
|
else:
|
||||||
|
return g[2], g[1]
|
||||||
|
raise ValueError("%s is not a item name" % text)
|
||||||
|
|
||||||
|
def push_item(name, rest):
|
||||||
|
if not name:
|
||||||
|
return
|
||||||
|
name, role = parse_item_name(name)
|
||||||
|
items.append((name, list(rest), role))
|
||||||
|
del rest[:]
|
||||||
|
|
||||||
|
current_func = None
|
||||||
|
rest = []
|
||||||
|
|
||||||
|
for line in content:
|
||||||
|
if not line.strip(): continue
|
||||||
|
|
||||||
|
m = self._name_rgx.match(line)
|
||||||
|
if m and line[m.end():].strip().startswith(':'):
|
||||||
|
push_item(current_func, rest)
|
||||||
|
current_func, line = line[:m.end()], line[m.end():]
|
||||||
|
rest = [line.split(':', 1)[1].strip()]
|
||||||
|
if not rest[0]:
|
||||||
|
rest = []
|
||||||
|
elif not line.startswith(' '):
|
||||||
|
push_item(current_func, rest)
|
||||||
|
current_func = None
|
||||||
|
if ',' in line:
|
||||||
|
for func in line.split(','):
|
||||||
|
push_item(func, [])
|
||||||
|
elif line.strip():
|
||||||
|
current_func = line
|
||||||
|
elif current_func is not None:
|
||||||
|
rest.append(line.strip())
|
||||||
|
push_item(current_func, rest)
|
||||||
|
return items
|
||||||
|
|
||||||
|
def _parse_index(self, section, content):
|
||||||
|
"""
|
||||||
|
.. index: default
|
||||||
|
:refguide: something, else, and more
|
||||||
|
|
||||||
|
"""
|
||||||
|
def strip_each_in(lst):
|
||||||
|
return [s.strip() for s in lst]
|
||||||
|
|
||||||
|
out = {}
|
||||||
|
section = section.split('::')
|
||||||
|
if len(section) > 1:
|
||||||
|
out['default'] = strip_each_in(section[1].split(','))[0]
|
||||||
|
for line in content:
|
||||||
|
line = line.split(':')
|
||||||
|
if len(line) > 2:
|
||||||
|
out[line[1]] = strip_each_in(line[2].split(','))
|
||||||
|
return out
|
||||||
|
|
||||||
|
def _parse_summary(self):
|
||||||
|
"""Grab signature (if given) and summary"""
|
||||||
|
if self._is_at_section():
|
||||||
|
return
|
||||||
|
|
||||||
|
summary = self._doc.read_to_next_empty_line()
|
||||||
|
summary_str = " ".join([s.strip() for s in summary]).strip()
|
||||||
|
if re.compile('^([\w., ]+=)?\s*[\w\.]+\(.*\)$').match(summary_str):
|
||||||
|
self['Signature'] = summary_str
|
||||||
|
if not self._is_at_section():
|
||||||
|
self['Summary'] = self._doc.read_to_next_empty_line()
|
||||||
|
else:
|
||||||
|
self['Summary'] = summary
|
||||||
|
|
||||||
|
if not self._is_at_section():
|
||||||
|
self['Extended Summary'] = self._read_to_next_section()
|
||||||
|
|
||||||
|
def _parse(self):
|
||||||
|
self._doc.reset()
|
||||||
|
self._parse_summary()
|
||||||
|
|
||||||
|
for (section,content) in self._read_sections():
|
||||||
|
if not section.startswith('..'):
|
||||||
|
section = ' '.join([s.capitalize() for s in section.split(' ')])
|
||||||
|
if section in ('Parameters', 'Attributes', 'Methods',
|
||||||
|
'Returns', 'Raises', 'Warns'):
|
||||||
|
self[section] = self._parse_param_list(content)
|
||||||
|
elif section.startswith('.. index::'):
|
||||||
|
self['index'] = self._parse_index(section, content)
|
||||||
|
elif section == 'See Also':
|
||||||
|
self['See Also'] = self._parse_see_also(content)
|
||||||
|
else:
|
||||||
|
self[section] = content
|
||||||
|
|
||||||
|
# string conversion routines
|
||||||
|
|
||||||
|
def _str_header(self, name, symbol='-'):
|
||||||
|
return [name, len(name)*symbol]
|
||||||
|
|
||||||
|
def _str_indent(self, doc, indent=4):
|
||||||
|
out = []
|
||||||
|
for line in doc:
|
||||||
|
out += [' '*indent + line]
|
||||||
|
return out
|
||||||
|
|
||||||
|
def _str_signature(self):
|
||||||
|
if self['Signature']:
|
||||||
|
return [self['Signature'].replace('*','\*')] + ['']
|
||||||
|
else:
|
||||||
|
return ['']
|
||||||
|
|
||||||
|
def _str_summary(self):
|
||||||
|
if self['Summary']:
|
||||||
|
return self['Summary'] + ['']
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def _str_extended_summary(self):
|
||||||
|
if self['Extended Summary']:
|
||||||
|
return self['Extended Summary'] + ['']
|
||||||
|
else:
|
||||||
|
return []
|
||||||
|
|
||||||
|
def _str_param_list(self, name):
|
||||||
|
out = []
|
||||||
|
if self[name]:
|
||||||
|
out += self._str_header(name)
|
||||||
|
for param,param_type,desc in self[name]:
|
||||||
|
out += ['%s : %s' % (param, param_type)]
|
||||||
|
out += self._str_indent(desc)
|
||||||
|
out += ['']
|
||||||
|
return out
|
||||||
|
|
||||||
|
def _str_section(self, name):
|
||||||
|
out = []
|
||||||
|
if self[name]:
|
||||||
|
out += self._str_header(name)
|
||||||
|
out += self[name]
|
||||||
|
out += ['']
|
||||||
|
return out
|
||||||
|
|
||||||
|
def _str_see_also(self, func_role):
|
||||||
|
if not self['See Also']: return []
|
||||||
|
out = []
|
||||||
|
out += self._str_header("See Also")
|
||||||
|
last_had_desc = True
|
||||||
|
for func, desc, role in self['See Also']:
|
||||||
|
if role:
|
||||||
|
link = ':%s:`%s`' % (role, func)
|
||||||
|
elif func_role:
|
||||||
|
link = ':%s:`%s`' % (func_role, func)
|
||||||
|
else:
|
||||||
|
link = "`%s`_" % func
|
||||||
|
if desc or last_had_desc:
|
||||||
|
out += ['']
|
||||||
|
out += [link]
|
||||||
|
else:
|
||||||
|
out[-1] += ", %s" % link
|
||||||
|
if desc:
|
||||||
|
out += self._str_indent([' '.join(desc)])
|
||||||
|
last_had_desc = True
|
||||||
|
else:
|
||||||
|
last_had_desc = False
|
||||||
|
out += ['']
|
||||||
|
return out
|
||||||
|
|
||||||
|
def _str_index(self):
|
||||||
|
idx = self['index']
|
||||||
|
out = []
|
||||||
|
out += ['.. index:: %s' % idx.get('default','')]
|
||||||
|
for section, references in idx.iteritems():
|
||||||
|
if section == 'default':
|
||||||
|
continue
|
||||||
|
out += [' :%s: %s' % (section, ', '.join(references))]
|
||||||
|
return out
|
||||||
|
|
||||||
|
def __str__(self, func_role=''):
|
||||||
|
out = []
|
||||||
|
out += self._str_signature()
|
||||||
|
out += self._str_summary()
|
||||||
|
out += self._str_extended_summary()
|
||||||
|
for param_list in ('Parameters','Returns','Raises'):
|
||||||
|
out += self._str_param_list(param_list)
|
||||||
|
out += self._str_section('Warnings')
|
||||||
|
out += self._str_see_also(func_role)
|
||||||
|
for s in ('Notes','References','Examples'):
|
||||||
|
out += self._str_section(s)
|
||||||
|
out += self._str_index()
|
||||||
|
return '\n'.join(out)
|
||||||
|
|
||||||
|
|
||||||
|
def indent(str,indent=4):
|
||||||
|
indent_str = ' '*indent
|
||||||
|
if str is None:
|
||||||
|
return indent_str
|
||||||
|
lines = str.split('\n')
|
||||||
|
return '\n'.join(indent_str + l for l in lines)
|
||||||
|
|
||||||
|
def header(text, style='-'):
|
||||||
|
return text + '\n' + style*len(text) + '\n'
|
||||||
|
|
||||||
|
|
||||||
|
class FunctionDoc(NumpyDocString):
|
||||||
|
def __init__(self, func, role='func'):
|
||||||
|
self._f = func
|
||||||
|
self._role = role # e.g. "func" or "meth"
|
||||||
|
try:
|
||||||
|
NumpyDocString.__init__(self,inspect.getdoc(func) or '')
|
||||||
|
except ValueError, e:
|
||||||
|
print '*'*78
|
||||||
|
print "ERROR: '%s' while parsing `%s`" % (e, self._f)
|
||||||
|
print '*'*78
|
||||||
|
#print "Docstring follows:"
|
||||||
|
#print doclines
|
||||||
|
#print '='*78
|
||||||
|
|
||||||
|
if not self['Signature']:
|
||||||
|
func, func_name = self.get_func()
|
||||||
|
try:
|
||||||
|
# try to read signature
|
||||||
|
argspec = inspect.getargspec(func)
|
||||||
|
argspec = inspect.formatargspec(*argspec)
|
||||||
|
argspec = argspec.replace('*','\*')
|
||||||
|
signature = '%s%s' % (func_name, argspec)
|
||||||
|
except TypeError, e:
|
||||||
|
signature = '%s()' % func_name
|
||||||
|
self['Signature'] = signature
|
||||||
|
|
||||||
|
def get_func(self):
|
||||||
|
func_name = getattr(self._f, '__name__', self.__class__.__name__)
|
||||||
|
if inspect.isclass(self._f):
|
||||||
|
func = getattr(self._f, '__call__', self._f.__init__)
|
||||||
|
else:
|
||||||
|
func = self._f
|
||||||
|
return func, func_name
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
out = ''
|
||||||
|
|
||||||
|
func, func_name = self.get_func()
|
||||||
|
signature = self['Signature'].replace('*', '\*')
|
||||||
|
|
||||||
|
roles = {'func': 'function',
|
||||||
|
'meth': 'method'}
|
||||||
|
|
||||||
|
if self._role:
|
||||||
|
if not roles.has_key(self._role):
|
||||||
|
print "Warning: invalid role %s" % self._role
|
||||||
|
out += '.. %s:: %s\n \n\n' % (roles.get(self._role,''),
|
||||||
|
func_name)
|
||||||
|
|
||||||
|
out += super(FunctionDoc, self).__str__(func_role=self._role)
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
class ClassDoc(NumpyDocString):
|
||||||
|
def __init__(self,cls,modulename='',func_doc=FunctionDoc):
|
||||||
|
if not inspect.isclass(cls):
|
||||||
|
raise ValueError("Initialise using a class. Got %r" % cls)
|
||||||
|
self._cls = cls
|
||||||
|
|
||||||
|
if modulename and not modulename.endswith('.'):
|
||||||
|
modulename += '.'
|
||||||
|
self._mod = modulename
|
||||||
|
self._name = cls.__name__
|
||||||
|
self._func_doc = func_doc
|
||||||
|
|
||||||
|
NumpyDocString.__init__(self, pydoc.getdoc(cls))
|
||||||
|
|
||||||
|
@property
|
||||||
|
def methods(self):
|
||||||
|
return [name for name,func in inspect.getmembers(self._cls)
|
||||||
|
if not name.startswith('_') and callable(func)]
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
out = ''
|
||||||
|
out += super(ClassDoc, self).__str__()
|
||||||
|
out += "\n\n"
|
||||||
|
|
||||||
|
#for m in self.methods:
|
||||||
|
# print "Parsing `%s`" % m
|
||||||
|
# out += str(self._func_doc(getattr(self._cls,m), 'meth')) + '\n\n'
|
||||||
|
# out += '.. index::\n single: %s; %s\n\n' % (self._name, m)
|
||||||
|
|
||||||
|
return out
|
||||||
|
|
||||||
|
|
133
sphinx/ext/autosummary/docscrape_sphinx.py
Normal file
133
sphinx/ext/autosummary/docscrape_sphinx.py
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
import re, inspect, textwrap, pydoc
|
||||||
|
from docscrape import NumpyDocString, FunctionDoc, ClassDoc
|
||||||
|
|
||||||
|
class SphinxDocString(NumpyDocString):
|
||||||
|
# string conversion routines
|
||||||
|
def _str_header(self, name, symbol='`'):
|
||||||
|
return ['.. rubric:: ' + name, '']
|
||||||
|
|
||||||
|
def _str_field_list(self, name):
|
||||||
|
return [':' + name + ':']
|
||||||
|
|
||||||
|
def _str_indent(self, doc, indent=4):
|
||||||
|
out = []
|
||||||
|
for line in doc:
|
||||||
|
out += [' '*indent + line]
|
||||||
|
return out
|
||||||
|
|
||||||
|
def _str_signature(self):
|
||||||
|
return ['']
|
||||||
|
if self['Signature']:
|
||||||
|
return ['``%s``' % self['Signature']] + ['']
|
||||||
|
else:
|
||||||
|
return ['']
|
||||||
|
|
||||||
|
def _str_summary(self):
|
||||||
|
return self['Summary'] + ['']
|
||||||
|
|
||||||
|
def _str_extended_summary(self):
|
||||||
|
return self['Extended Summary'] + ['']
|
||||||
|
|
||||||
|
def _str_param_list(self, name):
|
||||||
|
out = []
|
||||||
|
if self[name]:
|
||||||
|
out += self._str_field_list(name)
|
||||||
|
out += ['']
|
||||||
|
for param,param_type,desc in self[name]:
|
||||||
|
out += self._str_indent(['**%s** : %s' % (param.strip(),
|
||||||
|
param_type)])
|
||||||
|
out += ['']
|
||||||
|
out += self._str_indent(desc,8)
|
||||||
|
out += ['']
|
||||||
|
return out
|
||||||
|
|
||||||
|
def _str_section(self, name):
|
||||||
|
out = []
|
||||||
|
if self[name]:
|
||||||
|
out += self._str_header(name)
|
||||||
|
out += ['']
|
||||||
|
content = textwrap.dedent("\n".join(self[name])).split("\n")
|
||||||
|
out += content
|
||||||
|
out += ['']
|
||||||
|
return out
|
||||||
|
|
||||||
|
def _str_see_also(self, func_role):
|
||||||
|
out = []
|
||||||
|
if self['See Also']:
|
||||||
|
see_also = super(SphinxDocString, self)._str_see_also(func_role)
|
||||||
|
out = ['.. seealso::', '']
|
||||||
|
out += self._str_indent(see_also[2:])
|
||||||
|
return out
|
||||||
|
|
||||||
|
def _str_warnings(self):
|
||||||
|
out = []
|
||||||
|
if self['Warnings']:
|
||||||
|
out = ['.. warning::', '']
|
||||||
|
out += self._str_indent(self['Warnings'])
|
||||||
|
return out
|
||||||
|
|
||||||
|
def _str_index(self):
|
||||||
|
idx = self['index']
|
||||||
|
out = []
|
||||||
|
if len(idx) == 0:
|
||||||
|
return out
|
||||||
|
|
||||||
|
out += ['.. index:: %s' % idx.get('default','')]
|
||||||
|
for section, references in idx.iteritems():
|
||||||
|
if section == 'default':
|
||||||
|
continue
|
||||||
|
elif section == 'refguide':
|
||||||
|
out += [' single: %s' % (', '.join(references))]
|
||||||
|
else:
|
||||||
|
out += [' %s: %s' % (section, ','.join(references))]
|
||||||
|
return out
|
||||||
|
|
||||||
|
def _str_references(self):
|
||||||
|
out = []
|
||||||
|
if self['References']:
|
||||||
|
out += self._str_header('References')
|
||||||
|
if isinstance(self['References'], str):
|
||||||
|
self['References'] = [self['References']]
|
||||||
|
out.extend(self['References'])
|
||||||
|
out += ['']
|
||||||
|
return out
|
||||||
|
|
||||||
|
def __str__(self, indent=0, func_role="obj"):
|
||||||
|
out = []
|
||||||
|
out += self._str_signature()
|
||||||
|
out += self._str_index() + ['']
|
||||||
|
out += self._str_summary()
|
||||||
|
out += self._str_extended_summary()
|
||||||
|
for param_list in ('Parameters', 'Attributes', 'Methods',
|
||||||
|
'Returns','Raises'):
|
||||||
|
out += self._str_param_list(param_list)
|
||||||
|
out += self._str_warnings()
|
||||||
|
out += self._str_see_also(func_role)
|
||||||
|
out += self._str_section('Notes')
|
||||||
|
out += self._str_references()
|
||||||
|
out += self._str_section('Examples')
|
||||||
|
out = self._str_indent(out,indent)
|
||||||
|
return '\n'.join(out)
|
||||||
|
|
||||||
|
class SphinxFunctionDoc(SphinxDocString, FunctionDoc):
|
||||||
|
pass
|
||||||
|
|
||||||
|
class SphinxClassDoc(SphinxDocString, ClassDoc):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_doc_object(obj, what=None):
|
||||||
|
if what is None:
|
||||||
|
if inspect.isclass(obj):
|
||||||
|
what = 'class'
|
||||||
|
elif inspect.ismodule(obj):
|
||||||
|
what = 'module'
|
||||||
|
elif callable(obj):
|
||||||
|
what = 'function'
|
||||||
|
else:
|
||||||
|
what = 'object'
|
||||||
|
if what == 'class':
|
||||||
|
return SphinxClassDoc(obj, '', func_doc=SphinxFunctionDoc)
|
||||||
|
elif what in ('function', 'method'):
|
||||||
|
return SphinxFunctionDoc(obj, '')
|
||||||
|
else:
|
||||||
|
return SphinxDocString(pydoc.getdoc(obj))
|
0
sphinx/scripts/__init__.py
Normal file
0
sphinx/scripts/__init__.py
Normal file
198
sphinx/scripts/autosummary_generate.py
Executable file
198
sphinx/scripts/autosummary_generate.py
Executable file
@ -0,0 +1,198 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
r"""
|
||||||
|
autosummary_generate.py OPTIONS FILES
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Example Makefile rule::
|
||||||
|
|
||||||
|
generate:
|
||||||
|
./ext/autosummary_generate.py -o source/generated source/*.rst
|
||||||
|
|
||||||
|
"""
|
||||||
|
import glob, re, inspect, os, optparse
|
||||||
|
from sphinx.ext.autosummary import import_by_name
|
||||||
|
|
||||||
|
from jinja import Environment, PackageLoader
|
||||||
|
env = Environment(loader=PackageLoader('numpyext', 'templates'))
|
||||||
|
|
||||||
|
def main():
|
||||||
|
p = optparse.OptionParser(__doc__.strip())
|
||||||
|
p.add_option("-o", "--output-dir", action="store", type="string",
|
||||||
|
dest="output_dir", default=None,
|
||||||
|
help=("Write all output files to the given directory (instead "
|
||||||
|
"of writing them as specified in the autosummary:: "
|
||||||
|
"directives)"))
|
||||||
|
options, args = p.parse_args()
|
||||||
|
|
||||||
|
if len(args) == 0:
|
||||||
|
p.error("wrong number of arguments")
|
||||||
|
|
||||||
|
# read
|
||||||
|
names = {}
|
||||||
|
for name, loc in get_documented(args).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()):
|
||||||
|
if options.output_dir is not None:
|
||||||
|
path = options.output_dir
|
||||||
|
|
||||||
|
if not os.path.isdir(path):
|
||||||
|
os.makedirs(path)
|
||||||
|
|
||||||
|
try:
|
||||||
|
obj, name = import_by_name(name)
|
||||||
|
except ImportError, e:
|
||||||
|
print "Failed to import '%s': %s" % (name, e)
|
||||||
|
continue
|
||||||
|
|
||||||
|
fn = os.path.join(path, '%s.rst' % name)
|
||||||
|
|
||||||
|
if os.path.exists(fn):
|
||||||
|
# skip
|
||||||
|
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,
|
||||||
|
len_functions=len(functions),
|
||||||
|
len_classes=len(classes),
|
||||||
|
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'))
|
||||||
|
else:
|
||||||
|
f.write(format_modulemember(name, 'autoclass'))
|
||||||
|
elif inspect.ismethod(obj) or inspect.ismethoddescriptor(obj):
|
||||||
|
f.write(format_classmember(name, 'automethod'))
|
||||||
|
elif callable(obj):
|
||||||
|
f.write(format_modulemember(name, 'autofunction'))
|
||||||
|
elif hasattr(obj, '__get__'):
|
||||||
|
f.write(format_classmember(name, 'autoattribute'))
|
||||||
|
else:
|
||||||
|
f.write(format_modulemember(name, 'autofunction'))
|
||||||
|
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)
|
||||||
|
|
||||||
|
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)
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
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
|
||||||
|
toctree = None
|
||||||
|
current_module = None
|
||||||
|
in_autosummary = False
|
||||||
|
|
||||||
|
f = open(filename, 'r')
|
||||||
|
for line in f:
|
||||||
|
try:
|
||||||
|
if in_autosummary:
|
||||||
|
m = toctree_arg_re.match(line)
|
||||||
|
if m:
|
||||||
|
toctree = m.group(1)
|
||||||
|
continue
|
||||||
|
|
||||||
|
if line.strip().startswith(':'):
|
||||||
|
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)
|
||||||
|
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":
|
||||||
|
current_module = name
|
||||||
|
documented.setdefault(name, []).append(
|
||||||
|
(filename, current_title, "auto" + m.group(1), None))
|
||||||
|
continue
|
||||||
|
|
||||||
|
m = title_underline_re.match(line)
|
||||||
|
if m and last_line:
|
||||||
|
current_title = last_line.strip()
|
||||||
|
continue
|
||||||
|
|
||||||
|
m = module_re.match(line)
|
||||||
|
if m:
|
||||||
|
current_module = m.group(2)
|
||||||
|
continue
|
||||||
|
finally:
|
||||||
|
last_line = line
|
||||||
|
return documented
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
39
sphinx/templates/autosummary-module.html
Normal file
39
sphinx/templates/autosummary-module.html
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
:mod:`{{name}}`
|
||||||
|
===============================================================================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
.. automodule:: {{name}}
|
||||||
|
|
||||||
|
{% if len_functions > 0 %}
|
||||||
|
Functions
|
||||||
|
----------
|
||||||
|
{% for item in functions %}
|
||||||
|
.. autofunction:: {{item}}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if len_classes > 0 %}
|
||||||
|
Classes
|
||||||
|
--------
|
||||||
|
{% for item in classes %}
|
||||||
|
.. autoclass:: {{item}}
|
||||||
|
:show-inheritance:
|
||||||
|
:members:
|
||||||
|
:inherited-members:
|
||||||
|
:undoc-members:
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
|
||||||
|
{% if len_exceptions > 0 %}
|
||||||
|
Exceptions
|
||||||
|
------------
|
||||||
|
{% for item in exceptions %}
|
||||||
|
.. autoclass:: {{item}}
|
||||||
|
:show-inheritance:
|
||||||
|
:members:
|
||||||
|
:inherited-members:
|
||||||
|
:undoc-members:
|
||||||
|
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
Loading…
Reference in New Issue
Block a user