Skip to content

Python: Fix pattern matching false positives and add template auto-parenthesization#6814

Merged
knutwannheden merged 1 commit intomainfrom
fix/python-template-pattern-matching-and-precedence
Feb 25, 2026
Merged

Python: Fix pattern matching false positives and add template auto-parenthesization#6814
knutwannheden merged 1 commit intomainfrom
fix/python-template-pattern-matching-and-precedence

Conversation

@knutwannheden
Copy link
Copy Markdown
Contributor

Summary

Two fixes in the Python template system discovered while running cleanup recipes across 11 open-source Python projects:

  • PatternMatchingComparator: The default fallthrough for unhandled node types returned True, causing false positive matches. For example, pattern("{x} == None") would match x == b"hello" because ArrayAccess nodes weren't handled and any two nodes of an unrecognized type silently matched. Changed to return False and added explicit handlers for Empty (sentinel) and ArrayAccess nodes.

  • PlaceholderReplacementVisitor: Template substitution didn't account for operator precedence, producing semantically incorrect output. For example, template("{a} and {b}") with b captured as x or y would produce a and x or y instead of a and (x or y). Added auto-parenthesization in visit_binary, visit_python_binary, and visit_unary that wraps substituted expressions when they have lower precedence than the surrounding context.

Test plan

  • 15 new unit tests in test_comparator.py and test_replacement.py covering:
    • ArrayAccess matching (positive, index mismatch, indexed mismatch)
    • Empty sentinel node matching
    • Unhandled node type rejection
    • Auto-parenthesization for or in and, and in and (no parens), arithmetic precedence, Python in operator, not with and/or operands, not with identifiers/comparisons (no parens)
  • All 1020 existing framework tests pass
  • All 713 downstream recipe tests pass

…renthesization

Two fixes in the Python template system:

1. PatternMatchingComparator: Change default fallthrough from `return True`
   to `return False` so unhandled node types reject matches instead of
   silently accepting. Add explicit handlers for Empty (sentinel) and
   ArrayAccess nodes.

2. PlaceholderReplacementVisitor: Auto-wrap substituted expressions in
   parentheses when they have lower operator precedence than the
   surrounding context. For example, `template("{a} and {b}")` with
   `b = x or y` now correctly produces `a and (x or y)` instead of
   `a and x or y`. Handles Binary, Python Binary, and Unary (not).
@github-project-automation github-project-automation Bot moved this to In Progress in OpenRewrite Feb 25, 2026
@knutwannheden knutwannheden merged commit 9416341 into main Feb 25, 2026
1 check passed
@knutwannheden knutwannheden deleted the fix/python-template-pattern-matching-and-precedence branch February 25, 2026 09:56
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite Feb 25, 2026
macsux pushed a commit that referenced this pull request Feb 27, 2026
…renthesization (#6814)

Two fixes in the Python template system:

1. PatternMatchingComparator: Change default fallthrough from `return True`
   to `return False` so unhandled node types reject matches instead of
   silently accepting. Add explicit handlers for Empty (sentinel) and
   ArrayAccess nodes.

2. PlaceholderReplacementVisitor: Auto-wrap substituted expressions in
   parentheses when they have lower operator precedence than the
   surrounding context. For example, `template("{a} and {b}")` with
   `b = x or y` now correctly produces `a and (x or y)` instead of
   `a and x or y`. Handles Binary, Python Binary, and Unary (not).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

1 participant