mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix #7812: autodoc: crashed when given name is conflicted
Note: this partially reverts #7594 to avoid errors.
This commit is contained in:
parent
5afc77ee27
commit
659846b805
2
CHANGES
2
CHANGES
@ -21,6 +21,8 @@ Bugs fixed
|
|||||||
the autoclass directive
|
the autoclass directive
|
||||||
* #7850: autodoc: KeyError is raised for invalid mark up when autodoc_typehints
|
* #7850: autodoc: KeyError is raised for invalid mark up when autodoc_typehints
|
||||||
is 'description'
|
is 'description'
|
||||||
|
* #7812: autodoc: crashed if the target name matches to both an attribute and
|
||||||
|
module that are same name
|
||||||
* #7812: autosummary: generates broken stub files if the target code contains
|
* #7812: autosummary: generates broken stub files if the target code contains
|
||||||
an attribute and module that are same name
|
an attribute and module that are same name
|
||||||
* #7806: viewcode: Failed to resolve viewcode references on 3rd party builders
|
* #7806: viewcode: Failed to resolve viewcode references on 3rd party builders
|
||||||
|
@ -32,7 +32,6 @@ from sphinx.locale import _, __
|
|||||||
from sphinx.pycode import ModuleAnalyzer, PycodeError
|
from sphinx.pycode import ModuleAnalyzer, PycodeError
|
||||||
from sphinx.util import inspect
|
from sphinx.util import inspect
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util import split_full_qualified_name
|
|
||||||
from sphinx.util.docstrings import extract_metadata, prepare_docstring
|
from sphinx.util.docstrings import extract_metadata, prepare_docstring
|
||||||
from sphinx.util.inspect import getdoc, object_description, safe_getattr, stringify_signature
|
from sphinx.util.inspect import getdoc, object_description, safe_getattr, stringify_signature
|
||||||
from sphinx.util.typing import stringify as stringify_typehint
|
from sphinx.util.typing import stringify as stringify_typehint
|
||||||
@ -980,31 +979,15 @@ class ModuleLevelDocumenter(Documenter):
|
|||||||
) -> Tuple[str, List[str]]:
|
) -> Tuple[str, List[str]]:
|
||||||
if modname is None:
|
if modname is None:
|
||||||
if path:
|
if path:
|
||||||
stripped = path.rstrip('.')
|
modname = path.rstrip('.')
|
||||||
modname, qualname = split_full_qualified_name(stripped)
|
|
||||||
if modname is None:
|
|
||||||
# if documenting a toplevel object without explicit module,
|
|
||||||
# it can be contained in another auto directive ...
|
|
||||||
modname = self.env.temp_data.get('autodoc:module')
|
|
||||||
# ... or in the scope of a module directive
|
|
||||||
if not modname:
|
|
||||||
modname = self.env.ref_context.get('py:module')
|
|
||||||
|
|
||||||
if modname:
|
|
||||||
stripped = ".".join([modname, stripped])
|
|
||||||
modname, qualname = split_full_qualified_name(stripped)
|
|
||||||
|
|
||||||
if qualname:
|
|
||||||
parents = qualname.split(".")
|
|
||||||
else:
|
|
||||||
parents = []
|
|
||||||
else:
|
else:
|
||||||
|
# if documenting a toplevel object without explicit module,
|
||||||
|
# it can be contained in another auto directive ...
|
||||||
modname = self.env.temp_data.get('autodoc:module')
|
modname = self.env.temp_data.get('autodoc:module')
|
||||||
parents = []
|
# ... or in the scope of a module directive
|
||||||
|
|
||||||
if not modname:
|
if not modname:
|
||||||
modname = self.env.ref_context.get('py:module')
|
modname = self.env.ref_context.get('py:module')
|
||||||
|
# ... else, it stays None, which means invalid
|
||||||
return modname, parents + [base]
|
return modname, parents + [base]
|
||||||
|
|
||||||
|
|
||||||
@ -1030,25 +1013,14 @@ class ClassLevelDocumenter(Documenter):
|
|||||||
# ... if still None, there's no way to know
|
# ... if still None, there's no way to know
|
||||||
if mod_cls is None:
|
if mod_cls is None:
|
||||||
return None, []
|
return None, []
|
||||||
|
modname, sep, cls = mod_cls.rpartition('.')
|
||||||
modname, qualname = split_full_qualified_name(mod_cls)
|
parents = [cls]
|
||||||
if modname is None:
|
# if the module name is still missing, get it like above
|
||||||
# if documenting a toplevel object without explicit module,
|
if not modname:
|
||||||
# it can be contained in another auto directive ...
|
|
||||||
modname = self.env.temp_data.get('autodoc:module')
|
modname = self.env.temp_data.get('autodoc:module')
|
||||||
# ... or in the scope of a module directive
|
if not modname:
|
||||||
if not modname:
|
modname = self.env.ref_context.get('py:module')
|
||||||
modname = self.env.ref_context.get('py:module')
|
# ... else, it stays None, which means invalid
|
||||||
|
|
||||||
if modname:
|
|
||||||
stripped = ".".join([modname, mod_cls])
|
|
||||||
modname, qualname = split_full_qualified_name(stripped)
|
|
||||||
|
|
||||||
if qualname:
|
|
||||||
parents = qualname.split(".")
|
|
||||||
else:
|
|
||||||
parents = []
|
|
||||||
|
|
||||||
return modname, parents + [base]
|
return modname, parents + [base]
|
||||||
|
|
||||||
|
|
||||||
|
@ -0,0 +1,5 @@
|
|||||||
|
from .foo import bar
|
||||||
|
|
||||||
|
class foo:
|
||||||
|
"""docstring of target.name_conflict::foo."""
|
||||||
|
pass
|
2
tests/roots/test-ext-autodoc/target/name_conflict/foo.py
Normal file
2
tests/roots/test-ext-autodoc/target/name_conflict/foo.py
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
class bar:
|
||||||
|
"""docstring of target.name_conflict.foo::bar."""
|
@ -121,8 +121,8 @@ def test_parse_name(app):
|
|||||||
verify('class', 'Base', ('test_ext_autodoc', ['Base'], None, None))
|
verify('class', 'Base', ('test_ext_autodoc', ['Base'], None, None))
|
||||||
|
|
||||||
# for members
|
# for members
|
||||||
directive.env.ref_context['py:module'] = 'sphinx.testing'
|
directive.env.ref_context['py:module'] = 'sphinx.testing.util'
|
||||||
verify('method', 'util.SphinxTestApp.cleanup',
|
verify('method', 'SphinxTestApp.cleanup',
|
||||||
('sphinx.testing.util', ['SphinxTestApp', 'cleanup'], None, None))
|
('sphinx.testing.util', ['SphinxTestApp', 'cleanup'], None, None))
|
||||||
directive.env.ref_context['py:module'] = 'sphinx.testing.util'
|
directive.env.ref_context['py:module'] = 'sphinx.testing.util'
|
||||||
directive.env.ref_context['py:class'] = 'Foo'
|
directive.env.ref_context['py:class'] = 'Foo'
|
||||||
@ -801,14 +801,14 @@ def test_autodoc_inner_class(app):
|
|||||||
actual = do_autodoc(app, 'class', 'target.Outer.Inner', options)
|
actual = do_autodoc(app, 'class', 'target.Outer.Inner', options)
|
||||||
assert list(actual) == [
|
assert list(actual) == [
|
||||||
'',
|
'',
|
||||||
'.. py:class:: Outer.Inner()',
|
'.. py:class:: Inner()',
|
||||||
' :module: target',
|
' :module: target.Outer',
|
||||||
'',
|
'',
|
||||||
' Foo',
|
' Foo',
|
||||||
'',
|
'',
|
||||||
'',
|
'',
|
||||||
' .. py:method:: Outer.Inner.meth()',
|
' .. py:method:: Inner.meth()',
|
||||||
' :module: target',
|
' :module: target.Outer',
|
||||||
'',
|
'',
|
||||||
' Foo',
|
' Foo',
|
||||||
'',
|
'',
|
||||||
@ -1884,8 +1884,8 @@ def test_overload(app):
|
|||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_pymodule_for_ModuleLevelDocumenter(app):
|
def test_pymodule_for_ModuleLevelDocumenter(app):
|
||||||
app.env.ref_context['py:module'] = 'target'
|
app.env.ref_context['py:module'] = 'target.classes'
|
||||||
actual = do_autodoc(app, 'class', 'classes.Foo')
|
actual = do_autodoc(app, 'class', 'Foo')
|
||||||
assert list(actual) == [
|
assert list(actual) == [
|
||||||
'',
|
'',
|
||||||
'.. py:class:: Foo()',
|
'.. py:class:: Foo()',
|
||||||
@ -1896,8 +1896,8 @@ def test_pymodule_for_ModuleLevelDocumenter(app):
|
|||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_pymodule_for_ClassLevelDocumenter(app):
|
def test_pymodule_for_ClassLevelDocumenter(app):
|
||||||
app.env.ref_context['py:module'] = 'target'
|
app.env.ref_context['py:module'] = 'target.methods'
|
||||||
actual = do_autodoc(app, 'method', 'methods.Base.meth')
|
actual = do_autodoc(app, 'method', 'Base.meth')
|
||||||
assert list(actual) == [
|
assert list(actual) == [
|
||||||
'',
|
'',
|
||||||
'.. py:method:: Base.meth()',
|
'.. py:method:: Base.meth()',
|
||||||
@ -1937,3 +1937,26 @@ my_name
|
|||||||
|
|
||||||
alias of bug2437.autodoc_dummy_foo.Foo"""
|
alias of bug2437.autodoc_dummy_foo.Foo"""
|
||||||
assert warning.getvalue() == ''
|
assert warning.getvalue() == ''
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_name_conflict(app):
|
||||||
|
actual = do_autodoc(app, 'class', 'target.name_conflict.foo')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:class:: foo()',
|
||||||
|
' :module: target.name_conflict',
|
||||||
|
'',
|
||||||
|
' docstring of target.name_conflict::foo.',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
actual = do_autodoc(app, 'class', 'target.name_conflict.foo.bar')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:class:: bar()',
|
||||||
|
' :module: target.name_conflict.foo',
|
||||||
|
'',
|
||||||
|
' docstring of target.name_conflict.foo::bar.',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
@ -85,8 +85,8 @@ def test_methoddescriptor(app):
|
|||||||
actual = do_autodoc(app, 'function', 'builtins.int.__add__')
|
actual = do_autodoc(app, 'function', 'builtins.int.__add__')
|
||||||
assert list(actual) == [
|
assert list(actual) == [
|
||||||
'',
|
'',
|
||||||
'.. py:function:: int.__add__(self, value, /)',
|
'.. py:function:: __add__(self, value, /)',
|
||||||
' :module: builtins',
|
' :module: builtins.int',
|
||||||
'',
|
'',
|
||||||
' Return self+value.',
|
' Return self+value.',
|
||||||
'',
|
'',
|
||||||
|
Loading…
Reference in New Issue
Block a user