raises.py


Overview

The [raises.py](/projects/286/67496) file provides a core utility for the `pytest` testing framework to assert that code raises expected exceptions during test execution. It offers a flexible API to specify expected exceptions by type, match exception messages with regular expressions, or apply custom checks on raised exceptions.

Key functionalities include:

This file is integral to pytest's assertion mechanism for exception handling in tests, helping improve test clarity and robustness by providing detailed feedback on mismatched exceptions.


Classes and Functions

raises

def raises(
    expected_exception: type[E] | tuple[type[E], ...] | None = None,
    *args: Any,
    **kwargs: Any,
) -> RaisesExc[BaseException] | ExceptionInfo[E]:

Purpose

A versatile function and context manager to assert that a code block or a callable raises an expected exception. It supports both context manager and function-call styles.

Parameters

Returns

Usage Examples

# Using as a context manager
with raises(ZeroDivisionError):
    1 / 0

# Using match to test exception message
with raises(ValueError, match=r"must be \d+$"):
    raise ValueError("value must be 42")

# Using check callable for custom validation
with raises(OSError, check=lambda e: e.errno == errno.EACCES):
    raise OSError(errno.EACCES, "no permission to view")

# Using as a function with callable
def f(x): return 1 / x
raises(ZeroDivisionError, f, 0)

Important Notes


AbstractRaises

class AbstractRaises(ABC, Generic[BaseExcT_co]):

Purpose

An abstract base class providing shared functionality for checking exceptions, used by `RaisesExc` and `RaisesGroup`.

Key Methods

Properties


RaisesExc

class RaisesExc(AbstractRaises[BaseExcT_co_default]):

Purpose

Represents an expectation for a single exception or multiple exception types, optionally matched by regex or custom check. Constructed by `raises()` when expecting non-group exceptions.

Constructor Parameters

Key Methods

Usage Examples

with RaisesExc(ValueError, match="string"):
    raise ValueError("string")

with RaisesExc(check=lambda e: e.args == (3, "hello")):
    raise ValueError(3, "hello")

with RaisesExc(check=lambda e: type(e) is ValueError):
    raise ValueError()

RaisesGroup

class RaisesGroup(AbstractRaises[BaseExceptionGroup[BaseExcT_co]]):

Purpose

A context manager class to assert that an `ExceptionGroup` or `BaseExceptionGroup` is raised, matching a specified structure of nested exceptions and subgroups.

Constructor Parameters

Key Methods

Usage Examples

with RaisesGroup(ValueError):
    raise ExceptionGroup("", (ValueError(),))

with RaisesGroup(
    ValueError,
    RaisesExc(TypeError, match="^expected int$"),
    match="^my group$",
):
    raise ExceptionGroup(
        "my group",
        [
            ValueError(),
            TypeError("expected int"),
            ValueError(),
        ],
    )

with RaisesGroup(ValueError, allow_unwrapped=True):
    raise ValueError

ResultHolder

class ResultHolder:

Purpose

A utility class used internally by `RaisesGroup` to keep track of match results between expected exceptions and actual raised exceptions when matching groups.

Key Methods


possible_match

def possible_match(results: ResultHolder, used: set[int] | None = None) -> bool:

Purpose

A recursive helper function to detect if there exists any possible matching between expected and actual exceptions beyond the greedy algorithm used in `RaisesGroup`.


Important Implementation Details


Interaction with Other System Components


Visual Diagram

classDiagram
    direction TB

    class AbstractRaises {
        -match: Pattern[str] | None
        -check: Callable[[BaseExcT_co], bool] | None
        -_fail_reason: str | None
        +fail_reason: str | None
        +_parse_exc(exc, expected: str)
        +_check_raw_type(expected_type, exception)
        +_check_check(exception)
        +_check_match(exception)
        +matches(exception) <<abstract>>
    }

    class RaisesExc {
        -expected_exceptions: tuple[type[BaseException], ...]
        -_just_propagate: bool
        +__init__(expected_exception=None, *, match=None, check=None)
        +matches(exception)
        +__enter__()
        +__exit__(exc_type, exc_val, exc_tb)
        +__repr__()
    }

    class RaisesGroup {
        -expected_exceptions: tuple[type | RaisesExc | RaisesGroup, ...]
        -allow_unwrapped: bool
        -flatten_subgroups: bool
        +__init__(expected_exception, *other_exceptions, allow_unwrapped=False, flatten_subgroups=False, match=None, check=None)
        +matches(exception)
        +_check_exceptions(_exception, actual_exceptions)
        +__enter__()
        +__exit__(exc_type, exc_val, exc_tb)
        +expected_type()
        +__repr__()
    }

    class ResultHolder {
        -results: list[list[str | None]]
        +set_result(expected, actual, result)
        +get_result(expected, actual)
        +has_result(expected, actual)
        +no_match_for_expected(expected)
        +no_match_for_actual(actual)
    }

    AbstractRaises <|-- RaisesExc
    AbstractRaises <|-- RaisesGroup

    RaisesGroup --> ResultHolder : uses

Summary

The [raises.py](/projects/286/67496) file is a fundamental component of `pytest`'s exception assertion system. It provides both simple exception type checks and advanced support for Python exception groups, offering rich APIs for precise and readable test assertions. The system uses a combination of regex matching, callable checks, and type checking to validate raised exceptions. The design emphasizes detailed failure explanations and type safety, contributing significantly to pytest's user-friendly and powerful testing capabilities.