| 15 | |
| 16 | |
| 17 | def format_error( |
| 18 | e: Exception, |
| 19 | start_entries=20, |
| 20 | end_entries=15, |
| 21 | error_message_position: Literal["top", "bottom", "none"] = "top", |
| 22 | ): |
| 23 | # format traceback from the provided exception instead of the most recent one |
| 24 | traceback_text = "".join(traceback.format_exception(type(e), e, e.__traceback__)) |
| 25 | # Split the traceback into lines |
| 26 | lines = traceback_text.split("\n") |
| 27 | |
| 28 | if not start_entries and not end_entries: |
| 29 | trimmed_lines = [] |
| 30 | else: |
| 31 | |
| 32 | # Find all "File" lines |
| 33 | file_indices = [ |
| 34 | i for i, line in enumerate(lines) if line.strip().startswith("File ") |
| 35 | ] |
| 36 | |
| 37 | # If we found at least one "File" line, trim the middle if there are more than start_entries+end_entries lines |
| 38 | if len(file_indices) > start_entries + end_entries: |
| 39 | start_index = max(0, len(file_indices) - start_entries - end_entries) |
| 40 | trimmed_lines = ( |
| 41 | lines[: file_indices[start_index]] |
| 42 | + [ |
| 43 | f"\n>>> {len(file_indices) - start_entries - end_entries} stack lines skipped <<<\n" |
| 44 | ] |
| 45 | + lines[file_indices[start_index + end_entries] :] |
| 46 | ) |
| 47 | else: |
| 48 | # If no "File" lines found, or not enough to trim, just return the original traceback |
| 49 | trimmed_lines = lines |
| 50 | |
| 51 | # Find the error message at the end |
| 52 | error_message = "" |
| 53 | for line in reversed(lines): |
| 54 | # match both simple errors and module.path.Error patterns |
| 55 | if re.match(r"[\w\.]+Error:\s*", line): |
| 56 | error_message = line |
| 57 | break |
| 58 | |
| 59 | if error_message and error_message_position in ("top", "bottom", "none"): |
| 60 | for i in range(len(trimmed_lines) - 1, -1, -1): |
| 61 | if trimmed_lines[i].strip() == error_message.strip(): |
| 62 | trimmed_lines = trimmed_lines[:i] + trimmed_lines[i + 1 :] |
| 63 | break |
| 64 | |
| 65 | # Combine the trimmed traceback with the error message |
| 66 | if not trimmed_lines: |
| 67 | result = "" if error_message_position == "none" else error_message |
| 68 | else: |
| 69 | result = "Traceback (most recent call last):\n" + "\n".join(trimmed_lines) |
| 70 | |
| 71 | if error_message and error_message_position == "top": |
| 72 | result = f"{error_message}\n\n{result}" if result else error_message |
| 73 | elif error_message and error_message_position == "bottom": |
| 74 | result = f"{result}\n\n{error_message}" if result else error_message |