mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix #8800: autodoc: Uninitialized attributes in superclass are recognized as undocumented
Unintentionally, uninitialized attributes defined at superclasses are recognized as undocumented in the filtering step. Therefore, they are filtered if `:undoc-members:` option given.
This commit is contained in:
parent
7ca279e33a
commit
6d8c9183fa
2
CHANGES
2
CHANGES
@ -77,6 +77,8 @@ Bugs fixed
|
|||||||
contains invalid type comments
|
contains invalid type comments
|
||||||
* #8693: autodoc: Default values for overloaded functions are rendered as string
|
* #8693: autodoc: Default values for overloaded functions are rendered as string
|
||||||
* #8134: autodoc: crashes when mocked decorator takes arguments
|
* #8134: autodoc: crashes when mocked decorator takes arguments
|
||||||
|
* #8800: autodoc: Uninitialized attributes in superclass are recognized as
|
||||||
|
undocumented
|
||||||
* #8306: autosummary: mocked modules are documented as empty page when using
|
* #8306: autosummary: mocked modules are documented as empty page when using
|
||||||
:recursive: option
|
:recursive: option
|
||||||
* #8232: graphviz: Image node is not rendered if graph file is in subdirectory
|
* #8232: graphviz: Image node is not rendered if graph file is in subdirectory
|
||||||
|
@ -294,24 +294,35 @@ def get_class_members(subject: Any, objpath: List[str], attrgetter: Callable
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
for cls in getmro(subject):
|
for cls in getmro(subject):
|
||||||
# annotation only member (ex. attr: int)
|
|
||||||
for name in getannotations(cls):
|
|
||||||
name = unmangle(cls, name)
|
|
||||||
if name and name not in members:
|
|
||||||
members[name] = ObjectMember(name, INSTANCEATTR, class_=cls)
|
|
||||||
|
|
||||||
# append instance attributes (cf. self.attr1) if analyzer knows
|
|
||||||
try:
|
try:
|
||||||
modname = safe_getattr(cls, '__module__')
|
modname = safe_getattr(cls, '__module__')
|
||||||
qualname = safe_getattr(cls, '__qualname__')
|
qualname = safe_getattr(cls, '__qualname__')
|
||||||
analyzer = ModuleAnalyzer.for_module(modname)
|
analyzer = ModuleAnalyzer.for_module(modname)
|
||||||
analyzer.analyze()
|
analyzer.analyze()
|
||||||
|
except AttributeError:
|
||||||
|
qualname = None
|
||||||
|
analyzer = None
|
||||||
|
except PycodeError:
|
||||||
|
analyzer = None
|
||||||
|
|
||||||
|
# annotation only member (ex. attr: int)
|
||||||
|
for name in getannotations(cls):
|
||||||
|
name = unmangle(cls, name)
|
||||||
|
if name and name not in members:
|
||||||
|
if analyzer and (qualname, name) in analyzer.attr_docs:
|
||||||
|
docstring = '\n'.join(analyzer.attr_docs[qualname, name])
|
||||||
|
else:
|
||||||
|
docstring = None
|
||||||
|
|
||||||
|
members[name] = ObjectMember(name, INSTANCEATTR, class_=cls,
|
||||||
|
docstring=docstring)
|
||||||
|
|
||||||
|
# append instance attributes (cf. self.attr1) if analyzer knows
|
||||||
|
if analyzer:
|
||||||
for (ns, name), docstring in analyzer.attr_docs.items():
|
for (ns, name), docstring in analyzer.attr_docs.items():
|
||||||
if ns == qualname and name not in members:
|
if ns == qualname and name not in members:
|
||||||
members[name] = ObjectMember(name, INSTANCEATTR, class_=cls,
|
members[name] = ObjectMember(name, INSTANCEATTR, class_=cls,
|
||||||
docstring='\n'.join(docstring))
|
docstring='\n'.join(docstring))
|
||||||
except (AttributeError, PycodeError):
|
|
||||||
pass
|
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -0,0 +1,8 @@
|
|||||||
|
class Base:
|
||||||
|
attr1: int #: docstring
|
||||||
|
attr2: str
|
||||||
|
|
||||||
|
|
||||||
|
class Derived(Base):
|
||||||
|
attr3: int #: docstring
|
||||||
|
attr4: str
|
@ -106,6 +106,73 @@ def test_inherited_instance_variable(app):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.version_info < (3, 6), reason='py36+ is available since python3.6.')
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_uninitialized_attributes(app):
|
||||||
|
options = {"members": None,
|
||||||
|
"inherited-members": True}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.uninitialized_attributes.Derived', options)
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:class:: Derived()',
|
||||||
|
' :module: target.uninitialized_attributes',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
' .. py:attribute:: Derived.attr1',
|
||||||
|
' :module: target.uninitialized_attributes',
|
||||||
|
' :type: int',
|
||||||
|
'',
|
||||||
|
' docstring',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
' .. py:attribute:: Derived.attr3',
|
||||||
|
' :module: target.uninitialized_attributes',
|
||||||
|
' :type: int',
|
||||||
|
'',
|
||||||
|
' docstring',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.skipif(sys.version_info < (3, 6), reason='py36+ is available since python3.6.')
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_undocumented_uninitialized_attributes(app):
|
||||||
|
options = {"members": None,
|
||||||
|
"inherited-members": True,
|
||||||
|
"undoc-members": True}
|
||||||
|
actual = do_autodoc(app, 'class', 'target.uninitialized_attributes.Derived', options)
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:class:: Derived()',
|
||||||
|
' :module: target.uninitialized_attributes',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
' .. py:attribute:: Derived.attr1',
|
||||||
|
' :module: target.uninitialized_attributes',
|
||||||
|
' :type: int',
|
||||||
|
'',
|
||||||
|
' docstring',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
' .. py:attribute:: Derived.attr2',
|
||||||
|
' :module: target.uninitialized_attributes',
|
||||||
|
' :type: str',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
' .. py:attribute:: Derived.attr3',
|
||||||
|
' :module: target.uninitialized_attributes',
|
||||||
|
' :type: int',
|
||||||
|
'',
|
||||||
|
' docstring',
|
||||||
|
'',
|
||||||
|
'',
|
||||||
|
' .. py:attribute:: Derived.attr4',
|
||||||
|
' :module: target.uninitialized_attributes',
|
||||||
|
' :type: str',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
def test_decorators(app):
|
def test_decorators(app):
|
||||||
actual = do_autodoc(app, 'class', 'target.decorator.Baz')
|
actual = do_autodoc(app, 'class', 'target.decorator.Baz')
|
||||||
assert list(actual) == [
|
assert list(actual) == [
|
||||||
|
Loading…
Reference in New Issue
Block a user