Autodoc can now order members either alphabetically (like previously) or by member type;

configurable either with the config value ``autodoc_member_order`` or a ``member-order`` option per directive.

Also fix a bug that documented module-level functions as attributes.
This commit is contained in:
Georg Brandl 2009-02-27 15:48:41 +01:00
parent dd32405563
commit d2d3606158
3 changed files with 52 additions and 8 deletions

View File

@ -148,6 +148,11 @@ New features added
- Autodoc can document classes as functions now if explicitly - Autodoc can document classes as functions now if explicitly
marked with `autofunction`. marked with `autofunction`.
- Autodoc can now order members either alphabetically (like
previously) or by member type; configurable either with the
config value ``autodoc_member_order`` or a ``member-order``
option per directive.
- The function ``Sphinx.add_directive()`` now also supports - The function ``Sphinx.add_directive()`` now also supports
docutils 0.5-style directive classes. If they inherit from docutils 0.5-style directive classes. If they inherit from
``sphinx.util.compat.Directive``, they also work with ``sphinx.util.compat.Directive``, they also work with

View File

@ -135,6 +135,12 @@ directive.
.. versionadded:: 0.5 .. versionadded:: 0.5
* :dir:`automodule` and :dir:`autoclass` also has an ``member-order`` option
that can be used to override the global value of
:confval:`autodoc_member_order` for one directive.
.. versionadded:: 0.6
.. note:: .. note::
In an :dir:`automodule` directive with the ``members`` option set, only In an :dir:`automodule` directive with the ``members`` option set, only
@ -199,6 +205,14 @@ There are also new config values that you can set:
.. versionadded:: 0.3 .. versionadded:: 0.3
.. 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.
.. versionadded:: 0.6
Docstring preprocessing Docstring preprocessing
----------------------- -----------------------

View File

