diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index 15f0d66e2..d51d6854c 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -13,6 +13,7 @@ import enum import inspect import re import sys +import types import typing import warnings from functools import partial, partialmethod @@ -304,6 +305,18 @@ def isproperty(obj: Any) -> bool: return isinstance(obj, property) +def isgenericalias(obj: Any) -> bool: + """Check if the object is GenericAlias.""" + if (hasattr(typing, '_GenericAlias') and # only for py37+ + isinstance(obj, typing._GenericAlias)): # type: ignore + return True + elif (hasattr(types, 'GenericAlias') and # only for py39+ + isinstance(obj, types.GenericAlias)): # type: ignore + return True + else: + return False + + def safe_getattr(obj: Any, name: str, *defargs: Any) -> Any: """A getattr() that turns all exceptions into AttributeErrors.""" try: diff --git a/tests/roots/test-ext-autodoc/target/genericalias.py b/tests/roots/test-ext-autodoc/target/genericalias.py new file mode 100644 index 000000000..78b68cd63 --- /dev/null +++ b/tests/roots/test-ext-autodoc/target/genericalias.py @@ -0,0 +1,6 @@ +from typing import List, Callable + +#: A list of int +T = List[int] + +C = Callable[[int], None] # a generic alias not having a doccomment diff --git a/tests/test_util_inspect.py b/tests/test_util_inspect.py index f16feb698..ae4c34962 100644 --- a/tests/test_util_inspect.py +++ b/tests/test_util_inspect.py @@ -560,6 +560,18 @@ def test_isproperty(app): assert inspect.isproperty(func) is False # function +@pytest.mark.skipif(sys.version_info < (3, 7), reason='python 3.7+ is required.') +@pytest.mark.sphinx(testroot='ext-autodoc') +def test_isgenericalias(app): + from target.genericalias import C, T + from target.methods import Base + + assert inspect.isgenericalias(C) is True + assert inspect.isgenericalias(T) is True + assert inspect.isgenericalias(object()) is False + assert inspect.isgenericalias(Base) is False + + def test_unpartial(): def func1(a, b, c): pass