mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix #7551: autosummary: a nested class is indexed as non-nested class
This commit is contained in:
parent
6ce265dc81
commit
c4d4ba2835
1
CHANGES
1
CHANGES
@ -85,6 +85,7 @@ Bugs fixed
|
||||
* #6857: autodoc: failed to detect a classmethod on Enum class
|
||||
* #7562: autodoc: a typehint contains spaces is wrongly rendered under
|
||||
autodoc_typehints='description' mode
|
||||
* #7551: autosummary: a nested class is indexed as non-nested class
|
||||
* #7535: sphinx-autogen: crashes when custom template uses inheritance
|
||||
* #7536: sphinx-autogen: crashes when template uses i18n feature
|
||||
* #2785: html: Bad alignment of equation links
|
||||
|
@ -45,6 +45,7 @@ from sphinx.locale import __
|
||||
from sphinx.registry import SphinxComponentRegistry
|
||||
from sphinx.util import logging
|
||||
from sphinx.util import rst
|
||||
from sphinx.util import split_full_qualified_name
|
||||
from sphinx.util.inspect import safe_getattr
|
||||
from sphinx.util.osutil import ensuredir
|
||||
from sphinx.util.template import SphinxTemplateLoader
|
||||
@ -248,19 +249,19 @@ def generate_autosummary_content(name: str, obj: Any, parent: Any,
|
||||
ns['attributes'], ns['all_attributes'] = \
|
||||
get_members(obj, {'attribute', 'property'})
|
||||
|
||||
parts = name.split('.')
|
||||
modname, qualname = split_full_qualified_name(name)
|
||||
if doc.objtype in ('method', 'attribute', 'property'):
|
||||
mod_name = '.'.join(parts[:-2])
|
||||
cls_name = parts[-2]
|
||||
obj_name = '.'.join(parts[-2:])
|
||||
ns['class'] = cls_name
|
||||
ns['class'] = qualname.rsplit(".", 1)[0]
|
||||
|
||||
if doc.objtype in ('class',):
|
||||
shortname = qualname
|
||||
else:
|
||||
mod_name, obj_name = '.'.join(parts[:-1]), parts[-1]
|
||||
shortname = qualname.rsplit(".", 1)[-1]
|
||||
|
||||
ns['fullname'] = name
|
||||
ns['module'] = mod_name
|
||||
ns['objname'] = obj_name
|
||||
ns['name'] = parts[-1]
|
||||
ns['module'] = modname
|
||||
ns['objname'] = qualname
|
||||
ns['name'] = shortname
|
||||
|
||||
ns['objtype'] = doc.objtype
|
||||
ns['underline'] = len(name) * '='
|
||||
|
@ -570,6 +570,31 @@ def import_object(objname: str, source: str = None) -> Any:
|
||||
raise ExtensionError('Could not import %s' % objname, exc)
|
||||
|
||||
|
||||
def split_full_qualified_name(name: str) -> Tuple[str, str]:
|
||||
"""Split full qualified name to a pair of modname and qualname.
|
||||
|
||||
A qualname is an abbreviation for "Qualified name" introduced at PEP-3155
|
||||
(https://www.python.org/dev/peps/pep-3155/). It is a dotted path name
|
||||
from the module top-level.
|
||||
|
||||
A "full" qualified name means a string containing both module name and
|
||||
qualified name.
|
||||
|
||||
.. note:: This function imports module actually to check the exisitence.
|
||||
Therefore you need to mock 3rd party modules if needed before
|
||||
calling this function.
|
||||
"""
|
||||
parts = name.split('.')
|
||||
for i, part in enumerate(parts, 1):
|
||||
try:
|
||||
modname = ".".join(parts[:i])
|
||||
import_module(modname)
|
||||
except ImportError:
|
||||
return ".".join(parts[:i - 1]), ".".join(parts[i - 1:])
|
||||
|
||||
return name, ""
|
||||
|
||||
|
||||
def encode_uri(uri: str) -> str:
|
||||
split = list(urlsplit(uri))
|
||||
split[1] = split[1].encode('idna').decode('ascii')
|
||||
|
@ -3,6 +3,9 @@ from typing import Union
|
||||
|
||||
|
||||
class Foo:
|
||||
class Bar:
|
||||
pass
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
|
@ -9,5 +9,6 @@
|
||||
|
||||
autosummary_dummy_module
|
||||
autosummary_dummy_module.Foo
|
||||
autosummary_dummy_module.Foo.Bar
|
||||
autosummary_dummy_module.bar
|
||||
autosummary_importfail
|
||||
|
@ -203,6 +203,7 @@ def test_autosummary_generate(app, status, warning):
|
||||
[autosummary_table, nodes.table, nodes.tgroup, (nodes.colspec,
|
||||
nodes.colspec,
|
||||
[nodes.tbody, (nodes.row,
|
||||
nodes.row,
|
||||
nodes.row,
|
||||
nodes.row,
|
||||
nodes.row)])])
|
||||
@ -210,8 +211,9 @@ def test_autosummary_generate(app, status, warning):
|
||||
|
||||
assert doctree[3][0][0][2][0].astext() == 'autosummary_dummy_module\n\n'
|
||||
assert doctree[3][0][0][2][1].astext() == 'autosummary_dummy_module.Foo()\n\n'
|
||||
assert doctree[3][0][0][2][2].astext() == 'autosummary_dummy_module.bar(x[, y])\n\n'
|
||||
assert doctree[3][0][0][2][3].astext() == 'autosummary_importfail\n\n'
|
||||
assert doctree[3][0][0][2][2].astext() == 'autosummary_dummy_module.Foo.Bar\n\n'
|
||||
assert doctree[3][0][0][2][3].astext() == 'autosummary_dummy_module.bar(x[, y])\n\n'
|
||||
assert doctree[3][0][0][2][4].astext() == 'autosummary_importfail\n\n'
|
||||
|
||||
module = (app.srcdir / 'generated' / 'autosummary_dummy_module.rst').read_text()
|
||||
assert (' .. autosummary::\n'
|
||||
@ -231,6 +233,11 @@ def test_autosummary_generate(app, status, warning):
|
||||
' ~Foo.baz\n'
|
||||
' \n' in Foo)
|
||||
|
||||
FooBar = (app.srcdir / 'generated' / 'autosummary_dummy_module.Foo.Bar.rst').read_text()
|
||||
assert ('.. currentmodule:: autosummary_dummy_module\n'
|
||||
'\n'
|
||||
'.. autoclass:: Foo.Bar\n' in FooBar)
|
||||
|
||||
|
||||
@pytest.mark.sphinx('dummy', testroot='ext-autosummary',
|
||||
confoverrides={'autosummary_generate_overwrite': False})
|
||||
|
Loading…
Reference in New Issue
Block a user