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("""\
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 = [
--- /dev/null
+Improve ``assert`` error messages by providing exact error range.
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;