-
-
Notifications
You must be signed in to change notification settings - Fork 2.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add basic implementation of PEP657 style expression markers in tracebacks #13102
Changes from 5 commits
2a2844d
4895b72
3661ee3
85b0504
29102cb
ffc7e5b
23350b5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -849,6 +849,37 @@ def entry(): | |
assert basename in str(reprtb.reprfileloc.path) | ||
assert reprtb.reprfileloc.lineno == 3 | ||
|
||
@pytest.mark.skipif( | ||
"sys.version_info < (3,11)", | ||
reason="Column level traceback info added in python 3.11", | ||
) | ||
def test_repr_traceback_entry_short_carets(self, importasmod) -> None: | ||
mod = importasmod( | ||
""" | ||
def div_by_zero(): | ||
return 1 / 0 | ||
def func1(): | ||
return 42 + div_by_zero() | ||
def entry(): | ||
func1() | ||
""" | ||
) | ||
excinfo = pytest.raises(ZeroDivisionError, mod.entry) | ||
p = FormattedExcinfo(style="short") | ||
reprtb = p.repr_traceback_entry(excinfo.traceback[-3]) | ||
assert len(reprtb.lines) == 1 | ||
assert reprtb.lines[0] == " func1()" | ||
|
||
reprtb = p.repr_traceback_entry(excinfo.traceback[-2]) | ||
assert len(reprtb.lines) == 2 | ||
assert reprtb.lines[0] == " return 42 + div_by_zero()" | ||
assert reprtb.lines[1] == " ^^^^^^^^^^^^^" | ||
|
||
reprtb = p.repr_traceback_entry(excinfo.traceback[-1]) | ||
assert len(reprtb.lines) == 2 | ||
assert reprtb.lines[0] == " return 1 / 0" | ||
assert reprtb.lines[1] == " ^^^^^" | ||
Comment on lines
+880
to
+881
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
That would be very nice to have, but I'd be happy to merge something without that and open a follow-up issue: this is already a nice improvement on the status quo! |
||
|
||
def test_repr_tracebackentry_no(self, importasmod): | ||
mod = importasmod( | ||
""" | ||
|
@@ -1309,7 +1340,7 @@ def g(): | |
raise ValueError() | ||
|
||
def h(): | ||
raise AttributeError() | ||
if True: raise AttributeError() | ||
""" | ||
) | ||
excinfo = pytest.raises(AttributeError, mod.f) | ||
|
@@ -1370,12 +1401,22 @@ def h(): | |
assert tw_mock.lines[40] == ("_ ", None) | ||
assert tw_mock.lines[41] == "" | ||
assert tw_mock.lines[42] == " def h():" | ||
assert tw_mock.lines[43] == "> raise AttributeError()" | ||
assert tw_mock.lines[44] == "E AttributeError" | ||
assert tw_mock.lines[45] == "" | ||
line = tw_mock.get_write_msg(46) | ||
assert line.endswith("mod.py") | ||
assert tw_mock.lines[47] == ":15: AttributeError" | ||
# On python 3.11 and greater, check for carets in the traceback. | ||
if sys.version_info >= (3, 11): | ||
assert tw_mock.lines[43] == "> if True: raise AttributeError()" | ||
assert tw_mock.lines[44] == " ^^^^^^^^^^^^^^^^^^^^^^" | ||
assert tw_mock.lines[45] == "E AttributeError" | ||
assert tw_mock.lines[46] == "" | ||
line = tw_mock.get_write_msg(47) | ||
assert line.endswith("mod.py") | ||
assert tw_mock.lines[48] == ":15: AttributeError" | ||
else: | ||
assert tw_mock.lines[43] == "> if True: raise AttributeError()" | ||
assert tw_mock.lines[44] == "E AttributeError" | ||
assert tw_mock.lines[45] == "" | ||
line = tw_mock.get_write_msg(46) | ||
assert line.endswith("mod.py") | ||
assert tw_mock.lines[47] == ":15: AttributeError" | ||
|
||
@pytest.mark.parametrize("mode", ["from_none", "explicit_suppress"]) | ||
def test_exc_repr_chain_suppression(self, importasmod, mode, tw_mock): | ||
|
@@ -1494,23 +1535,44 @@ def unreraise(): | |
r = excinfo.getrepr(style="short") | ||
r.toterminal(tw_mock) | ||
out = "\n".join(line for line in tw_mock.lines if isinstance(line, str)) | ||
expected_out = textwrap.dedent( | ||
"""\ | ||
:13: in unreraise | ||
reraise() | ||
:10: in reraise | ||
raise Err() from e | ||
E test_exc_chain_repr_cycle0.mod.Err | ||
|
||
During handling of the above exception, another exception occurred: | ||
:15: in unreraise | ||
raise e.__cause__ | ||
:8: in reraise | ||
fail() | ||
:5: in fail | ||
return 0 / 0 | ||
E ZeroDivisionError: division by zero""" | ||
) | ||
# Assert highlighting carets in python3.11+ | ||
if sys.version_info >= (3, 11): | ||
expected_out = textwrap.dedent( | ||
"""\ | ||
:13: in unreraise | ||
reraise() | ||
:10: in reraise | ||
raise Err() from e | ||
E test_exc_chain_repr_cycle0.mod.Err | ||
|
||
During handling of the above exception, another exception occurred: | ||
:15: in unreraise | ||
raise e.__cause__ | ||
:8: in reraise | ||
fail() | ||
:5: in fail | ||
return 0 / 0 | ||
^^^^^ | ||
E ZeroDivisionError: division by zero""" | ||
) | ||
else: | ||
expected_out = textwrap.dedent( | ||
"""\ | ||
:13: in unreraise | ||
reraise() | ||
:10: in reraise | ||
raise Err() from e | ||
E test_exc_chain_repr_cycle0.mod.Err | ||
|
||
During handling of the above exception, another exception occurred: | ||
:15: in unreraise | ||
raise e.__cause__ | ||
:8: in reraise | ||
fail() | ||
:5: in fail | ||
return 0 / 0 | ||
E ZeroDivisionError: division by zero""" | ||
) | ||
assert out == expected_out | ||
|
||
def test_exec_type_error_filter(self, importasmod): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, looks like we need tests covering this branch - though I'm not sure there's a nice way to get that, so maybe a
# pragma: no cover
instead? Hmm.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, it would be tough to disable the column information to test this branch. Added a no cover.