typing_raises_group.py
Overview
This file provides extensive type checking and validation utilities focused on the `pytest` framework's exception-raising context managers, specifically `RaisesExc` and `RaisesGroup`. It contains a series of test-like functions that verify the correct typing behavior, constructor usage, type narrowing, and matching logic of these classes. These checks ensure type safety, proper covariance and contravariance in generics, and correct behavior when dealing with Python 3.11's `ExceptionGroup` and its backport `exceptiongroup`.
Key points:
It verifies the interaction between
pytest's exception context managers and Python'sExceptionGroups.It tests type narrowing and matching behavior for exceptions, especially nested exception groups.
It explores usage scenarios including nested
RaisesGroupinstances, multiple exceptions, and constructor argument variations.It highlights some typing limitations and discrepancies (noted with FIXME and
type: ignorecomments).
This file is primarily useful for maintainers of `pytest` or typing-related tooling to ensure that the exception-raising utilities behave correctly with static type checkers.
Classes, Functions, and Methods
Imported Entities
RaisesExc,RaisesGroup— Context managers frompytestfor testing raised exceptions.Failed, main_Failed — Exception classes related to test failures inpytest.ExceptionGroup,BaseExceptionGroup— Python 3.11+ exception groups or their backport.assert_type— Utility fromtyping_extensionsto assert static types in tests.
Functions
All functions are scoped tests or usage examples demonstrating typing and behavior of `RaisesExc` and `RaisesGroup`.
check_raisesexc_typevar_default(e: RaisesExc) -> None
Purpose:
Validates that theexpected_exceptionsattribute of aRaisesExcinstance is properly typed and notNone. Also demonstrates that callingexception_type()returns a type that supports attribute access (though .blah() is a dummy call to illustrate typing).Parameters:
e: Instance ofRaisesExc.
Returns:
None.Usage:
Used to verify static typing ofRaisesExc's internal types.
check_basic_contextmanager() -> None
Purpose:
Tests the basic usage ofRaisesGroupas a context manager with a single exception type (ValueError), raising anExceptionGroup. It asserts the type of the caught exception.Returns:
None.Example:
with RaisesGroup(ValueError) as e: raise ExceptionGroup("foo", (ValueError(),)) assert_type(e.value, ExceptionGroup[ValueError])
check_basic_matches() -> None
Purpose:
Verifies that the.matches()method ofRaisesGroupproperly narrows types when matching exceptions, including unions and base classes.Returns:
None.Details:
Shows howRaisesGroup(ValueError).matches()narrows an exception union and howBaseExceptionGroupis recognized for base exceptions.
check_matches_with_different_exception_type() -> None
Purpose:
Examines behavior whenRaisesGroupis used with an exception type that differs from the actual exception group's type. It notes that type checkers cannot warn about this mismatch currently.Returns:
None.
check_raisesexc_init() -> None
Purpose:
Tests various constructor signatures ofRaisesExc, including positional and keyword arguments, and verifies type constraints on thecheckcallable parameter.Details:
Shows that
expected_exceptionmust be positional-only.matchandcheckare keyword-only.Demonstrates correct and incorrect usage with
type: ignorefor invalid cases.
Returns:
None.
raisesgroup_check_type_narrowing() -> None
Purpose:
Tests type narrowing logic on thecheckargument ofRaisesGroupfor different exception types.Details:
Defines handlers for various exception groups.
Verifies which handlers are allowed or disallowed by the type checker.
Returns:
None.
raisesgroup_narrow_baseexceptiongroup() -> None
Purpose:
Verifies type narrowing for container exception groups (ExceptionGroup) specifically when used withRaisesGroup.Returns:
None.
check_raisesexc_transparent() -> None
Purpose:
Demonstrates transparent usage ofRaisesGroupwith a nestedRaisesExcand asserts the type of the caught exception.Returns:
None.
check_nested_raisesgroups_contextmanager() -> None
Purpose:
Tests nestedRaisesGroupcontext managers and verifies proper typing of nestedExceptionGroupstructures.Returns:
None.
check_nested_raisesgroups_matches() -> None
Purpose:
Tests nestedRaisesGroupusage with.matches()method and verifies type narrowing on nested exception groups.Returns:
None.
check_multiple_exceptions_1() -> None
Purpose:
Tests thatRaisesGroupcan be constructed with multiple exceptions orRaisesExcinstances and that type assignments are valid for a single exception type.Returns:
None.
check_multiple_exceptions_2() -> None
Purpose:
Ensures that covariance in the type variable ofRaisesGroupcorrectly allows assignment of multiple exception types to a broader exception type.Returns:
None.
check_raisesgroup_overloads() -> None
Purpose:
Tests different constructor argument combinations ofRaisesGroup, focusing onallow_unwrappedandflatten_subgroupsflags, and verifies which combinations are allowed or disallowed by type checkers.Returns:
None.
check_triple_nested_raisesgroup() -> None
Purpose:
Demonstrates triple nestedRaisesGroupusage and verifies the deeply nested exception group typing.Returns:
None.
check_check_typing() -> None
Purpose:
Asserts the typing of thecheckattribute on aRaisesGroupinstance, verifying it is a callable orNone.Returns:
None.
Important Implementation Details and Algorithms
Type Narrowing and Matching:
The core focus of this file is on howRaisesGroupandRaisesExcnarrow exception types through their.matches()methods and context manager usage. This involves Python 3.11'sExceptionGroupand its generic typing to ensure that exceptions are properly identified and matched in nested groups.Covariance and Contravariance:
Tests show thatRaisesGroupis designed with covariance in mind, allowing broader exception types to be assigned to narrower ones under certain conditions, which is critical for sound static typing in dynamic exception testing.Constructor Argument Validation:
The file documents, through examples, the expected usage ofRaisesExcandRaisesGroupconstructors, noting positional-only and keyword-only parameters, and howmatchstrings andcheckcallables interact.Backport Compatibility:
For Python versions prior to 3.11, the file importsBaseExceptionGroupandExceptionGroupfrom the third-partyexceptiongrouppackage to maintain compatibility.Type Assertions:
The use ofassert_typefromtyping_extensionsthroughout the file helps verify that the runtime types align with the expected static types, providing a form of "tests for the type checker."
Interaction with Other System Components
pytest Framework:
This file directly interacts withpytest's exception testing utilities (RaisesExc,RaisesGroup), which are used widely in test code to assert that exceptions occur as expected.Python Standard Library:
Uses Python 3.11'sExceptionGroupandBaseExceptionGrouptypes where available, or falls back on theexceptiongrouppackage for earlier versions.Static Type Checking Tools:
The file is intended to be used with static type checkers such asmypyorpyrightto validate type correctness of exception group handling in pytest.Type Hints and Typing Extensions:
Relies ontyping_extensions.assert_typefor runtime assertions of static types, enhancing confidence in type correctness.
Visual Diagram
classDiagram
class RaisesExc {
+__init__(expected_exception: BaseException | None = ..., match: str | None = ..., check: Callable | None = ...)
+expected_exceptions: type[BaseException] | tuple[type[BaseException], ...] | None
+exception_type() -> type[BaseException]
}
class RaisesGroup {
+__init__(*exceptions: RaisesExc | type[BaseException], match: str | None = ..., check: Callable | None = ..., allow_unwrapped: bool = False, flatten_subgroups: bool = False)
+matches(exc: BaseException | BaseExceptionGroup) -> bool
+check: Callable[[BaseExceptionGroup], bool] | None
+value: BaseExceptionGroup
}
class ExceptionGroup {
+exceptions: tuple[BaseException, ...]
+message: str
}
class BaseExceptionGroup {
+exceptions: tuple[BaseException, ...]
+message: str
}
RaisesExc --> BaseException
RaisesGroup --> RaisesExc
RaisesGroup --> BaseExceptionGroup
RaisesGroup --> BaseException
RaisesGroup --> ExceptionGroup
Summary
This file serves as a comprehensive set of static typing and usage tests for `pytest`'s advanced exception handling utilities, focusing on the interplay with Python’s `ExceptionGroup` mechanism. It is an essential aid in ensuring that exception-raising assertions in tests are both type-safe and semantically correct, particularly as Python’s exception grouping features evolve.
**End of documentation for `typing_raises_group.py`**