summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGeorg Brandl <georg@python.org>2014-11-07 15:03:06 +0100
committerGeorg Brandl <georg@python.org>2014-11-07 15:03:06 +0100
commit66dab2b56b51ac1cabd8e3962b183d6101cf4f7e (patch)
treeb120963d1c68b17ef48583a691ef65566e97316f
parent4dbb3f4cf65fb0aebaae0534726bac940a6abed7 (diff)
parent02f2c4b07258605c0c4f18141ea9c6b4ab3c58cc (diff)
downloadsphinx-66dab2b56b51ac1cabd8e3962b183d6101cf4f7e.tar.gz
merge with stable
-rw-r--r--CHANGES3
-rw-r--r--sphinx/ext/autodoc.py88
-rw-r--r--sphinx/util/docstrings.py3
-rw-r--r--tests/test_autodoc.py28
4 files changed, 61 insertions, 61 deletions
diff --git a/CHANGES b/CHANGES
index 292dffa0..f35e7ed5 100644
--- a/CHANGES
+++ b/CHANGES
@@ -14,6 +14,8 @@ Bugs fixed
----------
* PR#311: sphinx-quickstart does not work on python 3.4.
+* Fix :confval:`autodoc_docstring_signature` not working with signatures
+ in class docstrings.
Release 1.3b1 (released Oct 10, 2014)
@@ -127,6 +129,7 @@ Bugs fixed
* #1438: Updated jQuery version from 1.8.3 to 1.11.1.
* #1568: Fix a crash when a "centered" directive contains a reference.
+* Now sphinx.ext.autodoc works with python-2.5 again.
* #1563: :meth:`~sphinx.application.Sphinx.add_search_language` raises
AssertionError for correct type of argument. Thanks to rikoman.
* #1174: Fix smart quotes being applied inside roles like :rst:role:`program` or
diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py
index 5b0bda17..c6037224 100644
--- a/sphinx/ext/autodoc.py
+++ b/sphinx/ext/autodoc.py
@@ -945,36 +945,37 @@ class DocstringSignatureMixin(object):
"""
def _find_signature(self, encoding=None):
- docstrings = Documenter.get_doc(self, encoding)
- if len(docstrings) != 1:
- return
- doclines = docstrings[0]
- setattr(self, '__new_doclines', doclines)
- if not doclines:
- return
- # match first line of docstring against signature RE
- match = py_ext_sig_re.match(doclines[0])
- if not match:
- return
- exmod, path, base, args, retann = match.groups()
- # the base name must match ours
- if not self.objpath or base != self.objpath[-1]:
- return
- # re-prepare docstring to ignore indentation after signature
- docstrings = Documenter.get_doc(self, encoding, 2)
- doclines = docstrings[0]
- # ok, now jump over remaining empty lines and set the remaining
- # lines as the new doclines
- i = 1
- while i < len(doclines) and not doclines[i].strip():
- i += 1
- setattr(self, '__new_doclines', doclines[i:])
- return args, retann
+ docstrings = self.get_doc(encoding)
+ self._new_docstrings = docstrings[:]
+ result = None
+ for i, doclines in enumerate(docstrings):
+ # no lines in docstring, no match
+ if not doclines:
+ continue
+ # match first line of docstring against signature RE
+ match = py_ext_sig_re.match(doclines[0])
+ if not match:
+ continue
+ exmod, path, base, args, retann = match.groups()
+ # the base name must match ours
+ valid_names = [self.objpath[-1]]
+ if isinstance(self, ClassDocumenter):
+ valid_names.append('__init__')
+ if hasattr(self.object, '__mro__'):
+ valid_names.extend(cls.__name__ for cls in self.object.__mro__)
+ if base not in valid_names:
+ continue
+ # re-prepare docstring to ignore more leading indentation
+ self._new_docstrings[i] = prepare_docstring('\n'.join(doclines[1:]))
+ result = args, retann
+ # don't look any further
+ break
+ return result
def get_doc(self, encoding=None, ignore=1):
- lines = getattr(self, '__new_doclines', None)
+ lines = getattr(self, '_new_docstrings', None)
if lines is not None:
- return [lines]
+ return lines
return Documenter.get_doc(self, encoding, ignore)
def format_signature(self):
@@ -1046,7 +1047,7 @@ class FunctionDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
pass
-class ClassDocumenter(ModuleLevelDocumenter):
+class ClassDocumenter(DocstringSignatureMixin, ModuleLevelDocumenter):
"""
Specialized Documenter subclass for classes.
"""
@@ -1098,18 +1099,7 @@ class ClassDocumenter(ModuleLevelDocumenter):
if self.doc_as_attr:
return ''
- # get __init__ method signature from __init__.__doc__
- if self.env.config.autodoc_docstring_signature:
- # only act if the feature is enabled
- init_doc = MethodDocumenter(self.directive, '__init__')
- init_doc.object = self.get_attr(self.object, '__init__', None)
- init_doc.objpath = ['__init__']
- result = init_doc._find_signature()
- if result is not None:
- # use args only for Class signature
- return '(%s)' % result[0]
-
- return ModuleLevelDocumenter.format_signature(self)
+ return DocstringSignatureMixin.format_signature(self)
def add_directive_header(self, sig):
if self.doc_as_attr:
@@ -1128,6 +1118,10 @@ class ClassDocumenter(ModuleLevelDocumenter):
'<autodoc>')
def get_doc(self, encoding=None, ignore=1):
+ lines = getattr(self, '_new_docstrings', None)
+ if lines is not None:
+ return lines
+
content = self.env.config.autoclass_content
docstrings = []
@@ -1138,18 +1132,8 @@ class ClassDocumenter(ModuleLevelDocumenter):
# for classes, what the "docstring" is can be controlled via a
# config value; the default is only the class docstring
if content in ('both', 'init'):
- # get __init__ method document from __init__.__doc__
- if self.env.config.autodoc_docstring_signature:
- # only act if the feature is enabled
- init_doc = MethodDocumenter(self.directive, '__init__')
- init_doc.object = self.get_attr(self.object, '__init__', None)
- init_doc.objpath = ['__init__']
- init_doc._find_signature() # this effects to get_doc() result
- initdocstring = '\n'.join(
- ['\n'.join(l) for l in init_doc.get_doc(encoding)])
- else:
- initdocstring = self.get_attr(
- self.get_attr(self.object, '__init__', None), '__doc__')
+ initdocstring = self.get_attr(
+ self.get_attr(self.object, '__init__', None), '__doc__')
# for new-style classes, no __init__ means default __init__
if (initdocstring is not None and
(initdocstring == object.__init__.__doc__ or # for pypy
diff --git a/sphinx/util/docstrings.py b/sphinx/util/docstrings.py
index 6b66eee9..ae973d49 100644
--- a/sphinx/util/docstrings.py
+++ b/sphinx/util/docstrings.py
@@ -34,7 +34,8 @@ def prepare_docstring(s, ignore=1):
if i < len(lines):
lines[i] = lines[i].lstrip()
if margin < sys.maxsize:
- for i in range(ignore, len(lines)): lines[i] = lines[i][margin:]
+ for i in range(ignore, len(lines)):
+ lines[i] = lines[i][margin:]
# Remove any leading blank lines.
while lines and not lines[0]:
lines.pop(0)
diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py
index 10921b65..96e46196 100644
--- a/tests/test_autodoc.py
+++ b/tests/test_autodoc.py
@@ -151,9 +151,12 @@ def test_format_signature():
inst.fullname = name
inst.doc_as_attr = False # for class objtype
inst.object = obj
+ inst.objpath = [name]
inst.args = args
inst.retann = retann
- return inst.format_signature()
+ res = inst.format_signature()
+ print res
+ return res
# no signatures for modules
assert formatsig('module', 'test', None, None, None) == ''
@@ -186,7 +189,8 @@ def test_format_signature():
assert formatsig('class', 'C', C, None, None) == '(a, b=None)'
assert formatsig('class', 'C', D, 'a, b', 'X') == '(a, b) -> X'
- #__init__ have signature at first line of docstring
+ # __init__ have signature at first line of docstring
+ directive.env.config.autoclass_content = 'both'
class F2:
'''some docstring for F2.'''
def __init__(self, *args, **kw):
@@ -197,9 +201,11 @@ def test_format_signature():
'''
class G2(F2, object):
pass
- for C in (F2, G2):
- assert formatsig('class', 'C', C, None, None) == \
- '(a1, a2, kw1=True, kw2=False)'
+
+ assert formatsig('class', 'F2', F2, None, None) == \
+ '(a1, a2, kw1=True, kw2=False)'
+ assert formatsig('class', 'G2', G2, None, None) == \
+ '(a1, a2, kw1=True, kw2=False)'
# test for methods
class H:
@@ -215,6 +221,7 @@ def test_format_signature():
assert formatsig('method', 'H.foo', H.foo3, None, None) == r"(d='\\n')"
# test exception handling (exception is caught and args is '')
+ directive.env.config.autodoc_docstring_signature = False
assert formatsig('function', 'int', int, None, None) == ''
del _warnings[:]
@@ -242,9 +249,14 @@ def test_get_doc():
def getdocl(objtype, obj, encoding=None):
inst = AutoDirective._registry[objtype](directive, 'tmp')
inst.object = obj
+ inst.objpath = [obj.__name__]
+ inst.doc_as_attr = False
+ inst.format_signature() # handle docstring signatures!
ds = inst.get_doc(encoding)
# for testing purposes, concat them and strip the empty line at the end
- return sum(ds, [])[:-1]
+ res = sum(ds, [])[:-1]
+ print res
+ return res
# objects without docstring
def f():
@@ -305,7 +317,7 @@ def test_get_doc():
assert getdocl('class', D) == ['Class docstring', '', 'Init docstring',
'', 'Other', ' lines']
- #__init__ have signature at first line of docstring
+ # __init__ have signature at first line of docstring
class E:
"""Class docstring"""
def __init__(self, *args, **kw):
@@ -330,7 +342,7 @@ def test_get_doc():
# signature line in the docstring will be removed when
# autodoc_docstring_signature == True
- directive.env.config.autodoc_docstring_signature = True #default
+ directive.env.config.autodoc_docstring_signature = True # default
directive.env.config.autoclass_content = 'class'
assert getdocl('class', E) == ['Class docstring']
directive.env.config.autoclass_content = 'init'