python / python/cpython

Nested replacement fields switch f-string lexing out of format-spec mode

未關閉
#157,491 1 則留言 1 個 reaction 已指派 0 人 在 GitHub 檢視

還沒有人認領這個 Issue。

interpreter-core topic-parser type-bug
主要語言
Python
星號
77.2k
分支
35.9k
PR 合併指標
PR 指標待擷取

描述

Bug report

Summary

Closing a nested replacement field inside an f-string format specifier switches the lexer to middle-string mode even though the outer replacement field remains open. Braces that follow the nested field are then parsed as escaped literal content instead of expressions in the format specifier. The shared lexer path also affects t-strings and changes the diagnostic produced for a newline after a nested field.

Reproduction Code
class X:
    def __format__(self, spec):
        return repr(spec)


x = X()
y = "Y"
z = "Z"

print(f'{x:{{y}}}')
print(f'{x:{y}{{z}}}')
Actual Behavior
"{'Y'}"
'Y{z'}

The second f-string passes Y{z to X.__format__(). repr() returns 'Y{z', and the remaining } is appended as literal f-string content. The corresponding t-string, t'{x:{y}{{z}}}', records Y{z as its interpolation's format specifier and places the remaining } in the following literal string.

Expected Behavior

The second f-string should treat {{z}} as a nested replacement field whose expression is the set literal {z}. It should pass Y{'Z'} to X.__format__() and print:

"{'Y'}"
"Y{'Z'}"

The t-string interpolation should likewise record Y{'Z'} as its format specifier.

Root Cause

begin_ftstring_expr() increments replacement_depth when a replacement field starts. A nested replacement field within a format specifier therefore has a greater replacement depth than its enclosing field.

When the matching } is processed, _PyLexer_close_ftstring_expr() decrements replacement_depth and unconditionally selects FTSTRING_MODE_MIDDLE. After a nested field closes, the remaining non-zero replacement depth represents the still-open outer field, whose format specifier is still being scanned. Losing that state changes how _PyLexer_get_ftstring() handles subsequent braces and
newlines.

CPython versions tested on:

CPython main branch

Operating systems tested on:

Linux

Linked PRs
  • gh-157492

貢獻指南

開啟貢獻指南

從這裡開始

  1. 先讀完整個 Issue,再讀專案的貢獻指南。
  2. 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
  3. Fork 儲存庫,在一個分支上完成修改。
  4. 送出 Pull Request,並在描述裡引用這個 Issue 編號。

研究方向

執行兩個 f-string 範例,並將其輸出與預期行為進行比較,包括相應的 t-string 情況。然後閱讀 begin_ftstring_expr() 和 _PyLexer_close_ftstring_expr(),報告將它們識別為相關的 lexer 進入點;完成的標準是:外層格式指定符處於開啟狀態時,巢狀欄位仍能獲得正確處理。

由索引模型根據 Issue 內容生成。

評估

技術堆疊
python
領域
compilers
Issue 類型
缺陷
難度
4/5
預估耗時
3-5 天
活躍度
停滯
描述清晰度
描述清楚
新手友好度
35/100

把新 issue 寄到你的電子郵件信箱

精選適合新手參與的 GitHub issue 摘要。