From 97f36a2d027f50c021ae2f3a9f07cd64ae5c8071 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Tue, 29 Dec 2020 17:29:53 +0900 Subject: [PATCH] Fix #8602: autodoc: The ``autodoc-process-docstring`` event is emitted to the non-datadescriptors unexpectedly --- CHANGES | 3 +++ sphinx/ext/autodoc/__init__.py | 22 ++++++++++++++++++++-- tests/test_ext_autodoc_events.py | 17 +++++++++++++++++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 895293b7fb3..4fd3f69db8f 100644 --- a/CHANGES +++ b/CHANGES @@ -16,6 +16,9 @@ Features added Bugs fixed ---------- +* #8602: autodoc: The ``autodoc-process-docstring`` event is emitted to the + non-datadescriptors unexpectedly + Testing -------- diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index 85f9f6de255..54a2e8c3e74 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -2092,18 +2092,36 @@ class NonDataDescriptorMixin(DataDocumenterMixinBase): and :value: header will be suppressed unexpectedly. """ + def import_object(self, raiseerror: bool = False) -> bool: + ret = super().import_object(raiseerror) # type: ignore + if ret and not inspect.isattributedescriptor(self.object): + self.non_data_descriptor = True + else: + self.non_data_descriptor = False + + return ret + def should_suppress_value_header(self) -> bool: - return (inspect.isattributedescriptor(self.object) or + return (not getattr(self, 'non_data_descriptor', False) or super().should_suppress_directive_header()) def get_doc(self, encoding: str = None, ignore: int = None) -> List[List[str]]: - if not inspect.isattributedescriptor(self.object): + if getattr(self, 'non_data_descriptor', False): # the docstring of non datadescriptor is very probably the wrong thing # to display return [] else: return super().get_doc(encoding, ignore) # type: ignore + def add_content(self, more_content: Optional[StringList], no_docstring: bool = False + ) -> None: + if getattr(self, 'non_data_descriptor', False): + # the docstring of non datadescriptor is very probably the wrong thing + # to display + no_docstring = True + + super().add_content(more_content, no_docstring=no_docstring) # type: ignore + class SlotsMixin(DataDocumenterMixinBase): """ diff --git a/tests/test_ext_autodoc_events.py b/tests/test_ext_autodoc_events.py index ad6a811298a..d00dea180db 100644 --- a/tests/test_ext_autodoc_events.py +++ b/tests/test_ext_autodoc_events.py @@ -34,6 +34,23 @@ def on_process_docstring(app, what, name, obj, options, lines): ] +@pytest.mark.sphinx('html', testroot='ext-autodoc') +def test_process_docstring_for_nondatadescriptor(app): + def on_process_docstring(app, what, name, obj, options, lines): + raise + + app.connect('autodoc-process-docstring', on_process_docstring) + + actual = do_autodoc(app, 'attribute', 'target.AttCls.a1') + assert list(actual) == [ + '', + '.. py:attribute:: AttCls.a1', + ' :module: target', + ' :value: hello world', + '', + ] + + @pytest.mark.sphinx('html', testroot='ext-autodoc') def test_cut_lines(app): app.connect('autodoc-process-docstring',