|
12 | 12 | requires_debug_ranges, has_no_debug_ranges)
|
13 | 13 | from test.support.os_helper import TESTFN, unlink
|
14 | 14 | from test.support.script_helper import assert_python_ok, assert_python_failure
|
15 |
| -import textwrap |
16 | 15 |
|
| 16 | +import os |
| 17 | +import textwrap |
17 | 18 | import traceback
|
| 19 | +from functools import partial |
18 | 20 |
|
19 | 21 |
|
20 | 22 | test_code = namedtuple('code', ['co_filename', 'co_name'])
|
@@ -406,6 +408,82 @@ def f_with_multiline():
|
406 | 408 | result_lines = self.get_exception(f_with_multiline)
|
407 | 409 | self.assertEqual(result_lines, expected_f.splitlines())
|
408 | 410 |
|
| 411 | + def test_caret_for_binary_operators(self): |
| 412 | + def f_with_binary_operator(): |
| 413 | + divisor = 20 |
| 414 | + return 10 + divisor / 0 + 30 |
| 415 | + |
| 416 | + lineno_f = f_with_binary_operator.__code__.co_firstlineno |
| 417 | + expected_error = ( |
| 418 | + 'Traceback (most recent call last):\n' |
| 419 | + f' File "{__file__}", line {self.callable_line}, in get_exception\n' |
| 420 | + ' callable()\n' |
| 421 | + ' ^^^^^^^^^^\n' |
| 422 | + f' File "{__file__}", line {lineno_f+2}, in f_with_binary_operator\n' |
| 423 | + ' return 10 + divisor / 0 + 30\n' |
| 424 | + ' ~~~~~~~~^~~\n' |
| 425 | + ) |
| 426 | + result_lines = self.get_exception(f_with_binary_operator) |
| 427 | + self.assertEqual(result_lines, expected_error.splitlines()) |
| 428 | + |
| 429 | + def test_caret_for_binary_operators_two_char(self): |
| 430 | + def f_with_binary_operator(): |
| 431 | + divisor = 20 |
| 432 | + return 10 + divisor // 0 + 30 |
| 433 | + |
| 434 | + lineno_f = f_with_binary_operator.__code__.co_firstlineno |
| 435 | + expected_error = ( |
| 436 | + 'Traceback (most recent call last):\n' |
| 437 | + f' File "{__file__}", line {self.callable_line}, in get_exception\n' |
| 438 | + ' callable()\n' |
| 439 | + ' ^^^^^^^^^^\n' |
| 440 | + f' File "{__file__}", line {lineno_f+2}, in f_with_binary_operator\n' |
| 441 | + ' return 10 + divisor // 0 + 30\n' |
| 442 | + ' ~~~~~~~~^^~~\n' |
| 443 | + ) |
| 444 | + result_lines = self.get_exception(f_with_binary_operator) |
| 445 | + self.assertEqual(result_lines, expected_error.splitlines()) |
| 446 | + |
| 447 | + def test_caret_for_subscript(self): |
| 448 | + def f_with_subscript(): |
| 449 | + some_dict = {'x': {'y': None}} |
| 450 | + return some_dict['x']['y']['z'] |
| 451 | + |
| 452 | + lineno_f = f_with_subscript.__code__.co_firstlineno |
| 453 | + expected_error = ( |
| 454 | + 'Traceback (most recent call last):\n' |
| 455 | + f' File "{__file__}", line {self.callable_line}, in get_exception\n' |
| 456 | + ' callable()\n' |
| 457 | + ' ^^^^^^^^^^\n' |
| 458 | + f' File "{__file__}", line {lineno_f+2}, in f_with_subscript\n' |
| 459 | + " return some_dict['x']['y']['z']\n" |
| 460 | + ' ~~~~~~~~~~~~~~~~~~~^^^^^\n' |
| 461 | + ) |
| 462 | + result_lines = self.get_exception(f_with_subscript) |
| 463 | + self.assertEqual(result_lines, expected_error.splitlines()) |
| 464 | + |
| 465 | + def test_traceback_specialization_with_syntax_error(self): |
| 466 | + bytecode = compile("1 / 0 / 1 / 2\n", TESTFN, "exec") |
| 467 | + |
| 468 | + with open(TESTFN, "w") as file: |
| 469 | + # make the file's contents invalid |
| 470 | + file.write("1 $ 0 / 1 / 2\n") |
| 471 | + self.addCleanup(unlink, TESTFN) |
| 472 | + |
| 473 | + func = partial(exec, bytecode) |
| 474 | + result_lines = self.get_exception(func) |
| 475 | + |
| 476 | + lineno_f = bytecode.co_firstlineno |
| 477 | + expected_error = ( |
| 478 | + 'Traceback (most recent call last):\n' |
| 479 | + f' File "{__file__}", line {self.callable_line}, in get_exception\n' |
| 480 | + ' callable()\n' |
| 481 | + ' ^^^^^^^^^^\n' |
| 482 | + f' File "{TESTFN}", line {lineno_f}, in <module>\n' |
| 483 | + " 1 $ 0 / 1 / 2\n" |
| 484 | + ' ^^^^^\n' |
| 485 | + ) |
| 486 | + self.assertEqual(result_lines, expected_error.splitlines()) |
409 | 487 |
|
410 | 488 | @cpython_only
|
411 | 489 | @requires_debug_ranges()
|
@@ -1615,7 +1693,7 @@ def f():
|
1615 | 1693 | self.assertEqual(
|
1616 | 1694 | output.getvalue().split('\n')[-5:],
|
1617 | 1695 | [' x/0',
|
1618 |
| - ' ^^^', |
| 1696 | + ' ~^~', |
1619 | 1697 | ' x = 12',
|
1620 | 1698 | 'ZeroDivisionError: division by zero',
|
1621 | 1699 | ''])
|
|
0 commit comments