kivy/doc/sources/sphinxext/preprocess.py

108 lines
3.5 KiB
Python
Raw Normal View History

'''
Extension for enhancing sphinx documentation generation for cython module
'''
import re
import types
from sphinx.ext.autodoc import MethodDocumenter
class CythonMethodDocumenter(MethodDocumenter):
# XXX i don't understand the impact of having a priority more than the
# attribute or instance method but the things is, if it's a cython module,
# the attribute will be prefer over method.
priority = 12
def is_cython_extension(what, obj):
# try to check if the first line of the doc is a signature
doc = obj.__doc__
if not doc:
return False
doc = doc.split('\n')
if not len(doc):
return False
doc = doc[0]
# test for cython cpdef
if what in ('attribute', 'method') and hasattr(obj, '__objclass__'):
if not re.match('^([a-zA-Z_][a-zA-Z0-9_]*)\.([a-zA-Z_][a-zA-Z0-9_]*)\((.*)\)', doc):
return False
return True
# test for cython class
if what == 'class' and hasattr(obj, '__pyx_vtable__'):
if not re.match('^([a-zA-Z_][a-zA-Z0-9_]*)\((.*)\)', doc):
return False
return True
# test for python method in cython class
if what in ('method', 'function') and obj.__class__ == types.BuiltinFunctionType:
if not re.match('^([a-zA-Z_][a-zA-Z0-9_]*)\((.*)\)', doc):
return False
return True
def callback_docstring(app, what, name, obj, options, lines):
if what == 'module':
# remove empty lines
while len(lines):
line = lines[0].strip()
if not line.startswith('.. _') and line != '':
break
lines.pop(0)
# if we still have lines, remove the title
if len(lines):
lines.pop(0)
# if the title is followed by a separator, remove it.
if len(lines) and lines[0].startswith('=='):
lines.pop(0)
2011-09-28 20:58:15 +00:00
elif is_cython_extension(what, obj) and lines:
lines.pop(0)
line = lines.pop(0)
# trick to realign the first line to the second one.
# FIXME: fail if we finishing with ::
if line is not None and len(lines):
l = len(lines[0]) - len(lines[0].lstrip())
else:
l = 0
lines.insert(0, ' ' * l + line)
# calculate the minimum space available
min_space = 999
for line in lines:
if not line.strip():
continue
min_space = min(min_space, len(line) - len(line.lstrip()))
# remove that kind of space now.
if min_space > 0:
spaces = ' ' * min_space
for idx, line in enumerate(lines):
if not line.strip():
continue
if not line.startswith(spaces):
continue
lines[idx] = line[min_space:]
def callback_signature(app, what, name, obj, options, signature,
return_annotation):
# remove the first 'self' argument, because python autodoc don't
# add it for python method class. So do the same for cython class.
if is_cython_extension(what, obj):
try:
doc = obj.__doc__.split('\n').pop(0)
doc = '(%s' % doc.split('(')[1]
doc = doc.replace('(self, ', '(')
doc = doc.replace('(self)', '( )')
return (doc, None)
except AttributeError:
pass
except IndexError:
pass
def setup(app):
app.add_autodocumenter(CythonMethodDocumenter)
app.connect('autodoc-process-docstring', callback_docstring)
app.connect('autodoc-process-signature', callback_signature)