Skip to content

Commit 069560b

Browse files
authored
bpo-34463: Make python tracebacks identical to C tracebacks for SyntaxErrors without a lineno (pythonGH-23427)
1 parent 6afb730 commit 069560b

File tree

3 files changed

+35
-5
lines changed

3 files changed

+35
-5
lines changed

Lib/test/test_traceback.py

+25
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,31 @@ def e():
687687
msg = self.get_report(e).splitlines()
688688
self.assertEqual(msg[-2], ' ^')
689689

690+
def test_syntax_error_no_lineno(self):
691+
# See #34463.
692+
693+
# Without filename
694+
e = SyntaxError('bad syntax')
695+
msg = self.get_report(e).splitlines()
696+
self.assertEqual(msg,
697+
['SyntaxError: bad syntax'])
698+
e.lineno = 100
699+
msg = self.get_report(e).splitlines()
700+
self.assertEqual(msg,
701+
[' File "<string>", line 100', 'SyntaxError: bad syntax'])
702+
703+
# With filename
704+
e = SyntaxError('bad syntax')
705+
e.filename = 'myfile.py'
706+
707+
msg = self.get_report(e).splitlines()
708+
self.assertEqual(msg,
709+
['SyntaxError: bad syntax (myfile.py)'])
710+
e.lineno = 100
711+
msg = self.get_report(e).splitlines()
712+
self.assertEqual(msg,
713+
[' File "myfile.py", line 100', 'SyntaxError: bad syntax'])
714+
690715
def test_message_none(self):
691716
# A message that looks like "None" should not be treated specially
692717
err = self.get_report(Exception(None))

Lib/traceback.py

+9-5
Original file line numberDiff line numberDiff line change
@@ -525,7 +525,8 @@ def __init__(self, exc_type, exc_value, exc_traceback, *, limit=None,
525525
if exc_type and issubclass(exc_type, SyntaxError):
526526
# Handle SyntaxError's specially
527527
self.filename = exc_value.filename
528-
self.lineno = str(exc_value.lineno)
528+
lno = exc_value.lineno
529+
self.lineno = str(lno) if lno is not None else None
529530
self.text = exc_value.text
530531
self.offset = exc_value.offset
531532
self.msg = exc_value.msg
@@ -584,9 +585,12 @@ def format_exception_only(self):
584585
def _format_syntax_error(self, stype):
585586
"""Format SyntaxError exceptions (internal helper)."""
586587
# Show exactly where the problem was found.
587-
filename = self.filename or "<string>"
588-
lineno = str(self.lineno) or '?'
589-
yield ' File "{}", line {}\n'.format(filename, lineno)
588+
filename_suffix = ''
589+
if self.lineno is not None:
590+
yield ' File "{}", line {}\n'.format(
591+
self.filename or "<string>", self.lineno)
592+
elif self.filename is not None:
593+
filename_suffix = ' ({})'.format(self.filename)
590594

591595
text = self.text
592596
if text is not None:
@@ -604,7 +608,7 @@ def _format_syntax_error(self, stype):
604608
caretspace = ((c if c.isspace() else ' ') for c in ltext[:caret])
605609
yield ' {}^\n'.format(''.join(caretspace))
606610
msg = self.msg or "<no detail available>"
607-
yield "{}: {}\n".format(stype, msg)
611+
yield "{}: {}{}\n".format(stype, msg, filename_suffix)
608612

609613
def format(self, *, chain=True):
610614
"""Format the exception.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed discrepancy between :mod:`traceback` and the interpreter in formatting of SyntaxError with lineno not set (:mod:`traceback` was changed to match interpreter).

0 commit comments

Comments
 (0)