From 91f6892e6a68c55adc8c9113b427cf96e5c8ee22 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 14 Jul 2020 14:36:41 +0300 Subject: [PATCH 1/2] testing: add a file for checking no mypy errors We probably something a bit more elaborate in the future but for now it's something to verify fixes and catch regressions. --- testing/typing_checks.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 testing/typing_checks.py diff --git a/testing/typing_checks.py b/testing/typing_checks.py new file mode 100644 index 000000000..94c66ef51 --- /dev/null +++ b/testing/typing_checks.py @@ -0,0 +1,12 @@ +"""File for checking typing issues. + +This file is not executed, it is only checked by mypy to ensure that +none of the code triggers any mypy errors. +""" +import pytest + + +# Issue #7488. +@pytest.mark.xfail(raises=RuntimeError) +def check_mark_xfail_raises() -> None: + pass From bc17034a67c2ce9cc9169fd85b65bdd2a92db772 Mon Sep 17 00:00:00 2001 From: Ran Benita Date: Tue, 14 Jul 2020 13:05:38 +0300 Subject: [PATCH 2/2] Fix typing of params ids callable form The previous typing had an object passed to the user, which they can't do anything with without asserting, which is inconvenient. Change it to Any instead. Note that what comes *back* to pytest (the return value) should be an `object`, because we want to handle arbitrary objects without assuming anything about them. --- src/_pytest/fixtures.py | 14 +++++++------- src/_pytest/mark/structures.py | 2 +- src/_pytest/python.py | 11 ++++++----- testing/typing_checks.py | 12 ++++++++++++ 4 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/_pytest/fixtures.py b/src/_pytest/fixtures.py index 8fd56f8ac..b24fc5fd3 100644 --- a/src/_pytest/fixtures.py +++ b/src/_pytest/fixtures.py @@ -976,7 +976,7 @@ class FixtureDef(Generic[_FixtureValue]): ids: Optional[ Union[ Tuple[Union[None, str, float, int, bool], ...], - Callable[[object], Optional[object]], + Callable[[Any], Optional[object]], ] ] = None, ) -> None: @@ -1128,13 +1128,13 @@ def _ensure_immutable_ids( ids: Optional[ Union[ Iterable[Union[None, str, float, int, bool]], - Callable[[object], Optional[object]], + Callable[[Any], Optional[object]], ] ], ) -> Optional[ Union[ Tuple[Union[None, str, float, int, bool], ...], - Callable[[object], Optional[object]], + Callable[[Any], Optional[object]], ] ]: if ids is None: @@ -1180,7 +1180,7 @@ class FixtureFunctionMarker: ids = attr.ib( type=Union[ Tuple[Union[None, str, float, int, bool], ...], - Callable[[object], Optional[object]], + Callable[[Any], Optional[object]], ], default=None, converter=_ensure_immutable_ids, @@ -1223,7 +1223,7 @@ def fixture( ids: Optional[ Union[ Iterable[Union[None, str, float, int, bool]], - Callable[[object], Optional[object]], + Callable[[Any], Optional[object]], ] ] = ..., name: Optional[str] = ... @@ -1241,7 +1241,7 @@ def fixture( # noqa: F811 ids: Optional[ Union[ Iterable[Union[None, str, float, int, bool]], - Callable[[object], Optional[object]], + Callable[[Any], Optional[object]], ] ] = ..., name: Optional[str] = None @@ -1258,7 +1258,7 @@ def fixture( # noqa: F811 ids: Optional[ Union[ Iterable[Union[None, str, float, int, bool]], - Callable[[object], Optional[object]], + Callable[[Any], Optional[object]], ] ] = None, name: Optional[str] = None diff --git a/src/_pytest/mark/structures.py b/src/_pytest/mark/structures.py index c55e04755..5edeecdd5 100644 --- a/src/_pytest/mark/structures.py +++ b/src/_pytest/mark/structures.py @@ -433,7 +433,7 @@ if TYPE_CHECKING: ids: Optional[ Union[ Iterable[Union[None, str, float, int, bool]], - Callable[[object], Optional[object]], + Callable[[Any], Optional[object]], ] ] = ..., scope: Optional[_Scope] = ... diff --git a/src/_pytest/python.py b/src/_pytest/python.py index 7209bf1ed..aa8171486 100644 --- a/src/_pytest/python.py +++ b/src/_pytest/python.py @@ -11,6 +11,7 @@ from collections import Counter from collections import defaultdict from collections.abc import Sequence from functools import partial +from typing import Any from typing import Callable from typing import Dict from typing import Generator @@ -920,7 +921,7 @@ class Metafunc: ids: Optional[ Union[ Iterable[Union[None, str, float, int, bool]], - Callable[[object], Optional[object]], + Callable[[Any], Optional[object]], ] ] = None, scope: "Optional[_Scope]" = None, @@ -1040,7 +1041,7 @@ class Metafunc: ids: Optional[ Union[ Iterable[Union[None, str, float, int, bool]], - Callable[[object], Optional[object]], + Callable[[Any], Optional[object]], ] ], parameters: typing.Sequence[ParameterSet], @@ -1226,7 +1227,7 @@ def _idval( val: object, argname: str, idx: int, - idfn: Optional[Callable[[object], Optional[object]]], + idfn: Optional[Callable[[Any], Optional[object]]], nodeid: Optional[str], config: Optional[Config], ) -> str: @@ -1266,7 +1267,7 @@ def _idvalset( idx: int, parameterset: ParameterSet, argnames: Iterable[str], - idfn: Optional[Callable[[object], Optional[object]]], + idfn: Optional[Callable[[Any], Optional[object]]], ids: Optional[List[Union[None, str]]], nodeid: Optional[str], config: Optional[Config], @@ -1287,7 +1288,7 @@ def _idvalset( def idmaker( argnames: Iterable[str], parametersets: Iterable[ParameterSet], - idfn: Optional[Callable[[object], Optional[object]]] = None, + idfn: Optional[Callable[[Any], Optional[object]]] = None, ids: Optional[List[Union[None, str]]] = None, config: Optional[Config] = None, nodeid: Optional[str] = None, diff --git a/testing/typing_checks.py b/testing/typing_checks.py index 94c66ef51..0a6b5ad28 100644 --- a/testing/typing_checks.py +++ b/testing/typing_checks.py @@ -10,3 +10,15 @@ import pytest @pytest.mark.xfail(raises=RuntimeError) def check_mark_xfail_raises() -> None: pass + + +# Issue #7494. +@pytest.fixture(params=[(0, 0), (1, 1)], ids=lambda x: str(x[0])) +def check_fixture_ids_callable() -> None: + pass + + +# Issue #7494. +@pytest.mark.parametrize("func", [str, int], ids=lambda x: str(x.__name__)) +def check_parametrize_ids_callable(func) -> None: + pass