mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix #9283: autodoc: failed to build doc for attribute not commented
Autoattribute directive should check the existence of instance attribute that is defined inside __init__() but not having comments before accessing it.
This commit is contained in:
parent
2809b30c17
commit
9a9433e403
2
CHANGES
2
CHANGES
@ -55,6 +55,8 @@ Bugs fixed
|
|||||||
undocumented
|
undocumented
|
||||||
* #9185: autodoc: typehints for overloaded functions and methods are inaccurate
|
* #9185: autodoc: typehints for overloaded functions and methods are inaccurate
|
||||||
* #9250: autodoc: The inherited method not having docstring is wrongly parsed
|
* #9250: autodoc: The inherited method not having docstring is wrongly parsed
|
||||||
|
* #9283: autodoc: autoattribute directive failed to generate document for an
|
||||||
|
attribute not having any comment
|
||||||
* #9270: html theme : pyramid theme generates incorrect logo links
|
* #9270: html theme : pyramid theme generates incorrect logo links
|
||||||
* #9217: manpage: The name of manpage directory that is generated by
|
* #9217: manpage: The name of manpage directory that is generated by
|
||||||
:confval:`man_make_section_directory` is not correct
|
:confval:`man_make_section_directory` is not correct
|
||||||
|
@ -2356,9 +2356,29 @@ class RuntimeInstanceAttributeMixin(DataDocumenterMixinBase):
|
|||||||
# An instance variable defined in __init__().
|
# An instance variable defined in __init__().
|
||||||
if self.get_attribute_comment(parent, self.objpath[-1]): # type: ignore
|
if self.get_attribute_comment(parent, self.objpath[-1]): # type: ignore
|
||||||
return True
|
return True
|
||||||
|
elif self.is_runtime_instance_attribute_not_commented(parent):
|
||||||
|
return True
|
||||||
else:
|
else:
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
def is_runtime_instance_attribute_not_commented(self, parent: Any) -> bool:
|
||||||
|
"""Check the subject is an attribute defined in __init__() without comment."""
|
||||||
|
for cls in inspect.getmro(parent):
|
||||||
|
try:
|
||||||
|
module = safe_getattr(cls, '__module__')
|
||||||
|
qualname = safe_getattr(cls, '__qualname__')
|
||||||
|
|
||||||
|
analyzer = ModuleAnalyzer.for_module(module)
|
||||||
|
analyzer.analyze()
|
||||||
|
if qualname and self.objpath:
|
||||||
|
key = '.'.join([qualname, self.objpath[-1]])
|
||||||
|
if key in analyzer.tagorder:
|
||||||
|
return True
|
||||||
|
except (AttributeError, PycodeError):
|
||||||
|
pass
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
def import_object(self, raiseerror: bool = False) -> bool:
|
def import_object(self, raiseerror: bool = False) -> bool:
|
||||||
"""Check the existence of runtime instance attribute when failed to import the
|
"""Check the existence of runtime instance attribute when failed to import the
|
||||||
attribute."""
|
attribute."""
|
||||||
@ -2389,6 +2409,13 @@ class RuntimeInstanceAttributeMixin(DataDocumenterMixinBase):
|
|||||||
return (self.object is self.RUNTIME_INSTANCE_ATTRIBUTE or
|
return (self.object is self.RUNTIME_INSTANCE_ATTRIBUTE or
|
||||||
super().should_suppress_value_header())
|
super().should_suppress_value_header())
|
||||||
|
|
||||||
|
def get_doc(self, ignore: int = None) -> Optional[List[List[str]]]:
|
||||||
|
if (self.object is self.RUNTIME_INSTANCE_ATTRIBUTE and
|
||||||
|
self.is_runtime_instance_attribute_not_commented(self.parent)):
|
||||||
|
return None
|
||||||
|
else:
|
||||||
|
return super().get_doc(ignore) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
|
class UninitializedInstanceAttributeMixin(DataDocumenterMixinBase):
|
||||||
"""
|
"""
|
||||||
|
@ -8,3 +8,4 @@ class Bar(Foo):
|
|||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.attr2 = None #: docstring bar
|
self.attr2 = None #: docstring bar
|
||||||
self.attr3 = None #: docstring bar
|
self.attr3 = None #: docstring bar
|
||||||
|
self.attr4 = None
|
||||||
|
@ -100,6 +100,17 @@ def test_autoattribute_instance_variable_in_alias(app):
|
|||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
|
def test_autoattribute_instance_variable_without_comment(app):
|
||||||
|
actual = do_autodoc(app, 'attribute', 'target.instance_variable.Bar.attr4')
|
||||||
|
assert list(actual) == [
|
||||||
|
'',
|
||||||
|
'.. py:attribute:: Bar.attr4',
|
||||||
|
' :module: target.instance_variable',
|
||||||
|
'',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
@pytest.mark.sphinx('html', testroot='ext-autodoc')
|
||||||
def test_autoattribute_slots_variable_list(app):
|
def test_autoattribute_slots_variable_list(app):
|
||||||
actual = do_autodoc(app, 'attribute', 'target.slots.Foo.attr')
|
actual = do_autodoc(app, 'attribute', 'target.slots.Foo.attr')
|
||||||
|
Loading…
Reference in New Issue
Block a user