Skip to content

Commit 1a96f16

Browse files
committedJan 13, 2023·
Derive pytest.raises from AbstractContextManager
Makes `AbstractContextManager` the shared base class between "raises" and other context managers. The motivation is for type checkers to narrow `pytest.raises(...) if x else nullcontext()` to a `ContextManager` rather than `object`.
1 parent 3ad4344 commit 1a96f16

File tree

3 files changed

+15
-2
lines changed

3 files changed

+15
-2
lines changed
 

‎changelog/10660.bugfix.rst

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :py:func:`pytest.raises` to return a 'ContextManager' so that type-checkers could narrow
2+
:code:`pytest.raises(...) if ... else nullcontext()` down to 'ContextManager' rather than 'object'.

‎src/_pytest/python_api.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
from typing import Any
99
from typing import Callable
1010
from typing import cast
11-
from typing import Generic
11+
from typing import ContextManager
1212
from typing import List
1313
from typing import Mapping
1414
from typing import Optional
@@ -957,7 +957,7 @@ def raises( # noqa: F811
957957

958958

959959
@final
960-
class RaisesContext(Generic[E]):
960+
class RaisesContext(ContextManager[_pytest._code.ExceptionInfo[E]]):
961961
def __init__(
962962
self,
963963
expected_exception: Union[Type[E], Tuple[Type[E], ...]],

‎testing/typing_checks.py

+11
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,11 @@
33
This file is not executed, it is only checked by mypy to ensure that
44
none of the code triggers any mypy errors.
55
"""
6+
import contextlib
7+
from typing import Optional
8+
9+
from typing_extensions import assert_type
10+
611
import pytest
712

813

@@ -22,3 +27,9 @@ def check_fixture_ids_callable() -> None:
2227
@pytest.mark.parametrize("func", [str, int], ids=lambda x: str(x.__name__))
2328
def check_parametrize_ids_callable(func) -> None:
2429
pass
30+
31+
32+
def check_raises_is_a_context_manager(val: bool) -> None:
33+
with pytest.raises(RuntimeError) if val else contextlib.nullcontext() as excinfo:
34+
pass
35+
assert_type(excinfo, Optional[pytest.ExceptionInfo[RuntimeError]])

0 commit comments

Comments
 (0)
Please sign in to comment.