(
args: threading.ExceptHookArgs,
/,
*,
append: Callable[[ThreadExceptionMeta | BaseException], object],
)
| 90 | |
| 91 | |
| 92 | def thread_exception_hook( |
| 93 | args: threading.ExceptHookArgs, |
| 94 | /, |
| 95 | *, |
| 96 | append: Callable[[ThreadExceptionMeta | BaseException], object], |
| 97 | ) -> None: |
| 98 | try: |
| 99 | # we need to compute these strings here as they might change after |
| 100 | # the excepthook finishes and before the metadata object is |
| 101 | # collected by a pytest hook |
| 102 | thread_name = "<unknown>" if args.thread is None else args.thread.name |
| 103 | summary = f"Exception in thread {thread_name}" |
| 104 | traceback_message = "\n\n" + "".join( |
| 105 | traceback.format_exception( |
| 106 | args.exc_type, |
| 107 | args.exc_value, |
| 108 | args.exc_traceback, |
| 109 | ) |
| 110 | ) |
| 111 | tracemalloc_tb = "\n" + tracemalloc_message(args.thread) |
| 112 | msg = summary + traceback_message + tracemalloc_tb |
| 113 | cause_msg = summary + tracemalloc_tb |
| 114 | |
| 115 | append( |
| 116 | ThreadExceptionMeta( |
| 117 | # Compute these strings here as they might change later |
| 118 | msg=msg, |
| 119 | cause_msg=cause_msg, |
| 120 | exc_value=args.exc_value, |
| 121 | ) |
| 122 | ) |
| 123 | except BaseException as e: |
| 124 | append(e) |
| 125 | # Raising this will cause the exception to be logged twice, once in our |
| 126 | # collect_thread_exception and once by sys.excepthook |
| 127 | # which is fine - this should never happen anyway and if it does |
| 128 | # it should probably be reported as a pytest bug. |
| 129 | raise |
| 130 | |
| 131 | |
| 132 | def pytest_configure(config: Config) -> None: |
nothing calls this directly
no test coverage detected