diff --git a/CHANGES b/CHANGES index 5ccb86c98..5327660c0 100644 --- a/CHANGES +++ b/CHANGES @@ -89,6 +89,7 @@ Bugs fixed * #8917: autodoc: Raises a warning if function has wrong __globals__ value * #8415: autodoc: a TypeVar imported from other module is not resolved (in Python 3.7 or above) +* #8992: autodoc: Failed to resolve types.TracebackType type annotation * #8905: html: html_add_permalinks=None and html_add_permalinks="" are ignored * #8380: html search: Paragraphs in search results are not identified as ``
`` * #8915: html theme: The translation of sphinx_rtd_theme does not work diff --git a/sphinx/util/typing.py b/sphinx/util/typing.py index 128fbd542..450bc40e6 100644 --- a/sphinx/util/typing.py +++ b/sphinx/util/typing.py @@ -11,6 +11,7 @@ import sys import typing from struct import Struct +from types import TracebackType from typing import Any, Callable, Dict, Generator, List, Optional, Tuple, TypeVar, Union from docutils import nodes @@ -42,6 +43,13 @@ if False: from typing import Type # NOQA # for python3.5.1 +# builtin classes that have incorrect __module__ +INVALID_BUILTIN_CLASSES = { + Struct: 'struct.Struct', # Before Python 3.9 + TracebackType: 'types.TracebackType', +} + + # Text like nodes which are initialized with text and rawsource TextlikeNode = Union[nodes.Text, nodes.TextElement] @@ -101,9 +109,8 @@ def restify(cls: Optional["Type"]) -> str: return ':obj:`None`' elif cls is Ellipsis: return '...' - elif cls is Struct: - # Before Python 3.9, struct.Struct class has incorrect __module__. - return ':class:`struct.Struct`' + elif cls in INVALID_BUILTIN_CLASSES: + return ':class:`%s`' % INVALID_BUILTIN_CLASSES[cls] elif inspect.isNewType(cls): return ':class:`%s`' % cls.__name__ elif types_Union and isinstance(cls, types_Union): @@ -276,14 +283,13 @@ def stringify(annotation: Any) -> str: return repr(annotation) elif annotation is NoneType: return 'None' + elif annotation in INVALID_BUILTIN_CLASSES: + return INVALID_BUILTIN_CLASSES[annotation] elif (getattr(annotation, '__module__', None) == 'builtins' and hasattr(annotation, '__qualname__')): return annotation.__qualname__ elif annotation is Ellipsis: return '...' - elif annotation is Struct: - # Before Python 3.9, struct.Struct class has incorrect __module__. - return 'struct.Struct' if sys.version_info >= (3, 7): # py37+ return _stringify_py37(annotation) diff --git a/tests/test_util_typing.py b/tests/test_util_typing.py index 97732965e..5a5808ac5 100644 --- a/tests/test_util_typing.py +++ b/tests/test_util_typing.py @@ -11,6 +11,7 @@ import sys from numbers import Integral from struct import Struct +from types import TracebackType from typing import (Any, Callable, Dict, Generator, List, NewType, Optional, Tuple, TypeVar, Union) @@ -45,6 +46,7 @@ def test_restify(): assert restify(None) == ":obj:`None`" assert restify(Integral) == ":class:`numbers.Integral`" assert restify(Struct) == ":class:`struct.Struct`" + assert restify(TracebackType) == ":class:`types.TracebackType`" assert restify(Any) == ":obj:`Any`" @@ -133,7 +135,8 @@ def test_stringify(): assert stringify(str) == "str" assert stringify(None) == "None" assert stringify(Integral) == "numbers.Integral" - assert restify(Struct) == ":class:`struct.Struct`" + assert stringify(Struct) == "struct.Struct" + assert stringify(TracebackType) == "types.TracebackType" assert stringify(Any) == "Any"