diff --git a/CHANGES b/CHANGES index 4b28899b29..3ef35a5e4a 100644 --- a/CHANGES +++ b/CHANGES @@ -86,6 +86,9 @@ New features added - Autodoc now handles inner classes and their methods. + - Autodoc can document classes as functions now if explicitly + marked with `autofunction`. + - There is now a ``Sphinx.add_lexer()`` method to be able to use custom Pygments lexers easily. diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index 3ca92e86b6..2727fd6cfa 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -324,7 +324,18 @@ class RstGenerator(object): # can never get arguments of a C function or method getargs = False if getargs: - argspec = inspect.getargspec(obj) + try: + argspec = inspect.getargspec(obj) + except TypeError: + # if a class should be documented as function (yay duck + # typing) we try to use the constructor signature as function + # signature without the first argument. + try: + argspec = inspect.getargspec(obj.__new__) + except TypeError: + argspec = inspect.getargspec(obj.__init__) + if argspec[0]: + del argspec[0][0] if what in ('class', 'method', 'staticmethod', 'classmethod') and argspec[0] and \ argspec[0][0] in ('cls', 'self'): @@ -348,7 +359,7 @@ class RstGenerator(object): return '' def generate(self, what, name, members, add_content, indent=u'', check_module=False, - no_docstring=False): + no_docstring=False, real_module=None): """ Generate reST for the object in self.result. """ @@ -377,9 +388,17 @@ class RstGenerator(object): (what, str(fullname), err)) return + # if there is no real-module defined figure out which to use. The real module + # is used in the module analyzer to look up the module where the attribute + # documentation would actually be found in. + # This is used for situations where you have a module that collects the + # functions and classes of internal submodules. + if real_module is None: + real_module = getattr(todoc, '__module__', None) or mod + # try to also get a source code analyzer for attribute docs try: - analyzer = ModuleAnalyzer.for_module(mod) + analyzer = ModuleAnalyzer.for_module(real_module) # parse right now, to get PycodeErrors on parsing analyzer.parse() except PycodeError, err: @@ -454,14 +473,13 @@ class RstGenerator(object): sys.getfilesystemencoding(), 'replace') sourcename = u'%s:docstring of %s' % (srcname, fullname) attr_docs = analyzer.find_attr_docs() - if what in ('data', 'attribute'): - key = ('.'.join(objpath[:-1]), objpath[-1]) - if key in attr_docs: - no_docstring = True - docstrings = [attr_docs[key]] - for i, line in enumerate(self.process_doc(docstrings, what, - fullname, todoc)): - self.result.append(indent + line, sourcename, i) + key = ('.'.join(objpath[:-1]), objpath[-1]) + if key in attr_docs: + no_docstring = True + docstrings = [attr_docs[key]] + for i, line in enumerate(self.process_doc(docstrings, what, + fullname, todoc)): + self.result.append(indent + line, sourcename, i) else: sourcename = u'docstring of %s' % fullname attr_docs = {} @@ -594,7 +612,8 @@ class RstGenerator(object): full_membername = mod + '::' + '.'.join(objpath + [membername]) self.generate(memberwhat, full_membername, ['__all__'], add_content=content, no_docstring=bool(content), - indent=indent, check_module=members_check_module) + indent=indent, check_module=members_check_module, + real_module=real_module) self.env.autodoc_current_module = None self.env.autodoc_current_class = None diff --git a/sphinx/util/docstrings.py b/sphinx/util/docstrings.py index 1b0a599a6c..ea03340a03 100644 --- a/sphinx/util/docstrings.py +++ b/sphinx/util/docstrings.py @@ -49,8 +49,12 @@ def prepare_commentdoc(s): result = [] lines = [line.strip() for line in s.expandtabs().splitlines()] for line in lines: - if line.startswith('#: '): - result.append(line[3:]) + if line.startswith('#:'): + line = line[2:] + # the first space after the comment is ignored + if line and line[0] == ' ': + line = line[1:] + result.append(line) if result and result[-1]: result.append('') return result