Skip to content

Commit f10a62c

Browse files
committed
[3.11] gh-111366: Correctly show custom syntax error messages in the codeop module functions (GH-111384).
(cherry picked from commit cd6e0a0) Co-authored-by: Pablo Galindo Salgado <[email protected]>
1 parent 78150c6 commit f10a62c

File tree

3 files changed

+30
-15
lines changed

3 files changed

+30
-15
lines changed

Lib/codeop.py

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,14 @@ def _maybe_compile(compiler, source, filename, symbol):
7070
return None
7171
# fallthrough
7272

73-
return compiler(source, filename, symbol)
73+
return compiler(source, filename, symbol, incomplete_input=False)
7474

75-
76-
def _is_syntax_error(err1, err2):
77-
rep1 = repr(err1)
78-
rep2 = repr(err2)
79-
if "was never closed" in rep1 and "was never closed" in rep2:
80-
return False
81-
if rep1 == rep2:
82-
return True
83-
return False
84-
85-
def _compile(source, filename, symbol):
86-
return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT)
75+
def _compile(source, filename, symbol, incomplete_input=True):
76+
flags = 0
77+
if incomplete_input:
78+
flags |= PyCF_ALLOW_INCOMPLETE_INPUT
79+
flags |= PyCF_DONT_IMPLY_DEDENT
80+
return compile(source, filename, symbol, flags)
8781

8882
def compile_command(source, filename="<input>", symbol="single"):
8983
r"""Compile a command and determine whether it is incomplete.
@@ -114,8 +108,12 @@ class Compile:
114108
def __init__(self):
115109
self.flags = PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT
116110

117-
def __call__(self, source, filename, symbol):
118-
codeob = compile(source, filename, symbol, self.flags, True)
111+
def __call__(self, source, filename, symbol, **kwargs):
112+
flags = self.flags
113+
if kwargs.get('incomplete_input', True) is False:
114+
flags &= ~PyCF_DONT_IMPLY_DEDENT
115+
flags &= ~PyCF_ALLOW_INCOMPLETE_INPUT
116+
codeob = compile(source, filename, symbol, flags, True)
119117
for feature in _features:
120118
if codeob.co_flags & feature.compiler_flag:
121119
self.flags |= feature.compiler_flag

Lib/test/test_codeop.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import warnings
88
from test import support
99
from test.support import warnings_helper
10+
from textwrap import dedent
1011

1112
from codeop import compile_command, PyCF_DONT_IMPLY_DEDENT
1213
import io
@@ -341,6 +342,19 @@ def test_invalid_warning(self):
341342
self.assertRegex(str(w[0].message), 'invalid escape sequence')
342343
self.assertEqual(w[0].filename, '<input>')
343344

345+
def assertSyntaxErrorMatches(self, code, message):
346+
with self.subTest(code):
347+
with self.assertRaisesRegex(SyntaxError, message):
348+
compile_command(code, symbol='exec')
349+
350+
def test_syntax_errors(self):
351+
self.assertSyntaxErrorMatches(
352+
dedent("""\
353+
def foo(x,x):
354+
pass
355+
"""), "duplicate argument 'x' in function definition")
356+
357+
344358

345359
if __name__ == "__main__":
346360
unittest.main()
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
Fix an issue in the :mod:`codeop` that was causing :exc:`SyntaxError`
2+
exceptions raised in the presence of invalid syntax to not contain precise
3+
error messages. Patch by Pablo Galindo

0 commit comments

Comments
 (0)