@ -218,6 +218,8 @@ class Documenter(object):
content_indent = u' ' content_indent = u' '
#: priority if multiple documenters return True from can_document_member #: priority if multiple documenters return True from can_document_member
priority = 0 priority = 0
#: order if autodoc_member_order is set to 'groupwise'
member_order = 0
option_spec = {'noindex': bool_option} option_spec = {'noindex': bool_option}
@ -548,6 +550,7 @@ class Documenter(object):
members_check_module, members = self.get_object_members(want_all) members_check_module, members = self.get_object_members(want_all)
# document non-skipped members # document non-skipped members
memberdocumenters = []
for (mname, member, isattr) in self.filter_members(members, want_all): for (mname, member, isattr) in self.filter_members(members, want_all):
classes = [cls for cls in AutoDirective._registry.itervalues() classes = [cls for cls in AutoDirective._registry.itervalues()
if cls.can_document_member(member, mname, isattr, self)] if cls.can_document_member(member, mname, isattr, self)]
@ -560,11 +563,19 @@ class Documenter(object):
# of inner classes can be documented # of inner classes can be documented
full_mname = self.modname + '::' + \ full_mname = self.modname + '::' + \
'.'.join(self.objpath + [mname]) '.'.join(self.objpath + [mname])
memberdocmtr = classes[-1](self.directive, full_mname, memberdocumenters.append(
self.indent) classes[-1](self.directive, full_mname, self.indent))
memberdocmtr.generate(all_members=True,
real_modname=self.real_modname, if (self.options.member_order or self.env.config.autodoc_member_order) \
check_module=members_check_module) == '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)
for documenter in memberdocumenters:
documenter.generate(all_members=True,
real_modname=self.real_modname,
check_module=members_check_module)
# reset current objects # reset current objects
self.env.autodoc_current_module = None self.env.autodoc_current_module = None
@ -655,6 +666,7 @@ class ModuleDocumenter(Documenter):
'noindex': bool_option, 'inherited-members': bool_option, 'noindex': bool_option, 'inherited-members': bool_option,
'show-inheritance': bool_option, 'synopsis': identity, 'show-inheritance': bool_option, 'synopsis': identity,
'platform': identity, 'deprecated': bool_option, 'platform': identity, 'deprecated': bool_option,
'member-order': identity,
} }
@classmethod @classmethod
@ -767,6 +779,7 @@ class FunctionDocumenter(ModuleLevelDocumenter):
Specialized Documenter subclass for functions. Specialized Documenter subclass for functions.
""" """
objtype = 'function' objtype = 'function'
member_order = 30
@classmethod @classmethod
def can_document_member(cls, member, membername, isattr, parent): def can_document_member(cls, member, membername, isattr, parent):
@ -800,10 +813,11 @@ class ClassDocumenter(ModuleLevelDocumenter):
Specialized Documenter subclass for classes. Specialized Documenter subclass for classes.
""" """
objtype = 'class' objtype = 'class'
member_order = 20
option_spec = { option_spec = {
'members': members_option, 'undoc-members': bool_option, 'members': members_option, 'undoc-members': bool_option,
'noindex': bool_option, 'inherited-members': bool_option, 'noindex': bool_option, 'inherited-members': bool_option,
'show-inheritance': bool_option, 'show-inheritance': bool_option, 'member-order': identity,
} }
@classmethod @classmethod
@ -897,6 +911,7 @@ class ExceptionDocumenter(ClassDocumenter):
Specialized ClassDocumenter subclass for exceptions. Specialized ClassDocumenter subclass for exceptions.
""" """
objtype = 'exception' objtype = 'exception'
member_order = 10
# needs a higher priority than ClassDocumenter # needs a higher priority than ClassDocumenter
priority = 10 priority = 10
@ -912,6 +927,7 @@ class DataDocumenter(ModuleLevelDocumenter):
Specialized Documenter subclass for data items. Specialized Documenter subclass for data items.
""" """
objtype = 'data' objtype = 'data'
member_order = 40
@classmethod @classmethod
def can_document_member(cls, member, membername, isattr, parent): def can_document_member(cls, member, membername, isattr, parent):
@ -926,6 +942,7 @@ class MethodDocumenter(ClassLevelDocumenter):
Specialized Documenter subclass for methods (normal, static and class). Specialized Documenter subclass for methods (normal, static and class).
""" """
objtype = 'method' objtype = 'method'
member_order = 50
@classmethod @classmethod
def can_document_member(cls, member, membername, isattr, parent): def can_document_member(cls, member, membername, isattr, parent):
@ -939,10 +956,14 @@ class MethodDocumenter(ClassLevelDocumenter):
(isinstance(self.object, MethodType) and (isinstance(self.object, MethodType) and
self.object.im_self is not None): self.object.im_self is not None):
self.directivetype = 'classmethod' self.directivetype = 'classmethod'
# document class and static members before ordinary ones
self.member_order = self.member_order - 1
elif isinstance(self.object, FunctionType) or \ elif isinstance(self.object, FunctionType) or \
(isinstance(self.object, BuiltinFunctionType) and (isinstance(self.object, BuiltinFunctionType) and
self.object.__self__ is not None): self.object.__self__ is not None):
self.directivetype = 'staticmethod' self.directivetype = 'staticmethod'
# document class and static members before ordinary ones
self.member_order = self.member_order - 1
else: else:
self.directivetype = 'method' self.directivetype = 'method'
return ret return ret
@ -966,11 +987,13 @@ class AttributeDocumenter(ClassLevelDocumenter):
Specialized Documenter subclass for attributes. Specialized Documenter subclass for attributes.
""" """
objtype = 'attribute' objtype = 'attribute'
member_order = 60
@classmethod @classmethod
def can_document_member(cls, member, membername, isattr, parent): def can_document_member(cls, member, membername, isattr, parent):
return isdescriptor(member) or \ return (isdescriptor(member) and not
(not isinstance(parent, ModuleDocumenter) and isattr) isinstance(member, (FunctionType, BuiltinFunctionType))) \
or (not isinstance(parent, ModuleDocumenter) and isattr)
def document_members(self, all_members=False): def document_members(self, all_members=False):
pass pass
@ -1033,6 +1056,7 @@ class AutoDirective(Directive):
old_reporter = self.state.memo.reporter old_reporter = self.state.memo.reporter
self.state.memo.reporter = AutodocReporter(self.result, self.state.memo.reporter = AutodocReporter(self.result,
self.state.memo.reporter) self.state.memo.reporter)
if self.name == 'automodule': if self.name == 'automodule':
node = nodes.section() node = nodes.section()
# necessary so that the child nodes get the right source/line set # necessary so that the child nodes get the right source/line set
@ -1068,6 +1092,7 @@ def setup(app):
app.add_autodocumenter(AttributeDocumenter) app.add_autodocumenter(AttributeDocumenter)
app.add_config_value('autoclass_content', 'class', True) app.add_config_value('autoclass_content', 'class', True)
app.add_config_value('autodoc_member_order', 'alphabetic', True)
app.add_event('autodoc-process-docstring') app.add_event('autodoc-process-docstring')
app.add_event('autodoc-process-signature') app.add_event('autodoc-process-signature')
app.add_event('autodoc-skip-member') app.add_event('autodoc-skip-member')