Skip to content

Commit f5c5a85

Browse files
committed
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 f5c5a85

File tree

2 files changed

+12
-2
lines changed

2 files changed

+12
-2
lines changed

src/_pytest/python_api.py

Lines changed: 2 additions & 2 deletions
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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +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+
69
import pytest
10+
from typing_extensions import assert_type
711

812

913
# Issue #7488.
@@ -22,3 +26,9 @@ def check_fixture_ids_callable() -> None:
2226
@pytest.mark.parametrize("func", [str, int], ids=lambda x: str(x.__name__))
2327
def check_parametrize_ids_callable(func) -> None:
2428
pass
29+
30+
31+
def check_raises_is_a_context_manager(val: bool) -> None:
32+
with pytest.raises(RuntimeError) if val else contextlib.nullcontext() as excinfo:
33+
pass
34+
assert_type(excinfo, Optional[pytest.ExceptionInfo[RuntimeError]])

0 commit comments

Comments
 (0)