Repository: pytest-dev/pytest
File: src/_pytest/python_api.py (Python)

Code before:
        from that cycle (including all local variables in the current
        frame) alive until the next cyclic garbage collection run.
        More detailed information can be found in the official Python
        documentation for :ref:`the try statement <python:try>`.
    """
    __tracebackhide__ = True

    if not expected_exception:
        raise ValueError(
            f"Expected an exception type or a tuple of exception types, but got `{expected_exception!r}`. "
            f"Raising exceptions is already understood as failing the test, so you don't need "
            f"any special code to say 'this should never raise an exception'."
        )

    expected_exceptions: tuple[type[E], ...]
    origin_exc: type[E] | None = get_origin(expected_exception)
    if isinstance(expected_exception, type):
        expected_exceptions = (expected_exception,)
    elif origin_exc and issubclass(origin_exc, BaseExceptionGroup):
        expected_exceptions = (cast(type[E], expected_exception),)
    else:
        expected_exceptions = expected_exception

    def validate_exc(exc: type[E]) -> type[E]:
        origin_exc: type[E] | None = get_origin(exc)
        if origin_exc and issubclass(origin_exc, BaseExceptionGroup):
            exc_type = get_args(exc)[0]
            if issubclass(origin_exc, ExceptionGroup) and exc_type in (Exception, Any):
                return cast(type[E], origin_exc)
            elif issubclass(origin_exc, BaseExceptionGroup) and exc_type in (
                BaseException,
                Any,
            ):
                return cast(type[E], origin_exc)
            else:
                raise ValueError(
                    f"Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` "
                    f"are accepted as generic types but got `{exc}`. "
                    f"As `raises` will catch all instances of the specified group regardless of the "
                    f"generic argument specific nested exceptions has to be checked "
                    f"with `ExceptionInfo.group_contains()`"
                )

        elif not isinstance(exc, type) or not issubclass(exc, BaseException):
            msg = "expected exception must be a BaseException type, not {}"  # type: ignore[unreachable]
            not_a = exc.__name__ if isinstance(exc, type) else type(exc).__name__
            raise TypeError(msg.format(not_a))
        else:
            return exc

    expected_exceptions = tuple(validate_exc(exc) for exc in expected_exceptions)

Review comment (suggestion):
Let's hide this code from the traceback:

```suggestion
        __tracebackhide__ = True
        origin_exc: type[E] | None = get_origin(exc)
```

Code after:
        from that cycle (including all local variables in the current
        frame) alive until the next cyclic garbage collection run.
        More detailed information can be found in the official Python
        documentation for :ref:`the try statement <python:try>`.
    """
    __tracebackhide__ = True

    if not expected_exception:
        raise ValueError(
            f"Expected an exception type or a tuple of exception types, but got `{expected_exception!r}`. "
            f"Raising exceptions is already understood as failing the test, so you don't need "
            f"any special code to say 'this should never raise an exception'."
        )

    expected_exceptions: tuple[type[E], ...]
    origin_exc: type[E] | None = get_origin(expected_exception)
    if isinstance(expected_exception, type):
        expected_exceptions = (expected_exception,)
    elif origin_exc and issubclass(origin_exc, BaseExceptionGroup):
        expected_exceptions = (cast(type[E], expected_exception),)
    else:
        expected_exceptions = expected_exception

    def validate_exc(exc: type[E]) -> type[E]:
        __tracebackhide__ = True
        origin_exc: type[E] | None = get_origin(exc)
        if origin_exc and issubclass(origin_exc, BaseExceptionGroup):
            exc_type = get_args(exc)[0]
            if (
                issubclass(origin_exc, ExceptionGroup) and exc_type in (Exception, Any)
            ) or (
                issubclass(origin_exc, BaseExceptionGroup)
                and exc_type in (BaseException, Any)
            ):
                return cast(type[E], origin_exc)
            else:
                raise ValueError(
                    f"Only `ExceptionGroup[Exception]` or `BaseExceptionGroup[BaseExeption]` "
                    f"are accepted as generic types but got `{exc}`. "
                    f"As `raises` will catch all instances of the specified group regardless of the "
                    f"generic argument specific nested exceptions has to be checked "
                    f"with `ExceptionInfo.group_contains()`"
                )

        elif not isinstance(exc, type) or not issubclass(exc, BaseException):
            msg = "expected exception must be a BaseException type, not {}"  # type: ignore[unreachable]
            not_a = exc.__name__ if isinstance(exc, type) else type(exc).__name__
            raise TypeError(msg.format(not_a))
        else:
            return exc