Skip to content

gh-69919: Raise SyntaxError for all invalid sources in compile() - #157586

Open
serhiy-storchaka wants to merge 5 commits into
python:mainfrom
serhiy-storchaka:gh-69919-compile-syntaxerror
Open

serhiy-storchaka wants to merge 5 commits into
python:mainfrom
serhiy-storchaka:gh-69919-compile-syntaxerror

Conversation

@serhiy-storchaka

@serhiy-storchaka serhiy-storchaka commented Sep 15, 2026 •

Copy link
Copy Markdown
Member

compile(), exec(), eval() and ast.parse() now raise SyntaxError instead of ValueError (UnicodeEncodeError) if the source string contains surrogate characters — with the line, column and text of the offending character, like other syntax errors — instead of MemoryError ("Parser stack overflowed") or RecursionError ("Stack overflow during compilation") if the source is too complex to parse or compile, and instead of OverflowError if the source is too large (a line or string literal longer than 231 bytes, or more than 231 lines; verified manually, no tests at that size). This matches how null bytes and undecodable sources are already reported, and means consumers that handle SyntaxError — code.InteractiveInterpreter, the REPL, IDLE — need nothing else: IDLE's Shell no longer gets stuck after such input.

Compiling an AST object is unchanged: a cyclic or too deep tree still raises RecursionError, and an out-of-range lineno still raises OverflowError.

The code and codeop documentation no longer mention OverflowError and ValueError "for an invalid literal": that described Python 1.5/2.0 behavior (integer literals too large for a C long, bad escapes in string literals), which has been a SyntaxError since Python 2.4/3.0.

This is an alternative to #157585, which instead makes the consumers catch all exceptions and can be backported.

🤖 Generated with Claude Code

compile(), exec(), eval() and ast.parse() now raise SyntaxError instead
of ValueError if the source string contains surrogate characters, and
instead of MemoryError or RecursionError if the source is too complex
to parse or compile. Consumers that handle SyntaxError, like the code
module and IDLE, no longer need to handle those exceptions.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@serhiy-storchaka

Copy link
Copy Markdown
Member Author

@pablogsal @lysnikolaou This and #157585 are alternatives for the same problem; I would like your opinion on which to take. This one changes the exceptions raised by compile() — SyntaxError for surrogates (with a location), for the parser stack overflow (MemoryError today) and for the compiler stack overflow (RecursionError today) — so it is for main only. #157585 instead makes code, _pyrepl and IDLE catch all exceptions from compile(), and can be backported. They can also be combined.

@read-the-docs-community

read-the-docs-community Bot commented Sep 15, 2026 •

Copy link
Copy Markdown

Documentation build overview

📚 cpython-previews | 🛠️ Build #34735650 | 📁 Comparing cf4a5a0 against main (82952e3)

  🔍 Preview build  

27 files changed · + 1 added · ± 26 modified

+ Added

± Modified

A line longer than 2**31 bytes, more than 2**31 lines, or a string
literal longer than 2**31 bytes are syntax errors too. Drop the stale
mentions of OverflowError and ValueError for invalid literals in the
code and codeop documentation.
@terryjreedy

terryjreedy commented Sep 24, 2026 •

Copy link
Copy Markdown
Member

The other alternative has been merged (hence merge conflicts) and backported. Close this one?

serhiy-storchaka and others added 2 commits September 24, 2026 12:00
# Conflicts:
#	Doc/builtins/functions.rst
#	Doc/library/code.rst
#	Lib/code.py
Too complex source now raises SyntaxError, so the tests inject
MemoryError to test that any compile() error is reported.
Compiling a too deeply nested AST object still raises RecursionError.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
@serhiy-storchaka

Copy link
Copy Markdown
Member Author

Not necessarily, they are not exclusive. #157585 makes code, _pyrepl and IDLE survive any exception from compile(); this one makes compile() itself raise SyntaxError (with a location for surrogates) instead of ValueError, MemoryError, RecursionError or OverflowError, so it is for main only. It needs a closer look, but it is not urgent now that #157585 is merged. We can also convert only some of these exceptions and keep the others where they are more appropriate. I have merged main and updated the docs added by #157585; the tests added there now inject the error, since the source they used raises SyntaxError here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants