From 904d16effbd80fa781b42fcf4c31d1554a943847 Mon Sep 17 00:00:00 2001 From: Pablo Galindo Date: Fri, 27 Oct 2023 12:18:41 +0900 Subject: [PATCH] gh-111366: Correctly show custom syntax error messages in the codeop module functions --- Lib/codeop.py | 18 +++++++++++++----- Lib/test/test_codeop.py | 14 ++++++++++++++ ...3-10-27-12-17-49.gh-issue-111366._TSknV.rst | 3 +++ 3 files changed, 30 insertions(+), 5 deletions(-) create mode 100644 Misc/NEWS.d/next/Core and Builtins/2023-10-27-12-17-49.gh-issue-111366._TSknV.rst diff --git a/Lib/codeop.py b/Lib/codeop.py index a574aa4b70f1a8a..91146be2c438e2c 100644 --- a/Lib/codeop.py +++ b/Lib/codeop.py @@ -70,10 +70,14 @@ def _maybe_compile(compiler, source, filename, symbol): return None # fallthrough - return compiler(source, filename, symbol) + return compiler(source, filename, symbol, incomplete_input=False) -def _compile(source, filename, symbol): - return compile(source, filename, symbol, PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT) +def _compile(source, filename, symbol, incomplete_input=True): + flags = 0 + if incomplete_input: + flags |= PyCF_ALLOW_INCOMPLETE_INPUT + flags |= PyCF_DONT_IMPLY_DEDENT + return compile(source, filename, symbol, flags) def compile_command(source, filename="", symbol="single"): r"""Compile a command and determine whether it is incomplete. @@ -104,8 +108,12 @@ class Compile: def __init__(self): self.flags = PyCF_DONT_IMPLY_DEDENT | PyCF_ALLOW_INCOMPLETE_INPUT - def __call__(self, source, filename, symbol): - codeob = compile(source, filename, symbol, self.flags, True) + def __call__(self, source, filename, symbol, **kwargs): + flags = self.flags + if kwargs.get('incomplete_input', True) is False: + flags &= ~PyCF_DONT_IMPLY_DEDENT + flags &= ~PyCF_ALLOW_INCOMPLETE_INPUT + codeob = compile(source, filename, symbol, flags, True) for feature in _features: if codeob.co_flags & feature.compiler_flag: self.flags |= feature.compiler_flag diff --git a/Lib/test/test_codeop.py b/Lib/test/test_codeop.py index e3c382266fa0583..a3b524b4cdd3c58 100644 --- a/Lib/test/test_codeop.py +++ b/Lib/test/test_codeop.py @@ -5,6 +5,7 @@ import unittest import warnings from test.support import warnings_helper +from textwrap import dedent from codeop import compile_command, PyCF_DONT_IMPLY_DEDENT @@ -307,6 +308,19 @@ def test_invalid_warning(self): self.assertEqual(w[0].category, SyntaxWarning) self.assertRegex(str(w[0].message), 'invalid escape sequence') self.assertEqual(w[0].filename, '') + + def assertSyntaxErrorMatches(self, code, message): + with self.subTest(code): + with self.assertRaisesRegex(SyntaxError, message): + compile_command(code, symbol='exec') + + def test_syntax_errors(self): + self.assertSyntaxErrorMatches( + dedent("""\ + def foo(x,x): + pass + """), "duplicate argument 'x' in function definition") + if __name__ == "__main__": diff --git a/Misc/NEWS.d/next/Core and Builtins/2023-10-27-12-17-49.gh-issue-111366._TSknV.rst b/Misc/NEWS.d/next/Core and Builtins/2023-10-27-12-17-49.gh-issue-111366._TSknV.rst new file mode 100644 index 000000000000000..7e76ce916ea714b --- /dev/null +++ b/Misc/NEWS.d/next/Core and Builtins/2023-10-27-12-17-49.gh-issue-111366._TSknV.rst @@ -0,0 +1,3 @@ +Fix an issue in the :mod:`codeop` that was causing :exc:`SyntaxError` +exceptions raised in the presence of invalid syntax to not contain precise +error messages. Patch by Pablo Galindo