diff options
author | Batuhan Taskaya <batuhan@python.org> | 2021-07-25 22:01:44 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-07-25 22:01:44 (GMT) |
commit | 3e235e0447e373d81f195f4292959c7be9c013dc (patch) | |
tree | 3fe06bef120b56ff47d75abd70b32db050b7c99b /Python | |
parent | 96cf5a63d2dbadaebf236362b4c7c09c51fda55c (diff) | |
download | cpython-3e235e0447e373d81f195f4292959c7be9c013dc.zip cpython-3e235e0447e373d81f195f4292959c7be9c013dc.tar.gz cpython-3e235e0447e373d81f195f4292959c7be9c013dc.tar.bz2 |
bpo-43950: support some multi-line expressions for PEP 657 (GH-27339)
This is basically something that I noticed up while fixing test runs for another issue. It is really common to have multiline calls, and when they fail the display is kind of weird since we omit the annotations. E.g;
```
$ ./python t.py
Traceback (most recent call last):
File "/home/isidentical/cpython/cpython/t.py", line 11, in <module>
frame_1()
^^^^^^^^^
File "/home/isidentical/cpython/cpython/t.py", line 5, in frame_1
frame_2(
File "/home/isidentical/cpython/cpython/t.py", line 2, in frame_2
return a / 0 / b / c
~~^~~
ZeroDivisionError: division by zero
```
This patch basically adds support for annotating the rest of the line, if the instruction covers multiple lines (start_line != end_line).
Automerge-Triggered-By: GH:isidentical
Diffstat (limited to 'Python')
-rw-r--r-- | Python/traceback.c | 37 |
1 files changed, 28 insertions, 9 deletions
diff --git a/Python/traceback.c b/Python/traceback.c index 61e6838..6d23013 100644 --- a/Python/traceback.c +++ b/Python/traceback.c @@ -720,11 +720,11 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen &end_line, &end_col_byte_offset)) { goto done; } - if (start_line != end_line) { - goto done; - } - if (start_col_byte_offset < 0 || end_col_byte_offset < 0) { + if (start_line < 0 || end_line < 0 + || start_col_byte_offset < 0 + || end_col_byte_offset < 0) + { goto done; } @@ -762,11 +762,30 @@ tb_displayline(PyTracebackObject* tb, PyObject *f, PyObject *filename, int linen char *primary_error_char = "^"; char *secondary_error_char = primary_error_char; - int res = extract_anchors_from_line(filename, source_line, start_offset, end_offset, - &left_end_offset, &right_start_offset, - &primary_error_char, &secondary_error_char); - if (res < 0 && ignore_source_errors() < 0) { - goto done; + if (start_line == end_line) { + int res = extract_anchors_from_line(filename, source_line, start_offset, end_offset, + &left_end_offset, &right_start_offset, + &primary_error_char, &secondary_error_char); + if (res < 0 && ignore_source_errors() < 0) { + goto done; + } + } + else { + // If this is a multi-line expression, then we will highlight until + // the last non-whitespace character. + const char *source_line_str = PyUnicode_AsUTF8(source_line); + if (!source_line_str) { + goto done; + } + + Py_ssize_t i = PyUnicode_GET_LENGTH(source_line); + while (--i >= 0) { + if (!IS_WHITESPACE(source_line_str[i])) { + break; + } + } + + end_offset = i + 1; } err = print_error_location_carets(f, truncation, start_offset, end_offset, |