Skip to content

Conversation

@tausbn
Copy link
Contributor

@tausbn tausbn commented Dec 8, 2025

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 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.

@tausbn tausbn force-pushed the tausbn/python-support-relaxed-exception-groups branch from 545241a to 7f98e1e Compare December 16, 2025 22:58
tausbn added 4 commits January 6, 2026 13:40
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.
@tausbn tausbn force-pushed the tausbn/python-support-relaxed-exception-groups branch from 7f98e1e to 4a567ad Compare January 6, 2026 13:41
@tausbn tausbn marked this pull request as ready for review January 6, 2026 13:42
@tausbn tausbn requested review from a team as code owners January 6, 2026 13:42
Copilot AI review requested due to automatic review settings January 6, 2026 13:42
Copy link
Contributor

Copilot AI left a 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_list grammar node type that accepts comma-separated expressions
  • Updated except_clause and except_group_clause to 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 only as is 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:
Copy link

Copilot AI Jan 6, 2026

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).

Suggested change
except* x, y:
except* (x, y):

Copilot uses AI. Check for mistakes.
Copy link
Contributor

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
Copy link

Copilot AI Jan 6, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This statement is unreachable.

Suggested change
except a, b: # new, relaxed syntax
except a as b: # new, relaxed syntax

Copilot uses AI. Check for mistakes.
@geoffw0
Copy link
Contributor

geoffw0 commented Jan 7, 2026

In principle we could extend the QL libraries to account for this case (specifically when analysing Python 2 code).

What proportion of users are still using Python 2 these days?

Copy link
Contributor

@geoffw0 geoffw0 left a 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.

}
}
]
},
Copy link
Contributor

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.

Copy link
Contributor

@yoff yoff left a 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/).
Copy link
Contributor

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?

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.

4 participants