From beae7fd0ba063dd8ef980e15d66286a584aebc97 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Sat, 13 Aug 2022 21:04:59 +0300 Subject: [PATCH] doc: workaround for ugly API docs for overloaded functions with new Sphinx New Sphinx added support for overloads and always displays them all with full type annotations etc. This regresses the API reference for overloaded functions like `fixture()`, `warns()`, `raises()` and friends to become impossible to read. I tried various workarounds but none worked except this one. --- src/_pytest/compat.py | 11 ++++++++++- src/_pytest/fixtures.py | 6 +++--- src/_pytest/main.py | 6 +++--- src/_pytest/python_api.py | 6 +++--- src/_pytest/recwarn.py | 12 +++++++----- 5 files changed, 26 insertions(+), 15 deletions(-) diff --git a/src/_pytest/compat.py b/src/_pytest/compat.py index d0cb07b22..fab4c3110 100644 --- a/src/_pytest/compat.py +++ b/src/_pytest/compat.py @@ -20,6 +20,16 @@ from typing import Union import attr import py +# fmt: off +# Workaround for https://github.com/sphinx-doc/sphinx/issues/10351. +# If `overload` is imported from `compat` instead of from `typing`, +# Sphinx doesn't recognize it as `overload` and the API docs for +# overloaded functions look good again. But type checkers handle +# it fine. +# fmt: on +if True: + from typing import overload as overload + if TYPE_CHECKING: from typing_extensions import Final @@ -345,7 +355,6 @@ else: if sys.version_info >= (3, 8): from functools import cached_property as cached_property else: - from typing import overload from typing import Type class cached_property(Generic[_S, _T]): diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 30b6054d0..d79895c26 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -20,7 +20,6 @@ from typing import List from typing import MutableMapping from typing import NoReturn from typing import Optional -from typing import overload from typing import Sequence from typing import Set from typing import Tuple @@ -48,6 +47,7 @@ from _pytest.compat import getimfunc from _pytest.compat import getlocation from _pytest.compat import is_generator from _pytest.compat import NOTSET +from _pytest.compat import overload from _pytest.compat import safe_getattr from _pytest.config import _PluggyPlugin from _pytest.config import Config @@ -1231,7 +1231,7 @@ def fixture( @overload -def fixture( +def fixture( # noqa: F811 fixture_function: None = ..., *, scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = ..., @@ -1245,7 +1245,7 @@ def fixture( ... -def fixture( +def fixture( # noqa: F811 fixture_function: Optional[FixtureFunction] = None, *, scope: "Union[_ScopeName, Callable[[str, Config], _ScopeName]]" = "function", diff --git a/src/_pytest/main.py b/src/_pytest/main.py index 4a117fc2e..61fb7eaa4 100644 --- a/src/_pytest/main.py +++ b/src/_pytest/main.py @@ -12,7 +12,6 @@ from typing import FrozenSet from typing import Iterator from typing import List from typing import Optional -from typing import overload from typing import Sequence from typing import Set from typing import Tuple @@ -25,6 +24,7 @@ import attr import _pytest._code from _pytest import nodes from _pytest.compat import final +from _pytest.compat import overload from _pytest.config import Config from _pytest.config import directory_arg from _pytest.config import ExitCode @@ -597,12 +597,12 @@ class Session(nodes.FSCollector): ... @overload - def perform_collect( + def perform_collect( # noqa: F811 self, args: Optional[Sequence[str]] = ..., genitems: bool = ... ) -> Sequence[Union[nodes.Item, nodes.Collector]]: ... - def perform_collect( + def perform_collect( # noqa: F811 self, args: Optional[Sequence[str]] = None, genitems: bool = True ) -> Sequence[Union[nodes.Item, nodes.Collector]]: """Perform the collection phase for this session. diff --git a/src/_pytest/python_api.py b/src/_pytest/python_api.py index 00e377f40..515d437f0 100644 --- a/src/_pytest/python_api.py +++ b/src/_pytest/python_api.py @@ -12,7 +12,6 @@ from typing import Generic from typing import List from typing import Mapping from typing import Optional -from typing import overload from typing import Pattern from typing import Sequence from typing import Tuple @@ -28,6 +27,7 @@ if TYPE_CHECKING: import _pytest._code from _pytest.compat import final from _pytest.compat import STRING_TYPES +from _pytest.compat import overload from _pytest.outcomes import fail @@ -786,7 +786,7 @@ def raises( @overload -def raises( +def raises( # noqa: F811 expected_exception: Union[Type[E], Tuple[Type[E], ...]], func: Callable[..., Any], *args: Any, @@ -795,7 +795,7 @@ def raises( ... -def raises( +def raises( # noqa: F811 expected_exception: Union[Type[E], Tuple[Type[E], ...]], *args: Any, **kwargs: Any ) -> Union["RaisesContext[E]", _pytest._code.ExceptionInfo[E]]: r"""Assert that a code block/function call raises an exception. diff --git a/src/_pytest/recwarn.py b/src/_pytest/recwarn.py index 9c6e7e91d..9971bb52f 100644 --- a/src/_pytest/recwarn.py +++ b/src/_pytest/recwarn.py @@ -9,7 +9,6 @@ from typing import Generator from typing import Iterator from typing import List from typing import Optional -from typing import overload from typing import Pattern from typing import Tuple from typing import Type @@ -17,6 +16,7 @@ from typing import TypeVar from typing import Union from _pytest.compat import final +from _pytest.compat import overload from _pytest.deprecated import check_ispytest from _pytest.deprecated import WARNS_NONE_ARG from _pytest.fixtures import fixture @@ -47,11 +47,13 @@ def deprecated_call( @overload -def deprecated_call(func: Callable[..., T], *args: Any, **kwargs: Any) -> T: +def deprecated_call( # noqa: F811 + func: Callable[..., T], *args: Any, **kwargs: Any +) -> T: ... -def deprecated_call( +def deprecated_call( # noqa: F811 func: Optional[Callable[..., Any]] = None, *args: Any, **kwargs: Any ) -> Union["WarningsRecorder", Any]: """Assert that code produces a ``DeprecationWarning`` or ``PendingDeprecationWarning``. @@ -93,7 +95,7 @@ def warns( @overload -def warns( +def warns( # noqa: F811 expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]], func: Callable[..., T], *args: Any, @@ -102,7 +104,7 @@ def warns( ... -def warns( +def warns( # noqa: F811 expected_warning: Union[Type[Warning], Tuple[Type[Warning], ...]] = Warning, *args: Any, match: Optional[Union[str, Pattern[str]]] = None,