From 0bf514314e66ce4c2746674da2d40292d55b1fd8 Mon Sep 17 00:00:00 2001 From: Takeshi KOMIYA Date: Thu, 13 Aug 2020 00:05:27 +0900 Subject: [PATCH] Fix #8099: autodoc: NameError is raised when script uses TYPE_CHECKING `typing.get_type_hints()` raises NameError when the target object contains unresolavable type annotation (ex. TYPE_CHECKING). This handles the exception and use unresolved annotations for type hints. --- CHANGES | 1 + sphinx/ext/autodoc/__init__.py | 6 ++++++ tests/test_ext_autodoc.py | 21 +++++++++++++++++++++ 3 files changed, 28 insertions(+) diff --git a/CHANGES b/CHANGES index 1d523f3fd99..e4cc026a583 100644 --- a/CHANGES +++ b/CHANGES @@ -42,6 +42,7 @@ Bugs fixed class * #8091: autodoc: AttributeError is raised on documenting an attribute on Python 3.5.2 +* #8099: autodoc: NameError is raised when target code uses ``TYPE_CHECKING`` Testing -------- diff --git a/sphinx/ext/autodoc/__init__.py b/sphinx/ext/autodoc/__init__.py index f3820f71552..b61a96c8494 100644 --- a/sphinx/ext/autodoc/__init__.py +++ b/sphinx/ext/autodoc/__init__.py @@ -1608,6 +1608,9 @@ def add_directive_header(self, sig: str) -> None: # obtain annotation for this data try: annotations = get_type_hints(self.parent) + except NameError: + # Failed to evaluate ForwardRef (maybe TYPE_CHECKING) + annotations = safe_getattr(self.parent, '__annotations__', {}) except TypeError: annotations = {} except KeyError: @@ -1984,6 +1987,9 @@ def add_directive_header(self, sig: str) -> None: # obtain type annotation for this attribute try: annotations = get_type_hints(self.parent) + except NameError: + # Failed to evaluate ForwardRef (maybe TYPE_CHECKING) + annotations = safe_getattr(self.parent, '__annotations__', {}) except TypeError: annotations = {} except KeyError: diff --git a/tests/test_ext_autodoc.py b/tests/test_ext_autodoc.py index 15e1f35395e..ca6f0168c71 100644 --- a/tests/test_ext_autodoc.py +++ b/tests/test_ext_autodoc.py @@ -1740,6 +1740,27 @@ def test_autodoc_Annotated(app): ] +@pytest.mark.sphinx('html', testroot='ext-autodoc') +def test_autodoc_TYPE_CHECKING(app): + options = {"members": None, + "undoc-members": None} + actual = do_autodoc(app, 'module', 'target.TYPE_CHECKING', options) + assert list(actual) == [ + '', + '.. py:module:: target.TYPE_CHECKING', + '', + '', + '.. py:class:: Foo()', + ' :module: target.TYPE_CHECKING', + '', + '', + ' .. py:attribute:: Foo.attr1', + ' :module: target.TYPE_CHECKING', + ' :type: StringIO', + '', + ] + + @pytest.mark.sphinx('html', testroot='pycode-egg') def test_autodoc_for_egged_code(app): options = {"members": None,