Skip to content

Python: Add f-string support for Python template/pattern API#6854

Merged
knutwannheden merged 3 commits intomainfrom
rapid-gecko
Mar 3, 2026
Merged

Python: Add f-string support for Python template/pattern API#6854
knutwannheden merged 3 commits intomainfrom
rapid-gecko

Conversation

@knutwannheden
Copy link
Contributor

@knutwannheden knutwannheden commented Mar 3, 2026

Summary

Add f-string and t-string support for the Python template/pattern API, enabling a more natural syntax for defining captures in templates.

Three ways to create templates with captures:

expr = capture('expr')

# 1. Plain string with explicit kwargs (existing)
tmpl = template("print({expr})", expr=expr)

# 2. f-string (new) — no name duplication
tmpl = template(f"print({expr})")

# 3. t-string (Python 3.14+, new) — structured interpolation
tmpl = template(t"print({expr})")

All three paths produce identical results. RawCode (via raw()) can be mixed with captures in f-strings and t-strings for splice-time code insertion (e.g. dynamic method names).

Implementation

  • Capture.__format__ emits the internal placeholder identifier (__plh_name__) directly, making f-string code already in the engine's internal format — substitute_placeholders becomes a no-op
  • convert_tstring does the same for t-strings
  • Thread-safe auto-registration via contextvars.ContextVar prevents interference between concurrent f-string evaluations
  • Stale registry entries are always cleared to prevent leaking between calls
  • Shared resolve_captures() helper dispatches t-string / f-string / explicit-kwargs uniformly for both template() and pattern()

Test plan

  • test_capture.py__format__ output, auto-registration, stale cleanup, kwargs override
  • test_tstring_support.py — t-string conversion with captures, raw code, mixed usage
  • test_placeholder.py — placeholder conversion, substitution, validation
  • test_engine.py — parsing with placeholders, caching, auto-format integration
  • test_replacement.py — placeholder replacement, auto-parenthesization

Enable `template(f"print({expr})")` and `pattern(f"print({expr})")` as a
cleaner alternative to explicit kwargs like `template("print({expr})", expr=expr)`.

Works on all Python 3.6+ via `__format__` methods on Capture and RawCode:
- `Capture.__format__` returns `{name}` placeholder and auto-registers via contextvars
- `RawCode.__format__` splices code directly into the string
- `capture()` name parameter is now optional (auto-generated when omitted)
- `template()`/`pattern()` pick up auto-registered captures; explicit kwargs override
- Extract duplicated t-string/f-string/kwargs dispatch logic from
  template() and pattern() into resolve_captures() in _fstring_support.py
- Replace _capture_counter global with itertools.count(1)
- Fix inconsistent absolute imports in pattern.py to use relative imports
- Remove unused _pending import from tests
- Remove 6 redundant tests (30 -> 24): test_basic_format, test_empty_code,
  test_placeholder_output, test_multiple_captures,
  test_explicit_name_still_works, test_fstring_equivalent_to_kwargs
@knutwannheden knutwannheden changed the title Add f-string support for Python template/pattern API Python: Add f-string support for Python template/pattern API Mar 3, 2026
Have Capture.__format__, collect_captures, and convert_tstring produce
the internal __plh_name__ identifier directly instead of {name} braces.
This makes substitute_placeholders a no-op for f-string and t-string
paths, and avoids collision with Python's own brace syntax (dicts, sets).
Shorten the prefix from __placeholder_ to __plh_ for conciseness.
@knutwannheden knutwannheden merged commit 60d28f9 into main Mar 3, 2026
1 check failed
@knutwannheden knutwannheden deleted the rapid-gecko branch March 3, 2026 09:40
@github-project-automation github-project-automation bot moved this from In Progress to Done in OpenRewrite Mar 3, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

1 participant