Skip to content

Commit 47240cf

Browse files
committed
gh-142236: Fix incorrect keyword suggestions for syntax errors
The keyword typo suggestion mechanism in traceback would incorrectly suggest replacements when the extracted source code was merely incomplete rather than containing an actual typo. For example, when a missing comma caused a syntax error, the system would suggest replacing 'print' with 'not' because the incomplete code snippet happened to pass validation. The fix adds a validation step that first checks whether the original extracted code raises a SyntaxError. If the code compiles successfully or is simply incomplete (compile_command returns None), the function returns early since there is no way to verify that a keyword replacement would actually fix the problem.
1 parent f87eb4d commit 47240cf

File tree

2 files changed

+26
-0
lines changed

2 files changed

+26
-0
lines changed

Lib/test/test_traceback.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1784,6 +1784,23 @@ def test_keyword_suggestions_from_command_string(self):
17841784
stderr_text = stderr.decode('utf-8')
17851785
self.assertIn(f"Did you mean '{expected_kw}'", stderr_text)
17861786

1787+
def test_no_keyword_suggestion_for_comma_errors(self):
1788+
# When the parser identifies a missing comma, don't suggest
1789+
# bogus keyword replacements like 'print' -> 'not'
1790+
code = '''\
1791+
import sys
1792+
print(
1793+
"line1"
1794+
"line2"
1795+
file=sys.stderr
1796+
)
1797+
'''
1798+
source = textwrap.dedent(code).strip()
1799+
rc, stdout, stderr = assert_python_failure('-c', source)
1800+
stderr_text = stderr.decode('utf-8')
1801+
self.assertIn("Perhaps you forgot a comma", stderr_text)
1802+
self.assertNotIn("Did you mean", stderr_text)
1803+
17871804
@requires_debug_ranges()
17881805
@force_not_colorized_test_class
17891806
class PurePythonTracebackErrorCaretTests(

Lib/traceback.py

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,6 +1340,15 @@ def _find_keyword_typos(self):
13401340
if len(error_code) > 1024:
13411341
return
13421342

1343+
# If the original code doesn't raise SyntaxError, we can't validate
1344+
# that a keyword replacement actually fixes anything
1345+
try:
1346+
codeop.compile_command(error_code, symbol="exec")
1347+
except SyntaxError:
1348+
pass # Good - the original code has a syntax error we might fix
1349+
else:
1350+
return # Original code compiles or is incomplete - can't validate fixes
1351+
13431352
error_lines = error_code.splitlines()
13441353
tokens = tokenize.generate_tokens(io.StringIO(error_code).readline)
13451354
tokens_left_to_process = 10

0 commit comments

Comments
 (0)