Skip to content

Commit 343a058

Browse files
committed
gh-99180: Remove traceback anchors in return and assign statements that cover all the displayed range
Signed-off-by: Pablo Galindo <pablogsal@gmail.com> Apply suggestions from code review Co-authored-by: Alex Waygood <Alex.Waygood@Gmail.com> fix whitespace issue causing the lint check to fail
1 parent 5e1916b commit 343a058

File tree

3 files changed

+240
-33
lines changed

3 files changed

+240
-33
lines changed

Lib/test/test_traceback.py

Lines changed: 205 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -685,7 +685,6 @@ def f_with_multiline():
685685
' ~~~~~~~~^^\n'
686686
f' File "{__file__}", line {lineno_f+2}, in f_with_multiline\n'
687687
' return compile(code, "?", "exec")\n'
688-
' ~~~~~~~^^^^^^^^^^^^^^^^^^^\n'
689688
' File "?", line 7\n'
690689
' foo(a, z\n'
691690
' ^'
@@ -775,8 +774,8 @@ def f_with_binary_operator():
775774
def test_caret_for_binary_operators_with_spaces_and_parenthesis(self):
776775
def f_with_binary_operator():
777776
a = 1
778-
b = ""
779-
return ( a ) +b
777+
b = c = ""
778+
return ( a ) +b + c
780779

781780
lineno_f = f_with_binary_operator.__code__.co_firstlineno
782781
expected_error = (
@@ -785,7 +784,7 @@ def f_with_binary_operator():
785784
' callable()\n'
786785
' ~~~~~~~~^^\n'
787786
f' File "{__file__}", line {lineno_f+3}, in f_with_binary_operator\n'
788-
' return ( a ) +b\n'
787+
' return ( a ) +b + c\n'
789788
' ~~~~~~~~~~^~\n'
790789
)
791790
result_lines = self.get_exception(f_with_binary_operator)
@@ -973,7 +972,7 @@ def f1(a):
973972
def f2(b):
974973
raise RuntimeError("fail")
975974
return f2
976-
return f1("x")("y")
975+
return f1("x")("y")("z")
977976

978977
lineno_f = f_with_call.__code__.co_firstlineno
979978
expected_error = (
@@ -982,7 +981,7 @@ def f2(b):
982981
' callable()\n'
983982
' ~~~~~~~~^^\n'
984983
f' File "{__file__}", line {lineno_f+5}, in f_with_call\n'
985-
' return f1("x")("y")\n'
984+
' return f1("x")("y")("z")\n'
986985
' ~~~~~~~^^^^^\n'
987986
f' File "{__file__}", line {lineno_f+3}, in f2\n'
988987
' raise RuntimeError("fail")\n'
@@ -1497,6 +1496,184 @@ def f():
14971496
' raise MemoryError()']
14981497
self.assertEqual(actual, expected)
14991498

