mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
#187: Added support for source ordering of members in autodoc, with `autodoc_member_order = 'bysource'
`.
This commit is contained in:
parent
9a316a21a0
commit
a31e7e2f5d
3
CHANGES
3
CHANGES
@ -10,6 +10,9 @@ Release 1.0 (in development)
|
||||
|
||||
* Added a manual page builder.
|
||||
|
||||
* Added support for source ordering of members in autodoc, with
|
||||
``autodoc_member_order = 'bysource'``.
|
||||
|
||||
* In HTML output, inline roles now get a CSS class with their name,
|
||||
allowing styles to customize their appearance. Domain-specific
|
||||
roles get two classes, ``domain`` and ``domain-rolename``.
|
||||
|
@ -223,10 +223,16 @@ There are also new config values that you can set:
|
||||
.. confval:: autodoc_member_order
|
||||
|
||||
This value selects if automatically documented members are sorted
|
||||
alphabetical (value ``'alphabetical'``) or by member type (value
|
||||
``'groupwise'``). The default is alphabetical.
|
||||
alphabetical (value ``'alphabetical'``), by member type (value
|
||||
``'groupwise'``) or by source order (value ``'bysource'``). The default is
|
||||
alphabetical.
|
||||
|
||||
Note that for source order, the module must be a Python module with the
|
||||
source code available.
|
||||
|
||||
.. versionadded:: 0.6
|
||||
.. versionchanged:: 1.0
|
||||
Support for ``'bysource'``.
|
||||
|
||||
.. confval:: autodoc_default_flags
|
||||
|
||||
|
@ -599,12 +599,19 @@ class Documenter(object):
|
||||
'.'.join(self.objpath + [mname])
|
||||
memberdocumenters.append(
|
||||
classes[-1](self.directive, full_mname, self.indent))
|
||||
|
||||
if (self.options.member_order or self.env.config.autodoc_member_order) \
|
||||
== 'groupwise':
|
||||
member_order = self.options.member_order or \
|
||||
self.env.config.autodoc_member_order
|
||||
if member_order == 'groupwise':
|
||||
# sort by group; relies on stable sort to keep items in the
|
||||
# same group sorted alphabetically
|
||||
memberdocumenters.sort(key=lambda d: d.member_order)
|
||||
elif member_order == 'bysource' and self.analyzer:
|
||||
# sort by source order, by virtue of the module analyzer
|
||||
tagorder = self.analyzer.tagorder
|
||||
def keyfunc(documenter):
|
||||
fullname = documenter.name.split('::')[1]
|
||||
return tagorder.get(fullname, len(tagorder))
|
||||
memberdocumenters.sort(key=keyfunc)
|
||||
|
||||
for documenter in memberdocumenters:
|
||||
documenter.generate(all_members=True,
|
||||
|
@ -58,9 +58,17 @@ class AttrDocVisitor(nodes.NodeVisitor):
|
||||
self.encoding = encoding
|
||||
self.namespace = []
|
||||
self.collected = {}
|
||||
self.tagnumber = 0
|
||||
self.tagorder = {}
|
||||
|
||||
def add_tag(self, name):
|
||||
name = '.'.join(self.namespace + [name])
|
||||
self.tagorder[name] = self.tagnumber
|
||||
self.tagnumber += 1
|
||||
|
||||
def visit_classdef(self, node):
|
||||
"""Visit a class."""
|
||||
self.add_tag(node[1].value)
|
||||
self.namespace.append(node[1].value)
|
||||
self.generic_visit(node)
|
||||
self.namespace.pop()
|
||||
@ -68,6 +76,7 @@ class AttrDocVisitor(nodes.NodeVisitor):
|
||||
def visit_funcdef(self, node):
|
||||
"""Visit a function (or method)."""
|
||||
# usually, don't descend into functions -- nothing interesting there
|
||||
self.add_tag(node[1].value)
|
||||
if node[1].value == '__init__':
|
||||
# however, collect attributes set in __init__ methods
|
||||
self.in_init += 1
|
||||
@ -91,8 +100,7 @@ class AttrDocVisitor(nodes.NodeVisitor):
|
||||
prefix = pnode.get_prefix()
|
||||
prefix = prefix.decode(self.encoding)
|
||||
docstring = prepare_commentdoc(prefix)
|
||||
if docstring:
|
||||
self.add_docstring(node, docstring)
|
||||
self.add_docstring(node, docstring)
|
||||
|
||||
def visit_simple_stmt(self, node):
|
||||
"""Visit a docstring statement which may have an assignment before."""
|
||||
@ -133,9 +141,11 @@ class AttrDocVisitor(nodes.NodeVisitor):
|
||||
continue
|
||||
else:
|
||||
name = target.value
|
||||
namespace = '.'.join(self.namespace)
|
||||
if namespace.startswith(self.scope):
|
||||
self.collected[namespace, name] = docstring
|
||||
self.add_tag(name)
|
||||
if docstring:
|
||||
namespace = '.'.join(self.namespace)
|
||||
if namespace.startswith(self.scope):
|
||||
self.collected[namespace, name] = docstring
|
||||
|
||||
|
||||
class ModuleAnalyzer(object):
|
||||
@ -197,6 +207,7 @@ class ModuleAnalyzer(object):
|
||||
self.parsetree = None
|
||||
# will be filled by find_attr_docs()
|
||||
self.attr_docs = None
|
||||
self.tagorder = None
|
||||
# will be filled by find_tags()
|
||||
self.tags = None
|
||||
|
||||
@ -234,6 +245,7 @@ class ModuleAnalyzer(object):
|
||||
attr_visitor = AttrDocVisitor(number2name, scope, self.encoding)
|
||||
attr_visitor.visit(self.parsetree)
|
||||
self.attr_docs = attr_visitor.collected
|
||||
self.tagorder = attr_visitor.tagorder
|
||||
# now that we found everything we could in the tree, throw it away
|
||||
# (it takes quite a bit of memory for large modules)
|
||||
self.parsetree = None
|
||||
|
@ -341,6 +341,26 @@ def test_generate():
|
||||
assert item in directive.result
|
||||
del directive.result[:]
|
||||
|
||||
def assert_order(items, objtype, name, member_order, **kw):
|
||||
inst = AutoDirective._registry[objtype](directive, name)
|
||||
inst.options.member_order = member_order
|
||||
inst.generate(**kw)
|
||||
assert len(_warnings) == 0, _warnings
|
||||
items = list(reversed(items))
|
||||
lineiter = iter(directive.result)
|
||||
#for line in directive.result:
|
||||
# if line.strip():
|
||||
# print repr(line)
|
||||
while items:
|
||||
item = items.pop()
|
||||
for line in lineiter:
|
||||
if line == item:
|
||||
break
|
||||
else: # ran out of items!
|
||||
assert False, 'item %r not found in result or not in the ' \
|
||||
' correct order' % item
|
||||
del directive.result[:]
|
||||
|
||||
options.members = []
|
||||
|
||||
# no module found?
|
||||
@ -442,6 +462,22 @@ def test_generate():
|
||||
assert_processes([('function', 'time.asctime')], 'function', 'asctime')
|
||||
assert_processes([('function', 'time.asctime')], 'function', 'asctime')
|
||||
|
||||
# test autodoc_member_order == 'source'
|
||||
directive.env.temp_data['py:module'] = 'test_autodoc'
|
||||
assert_order(['.. py:class:: Class(arg)',
|
||||
' .. py:attribute:: Class.descr',
|
||||
' .. py:method:: Class.meth()',
|
||||
' .. py:method:: Class.undocmeth()',
|
||||
' .. py:attribute:: Class.attr',
|
||||
' .. py:attribute:: Class.prop',
|
||||
' .. py:attribute:: Class.docattr',
|
||||
' .. py:attribute:: Class.udocattr',
|
||||
' .. py:attribute:: Class.inst_attr_comment',
|
||||
' .. py:attribute:: Class.inst_attr_string',
|
||||
' .. py:method:: Class.inheritedmeth()',
|
||||
],
|
||||
'class', 'Class', member_order='bysource', all_members=True)
|
||||
|
||||
|
||||
# --- generate fodder ------------
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user