Skip to content

Python: Infer expression contexts in QL rather than in the extractor - #22878

Open
tausbn wants to merge 2 commits into
mainfrom
tausbn/python-infer-expression-contexts-in-ql
Open

tausbn wants to merge 2 commits into
mainfrom
tausbn/python-infer-expression-contexts-in-ql

Conversation

@tausbn

@tausbn tausbn commented Oct 23, 2026

Copy link
Copy Markdown
Contributor

Adds a simple recursive scheme for inferring expression contexts in QL. This means we no longer need to do this in the extractor, but the present PR does not attempt to remove that code.

Overall this is an improvement to the readability of the code. Instead of writing py_expr_contexts(_, 2, foo), we can write foo.isDeleteContext().

I validated this by running the newly added ExprContextParity query on python/cpython, where it had zero results (meaning all of the inferred contexts match exactly to the ones generated by the extractor).

Finally, the UselessClass query used ctx instanceof AugAssign, which never did anything in the first place since AugAssign isn't a valid context type. I therefore refactored it to (presumably) capture the original intent of also matching augmented assignments.

Adds a simple recursive scheme for inferring expression contexts. This
means we no longer need to do this in the extractor, but the present
commit does not attempt to remove that code.

Overall this is an improvement to the readability of the code. Instead
of writing `py_expr_contexts(_, 2, foo)`, we can write
`foo.isDeleteContext()`.

I validated this by running the newly added `ExprContextParity` query on
`python/cpython`, where it had zero results (meaning all of the inferred
contexts match exactly to the ones generated by the extractor).

Finally, the `UselessClass` query used `ctx instanceof AugAssign`, which
never did anything in the first place since `AugAssign` isn't a valid
context type. I therefore refactored it to (presumably) capture the
original intent of also matching augmented assignments.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🔵 Needs a closer look

The migration changes core name-binding and control-flow classification, and correctness across both parser paths still needs human validation.

2 open issues
What changed in this PR

Moves Python expression-context classification into QL while retaining extractor-generated contexts for comparison.

Changes:

  • Adds public Expr context predicates and migrates library and query consumers.
  • Adds parity tests covering legacy and modern Python syntax.
  • Updates py/useless-class to recognize augmented-assignment state changes.
File Description
python/​ql/​test/​query-tests/​Classes/​useless/​test.py Covers augmented attribute and subscript mutations.
python/​ql/​test/​library-tests/​expr-context-parity/​new_parser.py Adds modern-syntax parity fixtures.
python/​ql/​test/​library-tests/​expr-context-parity/​legacy.py Adds legacy-parser context fixtures.
python/​ql/​test/​library-tests/​expr-context-parity/​ExprContextParity.ql Compares inferred and extracted contexts.
python/​ql/​test/​library-tests/​expr-context-parity/​ExprContextParity.expected Establishes an empty parity-result baseline.
python/​ql/​src/​Classes/​UselessClass.ql Recognizes augmented assignments as state changes.
python/​ql/​src/​Classes/​OverwritingAttributeInSuperClass.ql Uses the new store-context predicate.
python/​ql/​src/​Classes/​ClassAttributes.qll Migrates the monkey-patching store check.
python/​ql/​src/​analysis/​RatioOfDefinitions.ql Uses inferred load contexts.
python/​ql/​lib/​semmle/​python/​SelfAttribute.qll Migrates attribute read and store classification.
python/​ql/​lib/​semmle/​python/​Flow.qll Uses inferred contexts for control-flow classification.
python/​ql/​lib/​semmle/​python/​Exprs.qll Implements context inference and public predicates.
python/​ql/​lib/​semmle/​python/​controlflow/​internal/​Cfg.qll Migrates internal control-flow context checks.
python/​ql/​lib/​change-notes/​2026-10-23-inferred-expression-contexts.md Documents the new library API.

Review effort: Max

Comment thread python/ql/lib/semmle/python/Exprs.qll
Comment thread python/ql/test/library-tests/expr-context-parity/new_parser.py
Limits `inferredNonLoadExpressionContext`, and extends the new parser
tests to also contain the legacy test cases.
@tausbn
tausbn marked this pull request as ready for review October 23, 2026 15:41
@tausbn
tausbn requested a review from a team as a code owner October 23, 2026 15:41

This branch has not been deployed

No deployments
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