mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
* Fix: autosummary can't handle nested classes correctly. Closes #1441
This commit is contained in:
parent
1d742bdcf5
commit
ff8ce91f77
1
CHANGES
1
CHANGES
@ -14,6 +14,7 @@ Bugs fixed
|
|||||||
object to str implicitly" error when link target url has a hash part.
|
object to str implicitly" error when link target url has a hash part.
|
||||||
Thanks to Jorge_C.
|
Thanks to Jorge_C.
|
||||||
* #1467: Exception on Python3 if nonexistent method is specified by automethod
|
* #1467: Exception on Python3 if nonexistent method is specified by automethod
|
||||||
|
* #1441: autosummary can't handle nested classes correctly.
|
||||||
|
|
||||||
Release 1.2.2 (released Mar 2, 2014)
|
Release 1.2.2 (released Mar 2, 2014)
|
||||||
====================================
|
====================================
|
||||||
|
@ -243,16 +243,21 @@ class Autosummary(Directive):
|
|||||||
display_name = name.split('.')[-1]
|
display_name = name.split('.')[-1]
|
||||||
|
|
||||||
try:
|
try:
|
||||||
real_name, obj, parent = import_by_name(name, prefixes=prefixes)
|
real_name, obj, parent, modname = import_by_name(name, prefixes=prefixes)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
self.warn('failed to import %s' % name)
|
self.warn('failed to import %s' % name)
|
||||||
items.append((name, '', '', name))
|
items.append((name, '', '', name))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# NB. using real_name here is important, since Documenters
|
|
||||||
# handle module prefixes slightly differently
|
|
||||||
self.result = ViewList() # initialize for each documenter
|
self.result = ViewList() # initialize for each documenter
|
||||||
documenter = get_documenter(obj, parent)(self, real_name)
|
full_name = real_name
|
||||||
|
if full_name.startswith(modname + '.'):
|
||||||
|
# give explicitly separated module name, so that members
|
||||||
|
# of inner classes can be documented
|
||||||
|
full_name = modname + '::' + full_name[len(modname)+1:]
|
||||||
|
# NB. using full_name here is important, since Documenters
|
||||||
|
# handle module prefixes slightly differently
|
||||||
|
documenter = get_documenter(obj, parent)(self, full_name)
|
||||||
if not documenter.parse_name():
|
if not documenter.parse_name():
|
||||||
self.warn('failed to parse name %s' % real_name)
|
self.warn('failed to parse name %s' % real_name)
|
||||||
items.append((display_name, '', '', real_name))
|
items.append((display_name, '', '', real_name))
|
||||||
@ -447,8 +452,8 @@ def import_by_name(name, prefixes=[None]):
|
|||||||
prefixed_name = '.'.join([prefix, name])
|
prefixed_name = '.'.join([prefix, name])
|
||||||
else:
|
else:
|
||||||
prefixed_name = name
|
prefixed_name = name
|
||||||
obj, parent = _import_by_name(prefixed_name)
|
obj, parent, modname = _import_by_name(prefixed_name)
|
||||||
return prefixed_name, obj, parent
|
return prefixed_name, obj, parent, modname
|
||||||
except ImportError:
|
except ImportError:
|
||||||
tried.append(prefixed_name)
|
tried.append(prefixed_name)
|
||||||
raise ImportError('no module named %s' % ' or '.join(tried))
|
raise ImportError('no module named %s' % ' or '.join(tried))
|
||||||
@ -464,7 +469,7 @@ def _import_by_name(name):
|
|||||||
try:
|
try:
|
||||||
__import__(modname)
|
__import__(modname)
|
||||||
mod = sys.modules[modname]
|
mod = sys.modules[modname]
|
||||||
return getattr(mod, name_parts[-1]), mod
|
return getattr(mod, name_parts[-1]), mod, modname
|
||||||
except (ImportError, IndexError, AttributeError):
|
except (ImportError, IndexError, AttributeError):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -487,9 +492,9 @@ def _import_by_name(name):
|
|||||||
for obj_name in name_parts[last_j:]:
|
for obj_name in name_parts[last_j:]:
|
||||||
parent = obj
|
parent = obj
|
||||||
obj = getattr(obj, obj_name)
|
obj = getattr(obj, obj_name)
|
||||||
return obj, parent
|
return obj, parent, modname
|
||||||
else:
|
else:
|
||||||
return sys.modules[modname], None
|
return sys.modules[modname], None, modname
|
||||||
except (ValueError, ImportError, AttributeError, KeyError), e:
|
except (ValueError, ImportError, AttributeError, KeyError), e:
|
||||||
raise ImportError(*e.args)
|
raise ImportError(*e.args)
|
||||||
|
|
||||||
@ -510,7 +515,7 @@ def autolink_role(typ, rawtext, etext, lineno, inliner,
|
|||||||
|
|
||||||
prefixes = get_import_prefixes_from_env(env)
|
prefixes = get_import_prefixes_from_env(env)
|
||||||
try:
|
try:
|
||||||
name, obj, parent = import_by_name(pnode['reftarget'], prefixes)
|
name, obj, parent, modname = import_by_name(pnode['reftarget'], prefixes)
|
||||||
except ImportError:
|
except ImportError:
|
||||||
content = pnode[0]
|
content = pnode[0]
|
||||||
r[0][0] = nodes.emphasis(rawtext, content[0].astext(),
|
r[0][0] = nodes.emphasis(rawtext, content[0].astext(),
|
||||||
|
@ -126,7 +126,7 @@ def generate_autosummary_docs(sources, output_dir=None, suffix='.rst',
|
|||||||
ensuredir(path)
|
ensuredir(path)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
name, obj, parent = import_by_name(name)
|
name, obj, parent, mod_name = import_by_name(name)
|
||||||
except ImportError, e:
|
except ImportError, e:
|
||||||
warn('[autosummary] failed to import %r: %s' % (name, e))
|
warn('[autosummary] failed to import %r: %s' % (name, e))
|
||||||
continue
|
continue
|
||||||
@ -235,7 +235,7 @@ def find_autosummary_in_docstring(name, module=None, filename=None):
|
|||||||
See `find_autosummary_in_lines`.
|
See `find_autosummary_in_lines`.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
real_name, obj, parent = import_by_name(name)
|
real_name, obj, parent, modname = import_by_name(name)
|
||||||
lines = pydoc.getdoc(obj).splitlines()
|
lines = pydoc.getdoc(obj).splitlines()
|
||||||
return find_autosummary_in_lines(lines, module=name, filename=filename)
|
return find_autosummary_in_lines(lines, module=name, filename=filename)
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
C.class_attr
|
C.class_attr
|
||||||
C.prop_attr1
|
C.prop_attr1
|
||||||
C.prop_attr2
|
C.prop_attr2
|
||||||
|
C.C2
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def withSentence():
|
def withSentence():
|
||||||
@ -63,3 +64,8 @@ class C:
|
|||||||
|
|
||||||
value is string.
|
value is string.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
class C2:
|
||||||
|
'''
|
||||||
|
This is a nested inner class docstring
|
||||||
|
'''
|
||||||
|
@ -10,11 +10,14 @@
|
|||||||
"""
|
"""
|
||||||
import sys
|
import sys
|
||||||
from functools import wraps
|
from functools import wraps
|
||||||
|
from StringIO import StringIO
|
||||||
|
|
||||||
from sphinx.ext.autosummary import mangle_signature
|
from sphinx.ext.autosummary import mangle_signature
|
||||||
|
|
||||||
from util import test_roots, TestApp
|
from util import test_roots, TestApp
|
||||||
|
|
||||||
|
html_warnfile = StringIO()
|
||||||
|
|
||||||
|
|
||||||
def with_autosummary_app(*args, **kw):
|
def with_autosummary_app(*args, **kw):
|
||||||
default_kw = {
|
default_kw = {
|
||||||
@ -75,7 +78,7 @@ def test_mangle_signature():
|
|||||||
assert res == outp, (u"'%s' -> '%s' != '%s'" % (inp, res, outp))
|
assert res == outp, (u"'%s' -> '%s' != '%s'" % (inp, res, outp))
|
||||||
|
|
||||||
|
|
||||||
@with_autosummary_app(buildername='html')
|
@with_autosummary_app(buildername='html', warning=html_warnfile)
|
||||||
def test_get_items_summary(app):
|
def test_get_items_summary(app):
|
||||||
app.builddir.rmtree(True)
|
app.builddir.rmtree(True)
|
||||||
|
|
||||||
@ -98,6 +101,9 @@ def test_get_items_summary(app):
|
|||||||
finally:
|
finally:
|
||||||
sphinx.ext.autosummary.Autosummary.get_items = orig_get_items
|
sphinx.ext.autosummary.Autosummary.get_items = orig_get_items
|
||||||
|
|
||||||
|
html_warnings = html_warnfile.getvalue()
|
||||||
|
assert html_warnings == ''
|
||||||
|
|
||||||
expected_values = {
|
expected_values = {
|
||||||
'withSentence': 'I have a sentence which spans multiple lines.',
|
'withSentence': 'I have a sentence which spans multiple lines.',
|
||||||
'noSentence': "this doesn't start with a",
|
'noSentence': "this doesn't start with a",
|
||||||
@ -106,6 +112,7 @@ def test_get_items_summary(app):
|
|||||||
'C.class_attr': 'This is a class attribute',
|
'C.class_attr': 'This is a class attribute',
|
||||||
'C.prop_attr1': 'This is a function docstring',
|
'C.prop_attr1': 'This is a function docstring',
|
||||||
'C.prop_attr2': 'This is a attribute docstring',
|
'C.prop_attr2': 'This is a attribute docstring',
|
||||||
|
'C.C2': 'This is a nested inner class docstring',
|
||||||
}
|
}
|
||||||
for key, expected in expected_values.iteritems():
|
for key, expected in expected_values.iteritems():
|
||||||
assert autosummary_items[key][2] == expected, 'Summary for %s was %r -'\
|
assert autosummary_items[key][2] == expected, 'Summary for %s was %r -'\
|
||||||
|
Loading…
Reference in New Issue
Block a user