gh-105724: Add location information to `assert` errors (GH-105935)

This commit is contained in:
Nikita Sobolev 2023-08-16 13:35:38 +03:00 committed by GitHub
parent fd9d70a94d
commit bdd8ddfda1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 124 additions and 6 deletions

View File

@ -1315,18 +1315,18 @@ class TestSourcePositions(unittest.TestCase):
snippet = textwrap.dedent("""\
assert (a > 0 and
bb > 0 and
ccc == 4), "error msg"
ccc == 1000000), "error msg"
""")
compiled_code, _ = self.check_positions_against_ast(snippet)
self.assertOpcodeSourcePositionIs(compiled_code, 'LOAD_ASSERTION_ERROR',
line=1, end_line=3, column=0, end_column=30, occurrence=1)
line=1, end_line=3, column=0, end_column=36, occurrence=1)
# The "error msg":
self.assertOpcodeSourcePositionIs(compiled_code, 'LOAD_CONST',
line=3, end_line=3, column=19, end_column=30, occurrence=4)
line=3, end_line=3, column=25, end_column=36, occurrence=4)
self.assertOpcodeSourcePositionIs(compiled_code, 'CALL',
line=1, end_line=3, column=0, end_column=30, occurrence=1)
line=1, end_line=3, column=0, end_column=36, occurrence=1)
self.assertOpcodeSourcePositionIs(compiled_code, 'RAISE_VARARGS',
line=1, end_line=3, column=0, end_column=30, occurrence=1)
line=1, end_line=3, column=8, end_column=22, occurrence=1)
def test_multiline_generator_expression(self):
snippet = textwrap.dedent("""\

View File

@ -1931,6 +1931,123 @@ class ImportErrorTests(unittest.TestCase):
self.assertEqual(exc.name, orig.name)
self.assertEqual(exc.path, orig.path)
class AssertionErrorTests(unittest.TestCase):
def tearDown(self):
unlink(TESTFN)
def write_source(self, source):
with open(TESTFN, 'w') as testfile:
testfile.write(dedent(source))
_rc, _out, err = script_helper.assert_python_failure('-Wd', '-X', 'utf8', TESTFN)
return err.decode('utf-8').splitlines()
def test_assertion_error_location(self):
cases = [
('assert None',
[
' assert None',
' ^^^^',
'AssertionError',
],
),
('assert 0',
[
' assert 0',
' ^',
'AssertionError',
],
),
('assert 1 > 2',
[
' assert 1 > 2',
' ^^^^^',
'AssertionError',
],
),
('assert 1 > 2 and 3 > 2',
[
' assert 1 > 2 and 3 > 2',
' ^^^^^^^^^^^^^^^',
'AssertionError',
],
),
('assert 1 > 2, "message"',
[
' assert 1 > 2, "message"',
' ^^^^^',
'AssertionError: message',
],
),
# Multiline:
("""
assert (
1 > 2)
""",
[
' 1 > 2)',
' ^^^^^',
'AssertionError',
],
),
("""
assert (
1 > 2), "Message"
""",
[
' 1 > 2), "Message"',
' ^^^^^',
'AssertionError: Message',
],
),
("""
assert (
1 > 2), \\
"Message"
""",
[
' 1 > 2), \\',
' ^^^^^',
'AssertionError: Message',
],
),
]
for source, expected in cases:
with self.subTest(source):
result = self.write_source(source)
self.assertEqual(result[-3:], expected)
def test_multiline_not_highlighted(self):
cases = [
("""
assert (
1 > 2
)
""",
[
' 1 > 2',
'AssertionError',
],
),
("""
assert (
1 < 2 and
3 > 4
)
""",
[
' 1 < 2 and',
'AssertionError',
],
),
]
for source, expected in cases:
with self.subTest(source):
result = self.write_source(source)
self.assertEqual(result[-2:], expected)
class SyntaxErrorTests(unittest.TestCase):
def test_range_of_offsets(self):
cases = [

View File

@ -0,0 +1 @@
Improve ``assert`` error messages by providing exact error range.

View File

@ -3952,7 +3952,7 @@ compiler_assert(struct compiler *c, stmt_ty s)
VISIT(c, expr, s->v.Assert.msg);
ADDOP_I(c, LOC(s), CALL, 0);
}
ADDOP_I(c, LOC(s), RAISE_VARARGS, 1);
ADDOP_I(c, LOC(s->v.Assert.test), RAISE_VARARGS, 1);
USE_LABEL(c, end);
return SUCCESS;