diff --git a/doc/autobuild.py b/doc/autobuild.py index 1b69b0d8d..78790aa43 100644 --- a/doc/autobuild.py +++ b/doc/autobuild.py @@ -11,6 +11,7 @@ ignore_list = ( 'kivy.graphics.buffer', 'kivy.graphics.vbo', 'kivy.graphics.vertex', + 'kivy.lib.osc' ) import os @@ -127,10 +128,22 @@ Examples template_examples_ref = \ '''# :ref:`Jump directly to Examples `''' +def extract_summary_line(doc): + if doc is None: + return + for line in doc.split('\n'): + line = line.strip() + # don't take empty line + if len(line) < 1: + continue + # ref mark + if line.startswith('.. _'): + continue + return line + for package in packages: - try: - summary = [x for x in sys.modules[package].__doc__.split("\n") if len(x) > 1][0] - except: + summary = extract_summary_line(sys.modules[package].__doc__) + if summary is None: summary = 'NO DOCUMENTATION (package %s)' % package t = template.replace('$SUMMARY', summary) t = t.replace('$PACKAGE', package) @@ -161,10 +174,9 @@ m = modules.keys() m.sort() refid = 0 for module in m: - try: - summary = [x for x in sys.modules[module].__doc__.split("\n") if len(x) > 1][0] - except: - summary = 'NO DOCUMENTATION (module %s)' % module + summary = extract_summary_line(sys.modules[module].__doc__) + if summary is None: + summary = 'NO DOCUMENTATION (module %s)' % package # search examples example_output = [] diff --git a/doc/sources/sphinxext/preprocess.py b/doc/sources/sphinxext/preprocess.py index 342bec917..8481b1356 100644 --- a/doc/sources/sphinxext/preprocess.py +++ b/doc/sources/sphinxext/preprocess.py @@ -2,6 +2,16 @@ 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__ @@ -11,20 +21,30 @@ def is_cython_extension(what, obj): if not len(doc): return False doc = doc[0] - if not '(' in doc or doc[-1] != ')': - return False - # check more if it's an extension - if what == 'attribute' and hasattr(obj, '__objclass__') and \ - hasattr(obj.__objclass__, '__pyx_vtable__'): + # 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 == 'method' 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) and lines[0].strip() == '': + 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 @@ -37,13 +57,37 @@ def callback_docstring(app, what, name, obj, options, lines): elif is_cython_extension(what, obj): lines.pop(0) - for idx in xrange(len(lines)): - line = lines[idx] - if line.startswith(' '): - lines[idx] = line[4:] + 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) @@ -51,10 +95,13 @@ def callback_signature(app, what, name, obj, options, signature, 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)