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

Code before:
            except pytest.PytestUnhandledThreadExceptionWarning as e:
                # This except happens when the warning is treated as an error (e.g. `-Werror`).
                if meta.exc_value is not None:
                    # Exceptions have a better way to show the traceback, but
                    # warnings do not, so hide the traceback from the msg and
                    # set the cause so the traceback shows up in the right place.
                    e.args = (meta.cause_msg,)
                    e.__cause__ = meta.exc_value
                errors.append(e)

        if len(errors) == 1:
            raise errors[0]
        if errors:
            raise ExceptionGroup("multiple thread exception warnings", errors)
    finally:
        del errors, meta, hook_error


def cleanup(
    *, config: Config, prev_hook: Callable[[threading.ExceptHookArgs], object]
) -> None:
    try:
        try:
            # We don't join threads here, so exceptions raised from any
            # threads still running by the time _threading_atexits joins them
            # do not get captured.
            collect_thread_exception(config)
        finally:
            threading.excepthook = prev_hook
    finally:
        del config.stash[thread_exceptions]


def thread_exception_hook(
    args: threading.ExceptHookArgs,
    /,
    *,
    append: Callable[[ThreadExceptionMeta | BaseException], object],
) -> None:
    try:
        # we need to compute these strings here as they might change after
        # the excepthook finishes and before the metadata object is
        # collected by a pytest hook
        thread_name = "<unknown>" if args.thread is None else args.thread.name
        summary = f"Exception in thread {thread_name}"
        traceback_message = "\n\n" + "".join(
            traceback.format_exception(
                args.exc_type,
                args.exc_value,
                args.exc_traceback,
            )

Review comment (suggestion):
```suggestion
            # do not get captured (see #13027).
```

Code after:
            except pytest.PytestUnhandledThreadExceptionWarning as e:
                # This except happens when the warning is treated as an error (e.g. `-Werror`).
                if meta.exc_value is not None:
                    # Exceptions have a better way to show the traceback, but
                    # warnings do not, so hide the traceback from the msg and
                    # set the cause so the traceback shows up in the right place.
                    e.args = (meta.cause_msg,)
                    e.__cause__ = meta.exc_value
                errors.append(e)

        if len(errors) == 1:
            raise errors[0]
        if errors:
            raise ExceptionGroup("multiple thread exception warnings", errors)
    finally:
        del errors, meta, hook_error


def cleanup(
    *, config: Config, prev_hook: Callable[[threading.ExceptHookArgs], object]
) -> None:
    try:
        try:
            # We don't join threads here, so exceptions raised from any
            # threads still running by the time _threading_atexits joins them
            # do not get captured (see #13027).
            collect_thread_exception(config)
        finally:
            threading.excepthook = prev_hook
    finally:
        del config.stash[thread_exceptions]


def thread_exception_hook(
    args: threading.ExceptHookArgs,
    /,
    *,
    append: Callable[[ThreadExceptionMeta | BaseException], object],
) -> None:
    try:
        # we need to compute these strings here as they might change after
        # the excepthook finishes and before the metadata object is
        # collected by a pytest hook
        thread_name = "<unknown>" if args.thread is None else args.thread.name
        summary = f"Exception in thread {thread_name}"
        traceback_message = "\n\n" + "".join(
            traceback.format_exception(
                args.exc_type,
                args.exc_value,
                args.exc_traceback,
            )