summaryrefslogtreecommitdiffstats
path: root/Python
diff options
context:
space:
mode:
authorJohn Belmonte <john@neggie.net>2022-07-11 11:27:29 (GMT)
committerGitHub <noreply@github.com>2022-07-11 11:27:29 (GMT)
commit45896f2a02f02f296d14cccd6959179ccd47e410 (patch)
tree0aae343b626ad11110716e5a3eddf9aba94d104c /Python
parentf3212b1ec7a70b69f44acd763221463a69beee4f (diff)
downloadcpython-45896f2a02f02f296d14cccd6959179ccd47e410.zip
cpython-45896f2a02f02f296d14cccd6959179ccd47e410.tar.gz
cpython-45896f2a02f02f296d14cccd6959179ccd47e410.tar.bz2
[3.11] gh-93883: elide traceback indicators when possible (GH-93994) (GH-94740)
Elide traceback column indicators when the entire line of the frame is implicated. This reduces traceback length and draws more attention to the remaining (very relevant) indicators. Example: ``` Traceback (most recent call last): File "query.py", line 99, in <module> bar() File "query.py", line 66, in bar foo() File "query.py", line 37, in foo magic_arithmetic('foo') File "query.py", line 18, in magic_arithmetic return add_counts(x) / 25 ^^^^^^^^^^^^^ File "query.py", line 24, in add_counts return 25 + query_user(user1) + query_user(user2) ^^^^^^^^^^^^^^^^^ File "query.py", line 32, in query_user return 1 + query_count(db, response['a']['b']['c']['user'], retry=True) ~~~~~~~~~~~~~~~~~~^^^^^ TypeError: 'NoneType' object is not subscriptable ``` Automerge-Triggered-By: GH:pablogsal
Diffstat (limited to 'Python')
-rw-r--r--Python/traceback.c18
1 files changed, 14 insertions, 4 deletions
diff --git a/Python/traceback.c b/Python/traceback.c
index 0c49a8c..20348c0 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -592,7 +592,6 @@ _Py_DisplaySourceLine(PyObject *f, PyObject *filename, int lineno, int indent,
* Traceback (most recent call last):
* File "/home/isidentical/cpython/cpython/t.py", line 10, in <module>
* add_values(1, 2, 'x', 3, 4)
- * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
* File "/home/isidentical/cpython/cpython/t.py", line 2, in add_values
* return a + b + c + d + e
* ~~~~~~^~~
@@ -736,7 +735,7 @@ print_error_location_carets(PyObject *f, int offset, Py_ssize_t start_offset, Py
int special_chars = (left_end_offset != -1 || right_start_offset != -1);
const char *str;
while (++offset <= end_offset) {
- if (offset <= start_offset || offset > end_offset) {
+ if (offset <= start_offset) {
str = " ";
} else if (special_chars && left_end_offset < offset && offset <= right_start_offset) {
str = secondary;
@@ -792,6 +791,7 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen
int code_offset = tb->tb_lasti;
PyCodeObject* code = frame->f_frame->f_code;
+ const Py_ssize_t source_line_len = PyUnicode_GET_LENGTH(source_line);
int start_line;
int end_line;
@@ -813,7 +813,7 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen
//
// ERROR LINE ERROR LINE ERROR LINE ERROR LINE ERROR LINE ERROR LINE ERROR LINE
// ~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^~~~~~~~~~~~~~~~~~~~
- // | |-> left_end_offset | |-> left_offset
+ // | |-> left_end_offset | |-> end_offset
// |-> start_offset |-> right_start_offset
//
// In general we will only have (start_offset, end_offset) but we can gather more information
@@ -822,6 +822,9 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen
// the different ranges (primary_error_char and secondary_error_char). If we cannot obtain the
// AST information or we cannot identify special ranges within it, then left_end_offset and
// right_end_offset will be set to -1.
+ //
+ // To keep the column indicators pertinent, they are not shown when the primary character
+ // spans the whole line.
// Convert the utf-8 byte offset to the actual character offset so we print the right number of carets.
assert(source_line);
@@ -859,7 +862,7 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen
goto done;
}
- Py_ssize_t i = PyUnicode_GET_LENGTH(source_line);
+ Py_ssize_t i = source_line_len;
while (--i >= 0) {
if (!IS_WHITESPACE(source_line_str[i])) {
break;
@@ -869,6 +872,13 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen
end_offset = i + 1;
}
+ // Elide indicators if primary char spans the frame line
+ Py_ssize_t stripped_line_len = source_line_len - truncation - _TRACEBACK_SOURCE_LINE_INDENT;
+ bool has_secondary_ranges = (left_end_offset != -1 || right_start_offset != -1);
+ if (end_offset - start_offset == stripped_line_len && !has_secondary_ranges) {
+ goto done;
+ }
+
if (_Py_WriteIndentedMargin(margin_indent, margin, f) < 0) {
err = -1;
goto done;