-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Python: Add support for PEP-758 exception syntax #20990
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
545241a to
7f98e1e
Compare
See https://peps.python.org/pep-0758/ for more details. We implement this by extending the syntax for exceptions and exception groups so that the `type` field can now contain either an expression (which matches the old behaviour), or a comma-separated list of at least two elements (representing the new behaviour). We model the latter case using a new node type `exception_list`, which in `tsg-python` is simply mapped to a tuple. This means it matches the existing behaviour (when the tuple is surrounded by parentheses) exactly, hence we don't need to change any other code. As a consequence of this, however, we cannot directly parse the Python 2.7 syntax `except Foo, e: ...` as `except Foo as e: ...`, as this would introduce an ambiguity in the grammar. Thus, we have removed support for the (deprecated) 2.7-style syntax, and only allow `as` to indicate binding of the exception. The syntax `except Foo, e: ...` continues to be parsed (in particular, it's not suddenly a syntax error), but it will be parsed as if it were `except (Foo, e): ...`, which may not give the correct results. In principle we could extend the QL libraries to account for this case (specifically when analysing Python 2 code). In practice, however, I expect this to have a minor impact on results, and not worth the additional investment at this time.
Note in particular that the `exceptions.py` test is unaffected.
7f98e1e to
4a567ad
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds support for PEP-758's relaxed exception syntax, allowing exception types to be specified as comma-separated lists without requiring parentheses (e.g., except A, B, C: instead of except (A, B, C):).
Key Changes:
- Introduced a new
exception_listgrammar node type that accepts comma-separated expressions - Updated
except_clauseandexcept_group_clauseto accept either an expression or an exception_list for the type field - Removed support for Python 2.7's deprecated
except Foo, e:syntax for exception binding (now onlyasis supported for binding)
Reviewed changes
Copilot reviewed 9 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
python/ql/lib/change-notes/2025-12-09-python-support-relaxed-except-syntax.md |
Documents the new PEP-758 support as a feature addition |
python/extractor/tsg-python/tsp/src/node-types.json |
Defines the new exception_list node type and updates exception clause type fields to accept it |
python/extractor/tsg-python/tsp/src/grammar.json |
Generated grammar definition matching the changes in grammar.js |
python/extractor/tsg-python/tsp/grammar.js |
Implements the core grammar changes: new exception_list rule and updated exception clause rules |
python/extractor/tsg-python/python.tsg |
Maps exception_list nodes to Tuple AST nodes and handles element relationships |
python/extractor/tests/parser/exceptions_new.py |
Test cases covering the new relaxed syntax alongside old parenthesized syntax |
python/extractor/tests/parser/exceptions_new.expected |
Expected AST output for the new exception syntax tests |
python/extractor/tests/parser/exception_groups_new.py |
Adds test case for exception groups with the new syntax (except* x, y:) |
python/extractor/tests/parser/exception_groups_new.expected |
Expected AST output including the new exception group syntax test |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
|
||
| try: | ||
| pass | ||
| except* x, y: |
Copilot
AI
Jan 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Syntax Error (in Python 3).
| except* x, y: | |
| except* (x, y): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
| @@ -0,0 +1,8 @@ | |||
| try: | |||
| pass | |||
| except a, b: # new, relaxed syntax | |||
Copilot
AI
Jan 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This statement is unreachable.
| except a, b: # new, relaxed syntax | |
| except a as b: # new, relaxed syntax |
What proportion of users are still using Python 2 these days? |
geoffw0
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks plausible and has tests. The DCA run failed.
| } | ||
| } | ||
| ] | ||
| }, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If this file is generated, it should be possible to mark it as such, then it will be hidden by default in these diffs.
yoff
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks generally reasonable. I guess we do have a breaking change, but I am not sure we have promised for the 2.7 semantics to keep working?
| --- | ||
| category: feature | ||
| --- | ||
| * The extractor now supports the new, relaxed syntax `except A, B, C: ...` (which would previously have to be written as `except (A, B, C): ...`) as defined in [PEP-758](https://peps.python.org/pep-0758/). |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we mention that we drop support for 2.7 syntax?
This PR is stacked on top of #20708, so that one should be reviewed first.That PR has now been merged.See https://peps.python.org/pep-0758/ for more details.
We implement this by extending the syntax for exceptions and exception groups so that the
typefield can now contain either an expression (which matches the old behaviour), or a comma-separated list of at least two elements (representing the new behaviour).We model the latter case using a new node type
exception_list, which intsg-pythonis simply mapped to a tuple. This means it matches the existing behaviour (when the tuple is surrounded by parentheses) exactly, hence we don't need to change any other code.As a consequence of this, however, we cannot directly parse the Python 2.7 syntax
except Foo, e: ...asexcept Foo as e: ..., as this would introduce an ambiguity in the grammar. Thus, we have removed support for the (deprecated) 2.7-style syntax, and only allowasto indicate binding of the exception. The syntaxexcept Foo, e: ...continues to be parsed (in particular, it's not suddenly a syntax error), but it will be parsed as if it wereexcept (Foo, e): ..., which may not give the correct results.In principle we could extend the QL libraries to account for this case (specifically when analysing Python 2 code). In practice, however, I expect this to have a minor impact on results, and not worth the additional investment at this time.