1499+
def test_anchors_for_simple_return_statements_are_elided(self):
1500+
def g():
1501+
1/0
1502+
1503+
def f():
1504+
return g()
1505+
1506+
result_lines = self.get_exception(f)
1507+
expected = ['Traceback (most recent call last):',
1508+
f" File \"{__file__}\", line {self.callable_line}, in get_exception",
1509+
" callable()",
1510+
" ~~~~~~~~^^",
1511+
f" File \"{__file__}\", line {f.__code__.co_firstlineno + 1}, in f",
1512+
" return g()",
1513+
f" File \"{__file__}\", line {g.__code__.co_firstlineno + 1}, in g",
1514+
" 1/0",
1515+
" ~^~"
1516+
]
1517+
self.assertEqual(result_lines, expected)
1518+
1519+
def g():
1520+
1/0
1521+
1522+
def f():
1523+
return g() + 1
1524+
1525+
result_lines = self.get_exception(f)
1526+
expected = ['Traceback (most recent call last):',
1527+
f" File \"{__file__}\", line {self.callable_line}, in get_exception",
1528+
" callable()",
1529+
" ~~~~~~~~^^",
1530+
f" File \"{__file__}\", line {f.__code__.co_firstlineno + 1}, in f",
1531+
" return g() + 1",
1532+
" ~^^",
1533+
f" File \"{__file__}\", line {g.__code__.co_firstlineno + 1}, in g",
1534+
" 1/0",
1535+
" ~^~"
1536+
]
1537+
self.assertEqual(result_lines, expected)
1538+
1539+
def g(*args):
1540+
1/0
1541+
1542+
def f():
1543+
return g(1,
1544+
2, 4,
1545+
5)
1546+
1547+
result_lines = self.get_exception(f)
1548+
expected = ['Traceback (most recent call last):',
1549+
f" File \"{__file__}\", line {self.callable_line}, in get_exception",
1550+
" callable()",
1551+
" ~~~~~~~~^^",
1552+
f" File \"{__file__}\", line {f.__code__.co_firstlineno + 1}, in f",
1553+
" return g(1,",
1554+
" 2, 4,",
1555+
" 5)",
1556+
f" File \"{__file__}\", line {g.__code__.co_firstlineno + 1}, in g",
1557+
" 1/0",
1558+
" ~^~"
1559+
]
1560+
self.assertEqual(result_lines, expected)
1561+
1562+
def g(*args):
1563+
1/0
1564+
1565+
def f():
1566+
return g(1,
1567+
2, 4,
1568+
5) + 1
1569+
1570+
result_lines = self.get_exception(f)
1571+
expected = ['Traceback (most recent call last):',
1572+
f" File \"{__file__}\", line {self.callable_line}, in get_exception",
1573+
" callable()",
1574+
" ~~~~~~~~^^",
1575+
f" File \"{__file__}\", line {f.__code__.co_firstlineno + 1}, in f",
1576+
" return g(1,",
1577+
" ~^^^",
1578+
" 2, 4,",
1579+
" ^^^^^",
1580+
" 5) + 1",
1581+
" ^^",
1582+
f" File \"{__file__}\", line {g.__code__.co_firstlineno + 1}, in g",
1583+
" 1/0",
1584+
" ~^~"
1585+
]
1586+
self.assertEqual(result_lines, expected)
1587+
1588+
def test_anchors_for_simple_assign_statements_are_elided(self):
1589+
def g():
1590+
1/0
1591+
1592+
def f():
1593+
x = g()
1594+
1595+
result_lines = self.get_exception(f)
1596+
expected = ['Traceback (most recent call last):',
1597+
f" File \"{__file__}\", line {self.callable_line}, in get_exception",
1598+
" callable()",
1599+
" ~~~~~~~~^^",
1600+
f" File \"{__file__}\", line {f.__code__.co_firstlineno + 1}, in f",
1601+
" x = g()",
1602+
f" File \"{__file__}\", line {g.__code__.co_firstlineno + 1}, in g",
1603+
" 1/0",
1604+
" ~^~"
1605+
]
1606+
self.assertEqual(result_lines, expected)
1607+
1608+
def g(*args):
1609+
1/0
1610+
1611+
def f():
1612+
x = g(1,
1613+
2, 3,
1614+
4)
1615+
1616+
result_lines = self.get_exception(f)
1617+
expected = ['Traceback (most recent call last):',
1618+
f" File \"{__file__}\", line {self.callable_line}, in get_exception",
1619+
" callable()",
1620+
" ~~~~~~~~^^",
1621+
f" File \"{__file__}\", line {f.__code__.co_firstlineno + 1}, in f",
1622+
" x = g(1,",
1623+
" 2, 3,",
1624+
" 4)",
1625+
f" File \"{__file__}\", line {g.__code__.co_firstlineno + 1}, in g",
1626+
" 1/0",
1627+
" ~^~"
1628+
]
1629+
self.assertEqual(result_lines, expected)
1630+
1631+
def g():
1632+
1/0
1633+
1634+
def f():
1635+
x = y = g()
1636+
1637+
result_lines = self.get_exception(f)
1638+
expected = ['Traceback (most recent call last):',
1639+
f" File \"{__file__}\", line {self.callable_line}, in get_exception",
1640+
" callable()",
1641+
" ~~~~~~~~^^",
1642+
f" File \"{__file__}\", line {f.__code__.co_firstlineno + 1}, in f",
1643+
" x = y = g()",
1644+
" ~^^",
1645+
f" File \"{__file__}\", line {g.__code__.co_firstlineno + 1}, in g",
1646+
" 1/0",
1647+
" ~^~"
1648+
]
1649+
self.assertEqual(result_lines, expected)
1650+
1651+
def g(*args):
1652+
1/0
1653+
1654+
def f():
1655+
x = y = g(1,
1656+
2, 3,
1657+
4)
1658+
1659+
result_lines = self.get_exception(f)
1660+
expected = ['Traceback (most recent call last):',
1661+
f" File \"{__file__}\", line {self.callable_line}, in get_exception",
1662+
" callable()",
1663+
" ~~~~~~~~^^",
1664+
f" File \"{__file__}\", line {f.__code__.co_firstlineno + 1}, in f",
1665+
" x = y = g(1,",
1666+
" ~^^^",
1667+
" 2, 3,",
1668+
" ^^^^^",
1669+
" 4)",
1670+
" ^^",
1671+
f" File \"{__file__}\", line {g.__code__.co_firstlineno + 1}, in g",
1672+
" 1/0",
1673+
" ~^~"
1674+
]
1675+
self.assertEqual(result_lines, expected)
1676+
15001677

15011678
@requires_debug_ranges()
15021679
class PurePythonTracebackErrorCaretTests(
@@ -1691,7 +1868,7 @@ def f():
16911868
# Check a known (limited) number of recursive invocations
16921869
def g(count=10):
16931870
if count:
1694-
return g(count-1)
1871+
return g(count-1) + 1
16951872
raise ValueError
16961873

16971874
with captured_output("stderr") as stderr_g:
@@ -1705,13 +1882,13 @@ def g(count=10):
17051882
lineno_g = g.__code__.co_firstlineno
17061883
result_g = (
17071884
f' File "{__file__}", line {lineno_g+2}, in g\n'
1708-
' return g(count-1)\n'
1885+
' return g(count-1) + 1\n'
17091886
' ~^^^^^^^^^\n'
17101887
f' File "{__file__}", line {lineno_g+2}, in g\n'
1711-
' return g(count-1)\n'
1888+
' return g(count-1) + 1\n'
17121889
' ~^^^^^^^^^\n'
17131890
f' File "{__file__}", line {lineno_g+2}, in g\n'
1714-
' return g(count-1)\n'
1891+
' return g(count-1) + 1\n'
17151892
' ~^^^^^^^^^\n'
17161893
' [Previous line repeated 7 more times]\n'
17171894
f' File "{__file__}", line {lineno_g+3}, in g\n'
@@ -1750,13 +1927,10 @@ def h(count=10):
17501927
' ~^^\n'
17511928
f' File "{__file__}", line {lineno_h+2}, in h\n'
17521929
' return h(count-1)\n'
1753-
' ~^^^^^^^^^\n'
17541930
f' File "{__file__}", line {lineno_h+2}, in h\n'
17551931
' return h(count-1)\n'
1756-
' ~^^^^^^^^^\n'
17571932
f' File "{__file__}", line {lineno_h+2}, in h\n'
17581933
' return h(count-1)\n'
1759-
' ~^^^^^^^^^\n'
17601934
' [Previous line repeated 7 more times]\n'
17611935
f' File "{__file__}", line {lineno_h+3}, in h\n'
17621936
' g()\n'
@@ -1776,21 +1950,21 @@ def h(count=10):
17761950
self.fail("no error raised")
17771951
result_g = (
17781952
f' File "{__file__}", line {lineno_g+2}, in g\n'
1779-
' return g(count-1)\n'
1953+
' return g(count-1) + 1\n'
17801954
' ~^^^^^^^^^\n'
17811955
f' File "{__file__}", line {lineno_g+2}, in g\n'
1782-
' return g(count-1)\n'
1956+
' return g(count-1) + 1\n'
17831957
' ~^^^^^^^^^\n'
17841958
f' File "{__file__}", line {lineno_g+2}, in g\n'
1785-
' return g(count-1)\n'
1959+
' return g(count-1) + 1\n'
17861960
' ~^^^^^^^^^\n'
17871961
f' File "{__file__}", line {lineno_g+3}, in g\n'
17881962
' raise ValueError\n'
17891963
'ValueError\n'
17901964
)
17911965
tb_line = (
17921966
'Traceback (most recent call last):\n'
1793-
f' File "{__file__}", line {lineno_g+80}, in _check_recursive_traceback_display\n'
1967+
f' File "{__file__}", line {lineno_g+77}, in _check_recursive_traceback_display\n'
17941968
' g(traceback._RECURSIVE_CUTOFF)\n'
17951969
' ~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n'
17961970
)
@@ -1808,13 +1982,13 @@ def h(count=10):
18081982
self.fail("no error raised")
18091983
result_g = (
18101984
f' File "{__file__}", line {lineno_g+2}, in g\n'
1811-
' return g(count-1)\n'
1985+
' return g(count-1) + 1\n'
18121986
' ~^^^^^^^^^\n'
18131987
f' File "{__file__}", line {lineno_g+2}, in g\n'
1814-
' return g(count-1)\n'
1988+
' return g(count-1) + 1\n'
18151989
' ~^^^^^^^^^\n'
18161990
f' File "{__file__}", line {lineno_g+2}, in g\n'
1817-
' return g(count-1)\n'
1991+
' return g(count-1) + 1\n'
18181992
' ~^^^^^^^^^\n'
18191993
' [Previous line repeated 1 more time]\n'
18201994
f' File "{__file__}", line {lineno_g+3}, in g\n'
@@ -1823,7 +1997,7 @@ def h(count=10):
18231997
)
18241998
tb_line = (
18251999
'Traceback (most recent call last):\n'
1826-
f' File "{__file__}", line {lineno_g+112}, in _check_recursive_traceback_display\n'
2000+
f' File "{__file__}", line {lineno_g+109}, in _check_recursive_traceback_display\n'
18272001
' g(traceback._RECURSIVE_CUTOFF + 1)\n'
18282002
' ~^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^\n'
18292003
)
@@ -4260,11 +4434,14 @@ def foo(*args):
42604434
x = {'a':{'b': None}}
42614435
y = x['a']['b']['c']
42624436

4263-
def baz(*args):
4264-
return foo(1,2,3,4)
4437+
def baz2(*args):
4438+
return (lambda *args: foo(*args))(1,2,3,4)
4439+
4440+
def baz1(*args):
4441+
return baz2(1,2,3,4)
42654442

42664443
def bar():
4267-
return baz(1,
4444+
return baz1(1,
42684445
2,3
42694446
,4)
42704447
try:
@@ -4278,10 +4455,10 @@ def bar():
42784455
boldr = traceback._ANSIColors.BOLD_RED
42794456
reset = traceback._ANSIColors.RESET
42804457
self.assertIn("y = " + red + "x['a']['b']" + reset + boldr + "['c']" + reset, lines)
4281-
self.assertIn("return " + red + "foo" + reset + boldr + "(1,2,3,4)" + reset, lines)
4282-
self.assertIn("return " + red + "baz" + reset + boldr + "(1," + reset, lines)
4283-
self.assertIn(boldr + "2,3" + reset, lines)
4284-
self.assertIn(boldr + ",4)" + reset, lines)
4458+
self.assertIn("return " + red + "(lambda *args: foo(*args))" + reset + boldr + "(1,2,3,4)" + reset, lines)
4459+
self.assertIn("return (lambda *args: " + red + "foo" + reset + boldr + "(*args)" + reset + ")(1,2,3,4)", lines)
4460+
self.assertIn("return baz2(1,2,3,4)", lines)
4461+
self.assertIn("return baz1(1,\n 2,3\n ,4)", lines)
42854462
self.assertIn(red + "bar" + reset + boldr + "()" + reset, lines)
42864463

42874464
def test_colorized_syntax_error(self):

0 commit comments

Comments
 (0)