Skip to content

patchedast: locate multi-line f-strings, replacement fields and match-sequence delimiters by parser coordinates - #882

Open
marlon-costa-dc wants to merge 3 commits into
python-rope:masterfrom
marlon-costa-dc:pr/parser-coordinates
Open

marlon-costa-dc wants to merge 3 commits into
python-rope:masterfrom
marlon-costa-dc:pr/parser-coordinates

Conversation

@marlon-costa-dc

Copy link
Copy Markdown
Contributor

Description

Three patchedast defects found by walking a ~6,300-file Python 3.13 codebase with get_patched_ast(source, True) and requiring write_ast() to reproduce each file exactly:

  1. Multi-line replacement fields (PEP 701). x = (f"{a}{\n b\n}{c}").upper() raised MismatchedTokenError: _JoinedStr located the literal with the textual string pattern, whose short-string form excludes newlines. The literal's region now comes from the node's own coordinates (ast_adapter), implicit concatenation included.
  2. Replacement field brace in a plain string of the same concatenation. In "({})," f"{a}" the field's { was searched for as text and matched the { inside the plain part, so the FormattedValue region started at ( and write_ast duplicated source. Since Python 3.12 the parser locates each FormattedValue at its own {; the walker starts there when the coordinate points at one (older parsers give the enclosing literal's position, which is left untouched). This also fixes the case covered by test_extract_method_f_string_false_format_value_in_regular_string, whose @expectedFailure is removed.
  3. Grouped first pattern in a match sequence (related to patchedast is currently not handling some match-case statement syntaxes #623). case (("a" | None), None): warned Unexpected character in MatchSequence's opening_paren <((> and duplicated the source on write, because every character before the first pattern was taken as the delimiter. The sequence's delimiters are now the bracket pair that encloses the whole node, found by tokenizing its segment; case (1), (2):, whose outer parentheses belong to its elements, is also handled.

Checklist

  • I have added tests that prove my fix is effective: three new tests in ropetest/refactor/patchedasttest.py fail on current master and pass here; the previously expected-failure extract test passes.
  • I have updated CHANGELOG.md

🤖 Generated with Claude Code

Marlon Costa and others added 3 commits September 25, 2026 12:28
A PEP 701 replacement field may span lines, which the textual string
pattern cannot match, so JoinedStr raised MismatchedTokenError; its
region now comes from the node's own coordinates, implicit concatenation
included. A MatchSequence took every character before its first pattern
as its opening delimiter, so a grouped first pattern (`((a | b), c)`)
produced `((`; the delimiters are now the bracket pair that encloses the
whole node, found by tokenizing its segment.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
In an implicit concatenation mixing f-strings and plain strings, the
field's opening brace was searched for as text and matched a "{" inside
a plain part (`"({})," f"{a}"`), shifting the field's region and
duplicating source on write. Since Python 3.12 the parser locates each
FormattedValue at its own "{"; the walker now starts there when the
coordinate points at one. test_extract_method_f_string_false_format_value
_in_regular_string, marked as an expected failure for this bug, passes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
marlon-costa-dc pushed a commit to marlon-costa-dc/rope that referenced this pull request Sep 25, 2026
Adds the parser-coordinate patchedast fixes (upstream PR python-rope#882): multi-line
f-string replacement fields, replacement-field braces in plain parts of a
concatenation, and grouped first patterns in match sequences.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@lieryan lieryan added this to the 1.16.0 milestone Sep 26, 2026

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants