This should really be its own Sphinx extension, but it was convenient to hack the autodoc module. It only handles methods, not attributes so far.
To show interface docs like this, put this in your markup like so (analogous to the autoclass directive):
..autointerface: my.interface.Class
:members:
After applying this patch:
Index: ext/autodoc.py
===================================================================
--- ext/autodoc.py (revision 62203)
+++ ext/autodoc.py (working copy)
@@ -78,7 +78,7 @@
if what == 'module':
mod = obj = name
objpath = []
- elif what in ('class', 'exception', 'function'):
+ elif what in ('class', 'exception', 'function', 'interface'):
mod, obj = rpartition(name, '.')
if not mod and hasattr(env, 'autodoc_current_module'):
mod = env.autodoc_current_module
@@ -107,11 +107,18 @@
if modfile.lower().endswith('.pyc') or modfile.lower().endswith('.pyo'):
modfile = modfile[:-1]
filename_set.add(modfile)
- for part in objpath:
- todoc = getattr(todoc, part)
- if hasattr(todoc, '__module__'):
- if todoc.__module__ != mod:
- return [], result
+ if what == 'interface_method':
+ ifirst, ilast = objpath[0:-1], objpath[-1]
+ for part in ifirst:
+ todoc = getattr(todoc, part)
+ todoc = todoc[ilast]
+ else:
+ for part in objpath:
+ todoc = getattr(todoc, part)
+ if what != 'interface_method':
+ if hasattr(todoc, '__module__'):
+ if todoc.__module__ != mod:
+ return [], result
docstring = todoc.__doc__
except (ImportError, AttributeError):
warning = document.reporter.warning(
@@ -130,6 +137,8 @@
args = '(' + args[7:]
elif args == '(self)':
args = '()'
+ elif what == 'interface_method':
+ args = todoc.getSignatureString()
else:
args = ''
except:
@@ -164,7 +173,8 @@
for line, src in zip(add_content.data, add_content.items):
result.append(indent + line, src[0], src[1])
- if not members or what in ('function', 'method', 'attribute'):
+ if not members or what in ('function', 'method', 'attribute',
+ 'interface_method'):
return [], result
env.autodoc_current_module = mod
@@ -175,11 +185,17 @@
# add members, if possible
_all = members == ['__all__']
if _all:
- all_members = sorted(inspect.getmembers(todoc))
+ if what == 'interface':
+ all_members = [ (mname, todoc[mname]) for mname in list(todoc) ]
+ else:
+ all_members = sorted(inspect.getmembers(todoc))
else:
- all_members = [(mname, getattr(todoc, mname)) for mname in members]
+ if what == 'interface':
+ all_members = [ (name, todoc[mname]) for mname in members ]
+ else:
+ all_members = [(mname, getattr(todoc, mname)) for mname in members]
for (membername, member) in all_members:
- if _all and membername.startswith('_'):
+ if _all and (not what == 'interface') and membername.startswith('_'):
continue
doc = getattr(member, '__doc__', None)
if not undoc and not doc:
@@ -196,6 +212,12 @@
else:
# XXX: todo -- attribute docs
continue
+ if what == 'interface':
+ if hasattr(member, 'required'):
+ memberwhat = 'interface_method'
+ else:
+ memberwhat = 'interface_attribute'
+
else:
if callable(member):
memberwhat = 'method'
@@ -225,9 +247,9 @@
undoc = 'undoc-members' in options
filename_set = set()
+
warnings, result = generate_rst(what, name, members, undoc, content,
state.document, lineno, filename_set=filename_set)
-
# record all filenames as dependencies -- this will at least partially make
# automatic invalidation possible
for fn in filename_set:
@@ -260,16 +282,23 @@
return ['__all__']
return [x.strip() for x in arg.split(',')]
-
def setup(app):
options = {'members': members_directive, 'undoc-members': directives.flag}
app.add_directive('automodule', auto_directive_withmembers,
1, (1, 0, 1), **options)
app.add_directive('autoclass', auto_directive_withmembers,
1, (1, 0, 1), **options)
+ app.add_directive('autointerface', auto_directive_withmembers,
+ 1, (1, 0, 1), **options)
app.add_directive('autoexception', auto_directive_withmembers,
1, (1, 0, 1), **options)
app.add_directive('autofunction', auto_directive, 1, (1, 0, 1))
app.add_directive('automethod', auto_directive, 1, (1, 0, 1))
app.add_directive('autoattribute', auto_directive, 1, (1, 0, 1))
app.add_config_value('automodule_skip_lines', 0, True)
+ from sphinx.directives import desc_directive
+ from sphinx.directives import additional_xref_types
+ additional_xref_types['interface'] = ('interface', 'interface; %s', None)
+ additional_xref_types['interface_method'] = ('interface_method', 'interface method; %s', None)
+ app.add_directive('interface', desc_directive, 1, (1, 0, 1))
+ app.add_directive('interface_method', desc_directive, 1, (1, 0, 1))